mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-06-14 14:52:09 +03:00
Initial Mapbase commit (squashed from mapbase-beta)
This commit is contained in:
parent
0d8dceea43
commit
3d464bc051
21
.gitignore
vendored
21
.gitignore
vendored
@ -54,3 +54,24 @@ config.cfg
|
|||||||
# shader files
|
# shader files
|
||||||
*.tmp
|
*.tmp
|
||||||
|
|
||||||
|
# Unnecessary files
|
||||||
|
*.lib
|
||||||
|
*.filters
|
||||||
|
*.vpc_crc
|
||||||
|
*.sentinel
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*.bak
|
||||||
|
|
||||||
|
# Build folders
|
||||||
|
sp/src/.vs/
|
||||||
|
sp/src/game/client/Debug_mod_episodic/
|
||||||
|
sp/src/game/client/Debug_mod_hl2/
|
||||||
|
sp/src/game/client/Release_mod_episodic/
|
||||||
|
sp/src/game/client/Release_mod_hl2/
|
||||||
|
sp/src/game/server/Debug_mod_episodic/
|
||||||
|
sp/src/game/server/Debug_mod_hl2/
|
||||||
|
sp/src/game/server/Release_mod_episodic/
|
||||||
|
sp/src/game/server/Release_mod_hl2/
|
||||||
|
sp/src/*/Debug/
|
||||||
|
sp/src/*/Release/
|
||||||
|
19
README
19
README
@ -1,3 +1,22 @@
|
|||||||
|
Mapbase - Source 2013
|
||||||
|
|
||||||
|
This repository contains the code and game files of the Source 2013 modification known as Mapbase.
|
||||||
|
|
||||||
|
The projected texture fixes within the "ASW_PROJECTED_TEXTURES" preprocessor are from Insolence 2013. (https://github.com/95Navigator/insolence-2013)
|
||||||
|
The projected texture fixes within the "C17EP1_PROJECTED_TEXTURES" preprocessor are from City 17: Episode One. (https://github.com/KyleGospo/City-17-Episode-One-Source)
|
||||||
|
The vortigaunt LOS fix is from Half-Life 2: Community Edition, more specifically dky.tehkingd.u. (https://gitlab.com/RaraCerberus/HL2CE)
|
||||||
|
The dynamic RTT shadow angles code is from Saul Rennison on the VDC. (https://developer.valvesoftware.com/wiki/Dynamic_RTT_shadow_angles_in_Source_2007)
|
||||||
|
Various other code and contributions were based off of pull requests in the Source 2013 SDK (https://github.com/ValveSoftware/source-sdk-2013/pulls) and snippets on the Valve Developer Community (http://developer.valvesoftware.com/).
|
||||||
|
|
||||||
|
All of the work mentioned above was open source when it was borrowed.
|
||||||
|
|
||||||
|
Miscellaneous credits can be found here:
|
||||||
|
https://trello.com/c/cnaEy4Jr
|
||||||
|
|
||||||
|
Please see the Source SDK 2013 license below:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SOURCE 1 SDK LICENSE
|
SOURCE 1 SDK LICENSE
|
||||||
|
|
||||||
Source SDK Copyright(c) Valve Corp.
|
Source SDK Copyright(c) Valve Corp.
|
||||||
|
@ -14,6 +14,99 @@
|
|||||||
#include "c_baseentity.h"
|
#include "c_baseentity.h"
|
||||||
#include "basetypes.h"
|
#include "basetypes.h"
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class C_EnvProjectedTexture : public C_BaseEntity
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( C_EnvProjectedTexture, C_BaseEntity );
|
||||||
|
public:
|
||||||
|
DECLARE_CLIENTCLASS();
|
||||||
|
|
||||||
|
void SetMaterial( IMaterial *pMaterial );
|
||||||
|
void SetLightColor( byte r, byte g, byte b, byte a );
|
||||||
|
void SetSize( float flSize );
|
||||||
|
void SetRotation( float flRotation );
|
||||||
|
|
||||||
|
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||||
|
void ShutDownLightHandle( void );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void Simulate();
|
||||||
|
#else
|
||||||
|
virtual bool Simulate();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void UpdateLight( void );
|
||||||
|
|
||||||
|
C_EnvProjectedTexture();
|
||||||
|
~C_EnvProjectedTexture();
|
||||||
|
|
||||||
|
static void SetVisibleBBoxMinHeight( float flVisibleBBoxMinHeight ) { m_flVisibleBBoxMinHeight = flVisibleBBoxMinHeight; }
|
||||||
|
static float GetVisibleBBoxMinHeight( void ) { return m_flVisibleBBoxMinHeight; }
|
||||||
|
static C_EnvProjectedTexture *Create( );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
inline bool IsBBoxVisible( void );
|
||||||
|
bool IsBBoxVisible( Vector vecExtentsMin,
|
||||||
|
Vector vecExtentsMax );
|
||||||
|
|
||||||
|
ClientShadowHandle_t m_LightHandle;
|
||||||
|
bool m_bForceUpdate;
|
||||||
|
|
||||||
|
EHANDLE m_hTargetEntity;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bDontFollowTarget;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool m_bState;
|
||||||
|
bool m_bAlwaysUpdate;
|
||||||
|
float m_flLightFOV;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float m_flLightHorFOV;
|
||||||
|
#endif
|
||||||
|
bool m_bEnableShadows;
|
||||||
|
bool m_bLightOnlyTarget;
|
||||||
|
bool m_bLightWorld;
|
||||||
|
bool m_bCameraSpace;
|
||||||
|
float m_flBrightnessScale;
|
||||||
|
color32 m_LightColor;
|
||||||
|
Vector m_CurrentLinearFloatLightColor;
|
||||||
|
float m_flCurrentLinearFloatLightAlpha;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float m_flCurrentBrightnessScale;
|
||||||
|
#endif
|
||||||
|
float m_flColorTransitionTime;
|
||||||
|
float m_flAmbient;
|
||||||
|
float m_flNearZ;
|
||||||
|
float m_flFarZ;
|
||||||
|
char m_SpotlightTextureName[ MAX_PATH ];
|
||||||
|
CTextureReference m_SpotlightTexture;
|
||||||
|
int m_nSpotlightTextureFrame;
|
||||||
|
int m_nShadowQuality;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bAlwaysDraw;
|
||||||
|
//bool m_bProjectedTextureVersion;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Vector m_vecExtentsMin;
|
||||||
|
Vector m_vecExtentsMax;
|
||||||
|
|
||||||
|
static float m_flVisibleBBoxMinHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool C_EnvProjectedTexture::IsBBoxVisible( void )
|
||||||
|
{
|
||||||
|
return IsBBoxVisible( GetAbsOrigin() + m_vecExtentsMin, GetAbsOrigin() + m_vecExtentsMax );
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -62,4 +155,6 @@ public:
|
|||||||
|
|
||||||
C_EnvProjectedTexture* GetEnvProjectedTextureList();
|
C_EnvProjectedTexture* GetEnvProjectedTextureList();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // C_ENVPROJECTEDTEXTURE_H
|
#endif // C_ENVPROJECTEDTEXTURE_H
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
#include "tier1/KeyValues.h"
|
#include "tier1/KeyValues.h"
|
||||||
#include "toolframework/itoolframework.h"
|
#include "toolframework/itoolframework.h"
|
||||||
#include "toolframework_client.h"
|
#include "toolframework_client.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "viewrender.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
@ -83,8 +86,30 @@ static inline bool ShouldDrawLocalPlayerViewModel( void )
|
|||||||
#if defined( PORTAL )
|
#if defined( PORTAL )
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// We shouldn't draw the viewmodel externally.
|
||||||
|
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
|
||||||
|
if (localplayer)
|
||||||
|
{
|
||||||
|
if (localplayer->m_bDrawPlayerModelExternally)
|
||||||
|
{
|
||||||
|
// If this isn't the main view, draw the weapon.
|
||||||
|
view_id_t viewID = CurrentViewID();
|
||||||
|
if (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since we already have the local player, check its own ShouldDrawThisPlayer() to avoid extra checks
|
||||||
|
return localplayer->ShouldDrawThisPlayer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
return !C_BasePlayer::ShouldDrawLocalPlayer();
|
return !C_BasePlayer::ShouldDrawLocalPlayer();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -432,6 +457,12 @@ bool C_BaseCombatWeapon::ShouldDraw( void )
|
|||||||
if ( !ShouldDrawLocalPlayerViewModel() )
|
if ( !ShouldDrawLocalPlayerViewModel() )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// We're drawing this in non-main views, handle it in DrawModel()
|
||||||
|
if ( pLocalPlayer->m_bDrawPlayerModelExternally )
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
// don't draw active weapon if not in some kind of 3rd person mode, the viewmodel will do that
|
// don't draw active weapon if not in some kind of 3rd person mode, the viewmodel will do that
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -480,6 +511,16 @@ int C_BaseCombatWeapon::DrawModel( int flags )
|
|||||||
|
|
||||||
if ( localplayer && localplayer->IsObserver() && GetOwner() )
|
if ( localplayer && localplayer->IsObserver() && GetOwner() )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (localplayer->m_bDrawPlayerModelExternally)
|
||||||
|
{
|
||||||
|
// If this isn't the main view, draw the weapon.
|
||||||
|
view_id_t viewID = CurrentViewID();
|
||||||
|
if (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)
|
||||||
|
return BaseClass::DrawModel( flags );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// don't draw weapon if chasing this guy as spectator
|
// don't draw weapon if chasing this guy as spectator
|
||||||
// we don't check that in ShouldDraw() since this may change
|
// we don't check that in ShouldDraw() since this may change
|
||||||
// without notification
|
// without notification
|
||||||
|
@ -1149,7 +1149,11 @@ void C_BaseFlex::SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightC
|
|||||||
{
|
{
|
||||||
// hack in an initialization
|
// hack in an initialization
|
||||||
LinkToGlobalFlexControllers( GetModelPtr() );
|
LinkToGlobalFlexControllers( GetModelPtr() );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iBlink = AddGlobalFlexController( "blink" );
|
||||||
|
#else
|
||||||
m_iBlink = AddGlobalFlexController( "UH" );
|
m_iBlink = AddGlobalFlexController( "UH" );
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( SetupGlobalWeights( pBoneToWorld, nFlexWeightCount, pFlexWeights, pFlexDelayedWeights ) )
|
if ( SetupGlobalWeights( pBoneToWorld, nFlexWeightCount, pFlexWeights, pFlexDelayedWeights ) )
|
||||||
{
|
{
|
||||||
|
@ -54,6 +54,10 @@
|
|||||||
#include "econ_wearable.h"
|
#include "econ_wearable.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "viewrender.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// NVNT haptics system interface
|
// NVNT haptics system interface
|
||||||
#include "haptics/ihaptics.h"
|
#include "haptics/ihaptics.h"
|
||||||
|
|
||||||
@ -176,6 +180,10 @@ BEGIN_RECV_TABLE_NOBASE( CPlayerLocalData, DT_Local )
|
|||||||
// 3d skybox data
|
// 3d skybox data
|
||||||
RecvPropInt(RECVINFO(m_skybox3d.scale)),
|
RecvPropInt(RECVINFO(m_skybox3d.scale)),
|
||||||
RecvPropVector(RECVINFO(m_skybox3d.origin)),
|
RecvPropVector(RECVINFO(m_skybox3d.origin)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropVector(RECVINFO(m_skybox3d.angles)),
|
||||||
|
RecvPropInt( RECVINFO( m_skybox3d.skycolor ), 0, RecvProxy_IntToColor32 ),
|
||||||
|
#endif
|
||||||
RecvPropInt(RECVINFO(m_skybox3d.area)),
|
RecvPropInt(RECVINFO(m_skybox3d.area)),
|
||||||
|
|
||||||
// 3d skybox fog data
|
// 3d skybox fog data
|
||||||
@ -187,6 +195,9 @@ BEGIN_RECV_TABLE_NOBASE( CPlayerLocalData, DT_Local )
|
|||||||
RecvPropFloat( RECVINFO( m_skybox3d.fog.start ) ),
|
RecvPropFloat( RECVINFO( m_skybox3d.fog.start ) ),
|
||||||
RecvPropFloat( RECVINFO( m_skybox3d.fog.end ) ),
|
RecvPropFloat( RECVINFO( m_skybox3d.fog.end ) ),
|
||||||
RecvPropFloat( RECVINFO( m_skybox3d.fog.maxdensity ) ),
|
RecvPropFloat( RECVINFO( m_skybox3d.fog.maxdensity ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropFloat( RECVINFO( m_skybox3d.fog.farz ) ),
|
||||||
|
#endif
|
||||||
|
|
||||||
// fog data
|
// fog data
|
||||||
RecvPropEHandle( RECVINFO( m_PlayerFog.m_hCtrl ) ),
|
RecvPropEHandle( RECVINFO( m_PlayerFog.m_hCtrl ) ),
|
||||||
@ -245,6 +256,14 @@ END_RECV_TABLE()
|
|||||||
RecvPropInt ( RECVINFO( m_nWaterLevel ) ),
|
RecvPropInt ( RECVINFO( m_nWaterLevel ) ),
|
||||||
RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )),
|
RecvPropFloat ( RECVINFO( m_flLaggedMovementValue )),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Transmitted from the server for internal player spawnflags.
|
||||||
|
// See baseplayer_shared.h for more details.
|
||||||
|
RecvPropInt ( RECVINFO( m_spawnflags ) ),
|
||||||
|
|
||||||
|
RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ),
|
||||||
|
#endif
|
||||||
|
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
|
||||||
@ -1054,6 +1073,16 @@ void C_BasePlayer::DetermineVguiInputMode( CUserCmd *pCmd )
|
|||||||
|
|
||||||
// If we're in vgui mode *and* we're holding down mouse buttons,
|
// If we're in vgui mode *and* we're holding down mouse buttons,
|
||||||
// stay in vgui mode even if we're outside the screen bounds
|
// stay in vgui mode even if we're outside the screen bounds
|
||||||
|
#ifdef VGUI_SCREEN_FIX
|
||||||
|
if (m_pCurrentVguiScreen.Get() && (pCmd->buttons & (IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT)))
|
||||||
|
{
|
||||||
|
SetVGuiScreenButtonState( m_pCurrentVguiScreen.Get(), pCmd->buttons );
|
||||||
|
|
||||||
|
// Kill all attack inputs if we're in vgui screen mode
|
||||||
|
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2 | IN_VALIDVGUIINPUT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (m_pCurrentVguiScreen.Get() && (pCmd->buttons & (IN_ATTACK | IN_ATTACK2)) )
|
if (m_pCurrentVguiScreen.Get() && (pCmd->buttons & (IN_ATTACK | IN_ATTACK2)) )
|
||||||
{
|
{
|
||||||
SetVGuiScreenButtonState( m_pCurrentVguiScreen.Get(), pCmd->buttons );
|
SetVGuiScreenButtonState( m_pCurrentVguiScreen.Get(), pCmd->buttons );
|
||||||
@ -1062,6 +1091,7 @@ void C_BasePlayer::DetermineVguiInputMode( CUserCmd *pCmd )
|
|||||||
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
|
pCmd->buttons &= ~(IN_ATTACK | IN_ATTACK2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// We're not in vgui input mode if we're moving, or have hit a key
|
// We're not in vgui input mode if we're moving, or have hit a key
|
||||||
// that will make us move...
|
// that will make us move...
|
||||||
@ -1183,7 +1213,12 @@ bool C_BasePlayer::CreateMove( float flInputSampleTime, CUserCmd *pCmd )
|
|||||||
m_vecOldViewAngles = pCmd->viewangles;
|
m_vecOldViewAngles = pCmd->viewangles;
|
||||||
|
|
||||||
// Check to see if we're in vgui input mode...
|
// Check to see if we're in vgui input mode...
|
||||||
|
#ifdef VGUI_SCREEN_FIX
|
||||||
|
if(pCmd->buttons & IN_VALIDVGUIINPUT)
|
||||||
DetermineVguiInputMode( pCmd );
|
DetermineVguiInputMode( pCmd );
|
||||||
|
#else
|
||||||
|
DetermineVguiInputMode( pCmd );
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1385,11 +1420,34 @@ bool C_BasePlayer::ShouldInterpolate()
|
|||||||
|
|
||||||
bool C_BasePlayer::ShouldDraw()
|
bool C_BasePlayer::ShouldDraw()
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// We have to "always draw" a player with m_bDrawPlayerModelExternally in order to show up in whatever rendering list all of the views use,
|
||||||
|
// but we can't put this in ShouldDrawThisPlayer() because we would have no way of knowing if it stomps the other checks that draw the player model anyway.
|
||||||
|
// As a result, we have to put it here in the central ShouldDraw() function. DrawModel() makes sure we only draw in non-main views and nothing's drawing the model anyway.
|
||||||
|
return (ShouldDrawThisPlayer() || m_bDrawPlayerModelExternally) && BaseClass::ShouldDraw();
|
||||||
|
#else
|
||||||
return ShouldDrawThisPlayer() && BaseClass::ShouldDraw();
|
return ShouldDrawThisPlayer() && BaseClass::ShouldDraw();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int C_BasePlayer::DrawModel( int flags )
|
int C_BasePlayer::DrawModel( int flags )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_bDrawPlayerModelExternally)
|
||||||
|
{
|
||||||
|
// Draw the player in any view except the main or "intro" view, both of which are default first-person views.
|
||||||
|
view_id_t viewID = CurrentViewID();
|
||||||
|
if (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA)
|
||||||
|
{
|
||||||
|
// Make sure the player model wouldn't draw anyway...
|
||||||
|
if (!ShouldDrawThisPlayer())
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BaseClass::DrawModel( flags );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PORTAL
|
#ifndef PORTAL
|
||||||
// In Portal this check is already performed as part of
|
// In Portal this check is already performed as part of
|
||||||
// C_Portal_Player::DrawModel()
|
// C_Portal_Player::DrawModel()
|
||||||
@ -1398,6 +1456,7 @@ int C_BasePlayer::DrawModel( int flags )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return BaseClass::DrawModel( flags );
|
return BaseClass::DrawModel( flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,6 +443,19 @@ public:
|
|||||||
float m_flConstraintWidth;
|
float m_flConstraintWidth;
|
||||||
float m_flConstraintSpeedFactor;
|
float m_flConstraintSpeedFactor;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Transmitted from the server for internal player spawnflags.
|
||||||
|
// See baseplayer_shared.h for more details.
|
||||||
|
int m_spawnflags;
|
||||||
|
|
||||||
|
inline bool HasSpawnFlags( int flags ) { return (m_spawnflags & flags) != 0; }
|
||||||
|
inline void RemoveSpawnFlags( int flags ) { m_spawnflags &= ~flags; }
|
||||||
|
inline void AddSpawnFlags( int flags ) { m_spawnflags |= flags; }
|
||||||
|
|
||||||
|
// Allows the player's model to draw on non-main views, like monitors or mirrors.
|
||||||
|
bool m_bDrawPlayerModelExternally;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
|
void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov );
|
||||||
|
@ -33,7 +33,14 @@ Vector g_vSplashColor( 0.5, 0.5, 0.5 );
|
|||||||
float g_flSplashScale = 0.15;
|
float g_flSplashScale = 0.15;
|
||||||
float g_flSplashLifetime = 0.5f;
|
float g_flSplashLifetime = 0.5f;
|
||||||
float g_flSplashAlpha = 0.3f;
|
float g_flSplashAlpha = 0.3f;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Rain splash stuff based on Tony Sergei's VDC code
|
||||||
|
// (r_RainParticle can be found in effects.cpp on the server as well)
|
||||||
|
ConVar r_RainParticle("r_RainParticle", "Rain_01_impact", FCVAR_CHEAT | FCVAR_REPLICATED);
|
||||||
|
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "99", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.
|
||||||
|
#else
|
||||||
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "20", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.
|
ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "20", FCVAR_CHEAT ); // N% chance of a rain particle making a splash.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
float GUST_INTERVAL_MIN = 1;
|
float GUST_INTERVAL_MIN = 1;
|
||||||
@ -324,6 +331,20 @@ inline bool CClient_Precipitation::SimulateRain( CPrecipitationParticle* pPartic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Based on Tony Sergi's code on the VDC. This version re-uses m_Splashes instead of dispatching the effect immediately.
|
||||||
|
trace_t trace;
|
||||||
|
UTIL_TraceLine(vOldPos, pParticle->m_Pos, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace);
|
||||||
|
|
||||||
|
if (trace.fraction < 1 || trace.DidHit())
|
||||||
|
{
|
||||||
|
if (RandomInt(0, 100) <= r_RainSplashPercentage.GetInt())
|
||||||
|
m_Splashes.AddToTail( trace.endpos );
|
||||||
|
|
||||||
|
// Tell the framework it's time to remove the particle from the list
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
// No longer in the air? punt.
|
// No longer in the air? punt.
|
||||||
if ( !IsInAir( pParticle->m_Pos ) )
|
if ( !IsInAir( pParticle->m_Pos ) )
|
||||||
{
|
{
|
||||||
@ -344,6 +365,7 @@ inline bool CClient_Precipitation::SimulateRain( CPrecipitationParticle* pPartic
|
|||||||
// Tell the framework it's time to remove the particle from the list
|
// Tell the framework it's time to remove the particle from the list
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// We still want this particle
|
// We still want this particle
|
||||||
return true;
|
return true;
|
||||||
@ -550,7 +572,15 @@ void CClient_Precipitation::CreateWaterSplashes()
|
|||||||
|
|
||||||
if ( CurrentViewForward().Dot( vSplash - CurrentViewOrigin() ) > 1 )
|
if ( CurrentViewForward().Dot( vSplash - CurrentViewOrigin() ) > 1 )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Use a particle or
|
||||||
|
if ( r_RainParticle.GetString()[0] != NULL )
|
||||||
|
DispatchParticleEffect(r_RainParticle.GetString(), vSplash, QAngle(RandomFloat(0, 360), RandomFloat(0, 360), RandomFloat(0, 360)), NULL);
|
||||||
|
else
|
||||||
FX_WaterRipple( vSplash, g_flSplashScale, &g_vSplashColor, g_flSplashLifetime, g_flSplashAlpha );
|
FX_WaterRipple( vSplash, g_flSplashScale, &g_vSplashColor, g_flSplashLifetime, g_flSplashAlpha );
|
||||||
|
#else
|
||||||
|
FX_WaterRipple( vSplash, g_flSplashScale, &g_vSplashColor, g_flSplashLifetime, g_flSplashAlpha );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_Splashes.Purge();
|
m_Splashes.Purge();
|
||||||
@ -668,6 +698,13 @@ void CClient_Precipitation::Precache( )
|
|||||||
|
|
||||||
case PRECIPITATION_TYPE_RAIN:
|
case PRECIPITATION_TYPE_RAIN:
|
||||||
Assert( m_nPrecipType == PRECIPITATION_TYPE_RAIN );
|
Assert( m_nPrecipType == PRECIPITATION_TYPE_RAIN );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (r_RainParticle.GetString()[0] != NULL)
|
||||||
|
{
|
||||||
|
PrecacheParticleSystem( r_RainParticle.GetString() );
|
||||||
|
DevMsg("Rain particle system \"%s\" precached!\n", r_RainParticle.GetString());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
m_Speed = RAIN_SPEED;
|
m_Speed = RAIN_SPEED;
|
||||||
m_MatHandle = materials->FindMaterial( "particle/rain", TEXTURE_GROUP_CLIENT_EFFECTS );
|
m_MatHandle = materials->FindMaterial( "particle/rain", TEXTURE_GROUP_CLIENT_EFFECTS );
|
||||||
m_InitialRamp = 1.0f;
|
m_InitialRamp = 1.0f;
|
||||||
@ -1206,6 +1243,11 @@ BEGIN_RECV_TABLE_NOBASE(CEnvWindShared, DT_EnvWindShared)
|
|||||||
RecvPropFloat (RECVINFO(m_flStartTime)),
|
RecvPropFloat (RECVINFO(m_flStartTime)),
|
||||||
RecvPropFloat (RECVINFO(m_flGustDuration)),
|
RecvPropFloat (RECVINFO(m_flGustDuration)),
|
||||||
// RecvPropInt (RECVINFO(m_iszGustSound)),
|
// RecvPropInt (RECVINFO(m_iszGustSound)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropFloat (RECVINFO(m_windRadius)),
|
||||||
|
RecvPropFloat (RECVINFO(m_windRadiusInner)),
|
||||||
|
RecvPropVector (RECVINFO(m_location)),
|
||||||
|
#endif
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
IMPLEMENT_CLIENTCLASS_DT( C_EnvWind, DT_EnvWind, CEnvWind )
|
IMPLEMENT_CLIENTCLASS_DT( C_EnvWind, DT_EnvWind, CEnvWind )
|
||||||
@ -1540,8 +1582,12 @@ public:
|
|||||||
|
|
||||||
pParticle->m_vecVelocity *= flSpeed;
|
pParticle->m_vecVelocity *= flSpeed;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector vecWindVelocity = GetWindspeedAtLocation( pParticle->m_Pos );
|
||||||
|
#else
|
||||||
Vector vecWindVelocity;
|
Vector vecWindVelocity;
|
||||||
GetWindspeedAtTime( gpGlobals->curtime, vecWindVelocity );
|
GetWindspeedAtTime( gpGlobals->curtime, vecWindVelocity );
|
||||||
|
#endif
|
||||||
pParticle->m_vecVelocity += ( vecWindVelocity * r_SnowWindScale.GetFloat() );
|
pParticle->m_vecVelocity += ( vecWindVelocity * r_SnowWindScale.GetFloat() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
331
sp/src/game/client/c_env_global_light.cpp
Normal file
331
sp/src/game/client/c_env_global_light.cpp
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||||
|
//
|
||||||
|
// Purpose: Sunlight shadow control entity.
|
||||||
|
//
|
||||||
|
// $NoKeywords: $
|
||||||
|
//=============================================================================//
|
||||||
|
#include "cbase.h"
|
||||||
|
|
||||||
|
#include "c_baseplayer.h"
|
||||||
|
#include "tier0/vprof.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "materialsystem/itexture.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern ConVar cl_sunlight_ortho_size;
|
||||||
|
extern ConVar cl_sunlight_depthbias;
|
||||||
|
|
||||||
|
ConVar cl_globallight_freeze( "cl_globallight_freeze", "0" );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// I imagine these values might've been designed for the ASW view.
|
||||||
|
// You can set these as KV anyway.
|
||||||
|
ConVar cl_globallight_xoffset( "cl_globallight_xoffset", "0" );
|
||||||
|
ConVar cl_globallight_yoffset( "cl_globallight_yoffset", "0" );
|
||||||
|
#else
|
||||||
|
ConVar cl_globallight_xoffset( "cl_globallight_xoffset", "-800" );
|
||||||
|
ConVar cl_globallight_yoffset( "cl_globallight_yoffset", "1600" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose : Sunlights shadow control entity
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
class C_GlobalLight : public C_BaseEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS( C_GlobalLight, C_BaseEntity );
|
||||||
|
|
||||||
|
DECLARE_CLIENTCLASS();
|
||||||
|
|
||||||
|
virtual ~C_GlobalLight();
|
||||||
|
|
||||||
|
void OnDataChanged( DataUpdateType_t updateType );
|
||||||
|
void Spawn();
|
||||||
|
bool ShouldDraw();
|
||||||
|
|
||||||
|
void ClientThink();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector m_shadowDirection;
|
||||||
|
bool m_bEnabled;
|
||||||
|
char m_TextureName[ MAX_PATH ];
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int m_nSpotlightTextureFrame;
|
||||||
|
#endif
|
||||||
|
CTextureReference m_SpotlightTexture;
|
||||||
|
color32 m_LightColor;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float m_flBrightnessScale;
|
||||||
|
float m_flCurrentBrightnessScale;
|
||||||
|
#endif
|
||||||
|
Vector m_CurrentLinearFloatLightColor;
|
||||||
|
float m_flCurrentLinearFloatLightAlpha;
|
||||||
|
float m_flColorTransitionTime;
|
||||||
|
float m_flSunDistance;
|
||||||
|
float m_flFOV;
|
||||||
|
float m_flNearZ;
|
||||||
|
float m_flNorthOffset;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float m_flEastOffset;
|
||||||
|
float m_flForwardOffset;
|
||||||
|
float m_flOrthoSize;
|
||||||
|
#endif
|
||||||
|
bool m_bEnableShadows;
|
||||||
|
bool m_bOldEnableShadows;
|
||||||
|
|
||||||
|
static ClientShadowHandle_t m_LocalFlashlightHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ClientShadowHandle_t C_GlobalLight::m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
||||||
|
|
||||||
|
|
||||||
|
IMPLEMENT_CLIENTCLASS_DT(C_GlobalLight, DT_GlobalLight, CGlobalLight)
|
||||||
|
RecvPropVector(RECVINFO(m_shadowDirection)),
|
||||||
|
RecvPropBool(RECVINFO(m_bEnabled)),
|
||||||
|
RecvPropString(RECVINFO(m_TextureName)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropInt(RECVINFO(m_nSpotlightTextureFrame)),
|
||||||
|
#endif
|
||||||
|
/*RecvPropInt(RECVINFO(m_LightColor), 0, RecvProxy_Int32ToColor32),*/
|
||||||
|
RecvPropInt(RECVINFO(m_LightColor), 0, RecvProxy_IntToColor32),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropFloat(RECVINFO(m_flBrightnessScale)),
|
||||||
|
#endif
|
||||||
|
RecvPropFloat(RECVINFO(m_flColorTransitionTime)),
|
||||||
|
RecvPropFloat(RECVINFO(m_flSunDistance)),
|
||||||
|
RecvPropFloat(RECVINFO(m_flFOV)),
|
||||||
|
RecvPropFloat(RECVINFO(m_flNearZ)),
|
||||||
|
RecvPropFloat(RECVINFO(m_flNorthOffset)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropFloat(RECVINFO(m_flEastOffset)),
|
||||||
|
RecvPropFloat(RECVINFO(m_flForwardOffset)),
|
||||||
|
RecvPropFloat(RECVINFO(m_flOrthoSize)),
|
||||||
|
#endif
|
||||||
|
RecvPropBool(RECVINFO(m_bEnableShadows)),
|
||||||
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
C_GlobalLight::~C_GlobalLight()
|
||||||
|
{
|
||||||
|
if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
|
||||||
|
m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_GlobalLight::OnDataChanged( DataUpdateType_t updateType )
|
||||||
|
{
|
||||||
|
if ( updateType == DATA_UPDATE_CREATED )
|
||||||
|
{
|
||||||
|
m_SpotlightTexture.Init( m_TextureName, TEXTURE_GROUP_OTHER, true );
|
||||||
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else //if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
|
||||||
|
{
|
||||||
|
// It could've been changed via input
|
||||||
|
if( !FStrEq(m_SpotlightTexture->GetName(), m_TextureName) )
|
||||||
|
{
|
||||||
|
m_SpotlightTexture.Init( m_TextureName, TEXTURE_GROUP_OTHER, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BaseClass::OnDataChanged( updateType );
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_GlobalLight::Spawn()
|
||||||
|
{
|
||||||
|
BaseClass::Spawn();
|
||||||
|
|
||||||
|
m_bOldEnableShadows = m_bEnableShadows;
|
||||||
|
|
||||||
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// We don't draw...
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool C_GlobalLight::ShouldDraw()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_GlobalLight::ClientThink()
|
||||||
|
{
|
||||||
|
VPROF("C_GlobalLight::ClientThink");
|
||||||
|
|
||||||
|
bool bSupressWorldLights = false;
|
||||||
|
|
||||||
|
if ( cl_globallight_freeze.GetBool() == true )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_bEnabled )
|
||||||
|
{
|
||||||
|
Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
|
||||||
|
float flLinearFloatLightAlpha = m_LightColor.a;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha || m_flCurrentBrightnessScale != m_flBrightnessScale )
|
||||||
|
{
|
||||||
|
if (m_flColorTransitionTime != 0.0f)
|
||||||
|
{
|
||||||
|
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
|
||||||
|
|
||||||
|
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
|
||||||
|
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
|
||||||
|
m_flCurrentBrightnessScale = Approach( m_flBrightnessScale, m_flCurrentBrightnessScale, flColorTransitionSpeed );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just do it instantly
|
||||||
|
m_CurrentLinearFloatLightColor.x = vLinearFloatLightColor.x;
|
||||||
|
m_CurrentLinearFloatLightColor.y = vLinearFloatLightColor.y;
|
||||||
|
m_CurrentLinearFloatLightColor.z = vLinearFloatLightColor.z;
|
||||||
|
m_flCurrentLinearFloatLightAlpha = flLinearFloatLightAlpha;
|
||||||
|
m_flCurrentBrightnessScale = m_flBrightnessScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
|
||||||
|
{
|
||||||
|
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
|
||||||
|
|
||||||
|
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
|
||||||
|
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FlashlightState_t state;
|
||||||
|
|
||||||
|
Vector vDirection = m_shadowDirection;
|
||||||
|
VectorNormalize( vDirection );
|
||||||
|
|
||||||
|
//Vector vViewUp = Vector( 0.0f, 1.0f, 0.0f );
|
||||||
|
Vector vSunDirection2D = vDirection;
|
||||||
|
vSunDirection2D.z = 0.0f;
|
||||||
|
|
||||||
|
/*HACK_GETLOCALPLAYER_GUARD( "C_GlobalLight::ClientThink" );*/
|
||||||
|
|
||||||
|
if ( !C_BasePlayer::GetLocalPlayer() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Vector vPos;
|
||||||
|
QAngle EyeAngles;
|
||||||
|
float flZNear, flZFar, flFov;
|
||||||
|
|
||||||
|
C_BasePlayer::GetLocalPlayer()->CalcView( vPos, EyeAngles, flZNear, flZFar, flFov );
|
||||||
|
// Vector vPos = C_BasePlayer::GetLocalPlayer()->GetAbsOrigin();
|
||||||
|
|
||||||
|
// vPos = Vector( 0.0f, 0.0f, 500.0f );
|
||||||
|
vPos = ( vPos + vSunDirection2D * m_flNorthOffset ) - vDirection * m_flSunDistance;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
vPos += Vector( m_flEastOffset + cl_globallight_xoffset.GetFloat(), m_flForwardOffset + cl_globallight_yoffset.GetFloat(), 0.0f );
|
||||||
|
#else
|
||||||
|
vPos += Vector( cl_globallight_xoffset.GetFloat(), cl_globallight_yoffset.GetFloat(), 0.0f );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QAngle angAngles;
|
||||||
|
VectorAngles( vDirection, angAngles );
|
||||||
|
|
||||||
|
Vector vForward, vRight, vUp;
|
||||||
|
AngleVectors( angAngles, &vForward, &vRight, &vUp );
|
||||||
|
|
||||||
|
state.m_fHorizontalFOVDegrees = m_flFOV;
|
||||||
|
state.m_fVerticalFOVDegrees = m_flFOV;
|
||||||
|
|
||||||
|
state.m_vecLightOrigin = vPos;
|
||||||
|
BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
|
||||||
|
|
||||||
|
state.m_fQuadraticAtten = 0.0f;
|
||||||
|
state.m_fLinearAtten = m_flSunDistance * 2.0f;
|
||||||
|
state.m_fConstantAtten = 0.0f;
|
||||||
|
state.m_FarZAtten = m_flSunDistance * 2.0f;
|
||||||
|
state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
|
||||||
|
state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
|
||||||
|
state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
|
||||||
|
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
|
||||||
|
state.m_NearZ = 4.0f;
|
||||||
|
state.m_FarZ = m_flSunDistance * 2.0f;
|
||||||
|
state.m_fBrightnessScale = 2.0f;
|
||||||
|
state.m_bGlobalLight = true;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float flOrthoSize = m_flOrthoSize;
|
||||||
|
#else
|
||||||
|
float flOrthoSize = 1000.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( flOrthoSize > 0 )
|
||||||
|
{
|
||||||
|
state.m_bOrtho = true;
|
||||||
|
state.m_fOrthoLeft = -flOrthoSize;
|
||||||
|
state.m_fOrthoTop = -flOrthoSize;
|
||||||
|
state.m_fOrthoRight = flOrthoSize;
|
||||||
|
state.m_fOrthoBottom = flOrthoSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.m_bOrtho = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MAPBASE // Don't draw that huge debug thing
|
||||||
|
state.m_bDrawShadowFrustum = true;
|
||||||
|
#endif
|
||||||
|
/*state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();;
|
||||||
|
state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();*/
|
||||||
|
state.m_bEnableShadows = m_bEnableShadows;
|
||||||
|
state.m_pSpotlightTexture = m_SpotlightTexture;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
|
||||||
|
#else
|
||||||
|
state.m_nSpotlightTextureFrame = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
state.m_nShadowQuality = 1; // Allow entity to affect shadow quality
|
||||||
|
// state.m_bShadowHighRes = true;
|
||||||
|
|
||||||
|
if ( m_bOldEnableShadows != m_bEnableShadows )
|
||||||
|
{
|
||||||
|
// If they change the shadow enable/disable, we need to make a new handle
|
||||||
|
if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
|
||||||
|
m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bOldEnableShadows = m_bEnableShadows;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_LocalFlashlightHandle == CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
m_LocalFlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->UpdateFlashlightState( m_LocalFlashlightHandle, state );
|
||||||
|
g_pClientShadowMgr->UpdateProjectedTexture( m_LocalFlashlightHandle, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
bSupressWorldLights = m_bEnableShadows;
|
||||||
|
}
|
||||||
|
else if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
|
||||||
|
m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pClientShadowMgr->SetShadowFromWorldLightsEnabled( !bSupressWorldLights );
|
||||||
|
|
||||||
|
BaseClass::ClientThink();
|
||||||
|
}
|
@ -5,6 +5,13 @@
|
|||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
#include "cbase.h"
|
#include "cbase.h"
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
#include "C_Env_Projected_Texture.h"
|
||||||
|
#include "vprof.h"
|
||||||
|
#endif
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "materialsystem/itexture.h"
|
||||||
|
#endif
|
||||||
#include "shareddefs.h"
|
#include "shareddefs.h"
|
||||||
#include "materialsystem/imesh.h"
|
#include "materialsystem/imesh.h"
|
||||||
#include "materialsystem/imaterial.h"
|
#include "materialsystem/imaterial.h"
|
||||||
@ -17,69 +24,84 @@
|
|||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
|
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
|
||||||
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.0005", FCVAR_CHEAT );
|
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.00001", FCVAR_CHEAT );
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
float C_EnvProjectedTexture::m_flVisibleBBoxMinHeight = -FLT_MAX;
|
||||||
// Purpose:
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
class C_EnvProjectedTexture : public C_BaseEntity
|
|
||||||
{
|
|
||||||
DECLARE_CLASS( C_EnvProjectedTexture, C_BaseEntity );
|
|
||||||
public:
|
|
||||||
DECLARE_CLIENTCLASS();
|
|
||||||
|
|
||||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
|
||||||
void ShutDownLightHandle( void );
|
|
||||||
|
|
||||||
virtual void Simulate();
|
|
||||||
|
|
||||||
void UpdateLight( bool bForceUpdate );
|
|
||||||
|
|
||||||
C_EnvProjectedTexture();
|
|
||||||
~C_EnvProjectedTexture();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
ClientShadowHandle_t m_LightHandle;
|
|
||||||
|
|
||||||
EHANDLE m_hTargetEntity;
|
|
||||||
|
|
||||||
bool m_bState;
|
|
||||||
float m_flLightFOV;
|
|
||||||
bool m_bEnableShadows;
|
|
||||||
bool m_bLightOnlyTarget;
|
|
||||||
bool m_bLightWorld;
|
|
||||||
bool m_bCameraSpace;
|
|
||||||
Vector m_LinearFloatLightColor;
|
|
||||||
float m_flAmbient;
|
|
||||||
float m_flNearZ;
|
|
||||||
float m_flFarZ;
|
|
||||||
char m_SpotlightTextureName[ MAX_PATH ];
|
|
||||||
int m_nSpotlightTextureFrame;
|
|
||||||
int m_nShadowQuality;
|
|
||||||
};
|
|
||||||
|
|
||||||
IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture )
|
IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture )
|
||||||
RecvPropEHandle( RECVINFO( m_hTargetEntity ) ),
|
RecvPropEHandle( RECVINFO( m_hTargetEntity ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool( RECVINFO( m_bDontFollowTarget )),
|
||||||
|
#endif
|
||||||
RecvPropBool( RECVINFO( m_bState ) ),
|
RecvPropBool( RECVINFO( m_bState ) ),
|
||||||
|
RecvPropBool( RECVINFO( m_bAlwaysUpdate ) ),
|
||||||
RecvPropFloat( RECVINFO( m_flLightFOV ) ),
|
RecvPropFloat( RECVINFO( m_flLightFOV ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropFloat( RECVINFO( m_flLightHorFOV ) ),
|
||||||
|
#endif
|
||||||
RecvPropBool( RECVINFO( m_bEnableShadows ) ),
|
RecvPropBool( RECVINFO( m_bEnableShadows ) ),
|
||||||
RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ),
|
RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ),
|
||||||
RecvPropBool( RECVINFO( m_bLightWorld ) ),
|
RecvPropBool( RECVINFO( m_bLightWorld ) ),
|
||||||
RecvPropBool( RECVINFO( m_bCameraSpace ) ),
|
RecvPropBool( RECVINFO( m_bCameraSpace ) ),
|
||||||
RecvPropVector( RECVINFO( m_LinearFloatLightColor ) ),
|
RecvPropFloat( RECVINFO( m_flBrightnessScale ) ),
|
||||||
|
RecvPropInt( RECVINFO( m_LightColor ), 0, RecvProxy_IntToColor32 ),
|
||||||
|
RecvPropFloat( RECVINFO( m_flColorTransitionTime ) ),
|
||||||
RecvPropFloat( RECVINFO( m_flAmbient ) ),
|
RecvPropFloat( RECVINFO( m_flAmbient ) ),
|
||||||
RecvPropString( RECVINFO( m_SpotlightTextureName ) ),
|
RecvPropString( RECVINFO( m_SpotlightTextureName ) ),
|
||||||
RecvPropInt( RECVINFO( m_nSpotlightTextureFrame ) ),
|
RecvPropInt( RECVINFO( m_nSpotlightTextureFrame ) ),
|
||||||
RecvPropFloat( RECVINFO( m_flNearZ ) ),
|
RecvPropFloat( RECVINFO( m_flNearZ ) ),
|
||||||
RecvPropFloat( RECVINFO( m_flFarZ ) ),
|
RecvPropFloat( RECVINFO( m_flFarZ ) ),
|
||||||
RecvPropInt( RECVINFO( m_nShadowQuality ) ),
|
RecvPropInt( RECVINFO( m_nShadowQuality ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool( RECVINFO( m_bAlwaysDraw ) ),
|
||||||
|
|
||||||
|
// Not needed on the client right now, change when it actually is needed
|
||||||
|
//RecvPropBool( RECVINFO( m_bProjectedTextureVersion ) ),
|
||||||
|
#endif
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
C_EnvProjectedTexture *C_EnvProjectedTexture::Create( )
|
||||||
|
{
|
||||||
|
C_EnvProjectedTexture *pEnt = new C_EnvProjectedTexture();
|
||||||
|
|
||||||
|
pEnt->m_flNearZ = 4.0f;
|
||||||
|
pEnt->m_flFarZ = 2000.0f;
|
||||||
|
// strcpy( pEnt->m_SpotlightTextureName, "particle/rj" );
|
||||||
|
pEnt->m_bLightWorld = true;
|
||||||
|
pEnt->m_bLightOnlyTarget = false;
|
||||||
|
pEnt->m_nShadowQuality = 1;
|
||||||
|
pEnt->m_flLightFOV = 10.0f;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
pEnt->m_flLightHorFOV = 10.0f;
|
||||||
|
#endif
|
||||||
|
pEnt->m_LightColor.r = 255;
|
||||||
|
pEnt->m_LightColor.g = 255;
|
||||||
|
pEnt->m_LightColor.b = 255;
|
||||||
|
pEnt->m_LightColor.a = 255;
|
||||||
|
pEnt->m_bEnableShadows = false;
|
||||||
|
pEnt->m_flColorTransitionTime = 1.0f;
|
||||||
|
pEnt->m_bCameraSpace = false;
|
||||||
|
pEnt->SetAbsAngles( QAngle( 90, 0, 0 ) );
|
||||||
|
pEnt->m_bAlwaysUpdate = true;
|
||||||
|
pEnt->m_bState = true;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
pEnt->m_bAlwaysDraw = false;
|
||||||
|
//pEnt->m_bProjectedTextureVersion = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return pEnt;
|
||||||
|
}
|
||||||
|
|
||||||
C_EnvProjectedTexture::C_EnvProjectedTexture( void )
|
C_EnvProjectedTexture::C_EnvProjectedTexture( void )
|
||||||
{
|
{
|
||||||
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
||||||
|
m_bForceUpdate = true;
|
||||||
|
#ifndef MAPBASE
|
||||||
|
AddToEntityList( ENTITY_LIST_SIMULATE );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
C_EnvProjectedTexture::~C_EnvProjectedTexture( void )
|
C_EnvProjectedTexture::~C_EnvProjectedTexture( void )
|
||||||
@ -97,32 +119,117 @@ void C_EnvProjectedTexture::ShutDownLightHandle( void )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C_EnvProjectedTexture::SetLightColor( byte r, byte g, byte b, byte a )
|
||||||
|
{
|
||||||
|
m_LightColor.r = r;
|
||||||
|
m_LightColor.g = g;
|
||||||
|
m_LightColor.b = b;
|
||||||
|
m_LightColor.a = a;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
// Input : updateType -
|
// Input : updateType -
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType )
|
void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType )
|
||||||
{
|
{
|
||||||
UpdateLight( true );
|
if ( updateType == DATA_UPDATE_CREATED )
|
||||||
|
{
|
||||||
|
m_SpotlightTexture.Init( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, true );
|
||||||
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else //if ( updateType == DATA_UPDATE_DATATABLE_CHANGED )
|
||||||
|
{
|
||||||
|
// It could've been changed via input
|
||||||
|
if( !FStrEq(m_SpotlightTexture->GetName(), m_SpotlightTextureName) )
|
||||||
|
{
|
||||||
|
m_SpotlightTexture.Init( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_bForceUpdate = true;
|
||||||
|
UpdateLight();
|
||||||
BaseClass::OnDataChanged( updateType );
|
BaseClass::OnDataChanged( updateType );
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
|
static ConVar asw_perf_wtf("asw_perf_wtf", "0", FCVAR_DEVELOPMENTONLY, "Disable updating of projected shadow textures from UpdateLight" );
|
||||||
|
void C_EnvProjectedTexture::UpdateLight( void )
|
||||||
{
|
{
|
||||||
if ( m_bState == false )
|
VPROF("C_EnvProjectedTexture::UpdateLight");
|
||||||
|
bool bVisible = true;
|
||||||
|
|
||||||
|
Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
|
||||||
|
float flLinearFloatLightAlpha = m_LightColor.a;
|
||||||
|
|
||||||
|
if ( m_bAlwaysUpdate )
|
||||||
{
|
{
|
||||||
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
m_bForceUpdate = true;
|
||||||
{
|
|
||||||
ShutDownLightHandle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha || m_flCurrentBrightnessScale != m_flBrightnessScale )
|
||||||
|
{
|
||||||
|
if (m_flColorTransitionTime != 0.0f)
|
||||||
|
{
|
||||||
|
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
|
||||||
|
|
||||||
|
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
|
||||||
|
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
|
||||||
|
m_flCurrentBrightnessScale = Approach( m_flBrightnessScale, m_flCurrentBrightnessScale, flColorTransitionSpeed );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just do it instantly
|
||||||
|
m_CurrentLinearFloatLightColor.x = vLinearFloatLightColor.x;
|
||||||
|
m_CurrentLinearFloatLightColor.y = vLinearFloatLightColor.y;
|
||||||
|
m_CurrentLinearFloatLightColor.z = vLinearFloatLightColor.z;
|
||||||
|
m_flCurrentLinearFloatLightAlpha = flLinearFloatLightAlpha;
|
||||||
|
m_flCurrentBrightnessScale = m_flBrightnessScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bForceUpdate = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
|
||||||
|
{
|
||||||
|
float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
|
||||||
|
|
||||||
|
m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
|
||||||
|
m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
|
||||||
|
m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
|
||||||
|
|
||||||
|
m_bForceUpdate = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( !m_bForceUpdate )
|
||||||
|
{
|
||||||
|
bVisible = IsBBoxVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_bState == false || !bVisible )
|
||||||
|
{
|
||||||
|
// Spotlight's extents aren't in view
|
||||||
|
ShutDownLightHandle();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
|
||||||
|
{
|
||||||
Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
|
Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
|
||||||
FlashlightState_t state;
|
FlashlightState_t state;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_hTargetEntity != NULL && !m_bDontFollowTarget )
|
||||||
|
#else
|
||||||
if ( m_hTargetEntity != NULL )
|
if ( m_hTargetEntity != NULL )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if ( m_bCameraSpace )
|
if ( m_bCameraSpace )
|
||||||
{
|
{
|
||||||
@ -162,6 +269,417 @@ void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
|
|||||||
//Quaternion q = DirectionToOrientation( dir );
|
//Quaternion q = DirectionToOrientation( dir );
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// JasonM - set up vRight, vUp
|
||||||
|
//
|
||||||
|
|
||||||
|
// VectorNormalize( vRight );
|
||||||
|
// VectorNormalize( vUp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float fHighFOV;
|
||||||
|
if( m_flLightFOV > m_flLightHorFOV )
|
||||||
|
fHighFOV = m_flLightFOV;
|
||||||
|
else
|
||||||
|
fHighFOV = m_flLightHorFOV;
|
||||||
|
|
||||||
|
state.m_fHorizontalFOVDegrees = m_flLightHorFOV;
|
||||||
|
#else
|
||||||
|
state.m_fHorizontalFOVDegrees = m_flLightFOV;
|
||||||
|
#endif
|
||||||
|
state.m_fVerticalFOVDegrees = m_flLightFOV;
|
||||||
|
|
||||||
|
state.m_vecLightOrigin = vPos;
|
||||||
|
BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
|
||||||
|
state.m_NearZ = m_flNearZ;
|
||||||
|
state.m_FarZ = m_flFarZ;
|
||||||
|
|
||||||
|
// quickly check the proposed light's bbox against the view frustum to determine whether we
|
||||||
|
// should bother to create it, if it doesn't exist, or cull it, if it does.
|
||||||
|
// get the half-widths of the near and far planes,
|
||||||
|
// based on the FOV which is in degrees. Remember that
|
||||||
|
// on planet Valve, x is forward, y left, and z up.
|
||||||
|
#ifdef MAPBASE
|
||||||
|
const float tanHalfAngle = tan( fHighFOV * ( M_PI/180.0f ) * 0.5f );
|
||||||
|
#else
|
||||||
|
const float tanHalfAngle = tan( m_flLightFOV * ( M_PI/180.0f ) * 0.5f );
|
||||||
|
#endif
|
||||||
|
const float halfWidthNear = tanHalfAngle * m_flNearZ;
|
||||||
|
const float halfWidthFar = tanHalfAngle * m_flFarZ;
|
||||||
|
// now we can build coordinates in local space: the near rectangle is eg
|
||||||
|
// (0, -halfWidthNear, -halfWidthNear), (0, halfWidthNear, -halfWidthNear),
|
||||||
|
// (0, halfWidthNear, halfWidthNear), (0, -halfWidthNear, halfWidthNear)
|
||||||
|
|
||||||
|
VectorAligned vNearRect[4] = {
|
||||||
|
VectorAligned( m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ, halfWidthNear, -halfWidthNear),
|
||||||
|
VectorAligned( m_flNearZ, halfWidthNear, halfWidthNear), VectorAligned( m_flNearZ, -halfWidthNear, halfWidthNear)
|
||||||
|
};
|
||||||
|
|
||||||
|
VectorAligned vFarRect[4] = {
|
||||||
|
VectorAligned( m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ, halfWidthFar, -halfWidthFar),
|
||||||
|
VectorAligned( m_flFarZ, halfWidthFar, halfWidthFar), VectorAligned( m_flFarZ, -halfWidthFar, halfWidthFar)
|
||||||
|
};
|
||||||
|
|
||||||
|
matrix3x4_t matOrientation( vForward, -vRight, vUp, vPos );
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kNEAR = 0,
|
||||||
|
kFAR = 1,
|
||||||
|
};
|
||||||
|
VectorAligned vOutRects[2][4];
|
||||||
|
|
||||||
|
for ( int i = 0 ; i < 4 ; ++i )
|
||||||
|
{
|
||||||
|
VectorTransform( vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base() );
|
||||||
|
}
|
||||||
|
for ( int i = 0 ; i < 4 ; ++i )
|
||||||
|
{
|
||||||
|
VectorTransform( vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// now take the min and max extents for the bbox, and see if it is visible.
|
||||||
|
Vector mins = **vOutRects;
|
||||||
|
Vector maxs = **vOutRects;
|
||||||
|
for ( int i = 1; i < 8 ; ++i )
|
||||||
|
{
|
||||||
|
VectorMin( mins, *(*vOutRects+i), mins );
|
||||||
|
VectorMax( maxs, *(*vOutRects+i), maxs );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 //for debugging the visibility frustum we just calculated
|
||||||
|
NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //first tri
|
||||||
|
NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //make it double sided
|
||||||
|
NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //second tri
|
||||||
|
NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //make it double sided
|
||||||
|
|
||||||
|
NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //first tri
|
||||||
|
NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //make it double sided
|
||||||
|
NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //second tri
|
||||||
|
NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //make it double sided
|
||||||
|
|
||||||
|
NDebugOverlay::Box( vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool bVisible = IsBBoxVisible( mins, maxs );
|
||||||
|
if (!bVisible)
|
||||||
|
{
|
||||||
|
// Spotlight's extents aren't in view
|
||||||
|
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
ShutDownLightHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f );
|
||||||
|
|
||||||
|
state.m_fQuadraticAtten = 0.0;
|
||||||
|
state.m_fLinearAtten = 100;
|
||||||
|
state.m_fConstantAtten = 0.0f;
|
||||||
|
state.m_FarZAtten = m_flFarZ;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
state.m_Color[0] = (m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
|
||||||
|
state.m_Color[1] = (m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
|
||||||
|
state.m_Color[2] = (m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha) * m_flCurrentBrightnessScale;
|
||||||
|
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
|
||||||
|
state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
|
||||||
|
state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
|
||||||
|
#else
|
||||||
|
state.m_fBrightnessScale = m_flBrightnessScale;
|
||||||
|
state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha;
|
||||||
|
state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha;
|
||||||
|
state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha;
|
||||||
|
state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
|
||||||
|
state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();
|
||||||
|
state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();
|
||||||
|
#endif
|
||||||
|
state.m_bEnableShadows = m_bEnableShadows;
|
||||||
|
state.m_pSpotlightTexture = m_SpotlightTexture;
|
||||||
|
state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
|
||||||
|
|
||||||
|
state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
state.m_bAlwaysDraw = m_bAlwaysDraw;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
|
||||||
|
|
||||||
|
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
m_bForceUpdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
|
||||||
|
m_bForceUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pClientShadowMgr->GetFrustumExtents( m_LightHandle, m_vecExtentsMin, m_vecExtentsMax );
|
||||||
|
|
||||||
|
m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
|
||||||
|
m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_bLightOnlyTarget )
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );
|
||||||
|
|
||||||
|
if ( !asw_perf_wtf.GetBool() && !m_bForceUpdate )
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_EnvProjectedTexture::Simulate( void )
|
||||||
|
{
|
||||||
|
UpdateLight();
|
||||||
|
|
||||||
|
BaseClass::Simulate();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C_EnvProjectedTexture::IsBBoxVisible( Vector vecExtentsMin, Vector vecExtentsMax )
|
||||||
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_bAlwaysDraw)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Z position clamped to the min height (but must be less than the max)
|
||||||
|
float flVisibleBBoxMinHeight = MIN( vecExtentsMax.z - 1.0f, m_flVisibleBBoxMinHeight );
|
||||||
|
vecExtentsMin.z = MAX( vecExtentsMin.z, flVisibleBBoxMinHeight );
|
||||||
|
|
||||||
|
// Check if the bbox is in the view
|
||||||
|
return !engine->CullBox( vecExtentsMin, vecExtentsMax );
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
|
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
|
||||||
|
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.0005", FCVAR_CHEAT );
|
||||||
|
#else
|
||||||
|
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "4", FCVAR_CHEAT );
|
||||||
|
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.00001", FCVAR_CHEAT );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class C_EnvProjectedTexture : public C_BaseEntity
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( C_EnvProjectedTexture, C_BaseEntity );
|
||||||
|
public:
|
||||||
|
DECLARE_CLIENTCLASS();
|
||||||
|
|
||||||
|
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||||
|
void ShutDownLightHandle( void );
|
||||||
|
|
||||||
|
virtual void Simulate();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void UpdateLight();
|
||||||
|
#else
|
||||||
|
void UpdateLight( bool bForceUpdate );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
C_EnvProjectedTexture();
|
||||||
|
~C_EnvProjectedTexture();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ClientShadowHandle_t m_LightHandle;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bForceUpdate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EHANDLE m_hTargetEntity;
|
||||||
|
|
||||||
|
bool m_bState;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bAlwaysUpdate;
|
||||||
|
#endif
|
||||||
|
float m_flLightFOV;
|
||||||
|
bool m_bEnableShadows;
|
||||||
|
bool m_bLightOnlyTarget;
|
||||||
|
bool m_bLightWorld;
|
||||||
|
bool m_bCameraSpace;
|
||||||
|
Vector m_LinearFloatLightColor;
|
||||||
|
float m_flAmbient;
|
||||||
|
float m_flNearZ;
|
||||||
|
float m_flFarZ;
|
||||||
|
char m_SpotlightTextureName[ MAX_PATH ];
|
||||||
|
int m_nSpotlightTextureFrame;
|
||||||
|
int m_nShadowQuality;
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture )
|
||||||
|
RecvPropEHandle( RECVINFO( m_hTargetEntity ) ),
|
||||||
|
RecvPropBool( RECVINFO( m_bState ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool( RECVINFO( m_bAlwaysUpdate ) ),
|
||||||
|
#endif
|
||||||
|
RecvPropFloat( RECVINFO( m_flLightFOV ) ),
|
||||||
|
RecvPropBool( RECVINFO( m_bEnableShadows ) ),
|
||||||
|
RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ),
|
||||||
|
RecvPropBool( RECVINFO( m_bLightWorld ) ),
|
||||||
|
RecvPropBool( RECVINFO( m_bCameraSpace ) ),
|
||||||
|
RecvPropVector( RECVINFO( m_LinearFloatLightColor ) ),
|
||||||
|
RecvPropFloat( RECVINFO( m_flAmbient ) ),
|
||||||
|
RecvPropString( RECVINFO( m_SpotlightTextureName ) ),
|
||||||
|
RecvPropInt( RECVINFO( m_nSpotlightTextureFrame ) ),
|
||||||
|
RecvPropFloat( RECVINFO( m_flNearZ ) ),
|
||||||
|
RecvPropFloat( RECVINFO( m_flFarZ ) ),
|
||||||
|
RecvPropInt( RECVINFO( m_nShadowQuality ) ),
|
||||||
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
C_EnvProjectedTexture::C_EnvProjectedTexture( void )
|
||||||
|
{
|
||||||
|
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
C_EnvProjectedTexture::~C_EnvProjectedTexture( void )
|
||||||
|
{
|
||||||
|
ShutDownLightHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_EnvProjectedTexture::ShutDownLightHandle( void )
|
||||||
|
{
|
||||||
|
// Clear out the light
|
||||||
|
if( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->DestroyFlashlight( m_LightHandle );
|
||||||
|
m_LightHandle = CLIENTSHADOW_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : updateType -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType )
|
||||||
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_bForceUpdate = true;
|
||||||
|
UpdateLight();
|
||||||
|
#else
|
||||||
|
UpdateLight( true );
|
||||||
|
#endif
|
||||||
|
BaseClass::OnDataChanged( updateType );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
|
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
|
||||||
|
#else
|
||||||
|
void C_EnvProjectedTexture::UpdateLight()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
|
if ( m_bState == false )
|
||||||
|
{
|
||||||
|
if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
|
||||||
|
{
|
||||||
|
ShutDownLightHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ( m_bAlwaysUpdate )
|
||||||
|
{
|
||||||
|
m_bForceUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_bState == false )
|
||||||
|
{
|
||||||
|
// Spotlight's extents aren't in view
|
||||||
|
ShutDownLightHandle();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
|
||||||
|
FlashlightState_t state;
|
||||||
|
|
||||||
|
if ( m_hTargetEntity != NULL )
|
||||||
|
{
|
||||||
|
if ( m_bCameraSpace )
|
||||||
|
{
|
||||||
|
const QAngle &angles = GetLocalAngles();
|
||||||
|
|
||||||
|
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||||
|
if( pPlayer )
|
||||||
|
{
|
||||||
|
const QAngle playerAngles = pPlayer->GetAbsAngles();
|
||||||
|
|
||||||
|
Vector vPlayerForward, vPlayerRight, vPlayerUp;
|
||||||
|
AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );
|
||||||
|
|
||||||
|
matrix3x4_t mRotMatrix;
|
||||||
|
AngleMatrix( angles, mRotMatrix );
|
||||||
|
|
||||||
|
VectorITransform( vPlayerForward, mRotMatrix, vForward );
|
||||||
|
VectorITransform( vPlayerRight, mRotMatrix, vRight );
|
||||||
|
VectorITransform( vPlayerUp, mRotMatrix, vUp );
|
||||||
|
|
||||||
|
float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
|
||||||
|
vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;
|
||||||
|
|
||||||
|
VectorNormalize( vForward );
|
||||||
|
VectorNormalize( vRight );
|
||||||
|
VectorNormalize( vUp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
|
vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
|
||||||
|
VectorNormalize( vForward );
|
||||||
|
#else
|
||||||
|
// VXP: Fixing targeting
|
||||||
|
Vector vecToTarget;
|
||||||
|
QAngle vecAngles;
|
||||||
|
if (m_hTargetEntity == NULL)
|
||||||
|
{
|
||||||
|
vecAngles = GetAbsAngles();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vecToTarget = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
|
||||||
|
VectorAngles(vecToTarget, vecAngles);
|
||||||
|
}
|
||||||
|
AngleVectors(vecAngles, &vForward, &vRight, &vUp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// JasonM - unimplemented
|
||||||
|
Assert (0);
|
||||||
|
|
||||||
|
//Quaternion q = DirectionToOrientation( dir );
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// JasonM - set up vRight, vUp
|
// JasonM - set up vRight, vUp
|
||||||
//
|
//
|
||||||
@ -204,11 +722,19 @@ void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
if ( m_hTargetEntity != NULL || bForceUpdate == true )
|
if ( m_hTargetEntity != NULL || bForceUpdate == true )
|
||||||
{
|
{
|
||||||
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
|
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
|
||||||
|
m_bForceUpdate = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if( m_bLightOnlyTarget )
|
if( m_bLightOnlyTarget )
|
||||||
{
|
{
|
||||||
@ -221,16 +747,29 @@ void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
|
|||||||
|
|
||||||
g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );
|
g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
if ( bForceUpdate == false )
|
if ( bForceUpdate == false )
|
||||||
{
|
{
|
||||||
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
|
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if ( !m_bForceUpdate )
|
||||||
|
{
|
||||||
|
g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void C_EnvProjectedTexture::Simulate( void )
|
void C_EnvProjectedTexture::Simulate( void )
|
||||||
{
|
{
|
||||||
|
#ifndef MAPBASE
|
||||||
UpdateLight( false );
|
UpdateLight( false );
|
||||||
|
#else
|
||||||
|
UpdateLight();
|
||||||
|
#endif
|
||||||
|
|
||||||
BaseClass::Simulate();
|
BaseClass::Simulate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -88,8 +88,9 @@ void CDustEffect::RenderParticles( CParticleRenderIterator *pIterator )
|
|||||||
void CDustEffect::SimulateParticles( CParticleSimulateIterator *pIterator )
|
void CDustEffect::SimulateParticles( CParticleSimulateIterator *pIterator )
|
||||||
{
|
{
|
||||||
Vector vecWind;
|
Vector vecWind;
|
||||||
|
#ifndef MAPBASE
|
||||||
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
|
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
|
||||||
|
#endif
|
||||||
|
|
||||||
CFuncDustParticle *pParticle = (CFuncDustParticle*)pIterator->GetFirst();
|
CFuncDustParticle *pParticle = (CFuncDustParticle*)pIterator->GetFirst();
|
||||||
while ( pParticle )
|
while ( pParticle )
|
||||||
@ -105,6 +106,9 @@ void CDustEffect::SimulateParticles( CParticleSimulateIterator *pIterator )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
vecWind = GetWindspeedAtLocation( pParticle->m_Pos );
|
||||||
|
#endif
|
||||||
for ( int i = 0 ; i < 2 ; i++ )
|
for ( int i = 0 ; i < 2 ; i++ )
|
||||||
{
|
{
|
||||||
if ( pParticle->m_vVelocity[i] < vecWind[i] )
|
if ( pParticle->m_vVelocity[i] < vecWind[i] )
|
||||||
|
@ -30,6 +30,9 @@ public:
|
|||||||
// These are documented in the server-side entity.
|
// These are documented in the server-side entity.
|
||||||
public:
|
public:
|
||||||
float m_fDisappearDist;
|
float m_fDisappearDist;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float m_fDisappearMaxDist;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -43,6 +46,9 @@ ConVar lod_TransitionDist("lod_TransitionDist", "800");
|
|||||||
// Datatable..
|
// Datatable..
|
||||||
IMPLEMENT_CLIENTCLASS_DT(C_Func_LOD, DT_Func_LOD, CFunc_LOD)
|
IMPLEMENT_CLIENTCLASS_DT(C_Func_LOD, DT_Func_LOD, CFunc_LOD)
|
||||||
RecvPropFloat(RECVINFO(m_fDisappearDist)),
|
RecvPropFloat(RECVINFO(m_fDisappearDist)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropFloat(RECVINFO(m_fDisappearMaxDist)),
|
||||||
|
#endif
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
|
||||||
@ -54,6 +60,9 @@ END_RECV_TABLE()
|
|||||||
C_Func_LOD::C_Func_LOD()
|
C_Func_LOD::C_Func_LOD()
|
||||||
{
|
{
|
||||||
m_fDisappearDist = 5000.0f;
|
m_fDisappearDist = 5000.0f;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_fDisappearMaxDist = 0.0f;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -61,7 +70,11 @@ C_Func_LOD::C_Func_LOD()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
unsigned char C_Func_LOD::GetClientSideFade()
|
unsigned char C_Func_LOD::GetClientSideFade()
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
return UTIL_ComputeEntityFade( this, m_fDisappearDist, m_fDisappearDist + (m_fDisappearMaxDist != 0 ? m_fDisappearMaxDist : lod_TransitionDist.GetFloat()), 1.0f );
|
||||||
|
#else
|
||||||
return UTIL_ComputeEntityFade( this, m_fDisappearDist, m_fDisappearDist + lod_TransitionDist.GetFloat(), 1.0f );
|
return UTIL_ComputeEntityFade( this, m_fDisappearDist, m_fDisappearDist + lod_TransitionDist.GetFloat(), 1.0f );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,6 +102,10 @@ public:
|
|||||||
C_LightGlowOverlay m_Glow;
|
C_LightGlowOverlay m_Glow;
|
||||||
|
|
||||||
float m_flGlowProxySize;
|
float m_flGlowProxySize;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bDisabled;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void RecvProxy_HDRColorScale( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
static void RecvProxy_HDRColorScale( const CRecvProxyData *pData, void *pStruct, void *pOut )
|
||||||
@ -123,6 +127,9 @@ IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_LightGlow, DT_LightGlow, CLightGlow )
|
|||||||
RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
|
RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ),
|
||||||
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
|
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
|
||||||
RecvPropFloat(RECVINFO(m_flGlowProxySize)),
|
RecvPropFloat(RECVINFO(m_flGlowProxySize)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool( RECVINFO( m_bDisabled ) ),
|
||||||
|
#endif
|
||||||
RecvPropFloat("HDRColorScale", 0, SIZEOF_IGNORE, 0, RecvProxy_HDRColorScale),
|
RecvPropFloat("HDRColorScale", 0, SIZEOF_IGNORE, 0, RecvProxy_HDRColorScale),
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
@ -202,7 +209,11 @@ void C_LightGlow::OnDataChanged( DataUpdateType_t updateType )
|
|||||||
void C_LightGlow::ClientThink( void )
|
void C_LightGlow::ClientThink( void )
|
||||||
{
|
{
|
||||||
Vector mins = GetAbsOrigin();
|
Vector mins = GetAbsOrigin();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( engine->IsBoxVisible( mins, mins ) && !m_bDisabled )
|
||||||
|
#else
|
||||||
if ( engine->IsBoxVisible( mins, mins ) )
|
if ( engine->IsBoxVisible( mins, mins ) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
m_Glow.Activate();
|
m_Glow.Activate();
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
int m_iEffectIndex;
|
int m_iEffectIndex;
|
||||||
bool m_bActive;
|
bool m_bActive;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bDestroyImmediately;
|
||||||
|
#endif
|
||||||
bool m_bOldActive;
|
bool m_bOldActive;
|
||||||
float m_flStartTime; // Time at which the effect started
|
float m_flStartTime; // Time at which the effect started
|
||||||
|
|
||||||
@ -56,6 +59,9 @@ BEGIN_RECV_TABLE_NOBASE( C_ParticleSystem, DT_ParticleSystem )
|
|||||||
|
|
||||||
RecvPropInt( RECVINFO( m_iEffectIndex ) ),
|
RecvPropInt( RECVINFO( m_iEffectIndex ) ),
|
||||||
RecvPropBool( RECVINFO( m_bActive ) ),
|
RecvPropBool( RECVINFO( m_bActive ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool( RECVINFO( m_bDestroyImmediately ) ),
|
||||||
|
#endif
|
||||||
RecvPropFloat( RECVINFO( m_flStartTime ) ),
|
RecvPropFloat( RECVINFO( m_flStartTime ) ),
|
||||||
|
|
||||||
RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ),
|
RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ),
|
||||||
@ -108,9 +114,18 @@ void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType )
|
|||||||
SetNextClientThink( gpGlobals->curtime );
|
SetNextClientThink( gpGlobals->curtime );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#ifdef MAPBASE
|
||||||
|
{
|
||||||
|
if (!m_bDestroyImmediately)
|
||||||
|
ParticleProp()->StopEmission();
|
||||||
|
else
|
||||||
|
ParticleProp()->StopEmissionAndDestroyImmediately();
|
||||||
|
}
|
||||||
|
#else
|
||||||
{
|
{
|
||||||
ParticleProp()->StopEmission();
|
ParticleProp()->StopEmission();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,9 @@ IMPLEMENT_CLIENTCLASS_DT( C_PointCamera, DT_PointCamera, CPointCamera )
|
|||||||
RecvPropFloat( RECVINFO( m_flFogMaxDensity ) ),
|
RecvPropFloat( RECVINFO( m_flFogMaxDensity ) ),
|
||||||
RecvPropInt( RECVINFO( m_bActive ) ),
|
RecvPropInt( RECVINFO( m_bActive ) ),
|
||||||
RecvPropInt( RECVINFO( m_bUseScreenAspectRatio ) ),
|
RecvPropInt( RECVINFO( m_bUseScreenAspectRatio ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropInt( RECVINFO( m_iSkyMode ) ),
|
||||||
|
#endif
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
C_EntityClassList<C_PointCamera> g_PointCameraList;
|
C_EntityClassList<C_PointCamera> g_PointCameraList;
|
||||||
@ -113,4 +116,11 @@ void C_PointCamera::GetToolRecordingState( KeyValues *msg )
|
|||||||
msg->SetPtr( "monitor", &state );
|
msg->SetPtr( "monitor", &state );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
IMPLEMENT_CLIENTCLASS_DT( C_PointCameraOrtho, DT_PointCameraOrtho, CPointCameraOrtho )
|
||||||
|
RecvPropInt( RECVINFO( m_bOrtho ) ),
|
||||||
|
RecvPropArray( RecvPropFloat( RECVINFO( m_OrthoDimensions[0] ) ), m_OrthoDimensions ),
|
||||||
|
END_RECV_TABLE()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +37,12 @@ public:
|
|||||||
float GetFogMaxDensity();
|
float GetFogMaxDensity();
|
||||||
float GetFogEnd();
|
float GetFogEnd();
|
||||||
bool UseScreenAspectRatio() const { return m_bUseScreenAspectRatio; }
|
bool UseScreenAspectRatio() const { return m_bUseScreenAspectRatio; }
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool IsOrtho() const { return false; }
|
||||||
|
virtual void GetOrthoDimensions(float &up, float &dn, float &lf, float &rt) const {}
|
||||||
|
|
||||||
|
SkyboxVisibility_t SkyMode() { return m_iSkyMode; }
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void GetToolRecordingState( KeyValues *msg );
|
virtual void GetToolRecordingState( KeyValues *msg );
|
||||||
|
|
||||||
@ -50,11 +56,35 @@ private:
|
|||||||
float m_flFogMaxDensity;
|
float m_flFogMaxDensity;
|
||||||
bool m_bActive;
|
bool m_bActive;
|
||||||
bool m_bUseScreenAspectRatio;
|
bool m_bUseScreenAspectRatio;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
SkyboxVisibility_t m_iSkyMode;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
C_PointCamera *m_pNext;
|
C_PointCamera *m_pNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
class C_PointCameraOrtho : public C_PointCamera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS( C_PointCameraOrtho, C_PointCamera );
|
||||||
|
DECLARE_CLIENTCLASS();
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool IsOrtho() const { return m_bOrtho; }
|
||||||
|
void GetOrthoDimensions( float &up, float &dn, float &lf, float &rt ) const
|
||||||
|
{
|
||||||
|
up = m_OrthoDimensions[0], dn = m_OrthoDimensions[1];
|
||||||
|
lf = m_OrthoDimensions[2], rt = m_OrthoDimensions[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_bOrtho;
|
||||||
|
float m_OrthoDimensions[4];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
C_PointCamera *GetPointCameraList();
|
C_PointCamera *GetPointCameraList();
|
||||||
|
|
||||||
#endif // C_POINTCAMERA_H
|
#endif // C_POINTCAMERA_H
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -107,7 +107,9 @@ public:
|
|||||||
|
|
||||||
// Get the rope material data.
|
// Get the rope material data.
|
||||||
IMaterial *GetSolidMaterial( void );
|
IMaterial *GetSolidMaterial( void );
|
||||||
|
#ifndef MAPBASE
|
||||||
IMaterial *GetBackMaterial( void );
|
IMaterial *GetBackMaterial( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
struct BuildRopeQueuedData_t
|
struct BuildRopeQueuedData_t
|
||||||
{
|
{
|
||||||
@ -119,7 +121,11 @@ public:
|
|||||||
float m_Slack;
|
float m_Slack;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void BuildRope( RopeSegData_t *pRopeSegment, const Vector &vCurrentViewForward, const Vector &vCurrentViewOrigin, BuildRopeQueuedData_t *pQueuedData );
|
||||||
|
#else
|
||||||
void BuildRope( RopeSegData_t *pRopeSegment, const Vector &vCurrentViewForward, const Vector &vCurrentViewOrigin, BuildRopeQueuedData_t *pQueuedData, bool bQueued );
|
void BuildRope( RopeSegData_t *pRopeSegment, const Vector &vCurrentViewForward, const Vector &vCurrentViewOrigin, BuildRopeQueuedData_t *pQueuedData, bool bQueued );
|
||||||
|
#endif
|
||||||
|
|
||||||
// C_BaseEntity overrides.
|
// C_BaseEntity overrides.
|
||||||
public:
|
public:
|
||||||
@ -196,19 +202,29 @@ private:
|
|||||||
float m_TextureScale; // pixels per inch
|
float m_TextureScale; // pixels per inch
|
||||||
|
|
||||||
int m_fLockedPoints; // Which points are locked down.
|
int m_fLockedPoints; // Which points are locked down.
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int m_nChangeCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
float m_Width;
|
float m_Width;
|
||||||
|
|
||||||
CPhysicsDelegate m_PhysicsDelegate;
|
CPhysicsDelegate m_PhysicsDelegate;
|
||||||
|
|
||||||
IMaterial *m_pMaterial;
|
IMaterial *m_pMaterial;
|
||||||
|
#ifndef MAPBASE
|
||||||
IMaterial *m_pBackMaterial; // Optional translucent background material for the rope to help reduce aliasing.
|
IMaterial *m_pBackMaterial; // Optional translucent background material for the rope to help reduce aliasing.
|
||||||
|
#endif
|
||||||
|
|
||||||
int m_TextureHeight; // Texture height, for texture scale calculations.
|
int m_TextureHeight; // Texture height, for texture scale calculations.
|
||||||
|
|
||||||
// Instantaneous force
|
// Instantaneous force
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector m_vecImpulse;
|
||||||
|
Vector m_vecPreviousImpulse;
|
||||||
|
#else
|
||||||
Vector m_flImpulse;
|
Vector m_flImpulse;
|
||||||
Vector m_flPreviousImpulse;
|
Vector m_flPreviousImpulse;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Simulated wind gusts.
|
// Simulated wind gusts.
|
||||||
float m_flCurrentGustTimer;
|
float m_flCurrentGustTimer;
|
||||||
@ -250,7 +266,9 @@ public:
|
|||||||
virtual void ResetRenderCache( void ) = 0;
|
virtual void ResetRenderCache( void ) = 0;
|
||||||
virtual void AddToRenderCache( C_RopeKeyframe *pRope ) = 0;
|
virtual void AddToRenderCache( C_RopeKeyframe *pRope ) = 0;
|
||||||
virtual void DrawRenderCache( bool bShadowDepth ) = 0;
|
virtual void DrawRenderCache( bool bShadowDepth ) = 0;
|
||||||
|
#ifndef MAPBASE
|
||||||
virtual void OnRenderStart( void ) = 0;
|
virtual void OnRenderStart( void ) = 0;
|
||||||
|
#endif
|
||||||
virtual void SetHolidayLightMode( bool bHoliday ) = 0;
|
virtual void SetHolidayLightMode( bool bHoliday ) = 0;
|
||||||
virtual bool IsHolidayLightMode( void ) = 0;
|
virtual bool IsHolidayLightMode( void ) = 0;
|
||||||
virtual int GetHolidayLightStyle( void ) = 0;
|
virtual int GetHolidayLightStyle( void ) = 0;
|
||||||
|
@ -804,11 +804,63 @@ CChoreoStringPool g_ChoreoStringPool;
|
|||||||
|
|
||||||
CChoreoScene *C_SceneEntity::LoadScene( const char *filename )
|
CChoreoScene *C_SceneEntity::LoadScene( const char *filename )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
char loadfile[MAX_PATH];
|
||||||
|
#else
|
||||||
char loadfile[ 512 ];
|
char loadfile[ 512 ];
|
||||||
|
#endif
|
||||||
Q_strncpy( loadfile, filename, sizeof( loadfile ) );
|
Q_strncpy( loadfile, filename, sizeof( loadfile ) );
|
||||||
Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) );
|
Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) );
|
||||||
Q_FixSlashes( loadfile );
|
Q_FixSlashes( loadfile );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//
|
||||||
|
// Raw scene file support
|
||||||
|
//
|
||||||
|
void *pBuffer = 0;
|
||||||
|
size_t bufsize = scenefilecache->GetSceneBufferSize( loadfile );
|
||||||
|
CChoreoScene *pScene = NULL;
|
||||||
|
if ( bufsize > 0 )
|
||||||
|
{
|
||||||
|
// Definitely in scenes.image
|
||||||
|
pBuffer = new char[ bufsize ];
|
||||||
|
if ( !scenefilecache->GetSceneData( filename, (byte *)pBuffer, bufsize ) )
|
||||||
|
{
|
||||||
|
delete[] pBuffer;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( IsBufferBinaryVCD( (char*)pBuffer, bufsize ) )
|
||||||
|
{
|
||||||
|
pScene = new CChoreoScene( this );
|
||||||
|
CUtlBuffer buf( pBuffer, bufsize, CUtlBuffer::READ_ONLY );
|
||||||
|
if ( !pScene->RestoreFromBinaryBuffer( buf, loadfile, &g_ChoreoStringPool ) )
|
||||||
|
{
|
||||||
|
Warning( "Unable to restore scene '%s'\n", loadfile );
|
||||||
|
delete pScene;
|
||||||
|
pScene = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (filesystem->ReadFileEx( loadfile, "MOD", &pBuffer, true ))
|
||||||
|
{
|
||||||
|
// Not in scenes.image, but it's a raw file
|
||||||
|
g_TokenProcessor.SetBuffer((char*)pBuffer);
|
||||||
|
pScene = ChoreoLoadScene( loadfile, this, &g_TokenProcessor, Scene_Printf );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Abandon ship
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pScene)
|
||||||
|
{
|
||||||
|
pScene->SetPrintFunc( Scene_Printf );
|
||||||
|
pScene->SetEventCallbackInterface( this );
|
||||||
|
}
|
||||||
|
#else
|
||||||
char *pBuffer = NULL;
|
char *pBuffer = NULL;
|
||||||
size_t bufsize = scenefilecache->GetSceneBufferSize( loadfile );
|
size_t bufsize = scenefilecache->GetSceneBufferSize( loadfile );
|
||||||
if ( bufsize <= 0 )
|
if ( bufsize <= 0 )
|
||||||
@ -843,6 +895,7 @@ CChoreoScene *C_SceneEntity::LoadScene( const char *filename )
|
|||||||
g_TokenProcessor.SetBuffer( pBuffer );
|
g_TokenProcessor.SetBuffer( pBuffer );
|
||||||
pScene = ChoreoLoadScene( loadfile, this, &g_TokenProcessor, Scene_Printf );
|
pScene = ChoreoLoadScene( loadfile, this, &g_TokenProcessor, Scene_Printf );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
delete[] pBuffer;
|
delete[] pBuffer;
|
||||||
return pScene;
|
return pScene;
|
||||||
|
@ -32,13 +32,24 @@ private:
|
|||||||
color32 m_shadowColor;
|
color32 m_shadowColor;
|
||||||
float m_flShadowMaxDist;
|
float m_flShadowMaxDist;
|
||||||
bool m_bDisableShadows;
|
bool m_bDisableShadows;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bEnableLocalLightShadows;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_CLIENTCLASS_DT(C_ShadowControl, DT_ShadowControl, CShadowControl)
|
IMPLEMENT_CLIENTCLASS_DT(C_ShadowControl, DT_ShadowControl, CShadowControl)
|
||||||
RecvPropVector(RECVINFO(m_shadowDirection)),
|
RecvPropVector(RECVINFO(m_shadowDirection)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
/*RecvPropInt(RECVINFO(m_shadowColor), 0, RecvProxy_Int32ToColor32),*/
|
||||||
|
RecvPropInt(RECVINFO(m_shadowColor), 0, RecvProxy_IntToColor32),
|
||||||
|
#else
|
||||||
RecvPropInt(RECVINFO(m_shadowColor)),
|
RecvPropInt(RECVINFO(m_shadowColor)),
|
||||||
|
#endif
|
||||||
RecvPropFloat(RECVINFO(m_flShadowMaxDist)),
|
RecvPropFloat(RECVINFO(m_flShadowMaxDist)),
|
||||||
RecvPropBool(RECVINFO(m_bDisableShadows)),
|
RecvPropBool(RECVINFO(m_bDisableShadows)),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool(RECVINFO(m_bEnableLocalLightShadows)),
|
||||||
|
#endif
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
|
||||||
@ -54,6 +65,9 @@ void C_ShadowControl::OnDataChanged(DataUpdateType_t updateType)
|
|||||||
g_pClientShadowMgr->SetShadowColor( m_shadowColor.r, m_shadowColor.g, m_shadowColor.b );
|
g_pClientShadowMgr->SetShadowColor( m_shadowColor.r, m_shadowColor.g, m_shadowColor.b );
|
||||||
g_pClientShadowMgr->SetShadowDistance( m_flShadowMaxDist );
|
g_pClientShadowMgr->SetShadowDistance( m_flShadowMaxDist );
|
||||||
g_pClientShadowMgr->SetShadowsDisabled( m_bDisableShadows );
|
g_pClientShadowMgr->SetShadowsDisabled( m_bDisableShadows );
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
g_pClientShadowMgr->SetShadowFromWorldLightsEnabled( m_bEnableLocalLightShadows );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -207,6 +207,9 @@ public:
|
|||||||
// "dsp_volume"
|
// "dsp_volume"
|
||||||
void ProcessDSPVolume( KeyValues *pKey, subsoundscapeparams_t ¶ms );
|
void ProcessDSPVolume( KeyValues *pKey, subsoundscapeparams_t ¶ms );
|
||||||
|
|
||||||
|
#ifdef MAPBASE // Moved to public space
|
||||||
|
void AddSoundScapeFile( const char *filename );
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -215,7 +218,9 @@ private:
|
|||||||
return gpGlobals->framecount == m_nRestoreFrame ? true : false;
|
return gpGlobals->framecount == m_nRestoreFrame ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MAPBASE // Moved to public space
|
||||||
void AddSoundScapeFile( const char *filename );
|
void AddSoundScapeFile( const char *filename );
|
||||||
|
#endif
|
||||||
|
|
||||||
void TouchPlayLooping( KeyValues *pAmbient );
|
void TouchPlayLooping( KeyValues *pAmbient );
|
||||||
void TouchPlayRandom( KeyValues *pPlayRandom );
|
void TouchPlayRandom( KeyValues *pPlayRandom );
|
||||||
@ -265,6 +270,13 @@ void Soundscape_Update( audioparams_t &audio )
|
|||||||
g_SoundscapeSystem.UpdateAudioParams( audio );
|
g_SoundscapeSystem.UpdateAudioParams( audio );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void Soundscape_AddFile( const char *szFile )
|
||||||
|
{
|
||||||
|
g_SoundscapeSystem.AddSoundScapeFile(szFile);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SOUNDSCAPE_MANIFEST_FILE "scripts/soundscapes_manifest.txt"
|
#define SOUNDSCAPE_MANIFEST_FILE "scripts/soundscapes_manifest.txt"
|
||||||
|
|
||||||
void C_SoundscapeSystem::AddSoundScapeFile( const char *filename )
|
void C_SoundscapeSystem::AddSoundScapeFile( const char *filename )
|
||||||
@ -310,6 +322,16 @@ bool C_SoundscapeSystem::Init()
|
|||||||
mapSoundscapeFilename = VarArgs( "scripts/soundscapes_%s.txt", mapname );
|
mapSoundscapeFilename = VarArgs( "scripts/soundscapes_%s.txt", mapname );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (filesystem->FileExists(VarArgs("maps/%s_soundscapes.txt", mapname)))
|
||||||
|
{
|
||||||
|
// A Mapbase-specific file exists. Load that instead.
|
||||||
|
// Any additional soundscape files, like the original scripts/soundscapes version,
|
||||||
|
// could be loaded through #include and/or #base.
|
||||||
|
mapSoundscapeFilename = VarArgs("maps/%s_soundscapes.txt", mapname);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
KeyValues *manifest = new KeyValues( SOUNDSCAPE_MANIFEST_FILE );
|
KeyValues *manifest = new KeyValues( SOUNDSCAPE_MANIFEST_FILE );
|
||||||
if ( filesystem->LoadKeyValues( *manifest, IFileSystem::TYPE_SOUNDSCAPE, SOUNDSCAPE_MANIFEST_FILE, "GAME" ) )
|
if ( filesystem->LoadKeyValues( *manifest, IFileSystem::TYPE_SOUNDSCAPE, SOUNDSCAPE_MANIFEST_FILE, "GAME" ) )
|
||||||
{
|
{
|
||||||
|
@ -24,4 +24,8 @@ extern void Soundscape_Update( audioparams_t &audio );
|
|||||||
// sounds are still playing when they're not.
|
// sounds are still playing when they're not.
|
||||||
void Soundscape_OnStopAllSounds();
|
void Soundscape_OnStopAllSounds();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void Soundscape_AddFile( const char *szFile );
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // C_SOUNDSCAPE_H
|
#endif // C_SOUNDSCAPE_H
|
||||||
|
@ -64,7 +64,12 @@ void C_TELargeFunnel::CreateFunnel( void )
|
|||||||
float ratio = 0.25;
|
float ratio = 0.25;
|
||||||
float invratio = 1 / ratio;
|
float invratio = 1 / ratio;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Uh...figure out how to fix this
|
||||||
PMaterialHandle hMaterial = pSimple->GetPMaterial( "sprites/flare6" );
|
PMaterialHandle hMaterial = pSimple->GetPMaterial( "sprites/flare6" );
|
||||||
|
#else
|
||||||
|
PMaterialHandle hMaterial = pSimple->GetPMaterial( "sprites/flare6" );
|
||||||
|
#endif
|
||||||
|
|
||||||
for ( i = -256 ; i <= 256 ; i += 24 ) //24 from 32.. little more dense
|
for ( i = -256 ; i <= 256 ; i += 24 ) //24 from 32.. little more dense
|
||||||
{
|
{
|
||||||
|
@ -597,8 +597,12 @@ bool C_LocalTempEntity::Frame( float frametime, int framenumber )
|
|||||||
|
|
||||||
if ( flags & FTENT_WINDBLOWN )
|
if ( flags & FTENT_WINDBLOWN )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector vecWind = GetWindspeedAtLocation( GetAbsOrigin() );
|
||||||
|
#else
|
||||||
Vector vecWind;
|
Vector vecWind;
|
||||||
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
|
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
|
||||||
|
#endif
|
||||||
|
|
||||||
for ( int i = 0 ; i < 2 ; i++ )
|
for ( int i = 0 ; i < 2 ; i++ )
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,12 @@ public:
|
|||||||
flFOV = m_flFOV;
|
flFOV = m_flFOV;
|
||||||
}
|
}
|
||||||
virtual void DrawHudElements();
|
virtual void DrawHudElements();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return m_bAllowStandardWeapons; }
|
||||||
|
bool m_bAllowStandardWeapons;
|
||||||
|
#else
|
||||||
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
|
virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; }
|
||||||
|
#endif
|
||||||
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd );
|
virtual void UpdateViewAngles( C_BasePlayer *pLocalPlayer, CUserCmd *pCmd );
|
||||||
virtual C_BaseCombatCharacter *GetPassenger( int nRole );
|
virtual C_BaseCombatCharacter *GetPassenger( int nRole );
|
||||||
virtual int GetPassengerRole( C_BaseCombatCharacter *pPassenger );
|
virtual int GetPassengerRole( C_BaseCombatCharacter *pPassenger );
|
||||||
@ -107,6 +112,9 @@ IMPLEMENT_CLIENTCLASS_DT(C_PropVehicleChoreoGeneric, DT_PropVehicleChoreoGeneric
|
|||||||
RecvPropFloat( RECVINFO( m_vehicleView.flYawMax ) ),
|
RecvPropFloat( RECVINFO( m_vehicleView.flYawMax ) ),
|
||||||
RecvPropFloat( RECVINFO( m_vehicleView.flPitchMin ) ),
|
RecvPropFloat( RECVINFO( m_vehicleView.flPitchMin ) ),
|
||||||
RecvPropFloat( RECVINFO( m_vehicleView.flPitchMax ) ),
|
RecvPropFloat( RECVINFO( m_vehicleView.flPitchMax ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool( RECVINFO( m_bAllowStandardWeapons ) ),
|
||||||
|
#endif
|
||||||
END_RECV_TABLE()
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,6 +147,11 @@
|
|||||||
#include "fbxsystem/fbxsystem.h"
|
#include "fbxsystem/fbxsystem.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DISCORD_RPC
|
||||||
|
#include "discord_rpc.h"
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern vgui::IInputInternal *g_InputInternal;
|
extern vgui::IInputInternal *g_InputInternal;
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@ -335,6 +340,13 @@ static ConVar s_cl_class("cl_class", "default", FCVAR_USERINFO|FCVAR_ARCHIVE, "D
|
|||||||
static ConVar s_cl_load_hl1_content("cl_load_hl1_content", "0", FCVAR_ARCHIVE, "Mount the content from Half-Life: Source if possible");
|
static ConVar s_cl_load_hl1_content("cl_load_hl1_content", "0", FCVAR_ARCHIVE, "Mount the content from Half-Life: Source if possible");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE_RPC
|
||||||
|
// Mapbase stuff
|
||||||
|
extern void MapbaseRPC_Init();
|
||||||
|
extern void MapbaseRPC_Shutdown();
|
||||||
|
extern void MapbaseRPC_Update( int iType, const char *pMapName );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Physics system
|
// Physics system
|
||||||
bool g_bLevelInitialized;
|
bool g_bLevelInitialized;
|
||||||
@ -843,6 +855,7 @@ CHLClient::CHLClient()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern IGameSystem *ViewportClientSystem();
|
extern IGameSystem *ViewportClientSystem();
|
||||||
|
|
||||||
|
|
||||||
@ -1085,6 +1098,10 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
|
|||||||
HookHapticMessages(); // Always hook the messages
|
HookHapticMessages(); // Always hook the messages
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE_RPC
|
||||||
|
MapbaseRPC_Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1210,6 +1227,10 @@ void CHLClient::Shutdown( void )
|
|||||||
ShutdownFbx();
|
ShutdownFbx();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE_RPC
|
||||||
|
MapbaseRPC_Shutdown();
|
||||||
|
#endif
|
||||||
|
|
||||||
// This call disconnects the VGui libraries which we rely on later in the shutdown path, so don't do it
|
// This call disconnects the VGui libraries which we rely on later in the shutdown path, so don't do it
|
||||||
// DisconnectTier3Libraries( );
|
// DisconnectTier3Libraries( );
|
||||||
DisconnectTier2Libraries( );
|
DisconnectTier2Libraries( );
|
||||||
@ -1622,6 +1643,13 @@ void CHLClient::LevelInitPreEntity( char const* pMapName )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE_RPC
|
||||||
|
if (!g_bTextMode)
|
||||||
|
{
|
||||||
|
MapbaseRPC_Update(RPCSTATE_LEVEL_INIT, pMapName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check low violence settings for this map
|
// Check low violence settings for this map
|
||||||
g_RagdollLVManager.SetLowViolence( pMapName );
|
g_RagdollLVManager.SetLowViolence( pMapName );
|
||||||
|
|
||||||
@ -1713,6 +1741,13 @@ void CHLClient::LevelShutdown( void )
|
|||||||
|
|
||||||
gHUD.LevelShutdown();
|
gHUD.LevelShutdown();
|
||||||
|
|
||||||
|
#ifdef MAPBASE_RPC
|
||||||
|
if (!g_bTextMode)
|
||||||
|
{
|
||||||
|
MapbaseRPC_Update(RPCSTATE_LEVEL_SHUTDOWN, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
internalCenterPrint->Clear();
|
internalCenterPrint->Clear();
|
||||||
|
|
||||||
messagechars->Clear();
|
messagechars->Clear();
|
||||||
@ -2143,7 +2178,9 @@ void OnRenderStart()
|
|||||||
// are at the correct location
|
// are at the correct location
|
||||||
view->OnRenderStart();
|
view->OnRenderStart();
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
RopeManager()->OnRenderStart();
|
RopeManager()->OnRenderStart();
|
||||||
|
#endif
|
||||||
|
|
||||||
// This will place all entities in the correct position in world space and in the KD-tree
|
// This will place all entities in the correct position in world space and in the KD-tree
|
||||||
C_BaseAnimating::UpdateClientSideAnimations();
|
C_BaseAnimating::UpdateClientSideAnimations();
|
||||||
|
@ -177,4 +177,16 @@ extern CSteamID GetSteamIDForPlayerIndex( int iPlayerIndex );
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Mapbase RPC stuff
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RPCSTATE_INIT,
|
||||||
|
RPCSTATE_LEVEL_INIT,
|
||||||
|
RPCSTATE_LEVEL_SHUTDOWN,
|
||||||
|
|
||||||
|
RPCSTATE_UPDATE,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // CDLL_CLIENT_INT_H
|
#endif // CDLL_CLIENT_INT_H
|
||||||
|
@ -703,6 +703,24 @@ int UTIL_EntitiesAlongRay( C_BaseEntity **pList, int listMax, const Ray_t &ray,
|
|||||||
return rayEnum.GetCount();
|
return rayEnum.GetCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Pass in an array of pointers and an array size, it fills the array and returns the number inserted
|
||||||
|
// Input : **pList -
|
||||||
|
// listMax -
|
||||||
|
// &point -
|
||||||
|
// flagMask -
|
||||||
|
// Output : int
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int UTIL_EntitiesAtPoint( C_BaseEntity **pList, int listMax, const Vector &point, int flagMask, int partitionMask )
|
||||||
|
{
|
||||||
|
CFlaggedEntitiesEnum rayEnum( pList, listMax, flagMask );
|
||||||
|
partition->EnumerateElementsAtPoint( partitionMask, point, false, &rayEnum );
|
||||||
|
|
||||||
|
return rayEnum.GetCount();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CEntitySphereQuery::CEntitySphereQuery( const Vector ¢er, float radius, int flagMask, int partitionMask )
|
CEntitySphereQuery::CEntitySphereQuery( const Vector ¢er, float radius, int flagMask, int partitionMask )
|
||||||
{
|
{
|
||||||
m_listIndex = 0;
|
m_listIndex = 0;
|
||||||
|
@ -119,6 +119,9 @@ void ClientPrint( C_BasePlayer *player, int msg_dest, const char *msg_name, cons
|
|||||||
int UTIL_EntitiesInBox( C_BaseEntity **pList, int listMax, const Vector &mins, const Vector &maxs, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
|
int UTIL_EntitiesInBox( C_BaseEntity **pList, int listMax, const Vector &mins, const Vector &maxs, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
|
||||||
int UTIL_EntitiesInSphere( C_BaseEntity **pList, int listMax, const Vector ¢er, float radius, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
|
int UTIL_EntitiesInSphere( C_BaseEntity **pList, int listMax, const Vector ¢er, float radius, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
|
||||||
int UTIL_EntitiesAlongRay( C_BaseEntity **pList, int listMax, const Ray_t &ray, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
|
int UTIL_EntitiesAlongRay( C_BaseEntity **pList, int listMax, const Ray_t &ray, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int UTIL_EntitiesAtPoint( C_BaseEntity **pList, int listMax, const Vector &point, int flagMask, int partitionMask = PARTITION_CLIENT_NON_STATIC_EDICTS );
|
||||||
|
#endif
|
||||||
|
|
||||||
// make this a fixed size so it just sits on the stack
|
// make this a fixed size so it just sits on the stack
|
||||||
#define MAX_SPHERE_QUERY 256
|
#define MAX_SPHERE_QUERY 256
|
||||||
@ -161,7 +164,13 @@ T *_CreateEntity( T *newClass, const char *className )
|
|||||||
// Misc useful
|
// Misc useful
|
||||||
inline bool FStrEq(const char *sz1, const char *sz2)
|
inline bool FStrEq(const char *sz1, const char *sz2)
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// V_stricmp() already checks if the pointers are equal, so having a comparison here is pointless.
|
||||||
|
// I had few reasons to do this, but maybe you'll thank me later.
|
||||||
|
return ( V_stricmp(sz1, sz2) == 0 );
|
||||||
|
#else
|
||||||
return ( sz1 == sz2 || V_stricmp(sz1, sz2) == 0 );
|
return ( sz1 == sz2 || V_stricmp(sz1, sz2) == 0 );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a vector, clamps the scalar axes to MAX_COORD_FLOAT ranges from worldsize.h
|
// Given a vector, clamps the scalar axes to MAX_COORD_FLOAT ranges from worldsize.h
|
||||||
|
@ -18,6 +18,9 @@ $include "$SRCDIR\vpc_scripts\protobuf_builder.vpc"
|
|||||||
$Include "$SRCDIR\vpc_scripts\source_replay.vpc" [$TF]
|
$Include "$SRCDIR\vpc_scripts\source_replay.vpc" [$TF]
|
||||||
$Include "$SRCDIR\game\protobuf_include.vpc"
|
$Include "$SRCDIR\game\protobuf_include.vpc"
|
||||||
|
|
||||||
|
// Mapbase stuff
|
||||||
|
$Include "$SRCDIR\game\client\client_mapbase.vpc" [$MAPBASE]
|
||||||
|
|
||||||
$Configuration "Debug"
|
$Configuration "Debug"
|
||||||
{
|
{
|
||||||
$General
|
$General
|
||||||
|
@ -79,7 +79,7 @@ $Project "Client (Episodic)"
|
|||||||
$File "hl2\c_weapon_crossbow.cpp"
|
$File "hl2\c_weapon_crossbow.cpp"
|
||||||
$File "episodic\c_weapon_hopwire.cpp"
|
$File "episodic\c_weapon_hopwire.cpp"
|
||||||
$File "hl2\c_weapon_physcannon.cpp"
|
$File "hl2\c_weapon_physcannon.cpp"
|
||||||
$File "hl2\c_weapon_stunstick.cpp"
|
$File "hl2\c_weapon_stunstick.cpp" [!$MAPBASE] // See client_mapbase.vpc
|
||||||
$File "$SRCDIR\game\shared\hl2\citadel_effects_shared.h"
|
$File "$SRCDIR\game\shared\hl2\citadel_effects_shared.h"
|
||||||
$File "hl2\clientmode_hlnormal.cpp"
|
$File "hl2\clientmode_hlnormal.cpp"
|
||||||
$File "hl2\clientmode_hlnormal.h"
|
$File "hl2\clientmode_hlnormal.h"
|
||||||
|
@ -74,7 +74,7 @@ $Project "Client (HL2)"
|
|||||||
$File "hl2\c_weapon__stubs_hl2.cpp"
|
$File "hl2\c_weapon__stubs_hl2.cpp"
|
||||||
$File "hl2\c_weapon_crossbow.cpp"
|
$File "hl2\c_weapon_crossbow.cpp"
|
||||||
$File "hl2\c_weapon_physcannon.cpp"
|
$File "hl2\c_weapon_physcannon.cpp"
|
||||||
$File "hl2\c_weapon_stunstick.cpp"
|
$File "hl2\c_weapon_stunstick.cpp" [!$MAPBASE] // See client_mapbase.vpc
|
||||||
$File "$SRCDIR\game\shared\hl2\citadel_effects_shared.h"
|
$File "$SRCDIR\game\shared\hl2\citadel_effects_shared.h"
|
||||||
$File "hl2\clientmode_hlnormal.cpp"
|
$File "hl2\clientmode_hlnormal.cpp"
|
||||||
$File "hl2\clientmode_hlnormal.h"
|
$File "hl2\clientmode_hlnormal.h"
|
||||||
|
51
sp/src/game/client/client_mapbase.vpc
Normal file
51
sp/src/game/client/client_mapbase.vpc
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// CLIENT_MAPBASE.VPC
|
||||||
|
//
|
||||||
|
// Project Script
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
$Configuration
|
||||||
|
{
|
||||||
|
$Compiler
|
||||||
|
{
|
||||||
|
$PreprocessorDefinitions "$BASE;ASW_PROJECTED_TEXTURES;DYNAMIC_RTT_SHADOWS"
|
||||||
|
|
||||||
|
$PreprocessorDefinitions "$BASE;MAPBASE_RPC;DISCORD_RPC;STEAM_RPC" [$MAPBASE_RPC]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Project
|
||||||
|
{
|
||||||
|
$Folder "Source Files"
|
||||||
|
{
|
||||||
|
$File "c_env_global_light.cpp"
|
||||||
|
$File "worldlight.cpp"
|
||||||
|
$File "worldlight.h"
|
||||||
|
|
||||||
|
$Folder "Mapbase"
|
||||||
|
{
|
||||||
|
$File "$SRCDIR\game\shared\mapbase\mapbase_shared.cpp"
|
||||||
|
$File "$SRCDIR\game\shared\mapbase\mapbase_rpc.cpp"
|
||||||
|
$File "$SRCDIR\game\shared\mapbase\MapEdit.cpp"
|
||||||
|
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
|
||||||
|
|
||||||
|
$File "mapbase\c_func_clientclip.cpp"
|
||||||
|
}
|
||||||
|
|
||||||
|
$Folder "HL2 DLL"
|
||||||
|
{
|
||||||
|
// Original stunstick files are conditional'd out in the HL2 VPCs
|
||||||
|
$File "$SRCDIR\game\shared\hl2mp\weapon_stunstick.cpp"
|
||||||
|
$File "$SRCDIR\game\shared\hl2mp\weapon_stunstick.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
$Folder "HL2MP"
|
||||||
|
{
|
||||||
|
$Folder "Weapons"
|
||||||
|
{
|
||||||
|
$File "$SRCDIR\game\shared\hl2mp\weapon_slam.cpp"
|
||||||
|
$File "$SRCDIR\game\shared\hl2mp\weapon_slam.h"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -77,6 +77,9 @@ class CHudVote;
|
|||||||
static vgui::HContext s_hVGuiContext = DEFAULT_VGUI_CONTEXT;
|
static vgui::HContext s_hVGuiContext = DEFAULT_VGUI_CONTEXT;
|
||||||
|
|
||||||
ConVar cl_drawhud( "cl_drawhud", "1", FCVAR_CHEAT, "Enable the rendering of the hud" );
|
ConVar cl_drawhud( "cl_drawhud", "1", FCVAR_CHEAT, "Enable the rendering of the hud" );
|
||||||
|
#ifdef DEMO_AUTORECORD
|
||||||
|
ConVar cl_autorecord("cl_autorecord", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Start recording demos automatically with an incremental name based on this value.");
|
||||||
|
#endif
|
||||||
ConVar hud_takesshots( "hud_takesshots", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Auto-save a scoreboard screenshot at the end of a map." );
|
ConVar hud_takesshots( "hud_takesshots", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Auto-save a scoreboard screenshot at the end of a map." );
|
||||||
ConVar hud_freezecamhide( "hud_freezecamhide", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Hide the HUD during freeze-cam" );
|
ConVar hud_freezecamhide( "hud_freezecamhide", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Hide the HUD during freeze-cam" );
|
||||||
ConVar cl_show_num_particle_systems( "cl_show_num_particle_systems", "0", FCVAR_CLIENTDLL, "Display the number of active particle systems." );
|
ConVar cl_show_num_particle_systems( "cl_show_num_particle_systems", "0", FCVAR_CLIENTDLL, "Display the number of active particle systems." );
|
||||||
@ -830,8 +833,54 @@ void ClientModeShared::LevelInit( const char *newmap )
|
|||||||
// Reset any player explosion/shock effects
|
// Reset any player explosion/shock effects
|
||||||
CLocalPlayerFilter filter;
|
CLocalPlayerFilter filter;
|
||||||
enginesound->SetPlayerDSP( filter, 0, true );
|
enginesound->SetPlayerDSP( filter, 0, true );
|
||||||
|
|
||||||
|
#ifdef DEMO_AUTORECORD
|
||||||
|
AutoRecord(newmap);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEMO_AUTORECORD
|
||||||
|
void ClientModeShared::AutoRecord(const char *map)
|
||||||
|
{
|
||||||
|
if (!cl_autorecord.GetBool()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (map == nullptr) {
|
||||||
|
Warning("null map in ClientModeShared::AutoRecord");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop any demo to make sure they're saved
|
||||||
|
engine->ClientCmd("stop");
|
||||||
|
|
||||||
|
// KLEMS: sanitize space in client name because having to type "" while playing back lots of demos is annoying
|
||||||
|
ConVarRef name("name");
|
||||||
|
char nameStr[128];
|
||||||
|
memset(nameStr, 0, sizeof(nameStr));
|
||||||
|
Q_snprintf(nameStr, sizeof(nameStr), "%s", name.GetString());
|
||||||
|
int i = 0;
|
||||||
|
while (nameStr[i]) {
|
||||||
|
char c = nameStr[i];
|
||||||
|
if (!( (c >= '0' && c <= '9') ||
|
||||||
|
(c >= 'a' && c <= 'z') ||
|
||||||
|
(c >= 'A' && c <= 'Z'))) {
|
||||||
|
nameStr[i] = '_';
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
nameStr[127] = 0;
|
||||||
|
|
||||||
|
char cmd[256];
|
||||||
|
Q_snprintf(cmd, sizeof(cmd), "record \"%s_%04d_%s\"", nameStr, cl_autorecord.GetInt(), map);
|
||||||
|
cl_autorecord.SetValue(cl_autorecord.GetInt() + 1);
|
||||||
|
engine->ClientCmd(cmd);
|
||||||
|
|
||||||
|
// write to config to make sure the cvar is recorded
|
||||||
|
engine->ClientCmd("host_writeconfig");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -42,6 +42,10 @@ class CReplayReminderPanel;
|
|||||||
|
|
||||||
#define USERID2PLAYER(i) ToBasePlayer( ClientEntityList().GetEnt( engine->GetPlayerForUserID( i ) ) )
|
#define USERID2PLAYER(i) ToBasePlayer( ClientEntityList().GetEnt( engine->GetPlayerForUserID( i ) ) )
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#define DEMO_AUTORECORD 1
|
||||||
|
#endif
|
||||||
|
|
||||||
extern IClientMode *GetClientModeNormal(); // must be implemented
|
extern IClientMode *GetClientModeNormal(); // must be implemented
|
||||||
|
|
||||||
// This class implements client mode functionality common to HL2 and TF2.
|
// This class implements client mode functionality common to HL2 and TF2.
|
||||||
@ -62,6 +66,10 @@ public:
|
|||||||
virtual void LevelInit( const char *newmap );
|
virtual void LevelInit( const char *newmap );
|
||||||
virtual void LevelShutdown( void );
|
virtual void LevelShutdown( void );
|
||||||
|
|
||||||
|
#ifdef DEMO_AUTORECORD
|
||||||
|
virtual void AutoRecord( const char *map );
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void Enable();
|
virtual void Enable();
|
||||||
virtual void Disable();
|
virtual void Disable();
|
||||||
virtual void Layout();
|
virtual void Layout();
|
||||||
|
@ -81,6 +81,16 @@
|
|||||||
#include "toolframework_client.h"
|
#include "toolframework_client.h"
|
||||||
#include "bonetoworldarray.h"
|
#include "bonetoworldarray.h"
|
||||||
#include "cmodel.h"
|
#include "cmodel.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "renderparm.h"
|
||||||
|
#endif
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
#include "flashlighteffect.h"
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
#include "debugoverlay_shared.h"
|
||||||
|
#include "worldlight.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
@ -89,6 +99,12 @@
|
|||||||
static ConVar r_flashlightdrawfrustum( "r_flashlightdrawfrustum", "0" );
|
static ConVar r_flashlightdrawfrustum( "r_flashlightdrawfrustum", "0" );
|
||||||
static ConVar r_flashlightmodels( "r_flashlightmodels", "1" );
|
static ConVar r_flashlightmodels( "r_flashlightmodels", "1" );
|
||||||
static ConVar r_shadowrendertotexture( "r_shadowrendertotexture", "0" );
|
static ConVar r_shadowrendertotexture( "r_shadowrendertotexture", "0" );
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
static ConVar r_shadow_lightpos_lerptime( "r_shadow_lightpos_lerptime", "0.5" );
|
||||||
|
static ConVar r_shadowfromworldlights_debug( "r_shadowfromworldlights_debug", "0", FCVAR_CHEAT );
|
||||||
|
static ConVar r_shadow_shortenfactor( "r_shadow_shortenfactor", "2" , 0, "Makes shadows cast from local lights shorter" );
|
||||||
|
static ConVar r_shadow_mincastintensity( "r_shadow_mincastintensity", "0.3", FCVAR_CHEAT, "Minimum brightness of a light to be classed as shadow casting", true, 0, false, 0 );
|
||||||
|
#endif
|
||||||
static ConVar r_flashlight_version2( "r_flashlight_version2", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
|
static ConVar r_flashlight_version2( "r_flashlight_version2", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
|
||||||
|
|
||||||
ConVar r_flashlightdepthtexture( "r_flashlightdepthtexture", "1" );
|
ConVar r_flashlightdepthtexture( "r_flashlightdepthtexture", "1" );
|
||||||
@ -96,10 +112,18 @@ ConVar r_flashlightdepthtexture( "r_flashlightdepthtexture", "1" );
|
|||||||
#if defined( _X360 )
|
#if defined( _X360 )
|
||||||
ConVar r_flashlightdepthres( "r_flashlightdepthres", "512" );
|
ConVar r_flashlightdepthres( "r_flashlightdepthres", "512" );
|
||||||
#else
|
#else
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar r_flashlightdepthres( "r_flashlightdepthres", "2048" );
|
||||||
|
#else
|
||||||
ConVar r_flashlightdepthres( "r_flashlightdepthres", "1024" );
|
ConVar r_flashlightdepthres( "r_flashlightdepthres", "1024" );
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
ConVar r_threaded_client_shadow_manager( "r_threaded_client_shadow_manager", "1" );
|
||||||
|
#else
|
||||||
ConVar r_threaded_client_shadow_manager( "r_threaded_client_shadow_manager", "0" );
|
ConVar r_threaded_client_shadow_manager( "r_threaded_client_shadow_manager", "0" );
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma warning( disable: 4701 )
|
#pragma warning( disable: 4701 )
|
||||||
@ -782,7 +806,11 @@ public:
|
|||||||
void RestoreRenderState();
|
void RestoreRenderState();
|
||||||
|
|
||||||
// Computes a rough bounding box encompassing the volume of the shadow
|
// Computes a rough bounding box encompassing the volume of the shadow
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
void ComputeShadowBBox( IClientRenderable *pRenderable, ClientShadowHandle_t shadowHandle, const Vector &vecAbsCenter, float flRadius, Vector *pAbsMins, Vector *pAbsMaxs );
|
||||||
|
#else
|
||||||
void ComputeShadowBBox( IClientRenderable *pRenderable, const Vector &vecAbsCenter, float flRadius, Vector *pAbsMins, Vector *pAbsMaxs );
|
void ComputeShadowBBox( IClientRenderable *pRenderable, const Vector &vecAbsCenter, float flRadius, Vector *pAbsMins, Vector *pAbsMaxs );
|
||||||
|
#endif
|
||||||
|
|
||||||
bool WillParentRenderBlobbyShadow( IClientRenderable *pRenderable );
|
bool WillParentRenderBlobbyShadow( IClientRenderable *pRenderable );
|
||||||
|
|
||||||
@ -794,6 +822,13 @@ public:
|
|||||||
r_shadows_gamecontrol.SetValue( bDisabled != 1 );
|
r_shadows_gamecontrol.SetValue( bDisabled != 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
// Toggle shadow casting from world light sources
|
||||||
|
virtual void SetShadowFromWorldLightsEnabled( bool bEnable );
|
||||||
|
void SuppressShadowFromWorldLights( bool bSuppress );
|
||||||
|
bool IsShadowingFromWorldLights() const { return m_bShadowFromWorldLights && !m_bSuppressShadowFromWorldLights; }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -811,8 +846,16 @@ private:
|
|||||||
unsigned short m_Flags;
|
unsigned short m_Flags;
|
||||||
VMatrix m_WorldToShadow;
|
VMatrix m_WorldToShadow;
|
||||||
Vector2D m_WorldSize;
|
Vector2D m_WorldSize;
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
Vector m_ShadowDir;
|
||||||
|
#endif
|
||||||
Vector m_LastOrigin;
|
Vector m_LastOrigin;
|
||||||
QAngle m_LastAngles;
|
QAngle m_LastAngles;
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
Vector m_CurrentLightPos; // When shadowing from local lights, stores the position of the currently shadowing light
|
||||||
|
Vector m_TargetLightPos; // When shadowing from local lights, stores the position of the new shadowing light
|
||||||
|
float m_LightPosLerp; // Lerp progress when going from current to target light
|
||||||
|
#endif
|
||||||
TextureHandle_t m_ShadowTexture;
|
TextureHandle_t m_ShadowTexture;
|
||||||
CTextureReference m_ShadowDepthTexture;
|
CTextureReference m_ShadowDepthTexture;
|
||||||
int m_nRenderFrame;
|
int m_nRenderFrame;
|
||||||
@ -825,6 +868,11 @@ private:
|
|||||||
void UpdateBrushShadow( IClientRenderable *pRenderable, ClientShadowHandle_t handle );
|
void UpdateBrushShadow( IClientRenderable *pRenderable, ClientShadowHandle_t handle );
|
||||||
void UpdateShadow( ClientShadowHandle_t handle, bool force );
|
void UpdateShadow( ClientShadowHandle_t handle, bool force );
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
// Updates shadow cast direction when shadowing from world lights
|
||||||
|
void UpdateShadowDirectionFromLocalLightSource( ClientShadowHandle_t shadowHandle );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Gets the entity whose shadow this shadow will render into
|
// Gets the entity whose shadow this shadow will render into
|
||||||
IClientRenderable *GetParentShadowEntity( ClientShadowHandle_t handle );
|
IClientRenderable *GetParentShadowEntity( ClientShadowHandle_t handle );
|
||||||
|
|
||||||
@ -842,6 +890,10 @@ private:
|
|||||||
|
|
||||||
void BuildPerspectiveWorldToFlashlightMatrix( VMatrix& matWorldToShadow, const FlashlightState_t &flashlightState );
|
void BuildPerspectiveWorldToFlashlightMatrix( VMatrix& matWorldToShadow, const FlashlightState_t &flashlightState );
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
void BuildOrthoWorldToFlashlightMatrix( VMatrix& matWorldToShadow, const FlashlightState_t &flashlightState );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Update a shadow
|
// Update a shadow
|
||||||
void UpdateProjectedTextureInternal( ClientShadowHandle_t handle, bool force );
|
void UpdateProjectedTextureInternal( ClientShadowHandle_t handle, bool force );
|
||||||
|
|
||||||
@ -910,6 +962,9 @@ private:
|
|||||||
// Returns renderable-specific shadow info
|
// Returns renderable-specific shadow info
|
||||||
float GetShadowDistance( IClientRenderable *pRenderable ) const;
|
float GetShadowDistance( IClientRenderable *pRenderable ) const;
|
||||||
const Vector &GetShadowDirection( IClientRenderable *pRenderable ) const;
|
const Vector &GetShadowDirection( IClientRenderable *pRenderable ) const;
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
const Vector &GetShadowDirection( ClientShadowHandle_t shadowHandle ) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialize, shutdown render-to-texture shadows
|
// Initialize, shutdown render-to-texture shadows
|
||||||
void InitDepthTextureShadows();
|
void InitDepthTextureShadows();
|
||||||
@ -933,6 +988,11 @@ private:
|
|||||||
// Set and clear flashlight target renderable
|
// Set and clear flashlight target renderable
|
||||||
void SetFlashlightTarget( ClientShadowHandle_t shadowHandle, EHANDLE targetEntity );
|
void SetFlashlightTarget( ClientShadowHandle_t shadowHandle, EHANDLE targetEntity );
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
// Get current frustum extents
|
||||||
|
void GetFrustumExtents( ClientShadowHandle_t handle, Vector &vecMin, Vector &vecMax );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set flashlight light world flag
|
// Set flashlight light world flag
|
||||||
void SetFlashlightLightWorld( ClientShadowHandle_t shadowHandle, bool bLightWorld );
|
void SetFlashlightLightWorld( ClientShadowHandle_t shadowHandle, bool bLightWorld );
|
||||||
|
|
||||||
@ -941,9 +1001,18 @@ private:
|
|||||||
// Builds a list of active shadows requiring shadow depth renders
|
// Builds a list of active shadows requiring shadow depth renders
|
||||||
int BuildActiveShadowDepthList( const CViewSetup &viewSetup, int nMaxDepthShadows, ClientShadowHandle_t *pActiveDepthShadows );
|
int BuildActiveShadowDepthList( const CViewSetup &viewSetup, int nMaxDepthShadows, ClientShadowHandle_t *pActiveDepthShadows );
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
// Builds a list of active flashlights
|
||||||
|
int BuildActiveFlashlightList( const CViewSetup &viewSetup, int nMaxFlashlights, ClientShadowHandle_t *pActiveFlashlights );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Sets the view's active flashlight render state
|
// Sets the view's active flashlight render state
|
||||||
void SetViewFlashlightState( int nActiveFlashlightCount, ClientShadowHandle_t* pActiveFlashlights );
|
void SetViewFlashlightState( int nActiveFlashlightCount, ClientShadowHandle_t* pActiveFlashlights );
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
void UpdateDirtyShadow( ClientShadowHandle_t handle );
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector m_SimpleShadowDir;
|
Vector m_SimpleShadowDir;
|
||||||
color32 m_AmbientLightColor;
|
color32 m_AmbientLightColor;
|
||||||
@ -963,6 +1032,10 @@ private:
|
|||||||
CUtlRBTree< ClientShadowHandle_t, unsigned short > m_DirtyShadows;
|
CUtlRBTree< ClientShadowHandle_t, unsigned short > m_DirtyShadows;
|
||||||
CUtlVector< ClientShadowHandle_t > m_TransparentShadows;
|
CUtlVector< ClientShadowHandle_t > m_TransparentShadows;
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
int m_nPrevFrameCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
// These members maintain current state of depth texturing (size and global active state)
|
// These members maintain current state of depth texturing (size and global active state)
|
||||||
// If either changes in a frame, PreRender() will catch it and do the appropriate allocation, deallocation or reallocation
|
// If either changes in a frame, PreRender() will catch it and do the appropriate allocation, deallocation or reallocation
|
||||||
bool m_bDepthTextureActive;
|
bool m_bDepthTextureActive;
|
||||||
@ -972,6 +1045,11 @@ private:
|
|||||||
CUtlVector< bool > m_DepthTextureCacheLocks;
|
CUtlVector< bool > m_DepthTextureCacheLocks;
|
||||||
int m_nMaxDepthTextureShadows;
|
int m_nMaxDepthTextureShadows;
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
bool m_bShadowFromWorldLights;
|
||||||
|
bool m_bSuppressShadowFromWorldLights;
|
||||||
|
#endif
|
||||||
|
|
||||||
friend class CVisibleShadowList;
|
friend class CVisibleShadowList;
|
||||||
friend class CVisibleShadowFrustumList;
|
friend class CVisibleShadowFrustumList;
|
||||||
};
|
};
|
||||||
@ -1064,6 +1142,12 @@ void CVisibleShadowList::EnumShadow( unsigned short clientShadowHandle )
|
|||||||
if ( shadow.m_nRenderFrame == gpGlobals->framecount )
|
if ( shadow.m_nRenderFrame == gpGlobals->framecount )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
// Don't bother with flashlights
|
||||||
|
if ( ( shadow.m_Flags & SHADOW_FLAGS_FLASHLIGHT ) != 0 )
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
// We don't need to bother with it if it's not render-to-texture
|
// We don't need to bother with it if it's not render-to-texture
|
||||||
if ( s_ClientShadowMgr.GetActualShadowCastType( clientShadowHandle ) != SHADOWS_RENDER_TO_TEXTURE )
|
if ( s_ClientShadowMgr.GetActualShadowCastType( clientShadowHandle ) != SHADOWS_RENDER_TO_TEXTURE )
|
||||||
return;
|
return;
|
||||||
@ -1088,7 +1172,11 @@ void CVisibleShadowList::EnumShadow( unsigned short clientShadowHandle )
|
|||||||
|
|
||||||
// Compute a box surrounding the shadow
|
// Compute a box surrounding the shadow
|
||||||
Vector vecAbsMins, vecAbsMaxs;
|
Vector vecAbsMins, vecAbsMaxs;
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
s_ClientShadowMgr.ComputeShadowBBox( pRenderable, shadow.m_ShadowHandle, vecAbsCenter, flRadius, &vecAbsMins, &vecAbsMaxs );
|
||||||
|
#else
|
||||||
s_ClientShadowMgr.ComputeShadowBBox( pRenderable, vecAbsCenter, flRadius, &vecAbsMins, &vecAbsMaxs );
|
s_ClientShadowMgr.ComputeShadowBBox( pRenderable, vecAbsCenter, flRadius, &vecAbsMins, &vecAbsMaxs );
|
||||||
|
#endif
|
||||||
|
|
||||||
// FIXME: Add distance check here?
|
// FIXME: Add distance check here?
|
||||||
|
|
||||||
@ -1167,8 +1255,19 @@ int CVisibleShadowList::FindShadows( const CViewSetup *pView, int nLeafCount, Le
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CClientShadowMgr::CClientShadowMgr() :
|
CClientShadowMgr::CClientShadowMgr() :
|
||||||
m_DirtyShadows( 0, 0, ShadowHandleCompareFunc ),
|
m_DirtyShadows( 0, 0, ShadowHandleCompareFunc ),
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
m_nPrevFrameCount( -1 ),
|
||||||
|
#endif
|
||||||
m_RenderToTextureActive( false ),
|
m_RenderToTextureActive( false ),
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
m_bDepthTextureActive( false ),
|
||||||
|
#else
|
||||||
m_bDepthTextureActive( false )
|
m_bDepthTextureActive( false )
|
||||||
|
#endif
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
m_bShadowFromWorldLights( false ),
|
||||||
|
m_bSuppressShadowFromWorldLights( false )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
m_nDepthTextureResolution = r_flashlightdepthres.GetInt();
|
m_nDepthTextureResolution = r_flashlightdepthres.GetInt();
|
||||||
m_bThreaded = false;
|
m_bThreaded = false;
|
||||||
@ -1271,6 +1370,15 @@ CON_COMMAND_F( r_shadowblobbycutoff, "some shadow stuff", FCVAR_CHEAT )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
void OnShadowFromWorldLights( IConVar *var, const char *pOldValue, float flOldValue );
|
||||||
|
static ConVar r_shadowfromworldlights( "r_shadowfromworldlights", "1", FCVAR_NONE, "Enable shadowing from world lights", OnShadowFromWorldLights );
|
||||||
|
void OnShadowFromWorldLights( IConVar *var, const char *pOldValue, float flOldValue )
|
||||||
|
{
|
||||||
|
s_ClientShadowMgr.SuppressShadowFromWorldLights( !r_shadowfromworldlights.GetBool() );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void ShadowRestoreFunc( int nChangeFlags )
|
static void ShadowRestoreFunc( int nChangeFlags )
|
||||||
{
|
{
|
||||||
s_ClientShadowMgr.RestoreRenderState();
|
s_ClientShadowMgr.RestoreRenderState();
|
||||||
@ -1290,8 +1398,14 @@ bool CClientShadowMgr::Init()
|
|||||||
|
|
||||||
SetShadowBlobbyCutoffArea( 0.005 );
|
SetShadowBlobbyCutoffArea( 0.005 );
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
bool bTools = CommandLine()->CheckParm( "-tools" ) != NULL;
|
bool bTools = CommandLine()->CheckParm( "-tools" ) != NULL;
|
||||||
m_nMaxDepthTextureShadows = bTools ? 4 : 1; // Just one shadow depth texture in games, more in tools
|
m_nMaxDepthTextureShadows = bTools ? 4 : 1; // Just one shadow depth texture in games, more in tools
|
||||||
|
#else
|
||||||
|
// 5 lets mappers use up to 4 shadow-casting projected textures, which is better than 3.
|
||||||
|
int iNumShadows = CommandLine()->ParmValue( "-numshadowtextures", 5 );
|
||||||
|
m_nMaxDepthTextureShadows = iNumShadows;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool bLowEnd = ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 );
|
bool bLowEnd = ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 );
|
||||||
|
|
||||||
@ -1336,6 +1450,14 @@ void CClientShadowMgr::InitDepthTextureShadows()
|
|||||||
{
|
{
|
||||||
VPROF_BUDGET( "CClientShadowMgr::InitDepthTextureShadows", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
|
VPROF_BUDGET( "CClientShadowMgr::InitDepthTextureShadows", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
|
||||||
|
|
||||||
|
#if defined(MAPBASE) //&& !defined(ASW_PROJECTED_TEXTURES)
|
||||||
|
// SAUL: start benchmark timer
|
||||||
|
//CFastTimer timer;
|
||||||
|
//timer.Start();
|
||||||
|
// SAUL: set m_nDepthTextureResolution to the depth resolution we want
|
||||||
|
m_nDepthTextureResolution = r_flashlightdepthres.GetInt();
|
||||||
|
#endif
|
||||||
|
|
||||||
if( !m_bDepthTextureActive )
|
if( !m_bDepthTextureActive )
|
||||||
{
|
{
|
||||||
m_bDepthTextureActive = true;
|
m_bDepthTextureActive = true;
|
||||||
@ -1351,8 +1473,13 @@ void CClientShadowMgr::InitDepthTextureShadows()
|
|||||||
// only need the dummy surface, don't care about color results
|
// only need the dummy surface, don't care about color results
|
||||||
m_DummyColorTexture.InitRenderTargetTexture( r_flashlightdepthres.GetInt(), r_flashlightdepthres.GetInt(), RT_SIZE_OFFSCREEN, IMAGE_FORMAT_BGR565, MATERIAL_RT_DEPTH_SHARED, false, "_rt_ShadowDummy" );
|
m_DummyColorTexture.InitRenderTargetTexture( r_flashlightdepthres.GetInt(), r_flashlightdepthres.GetInt(), RT_SIZE_OFFSCREEN, IMAGE_FORMAT_BGR565, MATERIAL_RT_DEPTH_SHARED, false, "_rt_ShadowDummy" );
|
||||||
m_DummyColorTexture.InitRenderTargetSurface( r_flashlightdepthres.GetInt(), r_flashlightdepthres.GetInt(), IMAGE_FORMAT_BGR565, true );
|
m_DummyColorTexture.InitRenderTargetSurface( r_flashlightdepthres.GetInt(), r_flashlightdepthres.GetInt(), IMAGE_FORMAT_BGR565, true );
|
||||||
|
#else
|
||||||
|
#if defined(MAPBASE) //&& !defined(ASW_PROJECTED_TEXTURES)
|
||||||
|
// SAUL: we want to create a render target of specific size, so use RT_SIZE_NO_CHANGE
|
||||||
|
m_DummyColorTexture.InitRenderTarget( m_nDepthTextureResolution, m_nDepthTextureResolution, RT_SIZE_NO_CHANGE, nullFormat, MATERIAL_RT_DEPTH_NONE, false, "_rt_ShadowDummy" );
|
||||||
#else
|
#else
|
||||||
m_DummyColorTexture.InitRenderTarget( r_flashlightdepthres.GetInt(), r_flashlightdepthres.GetInt(), RT_SIZE_OFFSCREEN, nullFormat, MATERIAL_RT_DEPTH_NONE, false, "_rt_ShadowDummy" );
|
m_DummyColorTexture.InitRenderTarget( r_flashlightdepthres.GetInt(), r_flashlightdepthres.GetInt(), RT_SIZE_OFFSCREEN, nullFormat, MATERIAL_RT_DEPTH_NONE, false, "_rt_ShadowDummy" );
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Create some number of depth-stencil textures
|
// Create some number of depth-stencil textures
|
||||||
@ -1371,9 +1498,19 @@ void CClientShadowMgr::InitDepthTextureShadows()
|
|||||||
// surface is effectively never used
|
// surface is effectively never used
|
||||||
depthTex.InitRenderTargetTexture( m_nDepthTextureResolution, m_nDepthTextureResolution, RT_SIZE_OFFSCREEN, dstFormat, MATERIAL_RT_DEPTH_NONE, false, strRTName );
|
depthTex.InitRenderTargetTexture( m_nDepthTextureResolution, m_nDepthTextureResolution, RT_SIZE_OFFSCREEN, dstFormat, MATERIAL_RT_DEPTH_NONE, false, strRTName );
|
||||||
depthTex.InitRenderTargetSurface( 1, 1, dstFormat, false );
|
depthTex.InitRenderTargetSurface( 1, 1, dstFormat, false );
|
||||||
|
#else
|
||||||
|
#if defined(MAPBASE) //&& !defined(ASW_PROJECTED_TEXTURES)
|
||||||
|
// SAUL: we want to create a *DEPTH TEXTURE* of specific size, so use RT_SIZE_NO_CHANGE and MATERIAL_RT_DEPTH_ONLY
|
||||||
|
depthTex.InitRenderTarget( m_nDepthTextureResolution, m_nDepthTextureResolution, RT_SIZE_NO_CHANGE, dstFormat, MATERIAL_RT_DEPTH_ONLY, false, strRTName );
|
||||||
#else
|
#else
|
||||||
depthTex.InitRenderTarget( m_nDepthTextureResolution, m_nDepthTextureResolution, RT_SIZE_OFFSCREEN, dstFormat, MATERIAL_RT_DEPTH_NONE, false, strRTName );
|
depthTex.InitRenderTarget( m_nDepthTextureResolution, m_nDepthTextureResolution, RT_SIZE_OFFSCREEN, dstFormat, MATERIAL_RT_DEPTH_NONE, false, strRTName );
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MAPBASE) //&& !defined(ASW_PROJECTED_TEXTURES)
|
||||||
|
// SAUL: ensure the depth texture size wasn't changed
|
||||||
|
Assert(depthTex->GetActualWidth() == m_nDepthTextureResolution);
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( i == 0 )
|
if ( i == 0 )
|
||||||
{
|
{
|
||||||
@ -1388,6 +1525,11 @@ void CClientShadowMgr::InitDepthTextureShadows()
|
|||||||
|
|
||||||
materials->EndRenderTargetAllocation();
|
materials->EndRenderTargetAllocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MAPBASE) && !defined(ASW_PROJECTED_TEXTURES)
|
||||||
|
//timer.End();
|
||||||
|
//DevMsg("InitDepthTextureShadows took %.2f msec\n", timer.GetDuration().GetMillisecondsF());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClientShadowMgr::ShutdownDepthTextureShadows()
|
void CClientShadowMgr::ShutdownDepthTextureShadows()
|
||||||
@ -1514,6 +1656,15 @@ void CClientShadowMgr::LevelInitPreEntity()
|
|||||||
{
|
{
|
||||||
m_bUpdatingDirtyShadows = false;
|
m_bUpdatingDirtyShadows = false;
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
// Default setting for this, can be overridden by shadow control entities
|
||||||
|
#ifdef MAPBASE
|
||||||
|
SetShadowFromWorldLightsEnabled( false );
|
||||||
|
#else
|
||||||
|
SetShadowFromWorldLightsEnabled( true );
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
Vector ambientColor;
|
Vector ambientColor;
|
||||||
engine->GetAmbientLightColor( ambientColor );
|
engine->GetAmbientLightColor( ambientColor );
|
||||||
ambientColor *= 3;
|
ambientColor *= 3;
|
||||||
@ -1698,6 +1849,158 @@ const Vector &CClientShadowMgr::GetShadowDirection( IClientRenderable *pRenderab
|
|||||||
return vecResult;
|
return vecResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
const Vector &CClientShadowMgr::GetShadowDirection( ClientShadowHandle_t shadowHandle ) const
|
||||||
|
{
|
||||||
|
Assert( shadowHandle != CLIENTSHADOW_INVALID_HANDLE );
|
||||||
|
|
||||||
|
IClientRenderable* pRenderable = ClientEntityList().GetClientRenderableFromHandle( m_Shadows[shadowHandle].m_Entity );
|
||||||
|
Assert( pRenderable );
|
||||||
|
|
||||||
|
if ( !IsShadowingFromWorldLights() )
|
||||||
|
{
|
||||||
|
return GetShadowDirection( pRenderable );
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector &vecResult = AllocTempVector();
|
||||||
|
vecResult = m_Shadows[shadowHandle].m_ShadowDir;
|
||||||
|
|
||||||
|
// Allow the renderable to override the default
|
||||||
|
pRenderable->GetShadowCastDirection( &vecResult, GetActualShadowCastType( pRenderable ) );
|
||||||
|
|
||||||
|
return vecResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClientShadowMgr::UpdateShadowDirectionFromLocalLightSource( ClientShadowHandle_t shadowHandle )
|
||||||
|
{
|
||||||
|
Assert( shadowHandle != CLIENTSHADOW_INVALID_HANDLE );
|
||||||
|
|
||||||
|
ClientShadow_t& shadow = m_Shadows[shadowHandle];
|
||||||
|
|
||||||
|
IClientRenderable* pRenderable = ClientEntityList().GetClientRenderableFromHandle( shadow.m_Entity );
|
||||||
|
|
||||||
|
// TODO: Figure out why this still gets hit
|
||||||
|
Assert( pRenderable );
|
||||||
|
if ( !pRenderable )
|
||||||
|
{
|
||||||
|
DevWarning( "%s(): Skipping shadow with invalid client renderable (shadow handle %d)\n", __FUNCTION__, shadowHandle );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector bbMin, bbMax;
|
||||||
|
pRenderable->GetRenderBoundsWorldspace( bbMin, bbMax );
|
||||||
|
Vector origin( 0.5f * ( bbMin + bbMax ) );
|
||||||
|
origin.z = bbMin.z; // Putting origin at the bottom of the bounding box makes the shadows a little shorter
|
||||||
|
|
||||||
|
Vector lightPos;
|
||||||
|
Vector lightBrightness;
|
||||||
|
|
||||||
|
if ( shadow.m_LightPosLerp >= 1.0f ) // skip finding new light source if we're in the middle of a lerp
|
||||||
|
{
|
||||||
|
// Calculate minimum brightness squared
|
||||||
|
float flMinBrightnessSqr = r_shadow_mincastintensity.GetFloat();
|
||||||
|
flMinBrightnessSqr *= flMinBrightnessSqr;
|
||||||
|
|
||||||
|
if(g_pWorldLights->GetBrightestLightSource(pRenderable->GetRenderOrigin(), lightPos, lightBrightness) == false ||
|
||||||
|
lightBrightness.LengthSqr() < flMinBrightnessSqr )
|
||||||
|
{
|
||||||
|
// didn't find a light source at all, use default shadow direction
|
||||||
|
// TODO: Could switch to using blobby shadow in this case
|
||||||
|
lightPos.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( shadow.m_LightPosLerp == FLT_MAX ) // first light pos ever, just init
|
||||||
|
{
|
||||||
|
shadow.m_CurrentLightPos = lightPos;
|
||||||
|
shadow.m_TargetLightPos = lightPos;
|
||||||
|
shadow.m_LightPosLerp = 1.0f;
|
||||||
|
}
|
||||||
|
else if ( shadow.m_LightPosLerp < 1.0f )
|
||||||
|
{
|
||||||
|
// We're in the middle of a lerp from current to target light. Finish it.
|
||||||
|
shadow.m_LightPosLerp += gpGlobals->frametime * 1.0f/r_shadow_lightpos_lerptime.GetFloat();
|
||||||
|
shadow.m_LightPosLerp = clamp( shadow.m_LightPosLerp, 0.0f, 1.0f );
|
||||||
|
|
||||||
|
Vector currLightPos( shadow.m_CurrentLightPos );
|
||||||
|
Vector targetLightPos( shadow.m_TargetLightPos );
|
||||||
|
if ( currLightPos.x == FLT_MAX )
|
||||||
|
{
|
||||||
|
currLightPos = origin - 200.0f * GetShadowDirection();
|
||||||
|
}
|
||||||
|
if ( targetLightPos.x == FLT_MAX )
|
||||||
|
{
|
||||||
|
targetLightPos = origin - 200.0f * GetShadowDirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// lerp light pos
|
||||||
|
Vector v1 = origin - shadow.m_CurrentLightPos;
|
||||||
|
v1.NormalizeInPlace();
|
||||||
|
|
||||||
|
Vector v2 = origin - shadow.m_TargetLightPos;
|
||||||
|
v2.NormalizeInPlace();
|
||||||
|
|
||||||
|
// SAULUNDONE: caused over top sweeping far too often
|
||||||
|
#if 0
|
||||||
|
if ( v1.Dot( v2 ) < 0.0f )
|
||||||
|
{
|
||||||
|
// if change in shadow angle is more than 90 degrees, lerp over the renderable's top to avoid long sweeping shadows
|
||||||
|
Vector fakeOverheadLightPos( origin.x, origin.y, origin.z + 200.0f );
|
||||||
|
if( shadow.m_LightPosLerp < 0.5f )
|
||||||
|
{
|
||||||
|
lightPos = Lerp( 2.0f * shadow.m_LightPosLerp, currLightPos, fakeOverheadLightPos );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lightPos = Lerp( 2.0f * shadow.m_LightPosLerp - 1.0f, fakeOverheadLightPos, targetLightPos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
lightPos = Lerp( shadow.m_LightPosLerp, currLightPos, targetLightPos );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( shadow.m_LightPosLerp >= 1.0f )
|
||||||
|
{
|
||||||
|
shadow.m_CurrentLightPos = shadow.m_TargetLightPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( shadow.m_LightPosLerp >= 1.0f )
|
||||||
|
{
|
||||||
|
// check if we have a new closest light position and start a new lerp
|
||||||
|
float flDistSq = ( lightPos - shadow.m_CurrentLightPos ).LengthSqr();
|
||||||
|
|
||||||
|
if ( flDistSq > 1.0f )
|
||||||
|
{
|
||||||
|
// light position has changed, which means we got a new light source. Initiate a lerp
|
||||||
|
shadow.m_TargetLightPos = lightPos;
|
||||||
|
shadow.m_LightPosLerp = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
lightPos = shadow.m_CurrentLightPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( lightPos.x == FLT_MAX )
|
||||||
|
{
|
||||||
|
lightPos = origin - 200.0f * GetShadowDirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector vecResult( origin - lightPos );
|
||||||
|
vecResult.NormalizeInPlace();
|
||||||
|
|
||||||
|
vecResult.z *= r_shadow_shortenfactor.GetFloat();
|
||||||
|
vecResult.NormalizeInPlace();
|
||||||
|
|
||||||
|
shadow.m_ShadowDir = vecResult;
|
||||||
|
|
||||||
|
if ( r_shadowfromworldlights_debug.GetBool() )
|
||||||
|
{
|
||||||
|
NDebugOverlay::Line( lightPos, origin, 255, 255, 0, false, 0.0f );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Sets the shadow distance
|
// Sets the shadow distance
|
||||||
@ -1815,6 +2118,12 @@ ClientShadowHandle_t CClientShadowMgr::CreateProjectedTexture( ClientEntityHandl
|
|||||||
shadow.m_ClientLeafShadowHandle = ClientLeafSystem()->AddShadow( h, flags );
|
shadow.m_ClientLeafShadowHandle = ClientLeafSystem()->AddShadow( h, flags );
|
||||||
shadow.m_Flags = flags;
|
shadow.m_Flags = flags;
|
||||||
shadow.m_nRenderFrame = -1;
|
shadow.m_nRenderFrame = -1;
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
shadow.m_ShadowDir = GetShadowDirection();
|
||||||
|
shadow.m_CurrentLightPos.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
||||||
|
shadow.m_TargetLightPos.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
||||||
|
shadow.m_LightPosLerp = FLT_MAX;
|
||||||
|
#endif
|
||||||
shadow.m_LastOrigin.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
shadow.m_LastOrigin.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
||||||
shadow.m_LastAngles.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
shadow.m_LastAngles.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
||||||
Assert( ( ( shadow.m_Flags & SHADOW_FLAGS_FLASHLIGHT ) == 0 ) !=
|
Assert( ( ( shadow.m_Flags & SHADOW_FLAGS_FLASHLIGHT ) == 0 ) !=
|
||||||
@ -1834,12 +2143,21 @@ ClientShadowHandle_t CClientShadowMgr::CreateProjectedTexture( ClientEntityHandl
|
|||||||
pShadowProxyData = (void*)(uintp)h;
|
pShadowProxyData = (void*)(uintp)h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
if( ( flags & SHADOW_FLAGS_USE_DEPTH_TEXTURE ) || ( flags & ( SHADOW_FLAGS_FLASHLIGHT ) ) )
|
||||||
|
{
|
||||||
|
pShadowMaterial = NULL; // these materials aren't used for shadow depth texture shadows.
|
||||||
|
pShadowModelMaterial = NULL;
|
||||||
|
pShadowProxyData = (void*)h;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if( flags & SHADOW_FLAGS_USE_DEPTH_TEXTURE )
|
if( flags & SHADOW_FLAGS_USE_DEPTH_TEXTURE )
|
||||||
{
|
{
|
||||||
pShadowMaterial = m_RenderShadow;
|
pShadowMaterial = m_RenderShadow;
|
||||||
pShadowModelMaterial = m_RenderModelShadow;
|
pShadowModelMaterial = m_RenderModelShadow;
|
||||||
pShadowProxyData = (void*)(uintp)h;
|
pShadowProxyData = (void*)(uintp)h;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int createShadowFlags;
|
int createShadowFlags;
|
||||||
if( flags & SHADOW_FLAGS_FLASHLIGHT )
|
if( flags & SHADOW_FLAGS_FLASHLIGHT )
|
||||||
@ -1902,7 +2220,27 @@ void CClientShadowMgr::UpdateFlashlightState( ClientShadowHandle_t shadowHandle,
|
|||||||
{
|
{
|
||||||
VPROF_BUDGET( "CClientShadowMgr::UpdateFlashlightState", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
|
VPROF_BUDGET( "CClientShadowMgr::UpdateFlashlightState", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
if( flashlightState.m_bEnableShadows && r_flashlightdepthtexture.GetBool() )
|
||||||
|
{
|
||||||
|
m_Shadows[shadowHandle].m_Flags |= SHADOW_FLAGS_USE_DEPTH_TEXTURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Shadows[shadowHandle].m_Flags &= ~SHADOW_FLAGS_USE_DEPTH_TEXTURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( flashlightState.m_bOrtho )
|
||||||
|
{
|
||||||
|
BuildOrthoWorldToFlashlightMatrix( m_Shadows[shadowHandle].m_WorldToShadow, flashlightState );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
BuildPerspectiveWorldToFlashlightMatrix( m_Shadows[shadowHandle].m_WorldToShadow, flashlightState );
|
BuildPerspectiveWorldToFlashlightMatrix( m_Shadows[shadowHandle].m_WorldToShadow, flashlightState );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
BuildPerspectiveWorldToFlashlightMatrix( m_Shadows[shadowHandle].m_WorldToShadow, flashlightState );
|
||||||
|
#endif
|
||||||
|
|
||||||
shadowmgr->UpdateFlashlightState( m_Shadows[shadowHandle].m_ShadowHandle, flashlightState );
|
shadowmgr->UpdateFlashlightState( m_Shadows[shadowHandle].m_ShadowHandle, flashlightState );
|
||||||
}
|
}
|
||||||
@ -2013,6 +2351,40 @@ void CClientShadowMgr::BuildPerspectiveWorldToFlashlightMatrix( VMatrix& matWorl
|
|||||||
MatrixMultiply( matPerspective, matWorldToShadowView, matWorldToShadow );
|
MatrixMultiply( matPerspective, matWorldToShadowView, matWorldToShadow );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
void CClientShadowMgr::BuildOrthoWorldToFlashlightMatrix( VMatrix& matWorldToShadow, const FlashlightState_t &flashlightState )
|
||||||
|
{
|
||||||
|
VPROF_BUDGET( "CClientShadowMgr::BuildPerspectiveWorldToFlashlightMatrix", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
|
||||||
|
|
||||||
|
// Buildworld to shadow matrix, then perspective projection and concatenate
|
||||||
|
VMatrix matWorldToShadowView, matPerspective;
|
||||||
|
BuildWorldToShadowMatrix( matWorldToShadowView, flashlightState.m_vecLightOrigin,
|
||||||
|
flashlightState.m_quatOrientation );
|
||||||
|
|
||||||
|
MatrixBuildOrtho( matPerspective,
|
||||||
|
flashlightState.m_fOrthoLeft, flashlightState.m_fOrthoTop, flashlightState.m_fOrthoRight, flashlightState.m_fOrthoBottom,
|
||||||
|
flashlightState.m_NearZ, flashlightState.m_FarZ );
|
||||||
|
|
||||||
|
// Shift it z/y to 0 to -2 space
|
||||||
|
VMatrix addW;
|
||||||
|
addW.Identity();
|
||||||
|
addW[0][3] = -1.0f;
|
||||||
|
addW[1][3] = -1.0f;
|
||||||
|
addW[2][3] = 0.0f;
|
||||||
|
MatrixMultiply( addW, matPerspective, matPerspective );
|
||||||
|
|
||||||
|
// Flip x/y to positive 0 to 1... flip z to negative
|
||||||
|
VMatrix scaleHalf;
|
||||||
|
scaleHalf.Identity();
|
||||||
|
scaleHalf[0][0] = -0.5f;
|
||||||
|
scaleHalf[1][1] = -0.5f;
|
||||||
|
scaleHalf[2][2] = -1.0f;
|
||||||
|
MatrixMultiply( scaleHalf, matPerspective, matPerspective );
|
||||||
|
|
||||||
|
MatrixMultiply( matPerspective, matWorldToShadowView, matWorldToShadow );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Compute the shadow origin and attenuation start distance
|
// Compute the shadow origin and attenuation start distance
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2286,7 +2658,11 @@ void CClientShadowMgr::BuildOrthoShadow( IClientRenderable* pRenderable,
|
|||||||
AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] );
|
AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] );
|
||||||
vec[1] *= -1.0f;
|
vec[1] *= -1.0f;
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
Vector vecShadowDir = GetShadowDirection( handle );
|
||||||
|
#else
|
||||||
Vector vecShadowDir = GetShadowDirection( pRenderable );
|
Vector vecShadowDir = GetShadowDirection( pRenderable );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Project the shadow casting direction into the space of the object
|
// Project the shadow casting direction into the space of the object
|
||||||
Vector localShadowDir;
|
Vector localShadowDir;
|
||||||
@ -2372,7 +2748,11 @@ void CClientShadowMgr::BuildOrthoShadow( IClientRenderable* pRenderable,
|
|||||||
|
|
||||||
// Compute extra clip planes to prevent poke-thru
|
// Compute extra clip planes to prevent poke-thru
|
||||||
// FIXME!!!!!!!!!!!!!! Removing this for now since it seems to mess up the blobby shadows.
|
// FIXME!!!!!!!!!!!!!! Removing this for now since it seems to mess up the blobby shadows.
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
ComputeExtraClipPlanes( pRenderable, handle, vec, mins, maxs, localShadowDir );
|
||||||
|
#else
|
||||||
// ComputeExtraClipPlanes( pEnt, handle, vec, mins, maxs, localShadowDir );
|
// ComputeExtraClipPlanes( pEnt, handle, vec, mins, maxs, localShadowDir );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Add the shadow to the client leaf system so it correctly marks
|
// Add the shadow to the client leaf system so it correctly marks
|
||||||
// leafs as being affected by a particular shadow
|
// leafs as being affected by a particular shadow
|
||||||
@ -2469,7 +2849,11 @@ void CClientShadowMgr::BuildRenderToTextureShadow( IClientRenderable* pRenderabl
|
|||||||
AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] );
|
AngleVectors( pRenderable->GetRenderAngles(), &vec[0], &vec[1], &vec[2] );
|
||||||
vec[1] *= -1.0f;
|
vec[1] *= -1.0f;
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
Vector vecShadowDir = GetShadowDirection( handle );
|
||||||
|
#else
|
||||||
Vector vecShadowDir = GetShadowDirection( pRenderable );
|
Vector vecShadowDir = GetShadowDirection( pRenderable );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Debugging aid
|
// Debugging aid
|
||||||
// const model_t *pModel = pRenderable->GetModel();
|
// const model_t *pModel = pRenderable->GetModel();
|
||||||
@ -2861,6 +3245,12 @@ bool CClientShadowMgr::ShouldUseParentShadow( IClientRenderable *pRenderable )
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CClientShadowMgr::PreRender()
|
void CClientShadowMgr::PreRender()
|
||||||
{
|
{
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
// only update shadows once per frame
|
||||||
|
Assert( gpGlobals->framecount != m_nPrevFrameCount );
|
||||||
|
m_nPrevFrameCount = gpGlobals->framecount;
|
||||||
|
#endif
|
||||||
|
|
||||||
VPROF_BUDGET( "CClientShadowMgr::PreRender", VPROF_BUDGETGROUP_SHADOW_RENDERING );
|
VPROF_BUDGET( "CClientShadowMgr::PreRender", VPROF_BUDGETGROUP_SHADOW_RENDERING );
|
||||||
MDLCACHE_CRITICAL_SECTION();
|
MDLCACHE_CRITICAL_SECTION();
|
||||||
|
|
||||||
@ -2933,8 +3323,12 @@ void CClientShadowMgr::PreRender()
|
|||||||
{
|
{
|
||||||
MDLCACHE_CRITICAL_SECTION();
|
MDLCACHE_CRITICAL_SECTION();
|
||||||
ClientShadowHandle_t& handle = m_DirtyShadows[ i ];
|
ClientShadowHandle_t& handle = m_DirtyShadows[ i ];
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
UpdateDirtyShadow(handle);
|
||||||
|
#else
|
||||||
Assert( m_Shadows.IsValidIndex( handle ) );
|
Assert( m_Shadows.IsValidIndex( handle ) );
|
||||||
UpdateProjectedTextureInternal( handle, false );
|
UpdateProjectedTextureInternal( handle, false );
|
||||||
|
#endif
|
||||||
i = m_DirtyShadows.NextInorder(i);
|
i = m_DirtyShadows.NextInorder(i);
|
||||||
}
|
}
|
||||||
m_DirtyShadows.RemoveAll();
|
m_DirtyShadows.RemoveAll();
|
||||||
@ -2950,6 +3344,20 @@ void CClientShadowMgr::PreRender()
|
|||||||
m_bUpdatingDirtyShadows = false;
|
m_bUpdatingDirtyShadows = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Updates a single dirty shadow
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CClientShadowMgr::UpdateDirtyShadow( ClientShadowHandle_t handle )
|
||||||
|
{
|
||||||
|
Assert( m_Shadows.IsValidIndex( handle ) );
|
||||||
|
if ( IsShadowingFromWorldLights() )
|
||||||
|
{
|
||||||
|
UpdateShadowDirectionFromLocalLightSource( handle );
|
||||||
|
}
|
||||||
|
UpdateProjectedTextureInternal( handle, false );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Gets the entity whose shadow this shadow will render into
|
// Gets the entity whose shadow this shadow will render into
|
||||||
@ -3124,7 +3532,11 @@ void CClientShadowMgr::UpdateShadow( ClientShadowHandle_t handle, bool force )
|
|||||||
const Vector& origin = pRenderable->GetRenderOrigin();
|
const Vector& origin = pRenderable->GetRenderOrigin();
|
||||||
const QAngle& angles = pRenderable->GetRenderAngles();
|
const QAngle& angles = pRenderable->GetRenderAngles();
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
if (force || (origin != shadow.m_LastOrigin) || (angles != shadow.m_LastAngles) || shadow.m_LightPosLerp < 1.0f)
|
||||||
|
#else
|
||||||
if (force || (origin != shadow.m_LastOrigin) || (angles != shadow.m_LastAngles))
|
if (force || (origin != shadow.m_LastOrigin) || (angles != shadow.m_LastAngles))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// Store off the new pos/orientation
|
// Store off the new pos/orientation
|
||||||
VectorCopy( origin, shadow.m_LastOrigin );
|
VectorCopy( origin, shadow.m_LastOrigin );
|
||||||
@ -3243,12 +3655,20 @@ void CClientShadowMgr::ComputeBoundingSphere( IClientRenderable* pRenderable, Ve
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Computes a rough AABB encompassing the volume of the shadow
|
// Computes a rough AABB encompassing the volume of the shadow
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
void CClientShadowMgr::ComputeShadowBBox( IClientRenderable *pRenderable, ClientShadowHandle_t shadowHandle, const Vector &vecAbsCenter, float flRadius, Vector *pAbsMins, Vector *pAbsMaxs )
|
||||||
|
#else
|
||||||
void CClientShadowMgr::ComputeShadowBBox( IClientRenderable *pRenderable, const Vector &vecAbsCenter, float flRadius, Vector *pAbsMins, Vector *pAbsMaxs )
|
void CClientShadowMgr::ComputeShadowBBox( IClientRenderable *pRenderable, const Vector &vecAbsCenter, float flRadius, Vector *pAbsMins, Vector *pAbsMaxs )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// This is *really* rough. Basically we simply determine the
|
// This is *really* rough. Basically we simply determine the
|
||||||
// maximum shadow casting length and extrude the box by that distance
|
// maximum shadow casting length and extrude the box by that distance
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
Vector vecShadowDir = GetShadowDirection( shadowHandle );
|
||||||
|
#else
|
||||||
Vector vecShadowDir = GetShadowDirection( pRenderable );
|
Vector vecShadowDir = GetShadowDirection( pRenderable );
|
||||||
|
#endif
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
float flShadowCastDistance = GetShadowDistance( pRenderable );
|
float flShadowCastDistance = GetShadowDistance( pRenderable );
|
||||||
@ -3346,7 +3766,11 @@ bool CClientShadowMgr::CullReceiver( ClientShadowHandle_t handle, IClientRendera
|
|||||||
if (foundSeparatingPlane)
|
if (foundSeparatingPlane)
|
||||||
{
|
{
|
||||||
// Compute which side of the plane the renderable is on..
|
// Compute which side of the plane the renderable is on..
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
Vector vecShadowDir = GetShadowDirection( handle );
|
||||||
|
#else
|
||||||
Vector vecShadowDir = GetShadowDirection( pSourceRenderable );
|
Vector vecShadowDir = GetShadowDirection( pSourceRenderable );
|
||||||
|
#endif
|
||||||
float shadowDot = DotProduct( vecShadowDir, plane.normal );
|
float shadowDot = DotProduct( vecShadowDir, plane.normal );
|
||||||
float receiverDot = DotProduct( plane.normal, origin );
|
float receiverDot = DotProduct( plane.normal, origin );
|
||||||
float sourceDot = DotProduct( plane.normal, originSource );
|
float sourceDot = DotProduct( plane.normal, originSource );
|
||||||
@ -3833,6 +4257,11 @@ void CClientShadowMgr::AdvanceFrame()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int CClientShadowMgr::BuildActiveShadowDepthList( const CViewSetup &viewSetup, int nMaxDepthShadows, ClientShadowHandle_t *pActiveDepthShadows )
|
int CClientShadowMgr::BuildActiveShadowDepthList( const CViewSetup &viewSetup, int nMaxDepthShadows, ClientShadowHandle_t *pActiveDepthShadows )
|
||||||
{
|
{
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
Frustum_t viewFrustum;
|
||||||
|
GeneratePerspectiveFrustum( viewSetup.origin, viewSetup.angles, viewSetup.zNear, viewSetup.zFar, viewSetup.fov, viewSetup.m_flAspectRatio, viewFrustum );
|
||||||
|
#endif
|
||||||
|
|
||||||
int nActiveDepthShadowCount = 0;
|
int nActiveDepthShadowCount = 0;
|
||||||
for ( ClientShadowHandle_t i = m_Shadows.Head(); i != m_Shadows.InvalidIndex(); i = m_Shadows.Next(i) )
|
for ( ClientShadowHandle_t i = m_Shadows.Head(); i != m_Shadows.InvalidIndex(); i = m_Shadows.Next(i) )
|
||||||
{
|
{
|
||||||
@ -3857,7 +4286,13 @@ int CClientShadowMgr::BuildActiveShadowDepthList( const CViewSetup &viewSetup, i
|
|||||||
|
|
||||||
// FIXME: Could do other sorts of culling here, such as frustum-frustum test, distance etc.
|
// FIXME: Could do other sorts of culling here, such as frustum-frustum test, distance etc.
|
||||||
// If it's not in the view frustum, move on
|
// If it's not in the view frustum, move on
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( !flashlightState.m_bAlwaysDraw && !flashlightState.m_bOrtho && R_CullBox( vecAbsMins, vecAbsMaxs, viewFrustum ) )
|
||||||
|
#elif ASW_PROJECTED_TEXTURES
|
||||||
|
if ( !flashlightState.m_bOrtho && R_CullBox( vecAbsMins, vecAbsMaxs, viewFrustum ) )
|
||||||
|
#else
|
||||||
if ( R_CullBox( vecAbsMins, vecAbsMaxs, viewFrustum ) )
|
if ( R_CullBox( vecAbsMins, vecAbsMaxs, viewFrustum ) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
shadowmgr->SetFlashlightDepthTexture( shadow.m_ShadowHandle, NULL, 0 );
|
shadowmgr->SetFlashlightDepthTexture( shadow.m_ShadowHandle, NULL, 0 );
|
||||||
continue;
|
continue;
|
||||||
@ -3882,6 +4317,53 @@ int CClientShadowMgr::BuildActiveShadowDepthList( const CViewSetup &viewSetup, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Re-render shadow depth textures that lie in the leaf list
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int CClientShadowMgr::BuildActiveFlashlightList( const CViewSetup &viewSetup, int nMaxFlashlights, ClientShadowHandle_t *pActiveFlashlights )
|
||||||
|
{
|
||||||
|
int nActiveFlashlightCount = 0;
|
||||||
|
for ( ClientShadowHandle_t i = m_Shadows.Head(); i != m_Shadows.InvalidIndex(); i = m_Shadows.Next(i) )
|
||||||
|
{
|
||||||
|
ClientShadow_t& shadow = m_Shadows[i];
|
||||||
|
|
||||||
|
if ( ( shadow.m_Flags & SHADOW_FLAGS_FLASHLIGHT ) == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Calculate an AABB around the shadow frustum
|
||||||
|
Vector vecAbsMins, vecAbsMaxs;
|
||||||
|
CalculateAABBFromProjectionMatrix( shadow.m_WorldToShadow, &vecAbsMins, &vecAbsMaxs );
|
||||||
|
|
||||||
|
Frustum_t viewFrustum;
|
||||||
|
GeneratePerspectiveFrustum( viewSetup.origin, viewSetup.angles, viewSetup.zNear, viewSetup.zFar, viewSetup.fov, viewSetup.m_flAspectRatio, viewFrustum );
|
||||||
|
|
||||||
|
// FIXME: Could do other sorts of culling here, such as frustum-frustum test, distance etc.
|
||||||
|
// If it's not in the view frustum, move on
|
||||||
|
if ( R_CullBox( vecAbsMins, vecAbsMaxs, viewFrustum ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nActiveFlashlightCount >= nMaxFlashlights )
|
||||||
|
{
|
||||||
|
static bool s_bOverflowWarning = false;
|
||||||
|
if ( !s_bOverflowWarning )
|
||||||
|
{
|
||||||
|
Warning( "Too many flashlights rendered in a single view!\n" );
|
||||||
|
Assert( 0 );
|
||||||
|
s_bOverflowWarning = true;
|
||||||
|
}
|
||||||
|
//shadowmgr->SetFlashlightDepthTexture( shadow.m_ShadowHandle, NULL, 0 );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pActiveFlashlights[nActiveFlashlightCount++] = i;
|
||||||
|
}
|
||||||
|
return nActiveFlashlightCount;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Sets the view's active flashlight render state
|
// Sets the view's active flashlight render state
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -3905,12 +4387,56 @@ void CClientShadowMgr::SetViewFlashlightState( int nActiveFlashlightCount, Clien
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
void AddPointToExtentsHelper( const VMatrix &flashlightToWorld, const Vector &vecPos, Vector &vecMin, Vector &vecMax )
|
||||||
|
{
|
||||||
|
Vector worldSpacePos;
|
||||||
|
|
||||||
|
Vector3DMultiplyPositionProjective( flashlightToWorld, vecPos, worldSpacePos );
|
||||||
|
VectorMin( vecMin, worldSpacePos, vecMin );
|
||||||
|
VectorMax( vecMax, worldSpacePos, vecMax );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CClientShadowMgr::GetFrustumExtents( ClientShadowHandle_t handle, Vector &vecMin, Vector &vecMax )
|
||||||
|
{
|
||||||
|
Assert( m_Shadows.IsValidIndex( handle ) );
|
||||||
|
|
||||||
|
CClientShadowMgr::ClientShadow_t &shadow = m_Shadows[ handle ];
|
||||||
|
|
||||||
|
VMatrix flashlightToWorld;
|
||||||
|
MatrixInverseGeneral( shadow.m_WorldToShadow, flashlightToWorld );
|
||||||
|
|
||||||
|
vecMin = Vector( FLT_MAX, FLT_MAX, FLT_MAX );
|
||||||
|
vecMax = Vector( -FLT_MAX, -FLT_MAX, -FLT_MAX );
|
||||||
|
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 0.0f, 0.0f, 0.0f ), vecMin, vecMax );
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 0.0f, 0.0f, 1.0f ), vecMin, vecMax );
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 0.0f, 1.0f, 0.0f ), vecMin, vecMax );
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 1.0f, 0.0f, 0.0f ), vecMin, vecMax );
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 0.0f, 1.0f, 1.0f ), vecMin, vecMax );
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 1.0f, 0.0f, 1.0f ), vecMin, vecMax );
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 1.0f, 1.0f, 0.0f ), vecMin, vecMax );
|
||||||
|
AddPointToExtentsHelper( flashlightToWorld, Vector( 1.0f, 1.0f, 1.0f ), vecMin, vecMax );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Re-render shadow depth textures that lie in the leaf list
|
// Re-render shadow depth textures that lie in the leaf list
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
|
void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
|
||||||
{
|
{
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
if ( !r_flashlightdepthtexture.GetBool() )
|
||||||
|
{
|
||||||
|
// Build list of active flashlights
|
||||||
|
ClientShadowHandle_t pActiveFlashlights[16];
|
||||||
|
int nActiveFlashlights = BuildActiveFlashlightList( viewSetup, ARRAYSIZE( pActiveFlashlights ), pActiveFlashlights );
|
||||||
|
SetViewFlashlightState( nActiveFlashlights, pActiveFlashlights );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
VPROF_BUDGET( "CClientShadowMgr::ComputeShadowDepthTextures", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
|
VPROF_BUDGET( "CClientShadowMgr::ComputeShadowDepthTextures", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
|
||||||
|
|
||||||
CMatRenderContextPtr pRenderContext( materials );
|
CMatRenderContextPtr pRenderContext( materials );
|
||||||
@ -3926,6 +4452,10 @@ void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
|
|||||||
{
|
{
|
||||||
ClientShadow_t& shadow = m_Shadows[ pActiveDepthShadows[j] ];
|
ClientShadow_t& shadow = m_Shadows[ pActiveDepthShadows[j] ];
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
FlashlightState_t& flashlightState = const_cast<FlashlightState_t&>( shadowmgr->GetFlashlightState( shadow.m_ShadowHandle ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
CTextureReference shadowDepthTexture;
|
CTextureReference shadowDepthTexture;
|
||||||
bool bGotShadowDepthTexture = LockShadowDepthTexture( &shadowDepthTexture );
|
bool bGotShadowDepthTexture = LockShadowDepthTexture( &shadowDepthTexture );
|
||||||
if ( !bGotShadowDepthTexture )
|
if ( !bGotShadowDepthTexture )
|
||||||
@ -3940,6 +4470,12 @@ void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
|
|||||||
|
|
||||||
Assert(0);
|
Assert(0);
|
||||||
shadowmgr->SetFlashlightDepthTexture( shadow.m_ShadowHandle, NULL, 0 );
|
shadowmgr->SetFlashlightDepthTexture( shadow.m_ShadowHandle, NULL, 0 );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( j <= ( INT_FLASHLIGHT_DEPTHTEXTURE_FALLBACK_LAST - INT_FLASHLIGHT_DEPTHTEXTURE_FALLBACK_FIRST ) )
|
||||||
|
{
|
||||||
|
pRenderContext->SetIntRenderingParameter( INT_FLASHLIGHT_DEPTHTEXTURE_FALLBACK_FIRST + j, 0 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3948,11 +4484,30 @@ void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
|
|||||||
shadowView.x = shadowView.y = 0;
|
shadowView.x = shadowView.y = 0;
|
||||||
shadowView.width = shadowDepthTexture->GetActualWidth();
|
shadowView.width = shadowDepthTexture->GetActualWidth();
|
||||||
shadowView.height = shadowDepthTexture->GetActualHeight();
|
shadowView.height = shadowDepthTexture->GetActualHeight();
|
||||||
|
#ifndef ASW_PROJECTED_TEXTURES
|
||||||
shadowView.m_bOrtho = false;
|
shadowView.m_bOrtho = false;
|
||||||
shadowView.m_bDoBloomAndToneMapping = false;
|
shadowView.m_bDoBloomAndToneMapping = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copy flashlight parameters
|
// Copy flashlight parameters
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
if ( !flashlightState.m_bOrtho )
|
||||||
|
{
|
||||||
|
shadowView.m_bOrtho = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shadowView.m_bOrtho = true;
|
||||||
|
shadowView.m_OrthoLeft = flashlightState.m_fOrthoLeft;
|
||||||
|
shadowView.m_OrthoTop = flashlightState.m_fOrthoTop;
|
||||||
|
shadowView.m_OrthoRight = flashlightState.m_fOrthoRight;
|
||||||
|
shadowView.m_OrthoBottom = flashlightState.m_fOrthoBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowView.m_bDoBloomAndToneMapping = false;
|
||||||
|
#else
|
||||||
const FlashlightState_t& flashlightState = shadowmgr->GetFlashlightState( shadow.m_ShadowHandle );
|
const FlashlightState_t& flashlightState = shadowmgr->GetFlashlightState( shadow.m_ShadowHandle );
|
||||||
|
#endif
|
||||||
shadowView.fov = shadowView.fovViewmodel = flashlightState.m_fHorizontalFOVDegrees;
|
shadowView.fov = shadowView.fovViewmodel = flashlightState.m_fHorizontalFOVDegrees;
|
||||||
shadowView.origin = flashlightState.m_vecLightOrigin;
|
shadowView.origin = flashlightState.m_vecLightOrigin;
|
||||||
QuaternionAngles( flashlightState.m_quatOrientation, shadowView.angles ); // Convert from Quaternion to QAngle
|
QuaternionAngles( flashlightState.m_quatOrientation, shadowView.angles ); // Convert from Quaternion to QAngle
|
||||||
@ -3973,6 +4528,19 @@ void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
|
|||||||
// Render to the shadow depth texture with appropriate view
|
// Render to the shadow depth texture with appropriate view
|
||||||
view->UpdateShadowDepthTexture( m_DummyColorTexture, shadowDepthTexture, shadowView );
|
view->UpdateShadowDepthTexture( m_DummyColorTexture, shadowDepthTexture, shadowView );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( j <= ( INT_FLASHLIGHT_DEPTHTEXTURE_FALLBACK_LAST - INT_FLASHLIGHT_DEPTHTEXTURE_FALLBACK_FIRST ) )
|
||||||
|
{
|
||||||
|
pRenderContext->SetIntRenderingParameter( INT_FLASHLIGHT_DEPTHTEXTURE_FALLBACK_FIRST + j, int((ITexture*)shadowDepthTexture) );
|
||||||
|
|
||||||
|
FlashlightState_t state = shadowmgr->GetFlashlightState( shadow.m_ShadowHandle );
|
||||||
|
|
||||||
|
state.m_nShadowQuality = state.m_nShadowQuality | ( ( j + 1 ) << 16 );
|
||||||
|
|
||||||
|
shadowmgr->UpdateFlashlightState( shadow.m_ShadowHandle, state );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Associate the shadow depth texture and stencil bit with the flashlight for use during scene rendering
|
// Associate the shadow depth texture and stencil bit with the flashlight for use during scene rendering
|
||||||
shadowmgr->SetFlashlightDepthTexture( shadow.m_ShadowHandle, shadowDepthTexture, 0 );
|
shadowmgr->SetFlashlightDepthTexture( shadow.m_ShadowHandle, shadowDepthTexture, 0 );
|
||||||
}
|
}
|
||||||
@ -3997,7 +4565,11 @@ void CClientShadowMgr::ComputeShadowTextures( const CViewSetup &view, int leafCo
|
|||||||
if ( !m_RenderToTextureActive || (r_shadows.GetInt() == 0) || r_shadows_gamecontrol.GetInt() == 0 )
|
if ( !m_RenderToTextureActive || (r_shadows.GetInt() == 0) || r_shadows_gamecontrol.GetInt() == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
m_bThreaded = ( r_threaded_client_shadow_manager.GetBool() && g_pThreadPool->NumIdleThreads() );
|
||||||
|
#else
|
||||||
m_bThreaded = false;//( r_threaded_client_shadow_manager.GetBool() && g_pThreadPool->NumIdleThreads() );
|
m_bThreaded = false;//( r_threaded_client_shadow_manager.GetBool() && g_pThreadPool->NumIdleThreads() );
|
||||||
|
#endif
|
||||||
|
|
||||||
MDLCACHE_CRITICAL_SECTION();
|
MDLCACHE_CRITICAL_SECTION();
|
||||||
// First grab all shadow textures we may want to render
|
// First grab all shadow textures we may want to render
|
||||||
@ -4181,6 +4753,28 @@ bool CClientShadowMgr::IsFlashlightTarget( ClientShadowHandle_t shadowHandle, IC
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
void CClientShadowMgr::SetShadowFromWorldLightsEnabled( bool bEnable )
|
||||||
|
{
|
||||||
|
bool bIsShadowingFromWorldLights = IsShadowingFromWorldLights();
|
||||||
|
m_bShadowFromWorldLights = bEnable;
|
||||||
|
if ( bIsShadowingFromWorldLights != IsShadowingFromWorldLights() )
|
||||||
|
{
|
||||||
|
UpdateAllShadows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CClientShadowMgr::SuppressShadowFromWorldLights( bool bSuppress )
|
||||||
|
{
|
||||||
|
bool bIsShadowingFromWorldLights = IsShadowingFromWorldLights();
|
||||||
|
m_bSuppressShadowFromWorldLights = bSuppress;
|
||||||
|
if ( bIsShadowingFromWorldLights != IsShadowingFromWorldLights() )
|
||||||
|
{
|
||||||
|
UpdateAllShadows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// A material proxy that resets the base texture to use the rendered shadow
|
// A material proxy that resets the base texture to use the rendered shadow
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1471,6 +1471,7 @@ void CDetailObjectSystem::LevelInitPreEntity()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
if ( m_DetailObjects.Count() || m_DetailSpriteDict.Count() )
|
if ( m_DetailObjects.Count() || m_DetailSpriteDict.Count() )
|
||||||
{
|
{
|
||||||
// There are detail objects in the level, so precache the material
|
// There are detail objects in the level, so precache the material
|
||||||
@ -1489,6 +1490,7 @@ void CDetailObjectSystem::LevelInitPreEntity()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int detailPropLightingLump;
|
int detailPropLightingLump;
|
||||||
if( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
|
if( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
|
||||||
@ -1512,6 +1514,32 @@ void CDetailObjectSystem::LevelInitPreEntity()
|
|||||||
|
|
||||||
void CDetailObjectSystem::LevelInitPostEntity()
|
void CDetailObjectSystem::LevelInitPostEntity()
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_DetailObjects.Count() || m_DetailSpriteDict.Count() )
|
||||||
|
{
|
||||||
|
const char *pDetailSpriteMaterial = DETAIL_SPRITE_MATERIAL;
|
||||||
|
C_World *pWorld = GetClientWorldEntity();
|
||||||
|
if ( pWorld && pWorld->GetDetailSpriteMaterial() && *(pWorld->GetDetailSpriteMaterial()) )
|
||||||
|
pDetailSpriteMaterial = pWorld->GetDetailSpriteMaterial();
|
||||||
|
|
||||||
|
m_DetailSpriteMaterial.Init( pDetailSpriteMaterial, TEXTURE_GROUP_OTHER );
|
||||||
|
PrecacheMaterial( pDetailSpriteMaterial );
|
||||||
|
IMaterial *pMat = m_DetailSpriteMaterial;
|
||||||
|
|
||||||
|
// adjust for non-square textures (cropped)
|
||||||
|
float flRatio = pMat->GetMappingWidth() / pMat->GetMappingHeight();
|
||||||
|
if ( flRatio > 1.0 )
|
||||||
|
{
|
||||||
|
for( int i = 0; i<m_DetailSpriteDict.Count(); i++ )
|
||||||
|
{
|
||||||
|
m_DetailSpriteDict[i].m_TexUL.y *= flRatio;
|
||||||
|
m_DetailSpriteDict[i].m_TexLR.y *= flRatio;
|
||||||
|
m_DetailSpriteDictFlipped[i].m_TexUL.y *= flRatio;
|
||||||
|
m_DetailSpriteDictFlipped[i].m_TexLR.y *= flRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
const char *pDetailSpriteMaterial = DETAIL_SPRITE_MATERIAL;
|
const char *pDetailSpriteMaterial = DETAIL_SPRITE_MATERIAL;
|
||||||
C_World *pWorld = GetClientWorldEntity();
|
C_World *pWorld = GetClientWorldEntity();
|
||||||
if ( pWorld && pWorld->GetDetailSpriteMaterial() && *(pWorld->GetDetailSpriteMaterial()) )
|
if ( pWorld && pWorld->GetDetailSpriteMaterial() && *(pWorld->GetDetailSpriteMaterial()) )
|
||||||
@ -1519,6 +1547,7 @@ void CDetailObjectSystem::LevelInitPostEntity()
|
|||||||
pDetailSpriteMaterial = pWorld->GetDetailSpriteMaterial();
|
pDetailSpriteMaterial = pWorld->GetDetailSpriteMaterial();
|
||||||
}
|
}
|
||||||
m_DetailSpriteMaterial.Init( pDetailSpriteMaterial, TEXTURE_GROUP_OTHER );
|
m_DetailSpriteMaterial.Init( pDetailSpriteMaterial, TEXTURE_GROUP_OTHER );
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( GetDetailController() )
|
if ( GetDetailController() )
|
||||||
{
|
{
|
||||||
|
@ -48,8 +48,16 @@ static ConVar r_flashlightvisualizetrace( "r_flashlightvisualizetrace", "0", FCV
|
|||||||
static ConVar r_flashlightambient( "r_flashlightambient", "0.0", FCVAR_CHEAT );
|
static ConVar r_flashlightambient( "r_flashlightambient", "0.0", FCVAR_CHEAT );
|
||||||
static ConVar r_flashlightshadowatten( "r_flashlightshadowatten", "0.35", FCVAR_CHEAT );
|
static ConVar r_flashlightshadowatten( "r_flashlightshadowatten", "0.35", FCVAR_CHEAT );
|
||||||
static ConVar r_flashlightladderdist( "r_flashlightladderdist", "40.0", FCVAR_CHEAT );
|
static ConVar r_flashlightladderdist( "r_flashlightladderdist", "40.0", FCVAR_CHEAT );
|
||||||
|
#ifndef MAPBASE
|
||||||
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
|
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
|
||||||
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.0005", FCVAR_CHEAT );
|
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.0005", FCVAR_CHEAT );
|
||||||
|
#else
|
||||||
|
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "4", FCVAR_CHEAT );
|
||||||
|
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.00001", FCVAR_CHEAT );
|
||||||
|
#endif
|
||||||
|
#ifdef MAPBASE
|
||||||
|
static ConVar r_flashlighttextureoverride( "r_flashlighttextureoverride", "", FCVAR_CHEAT );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void r_newflashlightCallback_f( IConVar *pConVar, const char *pOldString, float flOldValue )
|
void r_newflashlightCallback_f( IConVar *pConVar, const char *pOldString, float flOldValue )
|
||||||
@ -78,6 +86,13 @@ CFlashlightEffect::CFlashlightEffect(int nEntIndex)
|
|||||||
r_newflashlight.SetValue( 0 );
|
r_newflashlight.SetValue( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( r_flashlighttextureoverride.GetString()[0] != '\0' )
|
||||||
|
{
|
||||||
|
m_FlashlightTexture.Init( r_flashlighttextureoverride.GetString(), TEXTURE_GROUP_OTHER, true );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if ( g_pMaterialSystemHardwareConfig->SupportsBorderColor() )
|
if ( g_pMaterialSystemHardwareConfig->SupportsBorderColor() )
|
||||||
{
|
{
|
||||||
m_FlashlightTexture.Init( "effects/flashlight_border", TEXTURE_GROUP_OTHER, true );
|
m_FlashlightTexture.Init( "effects/flashlight_border", TEXTURE_GROUP_OTHER, true );
|
||||||
|
@ -66,6 +66,11 @@ C_BaseHLPlayer::C_BaseHLPlayer()
|
|||||||
m_flZoomRate = 0.0f;
|
m_flZoomRate = 0.0f;
|
||||||
m_flZoomStartTime = 0.0f;
|
m_flZoomStartTime = 0.0f;
|
||||||
m_flSpeedMod = cl_forwardspeed.GetFloat();
|
m_flSpeedMod = cl_forwardspeed.GetFloat();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVarRef scissor("r_flashlightscissor");
|
||||||
|
scissor.SetValue("0");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -53,6 +53,10 @@ private:
|
|||||||
float m_flBlendStartTime;
|
float m_flBlendStartTime;
|
||||||
bool m_bActive;
|
bool m_bActive;
|
||||||
EHANDLE m_hCameraEntity;
|
EHANDLE m_hCameraEntity;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool m_bDrawSky;
|
||||||
|
bool m_bDrawSky2;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fades
|
// Fades
|
||||||
float m_flFadeColor[3]; // Server's desired fade color
|
float m_flFadeColor[3]; // Server's desired fade color
|
||||||
@ -71,6 +75,10 @@ IMPLEMENT_CLIENTCLASS_DT( C_ScriptIntro, DT_ScriptIntro, CScriptIntro )
|
|||||||
RecvPropFloat( RECVINFO( m_flNextBlendTime ) ),
|
RecvPropFloat( RECVINFO( m_flNextBlendTime ) ),
|
||||||
RecvPropFloat( RECVINFO( m_flBlendStartTime ) ),
|
RecvPropFloat( RECVINFO( m_flBlendStartTime ) ),
|
||||||
RecvPropBool( RECVINFO( m_bActive ) ),
|
RecvPropBool( RECVINFO( m_bActive ) ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
RecvPropBool( RECVINFO( m_bDrawSky ) ),
|
||||||
|
RecvPropBool( RECVINFO( m_bDrawSky2 ) ),
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fov & fov blends
|
// Fov & fov blends
|
||||||
RecvPropInt( RECVINFO( m_iFOV ) ),
|
RecvPropInt( RECVINFO( m_iFOV ) ),
|
||||||
@ -140,6 +148,10 @@ void C_ScriptIntro::PostDataUpdate( DataUpdateType_t updateType )
|
|||||||
m_IntroData.m_vecCameraViewAngles = m_vecCameraViewAngles;
|
m_IntroData.m_vecCameraViewAngles = m_vecCameraViewAngles;
|
||||||
m_IntroData.m_Passes.SetCount( 0 );
|
m_IntroData.m_Passes.SetCount( 0 );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_IntroData.m_bDrawSky = m_bDrawSky;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Find/Create our first pass
|
// Find/Create our first pass
|
||||||
IntroDataBlendPass_t *pass1;
|
IntroDataBlendPass_t *pass1;
|
||||||
if ( m_IntroData.m_Passes.Count() == 0 )
|
if ( m_IntroData.m_Passes.Count() == 0 )
|
||||||
@ -161,6 +173,9 @@ void C_ScriptIntro::PostDataUpdate( DataUpdateType_t updateType )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_IntroData.m_bDrawPrimary = true;
|
m_IntroData.m_bDrawPrimary = true;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_IntroData.m_bDrawSky2 = m_bDrawSky2;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're currently blending to a new mode, set the second pass
|
// If we're currently blending to a new mode, set the second pass
|
||||||
|
@ -33,7 +33,9 @@ STUB_WEAPON_CLASS( weapon_shotgun, WeaponShotgun, C_BaseHLCombatWeapon );
|
|||||||
STUB_WEAPON_CLASS( weapon_smg1, WeaponSMG1, C_HLSelectFireMachineGun );
|
STUB_WEAPON_CLASS( weapon_smg1, WeaponSMG1, C_HLSelectFireMachineGun );
|
||||||
STUB_WEAPON_CLASS( weapon_357, Weapon357, C_BaseHLCombatWeapon );
|
STUB_WEAPON_CLASS( weapon_357, Weapon357, C_BaseHLCombatWeapon );
|
||||||
STUB_WEAPON_CLASS( weapon_crossbow, WeaponCrossbow, C_BaseHLCombatWeapon );
|
STUB_WEAPON_CLASS( weapon_crossbow, WeaponCrossbow, C_BaseHLCombatWeapon );
|
||||||
|
#ifndef MAPBASE
|
||||||
STUB_WEAPON_CLASS( weapon_slam, Weapon_SLAM, C_BaseHLCombatWeapon );
|
STUB_WEAPON_CLASS( weapon_slam, Weapon_SLAM, C_BaseHLCombatWeapon );
|
||||||
|
#endif
|
||||||
STUB_WEAPON_CLASS( weapon_crowbar, WeaponCrowbar, C_BaseHLBludgeonWeapon );
|
STUB_WEAPON_CLASS( weapon_crowbar, WeaponCrowbar, C_BaseHLBludgeonWeapon );
|
||||||
#ifdef HL2_EPISODIC
|
#ifdef HL2_EPISODIC
|
||||||
STUB_WEAPON_CLASS( weapon_hopwire, WeaponHopwire, C_BaseHLCombatWeapon );
|
STUB_WEAPON_CLASS( weapon_hopwire, WeaponHopwire, C_BaseHLCombatWeapon );
|
||||||
|
@ -109,6 +109,9 @@ private:
|
|||||||
|
|
||||||
float m_flScrollTime;
|
float m_flScrollTime;
|
||||||
float m_flSeparation;
|
float m_flSeparation;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int m_iEndLines;
|
||||||
|
#endif
|
||||||
float m_flFadeTime;
|
float m_flFadeTime;
|
||||||
bool m_bLastOneInPlace;
|
bool m_bLastOneInPlace;
|
||||||
int m_Alpha;
|
int m_Alpha;
|
||||||
@ -133,6 +136,10 @@ private:
|
|||||||
char m_szLogo2[256];
|
char m_szLogo2[256];
|
||||||
|
|
||||||
Color m_cColor;
|
Color m_cColor;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
char m_szCreditsFile[MAX_PATH];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -141,7 +148,11 @@ void CHudCredits::PrepareCredits( const char *pKeyName )
|
|||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
KeyValues *pKV= new KeyValues( "CreditsFile" );
|
KeyValues *pKV= new KeyValues( "CreditsFile" );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( !pKV->LoadFromFile( filesystem, m_szCreditsFile, "MOD" ) )
|
||||||
|
#else
|
||||||
if ( !pKV->LoadFromFile( filesystem, CREDITS_FILE, "MOD" ) )
|
if ( !pKV->LoadFromFile( filesystem, CREDITS_FILE, "MOD" ) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
pKV->deleteThis();
|
pKV->deleteThis();
|
||||||
|
|
||||||
@ -215,8 +226,8 @@ void CHudCredits::ReadNames( KeyValues *pKeyValue )
|
|||||||
while ( pKVNames )
|
while ( pKVNames )
|
||||||
{
|
{
|
||||||
creditname_t Credits;
|
creditname_t Credits;
|
||||||
Q_strcpy( Credits.szCreditName, pKVNames->GetName());
|
V_strcpy_safe( Credits.szCreditName, pKVNames->GetName() );
|
||||||
Q_strcpy( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) );
|
V_strcpy_safe( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) );
|
||||||
|
|
||||||
m_CreditsList.AddToTail( Credits );
|
m_CreditsList.AddToTail( Credits );
|
||||||
pKVNames = pKVNames->GetNextKey();
|
pKVNames = pKVNames->GetNextKey();
|
||||||
@ -233,6 +244,9 @@ void CHudCredits::ReadParams( KeyValues *pKeyValue )
|
|||||||
|
|
||||||
m_flScrollTime = pKeyValue->GetFloat( "scrolltime", 57 );
|
m_flScrollTime = pKeyValue->GetFloat( "scrolltime", 57 );
|
||||||
m_flSeparation = pKeyValue->GetFloat( "separation", 5 );
|
m_flSeparation = pKeyValue->GetFloat( "separation", 5 );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iEndLines = pKeyValue->GetInt( "endlines", 1 );
|
||||||
|
#endif
|
||||||
|
|
||||||
m_flFadeInTime = pKeyValue->GetFloat( "fadeintime", 1 );
|
m_flFadeInTime = pKeyValue->GetFloat( "fadeintime", 1 );
|
||||||
m_flFadeHoldTime = pKeyValue->GetFloat( "fadeholdtime", 3 );
|
m_flFadeHoldTime = pKeyValue->GetFloat( "fadeholdtime", 3 );
|
||||||
@ -296,9 +310,14 @@ void CHudCredits::DrawOutroCreditsName( void )
|
|||||||
|
|
||||||
Color cColor = m_TextColor;
|
Color cColor = m_TextColor;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Some lines should stick around and fade out
|
||||||
|
if ( i >= m_CreditsList.Count()-m_iEndLines )
|
||||||
|
#else
|
||||||
//HACKHACK
|
//HACKHACK
|
||||||
//Last one stays on screen and fades out
|
//Last one stays on screen and fades out
|
||||||
if ( i == m_CreditsList.Count()-1 )
|
if ( i == m_CreditsList.Count()-1 )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if ( m_bLastOneInPlace == false )
|
if ( m_bLastOneInPlace == false )
|
||||||
{
|
{
|
||||||
@ -638,6 +657,20 @@ void CHudCredits::PrepareOutroCredits( void )
|
|||||||
|
|
||||||
int iHeight = iTall;
|
int iHeight = iTall;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_iEndLines <= 0)
|
||||||
|
{
|
||||||
|
// We need a credit to fade out at the end so we know when the credits are done.
|
||||||
|
// Add a dummy credit to act as the "end line".
|
||||||
|
creditname_t DummyCredit;
|
||||||
|
V_strcpy_safe( DummyCredit.szCreditName, "");
|
||||||
|
V_strcpy_safe( DummyCredit.szFontName, "Default" );
|
||||||
|
|
||||||
|
m_CreditsList.AddToTail(DummyCredit);
|
||||||
|
m_iEndLines = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for ( int i = 0; i < m_CreditsList.Count(); i++ )
|
for ( int i = 0; i < m_CreditsList.Count(); i++ )
|
||||||
{
|
{
|
||||||
creditname_t *pCredit = &m_CreditsList[i];
|
creditname_t *pCredit = &m_CreditsList[i];
|
||||||
@ -706,6 +739,13 @@ void CHudCredits::MsgFunc_CreditsMsg( bf_read &msg )
|
|||||||
{
|
{
|
||||||
m_iCreditsType = msg.ReadByte();
|
m_iCreditsType = msg.ReadByte();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
msg.ReadString(m_szCreditsFile, sizeof(m_szCreditsFile));
|
||||||
|
|
||||||
|
if (m_szCreditsFile[0] == '\0')
|
||||||
|
Q_strncpy(m_szCreditsFile, CREDITS_FILE, sizeof(m_szCreditsFile));
|
||||||
|
#endif
|
||||||
|
|
||||||
switch ( m_iCreditsType )
|
switch ( m_iCreditsType )
|
||||||
{
|
{
|
||||||
case CREDITS_LOGO:
|
case CREDITS_LOGO:
|
||||||
@ -729,7 +769,17 @@ void CHudCredits::MsgFunc_CreditsMsg( bf_read &msg )
|
|||||||
void CHudCredits::MsgFunc_LogoTimeMsg( bf_read &msg )
|
void CHudCredits::MsgFunc_LogoTimeMsg( bf_read &msg )
|
||||||
{
|
{
|
||||||
m_iCreditsType = CREDITS_LOGO;
|
m_iCreditsType = CREDITS_LOGO;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float flLogoTime = msg.ReadFloat();
|
||||||
|
msg.ReadString(m_szCreditsFile, sizeof(m_szCreditsFile));
|
||||||
|
|
||||||
|
if (m_szCreditsFile[0] == '\0')
|
||||||
|
Q_strncpy(m_szCreditsFile, CREDITS_FILE, sizeof(m_szCreditsFile));
|
||||||
|
|
||||||
|
PrepareLogo(flLogoTime);
|
||||||
|
#else
|
||||||
PrepareLogo( msg.ReadFloat() );
|
PrepareLogo( msg.ReadFloat() );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,12 +31,20 @@
|
|||||||
extern ISoundEmitterSystemBase *soundemitterbase;
|
extern ISoundEmitterSystemBase *soundemitterbase;
|
||||||
|
|
||||||
// Marked as FCVAR_USERINFO so that the server can cull CC messages before networking them down to us!!!
|
// Marked as FCVAR_USERINFO so that the server can cull CC messages before networking them down to us!!!
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar closecaption( "closecaption", "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX | FCVAR_USERINFO, "Enable close captioning." );
|
||||||
|
#else
|
||||||
ConVar closecaption( "closecaption", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX | FCVAR_USERINFO, "Enable close captioning." );
|
ConVar closecaption( "closecaption", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX | FCVAR_USERINFO, "Enable close captioning." );
|
||||||
|
#endif
|
||||||
extern ConVar cc_lang;
|
extern ConVar cc_lang;
|
||||||
static ConVar cc_linger_time( "cc_linger_time", "1.0", FCVAR_ARCHIVE, "Close caption linger time." );
|
static ConVar cc_linger_time( "cc_linger_time", "1.0", FCVAR_ARCHIVE, "Close caption linger time." );
|
||||||
static ConVar cc_predisplay_time( "cc_predisplay_time", "0.25", FCVAR_ARCHIVE, "Close caption delay before showing caption." );
|
static ConVar cc_predisplay_time( "cc_predisplay_time", "0.25", FCVAR_ARCHIVE, "Close caption delay before showing caption." );
|
||||||
static ConVar cc_captiontrace( "cc_captiontrace", "1", 0, "Show missing closecaptions (0 = no, 1 = devconsole, 2 = show in hud)" );
|
static ConVar cc_captiontrace( "cc_captiontrace", "1", 0, "Show missing closecaptions (0 = no, 1 = devconsole, 2 = show in hud)" );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
static ConVar cc_subtitles( "cc_subtitles", "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "If set, don't show sound effect captions, just voice overs (i.e., won't help hearing impaired players)." );
|
||||||
|
#else
|
||||||
static ConVar cc_subtitles( "cc_subtitles", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "If set, don't show sound effect captions, just voice overs (i.e., won't help hearing impaired players)." );
|
static ConVar cc_subtitles( "cc_subtitles", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "If set, don't show sound effect captions, just voice overs (i.e., won't help hearing impaired players)." );
|
||||||
|
#endif
|
||||||
ConVar english( "english", "1", FCVAR_USERINFO, "If set to 1, running the english language set of assets." );
|
ConVar english( "english", "1", FCVAR_USERINFO, "If set to 1, running the english language set of assets." );
|
||||||
static ConVar cc_smallfontlength( "cc_smallfontlength", "300", 0, "If text stream is this long, force usage of small font size." );
|
static ConVar cc_smallfontlength( "cc_smallfontlength", "300", 0, "If text stream is this long, force usage of small font size." );
|
||||||
|
|
||||||
@ -2692,6 +2700,11 @@ CON_COMMAND_F_COMPLETION( cc_emit, "Emits a closed caption", 0, EmitCaptionCompl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE // 1upD
|
||||||
|
if (!closecaption.GetBool())
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption );
|
CHudCloseCaption *hudCloseCaption = GET_HUDELEMENT( CHudCloseCaption );
|
||||||
if ( hudCloseCaption )
|
if ( hudCloseCaption )
|
||||||
{
|
{
|
||||||
|
@ -599,10 +599,39 @@ bool CHudHintKeyDisplay::SetHintText( const char *text )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char *key = engine->Key_LookupBinding( *binding == '+' ? binding + 1 : binding );
|
const char *key = engine->Key_LookupBinding( *binding == '+' ? binding + 1 : binding );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( !key )
|
||||||
|
{
|
||||||
|
const char *pszNotBound = VarArgs("< %s, not bound >", *binding == '+' ? binding + 1 : binding);
|
||||||
|
if (strchr(binding, '&'))
|
||||||
|
{
|
||||||
|
// "%walk&use%" >> "ALT + E"
|
||||||
|
char *token = strtok(binding, "&");
|
||||||
|
while (token)
|
||||||
|
{
|
||||||
|
const char *tokenkey = engine->Key_LookupBinding( *token == '+' ? token + 1 : token );
|
||||||
|
|
||||||
|
key = VarArgs("%s%s%s", key ? key : "", key ? " + " : "", tokenkey ? tokenkey : pszNotBound);
|
||||||
|
|
||||||
|
token = strtok(NULL, "&");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (binding[0] == '$')
|
||||||
|
{
|
||||||
|
// "%$COOL STRING DUDE%" >> "COOL STRING DUDE"
|
||||||
|
key = binding + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key = pszNotBound;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( !key )
|
if ( !key )
|
||||||
{
|
{
|
||||||
key = "< not bound >";
|
key = "< not bound >";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_snprintf( friendlyName, sizeof(friendlyName), "#%s", key );
|
Q_snprintf( friendlyName, sizeof(friendlyName), "#%s", key );
|
||||||
Q_strupr( friendlyName );
|
Q_strupr( friendlyName );
|
||||||
|
@ -97,6 +97,15 @@ public:
|
|||||||
// Set flashlight light world flag
|
// Set flashlight light world flag
|
||||||
virtual void SetFlashlightLightWorld( ClientShadowHandle_t shadowHandle, bool bLightWorld ) = 0;
|
virtual void SetFlashlightLightWorld( ClientShadowHandle_t shadowHandle, bool bLightWorld ) = 0;
|
||||||
|
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
virtual void GetFrustumExtents( ClientShadowHandle_t handle, Vector &vecMin, Vector &vecMax ) = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DYNAMIC_RTT_SHADOWS
|
||||||
|
// Toggle shadow casting from world light sources
|
||||||
|
virtual void SetShadowFromWorldLightsEnabled( bool bEnable ) = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void SetShadowsDisabled( bool bDisabled ) = 0;
|
virtual void SetShadowsDisabled( bool bDisabled ) = 0;
|
||||||
|
|
||||||
virtual void ComputeShadowDepthTextures( const CViewSetup &pView ) = 0;
|
virtual void ComputeShadowDepthTextures( const CViewSetup &pView ) = 0;
|
||||||
|
@ -1219,6 +1219,9 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Let the move manager override anything it wants to.
|
// Let the move manager override anything it wants to.
|
||||||
|
#ifdef VGUI_SCREEN_FIX
|
||||||
|
cmd->buttons |= IN_VALIDVGUIINPUT;
|
||||||
|
#endif
|
||||||
if ( g_pClientMode->CreateMove( input_sample_frametime, cmd ) )
|
if ( g_pClientMode->CreateMove( input_sample_frametime, cmd ) )
|
||||||
{
|
{
|
||||||
// Get current view angles after the client mode tweaks with it
|
// Get current view angles after the client mode tweaks with it
|
||||||
|
93
sp/src/game/client/mapbase/c_func_clientclip.cpp
Normal file
93
sp/src/game/client/mapbase/c_func_clientclip.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||||
|
//
|
||||||
|
// Purpose:
|
||||||
|
//
|
||||||
|
//===========================================================================//
|
||||||
|
|
||||||
|
#include "cbase.h"
|
||||||
|
|
||||||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
|
|
||||||
|
class C_FuncClientClip : public C_BaseEntity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DECLARE_CLASS( C_FuncClientClip, C_BaseEntity );
|
||||||
|
DECLARE_CLIENTCLASS();
|
||||||
|
|
||||||
|
void OnDataChanged( DataUpdateType_t type );
|
||||||
|
void ClientThink();
|
||||||
|
bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace );
|
||||||
|
|
||||||
|
bool m_bDisabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
IMPLEMENT_CLIENTCLASS_DT( C_FuncClientClip, DT_FuncClientClip, CFuncClientClip )
|
||||||
|
RecvPropBool( RECVINFO( m_bDisabled ) ),
|
||||||
|
END_RECV_TABLE()
|
||||||
|
|
||||||
|
void C_FuncClientClip::OnDataChanged( DataUpdateType_t type )
|
||||||
|
{
|
||||||
|
BaseClass::OnDataChanged( type );
|
||||||
|
|
||||||
|
//if ( type == DATA_UPDATE_CREATED )
|
||||||
|
//{
|
||||||
|
SetSolid(GetMoveParent() ? SOLID_VPHYSICS : SOLID_BSP); // SOLID_VPHYSICS
|
||||||
|
//}
|
||||||
|
|
||||||
|
if ( !m_bDisabled )
|
||||||
|
{
|
||||||
|
VPhysicsDestroyObject();
|
||||||
|
VPhysicsInitShadow( true, true );
|
||||||
|
|
||||||
|
// Think constantly updates the shadow
|
||||||
|
if (GetMoveParent())
|
||||||
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Disabling
|
||||||
|
VPhysicsDestroyObject();
|
||||||
|
SetNextClientThink( CLIENT_THINK_NEVER );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void C_FuncClientClip::ClientThink()
|
||||||
|
{
|
||||||
|
// We shouldn't be thinking if we're disabled
|
||||||
|
Assert(!m_bDisabled);
|
||||||
|
|
||||||
|
if (VPhysicsGetObject())
|
||||||
|
{
|
||||||
|
// Constantly updates the shadow.
|
||||||
|
// This think function should really only be active when we're parented.
|
||||||
|
VPhysicsGetObject()->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, TICK_INTERVAL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This should never happen...
|
||||||
|
VPhysicsInitShadow( true, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseClass::ClientThink();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool C_FuncClientClip::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace )
|
||||||
|
{
|
||||||
|
if ( m_bDisabled )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( !VPhysicsGetObject() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
physcollision->TraceBox( ray, VPhysicsGetObject()->GetCollide(), GetAbsOrigin(), GetAbsAngles(), &trace );
|
||||||
|
|
||||||
|
if ( trace.DidHit() )
|
||||||
|
{
|
||||||
|
trace.surface.surfaceProps = VPhysicsGetObject()->GetMaterialIndex();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
@ -234,6 +234,14 @@ CPanelMetaClassMgrImp::CPanelMetaClassMgrImp() : m_PanelTypeDict( true, 0, 32 )
|
|||||||
|
|
||||||
CPanelMetaClassMgrImp::~CPanelMetaClassMgrImp()
|
CPanelMetaClassMgrImp::~CPanelMetaClassMgrImp()
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE // VDC Memory Leak Fixes
|
||||||
|
while (m_MetaClassKeyValues.Count()>0)
|
||||||
|
{
|
||||||
|
if (m_MetaClassKeyValues[0])
|
||||||
|
m_MetaClassKeyValues[0]->deleteThis();
|
||||||
|
m_MetaClassKeyValues.RemoveAt(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -308,8 +308,12 @@ void CSimpleEmitter::UpdateVelocity( SimpleParticle *pParticle, float timeDelta
|
|||||||
{
|
{
|
||||||
if (pParticle->m_iFlags & SIMPLE_PARTICLE_FLAG_WINDBLOWN)
|
if (pParticle->m_iFlags & SIMPLE_PARTICLE_FLAG_WINDBLOWN)
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector vecWind = GetWindspeedAtLocation( pParticle->m_Pos );
|
||||||
|
#else
|
||||||
Vector vecWind;
|
Vector vecWind;
|
||||||
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
|
GetWindspeedAtTime( gpGlobals->curtime, vecWind );
|
||||||
|
#endif
|
||||||
|
|
||||||
for ( int i = 0 ; i < 2 ; i++ )
|
for ( int i = 0 ; i < 2 ; i++ )
|
||||||
{
|
{
|
||||||
|
@ -30,6 +30,13 @@
|
|||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// This turned out to be causing major issues with VPhysics collision.
|
||||||
|
// It's deactivated until a fix is found.
|
||||||
|
// See player_command.cpp as well.
|
||||||
|
//#define PLAYER_COMMAND_FIX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
IPredictionSystem *IPredictionSystem::g_pPredictionSystems = NULL;
|
IPredictionSystem *IPredictionSystem::g_pPredictionSystems = NULL;
|
||||||
|
|
||||||
#if !defined( NO_ENTITY_PREDICTION )
|
#if !defined( NO_ENTITY_PREDICTION )
|
||||||
@ -903,9 +910,15 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
|||||||
pVehicle->ProcessMovement( player, g_pMoveData );
|
pVehicle->ProcessMovement( player, g_pMoveData );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PLAYER_COMMAND_FIX
|
||||||
|
RunPostThink( player );
|
||||||
|
|
||||||
|
FinishMove( player, ucmd, g_pMoveData );
|
||||||
|
#else
|
||||||
FinishMove( player, ucmd, g_pMoveData );
|
FinishMove( player, ucmd, g_pMoveData );
|
||||||
|
|
||||||
RunPostThink( player );
|
RunPostThink( player );
|
||||||
|
#endif
|
||||||
|
|
||||||
g_pGameMovement->FinishTrackPredictionErrors( player );
|
g_pGameMovement->FinishTrackPredictionErrors( player );
|
||||||
|
|
||||||
|
@ -1327,6 +1327,9 @@ void CViewRender::ViewDrawScene( bool bDrew3dSkybox, SkyboxVisibility_t nSkyboxV
|
|||||||
if ( r_flashlightdepthtexture.GetBool() && (viewID == VIEW_MAIN) )
|
if ( r_flashlightdepthtexture.GetBool() && (viewID == VIEW_MAIN) )
|
||||||
{
|
{
|
||||||
g_pClientShadowMgr->ComputeShadowDepthTextures( view );
|
g_pClientShadowMgr->ComputeShadowDepthTextures( view );
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
CMatRenderContextPtr pRenderContext( materials );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
m_BaseDrawFlags = baseDrawFlags;
|
m_BaseDrawFlags = baseDrawFlags;
|
||||||
@ -1980,6 +1983,7 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
|
|||||||
bool bDrew3dSkybox = false;
|
bool bDrew3dSkybox = false;
|
||||||
SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE;
|
SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE;
|
||||||
|
|
||||||
|
#ifndef MAPBASE // Moved to respective ViewDrawScenes() for script_intro skybox fix
|
||||||
// if the 3d skybox world is drawn, then don't draw the normal skybox
|
// if the 3d skybox world is drawn, then don't draw the normal skybox
|
||||||
CSkyboxView *pSkyView = new CSkyboxView( this );
|
CSkyboxView *pSkyView = new CSkyboxView( this );
|
||||||
if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible ) ) != false )
|
if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible ) ) != false )
|
||||||
@ -1987,6 +1991,7 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
|
|||||||
AddViewToScene( pSkyView );
|
AddViewToScene( pSkyView );
|
||||||
}
|
}
|
||||||
SafeRelease( pSkyView );
|
SafeRelease( pSkyView );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Force it to clear the framebuffer if they're in solid space.
|
// Force it to clear the framebuffer if they're in solid space.
|
||||||
if ( ( nClearFlags & VIEW_CLEAR_COLOR ) == 0 )
|
if ( ( nClearFlags & VIEW_CLEAR_COLOR ) == 0 )
|
||||||
@ -1997,14 +2002,37 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// For script_intro viewmodel fix
|
||||||
|
bool bDrawnViewmodel = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Render world and all entities, particles, etc.
|
// Render world and all entities, particles, etc.
|
||||||
if( !g_pIntroData )
|
if( !g_pIntroData )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Moved here for the script_intro skybox fix.
|
||||||
|
// We can't put it in ViewDrawScene() directly because other functions use it as well.
|
||||||
|
|
||||||
|
// if the 3d skybox world is drawn, then don't draw the normal skybox
|
||||||
|
CSkyboxView *pSkyView = new CSkyboxView( this );
|
||||||
|
if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible ) ) != false )
|
||||||
|
{
|
||||||
|
AddViewToScene( pSkyView );
|
||||||
|
}
|
||||||
|
SafeRelease( pSkyView );
|
||||||
|
#endif
|
||||||
|
|
||||||
ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
|
ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ViewDrawScene_Intro( view, nClearFlags, *g_pIntroData, bDrew3dSkybox, nSkyboxVisible, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
|
||||||
|
bDrawnViewmodel = true;
|
||||||
|
#else
|
||||||
ViewDrawScene_Intro( view, nClearFlags, *g_pIntroData );
|
ViewDrawScene_Intro( view, nClearFlags, *g_pIntroData );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can still use the 'current view' stuff set up in ViewDrawScene
|
// We can still use the 'current view' stuff set up in ViewDrawScene
|
||||||
@ -2040,6 +2068,9 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
|
|||||||
GetClientModeNormal()->DoPostScreenSpaceEffects( &view );
|
GetClientModeNormal()->DoPostScreenSpaceEffects( &view );
|
||||||
|
|
||||||
// Now actually draw the viewmodel
|
// Now actually draw the viewmodel
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (!bDrawnViewmodel)
|
||||||
|
#endif
|
||||||
DrawViewModels( view, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
|
DrawViewModels( view, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
|
||||||
|
|
||||||
DrawUnderwaterOverlay();
|
DrawUnderwaterOverlay();
|
||||||
@ -2858,7 +2889,12 @@ void CViewRender::GetWaterLODParams( float &flCheapWaterStartDistance, float &fl
|
|||||||
// Input : &view -
|
// Input : &view -
|
||||||
// &introData -
|
// &introData -
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags, const IntroData_t &introData,
|
||||||
|
bool bDrew3dSkybox, SkyboxVisibility_t nSkyboxVisible, bool bDrawViewModel, ViewCustomVisibility_t *pCustomVisibility )
|
||||||
|
#else
|
||||||
void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags, const IntroData_t &introData )
|
void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags, const IntroData_t &introData )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
VPROF( "CViewRender::ViewDrawScene" );
|
VPROF( "CViewRender::ViewDrawScene" );
|
||||||
|
|
||||||
@ -2893,6 +2929,29 @@ void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags,
|
|||||||
playerView.fov = ScaleFOVByWidthRatio( introData.m_playerViewFOV, engine->GetScreenAspectRatio() / ( 4.0f / 3.0f ) );
|
playerView.fov = ScaleFOVByWidthRatio( introData.m_playerViewFOV, engine->GetScreenAspectRatio() / ( 4.0f / 3.0f ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool drawSkybox;
|
||||||
|
int nViewFlags;
|
||||||
|
if (introData.m_bDrawSky2)
|
||||||
|
{
|
||||||
|
drawSkybox = r_skybox.GetBool();
|
||||||
|
nViewFlags = VIEW_CLEAR_DEPTH;
|
||||||
|
|
||||||
|
// if the 3d skybox world is drawn, then don't draw the normal skybox
|
||||||
|
CSkyboxView *pSkyView = new CSkyboxView( this );
|
||||||
|
if ( ( bDrew3dSkybox = pSkyView->Setup( playerView, &nClearFlags, &nSkyboxVisible ) ) != false )
|
||||||
|
{
|
||||||
|
AddViewToScene( pSkyView );
|
||||||
|
}
|
||||||
|
SafeRelease( pSkyView );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drawSkybox = false;
|
||||||
|
nViewFlags = (VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
g_pClientShadowMgr->PreRender();
|
g_pClientShadowMgr->PreRender();
|
||||||
|
|
||||||
// Shadowed flashlights supported on ps_2_b and up...
|
// Shadowed flashlights supported on ps_2_b and up...
|
||||||
@ -2907,10 +2966,38 @@ void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags,
|
|||||||
IGameSystem::PreRenderAllSystems();
|
IGameSystem::PreRenderAllSystems();
|
||||||
|
|
||||||
// Start view, clear frame/z buffer if necessary
|
// Start view, clear frame/z buffer if necessary
|
||||||
|
#ifdef MAPBASE
|
||||||
|
SetupVis( playerView, visFlags, pCustomVisibility );
|
||||||
|
#else
|
||||||
SetupVis( playerView, visFlags );
|
SetupVis( playerView, visFlags );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (introData.m_bDrawSky2)
|
||||||
|
{
|
||||||
|
if ( !bDrew3dSkybox &&
|
||||||
|
( nSkyboxVisible == SKYBOX_NOT_VISIBLE ) /*&& ( visFlags & IVRenderView::VIEW_SETUP_VIS_EX_RETURN_FLAGS_USES_RADIAL_VIS )*/ )
|
||||||
|
{
|
||||||
|
// This covers the case where we don't see a 3dskybox, yet radial vis is clipping
|
||||||
|
// the far plane. Need to clear to fog color in this case.
|
||||||
|
nClearFlags |= VIEW_CLEAR_COLOR;
|
||||||
|
//SetClearColorToFogColor( );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bDrew3dSkybox || ( nSkyboxVisible == SKYBOX_NOT_VISIBLE ) )
|
||||||
|
{
|
||||||
|
drawSkybox = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
render->Push3DView( playerView, nViewFlags, NULL, GetFrustum() );
|
||||||
|
DrawWorldAndEntities( drawSkybox, playerView, nViewFlags );
|
||||||
|
#else
|
||||||
render->Push3DView( playerView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, NULL, GetFrustum() );
|
render->Push3DView( playerView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, NULL, GetFrustum() );
|
||||||
DrawWorldAndEntities( true /* drawSkybox */, playerView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH );
|
DrawWorldAndEntities( true /* drawSkybox */, playerView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH );
|
||||||
|
#endif
|
||||||
render->PopView( GetFrustum() );
|
render->PopView( GetFrustum() );
|
||||||
|
|
||||||
// Free shadow depth textures for use in future view
|
// Free shadow depth textures for use in future view
|
||||||
@ -2926,12 +3013,28 @@ void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags,
|
|||||||
Rect_t actualRect;
|
Rect_t actualRect;
|
||||||
UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height, false, &actualRect );
|
UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height, false, &actualRect );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (introData.m_bDrawSky)
|
||||||
|
{
|
||||||
|
// if the 3d skybox world is drawn, then don't draw the normal skybox
|
||||||
|
CSkyboxView *pSkyView = new CSkyboxView( this );
|
||||||
|
if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible ) ) != false )
|
||||||
|
{
|
||||||
|
AddViewToScene( pSkyView );
|
||||||
|
}
|
||||||
|
SafeRelease( pSkyView );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
g_pClientShadowMgr->PreRender();
|
g_pClientShadowMgr->PreRender();
|
||||||
|
|
||||||
// Shadowed flashlights supported on ps_2_b and up...
|
// Shadowed flashlights supported on ps_2_b and up...
|
||||||
if ( r_flashlightdepthtexture.GetBool() )
|
if ( r_flashlightdepthtexture.GetBool() )
|
||||||
{
|
{
|
||||||
g_pClientShadowMgr->ComputeShadowDepthTextures( view );
|
g_pClientShadowMgr->ComputeShadowDepthTextures( view );
|
||||||
|
#ifdef ASW_PROJECTED_TEXTURES
|
||||||
|
CMatRenderContextPtr pRenderContext( materials );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@ -2948,7 +3051,41 @@ void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags,
|
|||||||
// Clear alpha to 255 so that masking with the vortigaunts (0) works properly.
|
// Clear alpha to 255 so that masking with the vortigaunts (0) works properly.
|
||||||
pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
|
pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool drawSkybox;
|
||||||
|
int nViewFlags;
|
||||||
|
if (introData.m_bDrawSky)
|
||||||
|
{
|
||||||
|
drawSkybox = r_skybox.GetBool();
|
||||||
|
nViewFlags = VIEW_CLEAR_DEPTH;
|
||||||
|
|
||||||
|
if ( !bDrew3dSkybox &&
|
||||||
|
( nSkyboxVisible == SKYBOX_NOT_VISIBLE ) /*&& ( visFlags & IVRenderView::VIEW_SETUP_VIS_EX_RETURN_FLAGS_USES_RADIAL_VIS )*/ )
|
||||||
|
{
|
||||||
|
// This covers the case where we don't see a 3dskybox, yet radial vis is clipping
|
||||||
|
// the far plane. Need to clear to fog color in this case.
|
||||||
|
nViewFlags |= VIEW_CLEAR_COLOR;
|
||||||
|
//SetClearColorToFogColor( );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bDrew3dSkybox || ( nSkyboxVisible == SKYBOX_NOT_VISIBLE ) )
|
||||||
|
{
|
||||||
|
drawSkybox = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drawSkybox = false;
|
||||||
|
nViewFlags = (VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawWorldAndEntities( drawSkybox, view, nViewFlags );
|
||||||
|
|
||||||
|
// Solution for viewmodels not drawing in script_intro
|
||||||
|
DrawViewModels( view, bDrawViewModel );
|
||||||
|
#else
|
||||||
DrawWorldAndEntities( true /* drawSkybox */, view, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH );
|
DrawWorldAndEntities( true /* drawSkybox */, view, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH );
|
||||||
|
#endif
|
||||||
|
|
||||||
UpdateScreenEffectTexture( 1, view.x, view.y, view.width, view.height );
|
UpdateScreenEffectTexture( 1, view.x, view.y, view.width, view.height );
|
||||||
|
|
||||||
@ -3027,6 +3164,11 @@ void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags,
|
|||||||
// Let the particle manager simulate things that haven't been simulated.
|
// Let the particle manager simulate things that haven't been simulated.
|
||||||
ParticleMgr()->PostRender();
|
ParticleMgr()->PostRender();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Invoke post-render methods
|
||||||
|
IGameSystem::PostRenderAllSystems();
|
||||||
|
#endif
|
||||||
|
|
||||||
FinishCurrentView();
|
FinishCurrentView();
|
||||||
|
|
||||||
// Free shadow depth textures for use in future view
|
// Free shadow depth textures for use in future view
|
||||||
@ -3096,15 +3238,62 @@ bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_Poin
|
|||||||
monitorView.origin = pCameraEnt->GetAbsOrigin();
|
monitorView.origin = pCameraEnt->GetAbsOrigin();
|
||||||
monitorView.angles = pCameraEnt->GetAbsAngles();
|
monitorView.angles = pCameraEnt->GetAbsAngles();
|
||||||
monitorView.fov = pCameraEnt->GetFOV();
|
monitorView.fov = pCameraEnt->GetFOV();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (pCameraEnt->IsOrtho())
|
||||||
|
{
|
||||||
|
monitorView.m_bOrtho = true;
|
||||||
|
pCameraEnt->GetOrthoDimensions( monitorView.m_OrthoTop, monitorView.m_OrthoBottom,
|
||||||
|
monitorView.m_OrthoLeft, monitorView.m_OrthoRight );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
monitorView.m_bOrtho = false;
|
monitorView.m_bOrtho = false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
monitorView.m_bOrtho = false;
|
||||||
|
#endif
|
||||||
monitorView.m_flAspectRatio = pCameraEnt->UseScreenAspectRatio() ? 0.0f : 1.0f;
|
monitorView.m_flAspectRatio = pCameraEnt->UseScreenAspectRatio() ? 0.0f : 1.0f;
|
||||||
monitorView.m_bViewToProjectionOverride = false;
|
monitorView.m_bViewToProjectionOverride = false;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//
|
||||||
|
// Monitor sky handling
|
||||||
|
//
|
||||||
|
if ( pCameraEnt->SkyMode() == SKYBOX_3DSKYBOX_VISIBLE )
|
||||||
|
{
|
||||||
|
int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR);
|
||||||
|
bool bDrew3dSkybox = false;
|
||||||
|
SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode();
|
||||||
|
|
||||||
|
Frustum frustum;
|
||||||
|
render->Push3DView( monitorView, nClearFlags, pRenderTarget, (VPlane *)frustum );
|
||||||
|
|
||||||
|
// if the 3d skybox world is drawn, then don't draw the normal skybox
|
||||||
|
CSkyboxView *pSkyView = new CSkyboxView( this );
|
||||||
|
if ( ( bDrew3dSkybox = pSkyView->Setup( monitorView, &nClearFlags, &nSkyMode ) ) != false )
|
||||||
|
{
|
||||||
|
AddViewToScene( pSkyView );
|
||||||
|
}
|
||||||
|
SafeRelease( pSkyView );
|
||||||
|
|
||||||
|
ViewDrawScene( bDrew3dSkybox, nSkyMode, monitorView, nClearFlags, VIEW_MONITOR );
|
||||||
|
render->PopView( frustum );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// @MULTICORE (toml 8/11/2006): this should be a renderer....
|
// @MULTICORE (toml 8/11/2006): this should be a renderer....
|
||||||
Frustum frustum;
|
Frustum frustum;
|
||||||
render->Push3DView( monitorView, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pRenderTarget, (VPlane *)frustum );
|
render->Push3DView( monitorView, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pRenderTarget, (VPlane *)frustum );
|
||||||
ViewDrawScene( false, SKYBOX_2DSKYBOX_VISIBLE, monitorView, 0, VIEW_MONITOR );
|
ViewDrawScene( false, SKYBOX_2DSKYBOX_VISIBLE, monitorView, 0, VIEW_MONITOR );
|
||||||
render->PopView( frustum );
|
render->PopView( frustum );
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// @MULTICORE (toml 8/11/2006): this should be a renderer....
|
||||||
|
Frustum frustum;
|
||||||
|
render->Push3DView( monitorView, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pRenderTarget, (VPlane *)frustum );
|
||||||
|
ViewDrawScene( false, SKYBOX_2DSKYBOX_VISIBLE, monitorView, 0, VIEW_MONITOR );
|
||||||
|
render->PopView( frustum );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reset the world fog parameters.
|
// Reset the world fog parameters.
|
||||||
if ( fogEnabled )
|
if ( fogEnabled )
|
||||||
@ -4748,6 +4937,16 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR
|
|||||||
// with this near plane. If so, move it in a bit. It's at 2.0 to give us more precision. That means you
|
// with this near plane. If so, move it in a bit. It's at 2.0 to give us more precision. That means you
|
||||||
// need to keep the eye position at least 2 * scale away from the geometry in the skybox
|
// need to keep the eye position at least 2 * scale away from the geometry in the skybox
|
||||||
zNear = 2.0;
|
zNear = 2.0;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Use the fog's farz if specified
|
||||||
|
if (m_pSky3dParams->fog.farz > 0)
|
||||||
|
{
|
||||||
|
zFar = ( m_pSky3dParams->scale > 0.0f ?
|
||||||
|
m_pSky3dParams->fog.farz / m_pSky3dParams->scale :
|
||||||
|
m_pSky3dParams->fog.farz );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
zFar = MAX_TRACE_LENGTH;
|
zFar = MAX_TRACE_LENGTH;
|
||||||
|
|
||||||
// scale origin by sky scale
|
// scale origin by sky scale
|
||||||
@ -4757,6 +4956,56 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR
|
|||||||
VectorScale( origin, scale, origin );
|
VectorScale( origin, scale, origin );
|
||||||
}
|
}
|
||||||
Enable3dSkyboxFog();
|
Enable3dSkyboxFog();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Skybox angle support.
|
||||||
|
//
|
||||||
|
// If any of the angles aren't 0, do the rotation code.
|
||||||
|
if (m_pSky3dParams->angles.GetX() != 0 ||
|
||||||
|
m_pSky3dParams->angles.GetY() != 0 ||
|
||||||
|
m_pSky3dParams->angles.GetZ() != 0)
|
||||||
|
{
|
||||||
|
// Unfortunately, it's not as simple as "angles += m_pSky3dParams->angles".
|
||||||
|
// This stuff took a long time to figure out. I'm glad I got it working.
|
||||||
|
|
||||||
|
// First, create a matrix for the sky's angles.
|
||||||
|
matrix3x4_t matSkyAngles;
|
||||||
|
AngleMatrix( m_pSky3dParams->angles, matSkyAngles );
|
||||||
|
|
||||||
|
// The code in between the lines below was mostly lifted from projected texture screenspace code and was a huge lifesaver.
|
||||||
|
// The comments are my attempt at explaining the little I understand of what's going on here.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// These are the vectors that would eventually become our final angle directions.
|
||||||
|
Vector vecSkyForward, vecSkyRight, vecSkyUp;
|
||||||
|
|
||||||
|
// Get vectors from our original angles.
|
||||||
|
Vector vPlayerForward, vPlayerRight, vPlayerUp;
|
||||||
|
AngleVectors( angles, &vPlayerForward, &vPlayerRight, &vPlayerUp );
|
||||||
|
|
||||||
|
// Transform them from our sky angles matrix and put the results in those vectors we declared earlier.
|
||||||
|
VectorTransform( vPlayerForward, matSkyAngles, vecSkyForward );
|
||||||
|
VectorTransform( vPlayerRight, matSkyAngles, vecSkyRight );
|
||||||
|
VectorTransform( vPlayerUp, matSkyAngles, vecSkyUp );
|
||||||
|
|
||||||
|
// Normalize them.
|
||||||
|
VectorNormalize( vecSkyForward );
|
||||||
|
VectorNormalize( vecSkyRight );
|
||||||
|
VectorNormalize( vecSkyUp );
|
||||||
|
|
||||||
|
// Now do a bit of quaternion magic and apply that to our original angles.
|
||||||
|
// This works perfectly, so I'm not gonna touch it.
|
||||||
|
Quaternion quat;
|
||||||
|
BasisToQuaternion( vecSkyForward, vecSkyRight, vecSkyUp, quat );
|
||||||
|
QuaternionAngles( quat, angles );
|
||||||
|
|
||||||
|
// 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(origin), matSkyAngles, origin);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
VectorAdd( origin, m_pSky3dParams->origin, origin );
|
VectorAdd( origin, m_pSky3dParams->origin, origin );
|
||||||
|
|
||||||
// BUGBUG: Fix this!!! We shouldn't need to call setup vis for the sky if we're connecting
|
// BUGBUG: Fix this!!! We shouldn't need to call setup vis for the sky if we're connecting
|
||||||
@ -4844,6 +5093,20 @@ bool CSkyboxView::Setup( const CViewSetup &view, int *pClearFlags, SkyboxVisibil
|
|||||||
*pClearFlags |= VIEW_CLEAR_DEPTH; // Need to clear depth after rednering the skybox
|
*pClearFlags |= VIEW_CLEAR_DEPTH; // Need to clear depth after rednering the skybox
|
||||||
|
|
||||||
m_DrawFlags = DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER | DF_RENDER_WATER;
|
m_DrawFlags = DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER | DF_RENDER_WATER;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_pSky3dParams->skycolor.GetA() != 0 && *pSkyboxVisible != SKYBOX_NOT_VISIBLE)
|
||||||
|
{
|
||||||
|
m_ClearFlags |= (VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH);
|
||||||
|
m_DrawFlags |= DF_CLIP_SKYBOX;
|
||||||
|
|
||||||
|
color32 color = m_pSky3dParams->skycolor.Get();
|
||||||
|
|
||||||
|
CMatRenderContextPtr pRenderContext( materials );
|
||||||
|
pRenderContext->ClearColor4ub( color.r, color.g, color.b, color.a );
|
||||||
|
pRenderContext.SafeRelease();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if( r_skybox.GetBool() )
|
if( r_skybox.GetBool() )
|
||||||
{
|
{
|
||||||
m_DrawFlags |= DF_DRAWSKYBOX;
|
m_DrawFlags |= DF_DRAWSKYBOX;
|
||||||
|
@ -56,6 +56,13 @@ struct IntroData_t
|
|||||||
|
|
||||||
// Fade overriding for the intro
|
// Fade overriding for the intro
|
||||||
float m_flCurrentFadeColor[4];
|
float m_flCurrentFadeColor[4];
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Draws the skybox.
|
||||||
|
bool m_bDrawSky;
|
||||||
|
// Draws the skybox in the secondary camera as well.
|
||||||
|
bool m_bDrawSky2;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Robin, make this point at something to get intro mode.
|
// Robin, make this point at something to get intro mode.
|
||||||
@ -452,7 +459,11 @@ private:
|
|||||||
// Water-related methods
|
// Water-related methods
|
||||||
void DrawWorldAndEntities( bool drawSkybox, const CViewSetup &view, int nClearFlags, ViewCustomVisibility_t *pCustomVisibility = NULL );
|
void DrawWorldAndEntities( bool drawSkybox, const CViewSetup &view, int nClearFlags, ViewCustomVisibility_t *pCustomVisibility = NULL );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags, const IntroData_t &introData, bool bDrew3dSkybox = false, SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE, bool bDrawViewModel = false, ViewCustomVisibility_t *pCustomVisibility = NULL );
|
||||||
|
#else
|
||||||
virtual void ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags, const IntroData_t &introData );
|
virtual void ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags, const IntroData_t &introData );
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PORTAL
|
#ifdef PORTAL
|
||||||
// Intended for use in the middle of another ViewDrawScene call, this allows stencils to be drawn after opaques but before translucents are drawn in the main view.
|
// Intended for use in the middle of another ViewDrawScene call, this allows stencils to be drawn after opaques but before translucents are drawn in the main view.
|
||||||
|
305
sp/src/game/client/worldlight.cpp
Normal file
305
sp/src/game/client/worldlight.cpp
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
//========= Copyright (C) 2018, CSProMod Team, All rights reserved. =========//
|
||||||
|
//
|
||||||
|
// Purpose: provide world light related functions to the client
|
||||||
|
//
|
||||||
|
// As the engine provides no access to brush/model data (brushdata_t, model_t),
|
||||||
|
// we hence have no access to dworldlight_t. Therefore, we manually extract the
|
||||||
|
// world light data from the BSP itself, before entities are initialised on map
|
||||||
|
// load.
|
||||||
|
//
|
||||||
|
// To find the brightest light at a point, all world lights are iterated.
|
||||||
|
// Lights whose radii do not encompass our sample point are quickly rejected,
|
||||||
|
// as are lights which are not in our PVS, or visible from the sample point.
|
||||||
|
// If the sky light is visible from the sample point, then it shall supersede
|
||||||
|
// all other world lights.
|
||||||
|
//
|
||||||
|
// Written: November 2011
|
||||||
|
// Author: Saul Rennison
|
||||||
|
//
|
||||||
|
//===========================================================================//
|
||||||
|
|
||||||
|
#include "cbase.h"
|
||||||
|
#include "worldlight.h"
|
||||||
|
#include "bspfile.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "client_factorylist.h" // FactoryList_Retrieve
|
||||||
|
#include "eiface.h" // IVEngineServer
|
||||||
|
|
||||||
|
static IVEngineServer *g_pEngineServer = NULL;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Singleton exposure
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static CWorldLights s_WorldLights;
|
||||||
|
CWorldLights *g_pWorldLights = &s_WorldLights;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: calculate intensity ratio for a worldlight by distance
|
||||||
|
// Author: Valve Software
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static float Engine_WorldLightDistanceFalloff( const dworldlight_t *wl, const Vector& delta )
|
||||||
|
{
|
||||||
|
float falloff;
|
||||||
|
|
||||||
|
switch (wl->type)
|
||||||
|
{
|
||||||
|
case emit_surface:
|
||||||
|
// Cull out stuff that's too far
|
||||||
|
if(wl->radius != 0)
|
||||||
|
{
|
||||||
|
if(DotProduct( delta, delta ) > (wl->radius * wl->radius))
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvRSquared(delta);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case emit_skylight:
|
||||||
|
return 1.f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case emit_quakelight:
|
||||||
|
// X - r;
|
||||||
|
falloff = wl->linear_attn - FastSqrt( DotProduct( delta, delta ) );
|
||||||
|
if(falloff < 0)
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
return falloff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case emit_skyambient:
|
||||||
|
return 1.f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case emit_point:
|
||||||
|
case emit_spotlight: // directional & positional
|
||||||
|
{
|
||||||
|
float dist2, dist;
|
||||||
|
|
||||||
|
dist2 = DotProduct(delta, delta);
|
||||||
|
dist = FastSqrt(dist2);
|
||||||
|
|
||||||
|
// Cull out stuff that's too far
|
||||||
|
if(wl->radius != 0 && dist > wl->radius)
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
return 1.f / (wl->constant_attn + wl->linear_attn * dist + wl->quadratic_attn * dist2);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: initialise game system and members
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
CWorldLights::CWorldLights() : CAutoGameSystem("World lights")
|
||||||
|
{
|
||||||
|
m_nWorldLights = 0;
|
||||||
|
m_pWorldLights = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: clear worldlights, free memory
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CWorldLights::Clear()
|
||||||
|
{
|
||||||
|
m_nWorldLights = 0;
|
||||||
|
|
||||||
|
if(m_pWorldLights)
|
||||||
|
{
|
||||||
|
delete [] m_pWorldLights;
|
||||||
|
m_pWorldLights = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: get the IVEngineServer, we need this for the PVS functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CWorldLights::Init()
|
||||||
|
{
|
||||||
|
factorylist_t factories;
|
||||||
|
FactoryList_Retrieve(factories);
|
||||||
|
|
||||||
|
if((g_pEngineServer = (IVEngineServer*)factories.appSystemFactory(INTERFACEVERSION_VENGINESERVER, NULL)) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: get all world lights from the BSP
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CWorldLights::LevelInitPreEntity()
|
||||||
|
{
|
||||||
|
// Get the map path
|
||||||
|
const char *pszMapName = modelinfo->GetModelName(modelinfo->GetModel(1));
|
||||||
|
|
||||||
|
// Open map
|
||||||
|
FileHandle_t hFile = g_pFullFileSystem->Open(pszMapName, "rb");
|
||||||
|
if(!hFile)
|
||||||
|
{
|
||||||
|
Warning("CWorldLights: unable to open map\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the BSP header. We don't need to do any version checks, etc. as we
|
||||||
|
// can safely assume that the engine did this for us
|
||||||
|
dheader_t hdr;
|
||||||
|
g_pFullFileSystem->Read(&hdr, sizeof(hdr), hFile);
|
||||||
|
|
||||||
|
// Grab the light lump and seek to it
|
||||||
|
lump_t &lightLump = hdr.lumps[LUMP_WORLDLIGHTS];
|
||||||
|
|
||||||
|
// INSOLENCE: If the worldlights lump is empty, that means theres no normal, LDR lights to extract
|
||||||
|
// This can happen when, for example, the map is compiled in HDR mode only
|
||||||
|
// So move on to the HDR worldlights lump
|
||||||
|
if (lightLump.filelen == 0)
|
||||||
|
{
|
||||||
|
lightLump = hdr.lumps[LUMP_WORLDLIGHTS_HDR];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we can't divide the lump data into a whole number of worldlights,
|
||||||
|
// then the BSP format changed and we're unaware
|
||||||
|
if(lightLump.filelen % sizeof(dworldlight_t))
|
||||||
|
{
|
||||||
|
Warning("CWorldLights: unknown world light lump\n");
|
||||||
|
|
||||||
|
// Close file
|
||||||
|
g_pFullFileSystem->Close(hFile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pFullFileSystem->Seek(hFile, lightLump.fileofs, FILESYSTEM_SEEK_HEAD);
|
||||||
|
|
||||||
|
// Allocate memory for the worldlights
|
||||||
|
m_nWorldLights = lightLump.filelen / sizeof(dworldlight_t);
|
||||||
|
m_pWorldLights = new dworldlight_t[m_nWorldLights];
|
||||||
|
|
||||||
|
// Read worldlights then close
|
||||||
|
g_pFullFileSystem->Read(m_pWorldLights, lightLump.filelen, hFile);
|
||||||
|
g_pFullFileSystem->Close(hFile);
|
||||||
|
|
||||||
|
DevMsg("CWorldLights: load successful (%d lights at 0x%p)\n", m_nWorldLights, m_pWorldLights);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: find the brightest light source at a point
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CWorldLights::GetBrightestLightSource(const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness)
|
||||||
|
{
|
||||||
|
if(!m_nWorldLights || !m_pWorldLights)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Default light position and brightness to zero
|
||||||
|
vecLightBrightness.Init();
|
||||||
|
vecLightPos.Init();
|
||||||
|
|
||||||
|
// Find the size of the PVS for our current position
|
||||||
|
int nCluster = g_pEngineServer->GetClusterForOrigin(vecPosition);
|
||||||
|
int nPVSSize = g_pEngineServer->GetPVSForCluster(nCluster, 0, NULL);
|
||||||
|
|
||||||
|
// Get the PVS at our position
|
||||||
|
byte *pvs = new byte[nPVSSize];
|
||||||
|
g_pEngineServer->GetPVSForCluster(nCluster, nPVSSize, pvs);
|
||||||
|
|
||||||
|
// Iterate through all the worldlights
|
||||||
|
for(int i = 0; i < m_nWorldLights; ++i)
|
||||||
|
{
|
||||||
|
dworldlight_t *light = &m_pWorldLights[i];
|
||||||
|
|
||||||
|
// Skip skyambient
|
||||||
|
if(light->type == emit_skyambient)
|
||||||
|
{
|
||||||
|
//engine->Con_NPrintf(i, "%d: skyambient", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle sun
|
||||||
|
if(light->type == emit_skylight)
|
||||||
|
{
|
||||||
|
// Calculate sun position
|
||||||
|
Vector vecAbsStart = vecPosition + Vector(0,0,30);
|
||||||
|
Vector vecAbsEnd = vecAbsStart - (light->normal * MAX_TRACE_LENGTH);
|
||||||
|
|
||||||
|
trace_t tr;
|
||||||
|
UTIL_TraceLine(vecPosition, vecAbsEnd, MASK_OPAQUE, NULL, COLLISION_GROUP_NONE, &tr);
|
||||||
|
|
||||||
|
// If we didn't hit anything then we have a problem
|
||||||
|
if(!tr.DidHit())
|
||||||
|
{
|
||||||
|
//engine->Con_NPrintf(i, "%d: skylight: couldn't touch sky", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we did hit something, and it wasn't the skybox, then skip
|
||||||
|
// this worldlight
|
||||||
|
if(!(tr.surface.flags & SURF_SKY) && !(tr.surface.flags & SURF_SKY2D))
|
||||||
|
{
|
||||||
|
//engine->Con_NPrintf(i, "%d: skylight: no sight to sun", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Act like we didn't find any valid worldlights, so the shadow
|
||||||
|
// manager uses the default shadow direction instead (should be the
|
||||||
|
// sun direction)
|
||||||
|
|
||||||
|
delete[] pvs;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate square distance to this worldlight
|
||||||
|
Vector vecDelta = light->origin - vecPosition;
|
||||||
|
float flDistSqr = vecDelta.LengthSqr();
|
||||||
|
float flRadiusSqr = light->radius * light->radius;
|
||||||
|
|
||||||
|
// Skip lights that are out of our radius
|
||||||
|
if(flRadiusSqr > 0 && flDistSqr >= flRadiusSqr)
|
||||||
|
{
|
||||||
|
//engine->Con_NPrintf(i, "%d: out-of-radius (dist: %d, radius: %d)", i, sqrt(flDistSqr), light->radius);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it out of our PVS?
|
||||||
|
if(!g_pEngineServer->CheckOriginInPVS(light->origin, pvs, nPVSSize))
|
||||||
|
{
|
||||||
|
//engine->Con_NPrintf(i, "%d: out of PVS", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate intensity at our position
|
||||||
|
float flRatio = Engine_WorldLightDistanceFalloff(light, vecDelta);
|
||||||
|
Vector vecIntensity = light->intensity * flRatio;
|
||||||
|
|
||||||
|
// Is this light more intense than the one we already found?
|
||||||
|
if(vecIntensity.LengthSqr() <= vecLightBrightness.LengthSqr())
|
||||||
|
{
|
||||||
|
//engine->Con_NPrintf(i, "%d: too dim", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can we see the light?
|
||||||
|
trace_t tr;
|
||||||
|
Vector vecAbsStart = vecPosition + Vector(0,0,30);
|
||||||
|
UTIL_TraceLine(vecAbsStart, light->origin, MASK_OPAQUE, NULL, COLLISION_GROUP_NONE, &tr);
|
||||||
|
|
||||||
|
if(tr.DidHit())
|
||||||
|
{
|
||||||
|
//engine->Con_NPrintf(i, "%d: trace failed", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vecLightPos = light->origin;
|
||||||
|
vecLightBrightness = vecIntensity;
|
||||||
|
|
||||||
|
//engine->Con_NPrintf(i, "%d: set (%.2f)", i, vecIntensity.Length());
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] pvs;
|
||||||
|
|
||||||
|
//engine->Con_NPrintf(m_nWorldLights, "result: %d", !vecLightBrightness.IsZero());
|
||||||
|
return !vecLightBrightness.IsZero();
|
||||||
|
}
|
47
sp/src/game/client/worldlight.h
Normal file
47
sp/src/game/client/worldlight.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//========= Copyright (C) 2018, CSProMod Team, All rights reserved. =========//
|
||||||
|
//
|
||||||
|
// Purpose: provide world light related functions to the client
|
||||||
|
//
|
||||||
|
// Written: November 2011
|
||||||
|
// Author: Saul Rennison
|
||||||
|
//
|
||||||
|
//===========================================================================//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "igamesystem.h" // CAutoGameSystem
|
||||||
|
|
||||||
|
class Vector;
|
||||||
|
struct dworldlight_t;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class CWorldLights : public CAutoGameSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CWorldLights();
|
||||||
|
~CWorldLights() { Clear(); }
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Find the brightest light source at a point
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
bool GetBrightestLightSource(const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness);
|
||||||
|
|
||||||
|
// CAutoGameSystem overrides
|
||||||
|
public:
|
||||||
|
virtual bool Init();
|
||||||
|
virtual void LevelInitPreEntity();
|
||||||
|
virtual void LevelShutdownPostEntity() { Clear(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
int m_nWorldLights;
|
||||||
|
dworldlight_t *m_pWorldLights;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Singleton exposure
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
extern CWorldLights *g_pWorldLights;
|
@ -176,6 +176,22 @@ void AI_CriteriaSet::Describe()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Merges another AI_CriteriaSet without clearing
|
||||||
|
// Input : src -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void AI_CriteriaSet::MergeSet( const AI_CriteriaSet& src )
|
||||||
|
{
|
||||||
|
for ( short i = src.m_Lookup.FirstInorder();
|
||||||
|
i != src.m_Lookup.InvalidIndex();
|
||||||
|
i = src.m_Lookup.NextInorder( i ) )
|
||||||
|
{
|
||||||
|
m_Lookup.Insert( src.m_Lookup[ i ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BEGIN_SIMPLE_DATADESC( AI_ResponseParams )
|
BEGIN_SIMPLE_DATADESC( AI_ResponseParams )
|
||||||
DEFINE_FIELD( flags, FIELD_SHORT ),
|
DEFINE_FIELD( flags, FIELD_SHORT ),
|
||||||
DEFINE_FIELD( odds, FIELD_SHORT ),
|
DEFINE_FIELD( odds, FIELD_SHORT ),
|
||||||
@ -202,7 +218,11 @@ AI_Response::AI_Response()
|
|||||||
m_pCriteria = NULL;
|
m_pCriteria = NULL;
|
||||||
m_szMatchingRule[0]=0;
|
m_szMatchingRule[0]=0;
|
||||||
m_szContext = NULL;
|
m_szContext = NULL;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iContextFlags = 0;
|
||||||
|
#else
|
||||||
m_bApplyContextToWorld = false;
|
m_bApplyContextToWorld = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -215,7 +235,11 @@ AI_Response::AI_Response( const AI_Response &from )
|
|||||||
m_pCriteria = NULL;
|
m_pCriteria = NULL;
|
||||||
m_szContext = NULL;
|
m_szContext = NULL;
|
||||||
SetContext( from.m_szContext );
|
SetContext( from.m_szContext );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iContextFlags = from.m_iContextFlags;
|
||||||
|
#else
|
||||||
m_bApplyContextToWorld = from.m_bApplyContextToWorld;
|
m_bApplyContextToWorld = from.m_bApplyContextToWorld;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -237,7 +261,11 @@ AI_Response &AI_Response::operator=( const AI_Response &from )
|
|||||||
m_pCriteria = NULL;
|
m_pCriteria = NULL;
|
||||||
m_szContext = NULL;
|
m_szContext = NULL;
|
||||||
SetContext( from.m_szContext );
|
SetContext( from.m_szContext );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iContextFlags = from.m_iContextFlags;
|
||||||
|
#else
|
||||||
m_bApplyContextToWorld = from.m_bApplyContextToWorld;
|
m_bApplyContextToWorld = from.m_bApplyContextToWorld;
|
||||||
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,9 +283,32 @@ void AI_Response::Init( ResponseType_t type, const char *responseName, const AI_
|
|||||||
Q_strncpy( m_szMatchingRule, ruleName ? ruleName : "NULL", sizeof( m_szMatchingRule ) );
|
Q_strncpy( m_szMatchingRule, ruleName ? ruleName : "NULL", sizeof( m_szMatchingRule ) );
|
||||||
m_Params = responseparams;
|
m_Params = responseparams;
|
||||||
SetContext( applyContext );
|
SetContext( applyContext );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bApplyContextToWorld ? m_iContextFlags = APPLYCONTEXT_WORLD : m_iContextFlags = 0;
|
||||||
|
#else
|
||||||
m_bApplyContextToWorld = bApplyContextToWorld;
|
m_bApplyContextToWorld = bApplyContextToWorld;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : *response -
|
||||||
|
// *criteria -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void AI_Response::Init( ResponseType_t type, const char *responseName, const AI_CriteriaSet& criteria, const AI_ResponseParams& responseparams, const char *ruleName, const char *applyContext, int iContextFlags )
|
||||||
|
{
|
||||||
|
m_Type = type;
|
||||||
|
Q_strncpy( m_szResponseName, responseName, sizeof( m_szResponseName ) );
|
||||||
|
// Copy underlying criteria
|
||||||
|
m_pCriteria = new AI_CriteriaSet( criteria );
|
||||||
|
Q_strncpy( m_szMatchingRule, ruleName ? ruleName : "NULL", sizeof( m_szMatchingRule ) );
|
||||||
|
m_Params = responseparams;
|
||||||
|
SetContext( applyContext );
|
||||||
|
m_iContextFlags = iContextFlags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -274,7 +325,19 @@ void AI_Response::Describe()
|
|||||||
}
|
}
|
||||||
if ( m_szContext )
|
if ( m_szContext )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DevMsg( "Contexts to set '%s' on ", m_szContext );
|
||||||
|
if (m_iContextFlags & APPLYCONTEXT_WORLD)
|
||||||
|
DevMsg("world, ");
|
||||||
|
else if (m_iContextFlags & APPLYCONTEXT_SQUAD)
|
||||||
|
DevMsg("squad, ");
|
||||||
|
else if (m_iContextFlags & APPLYCONTEXT_ENEMY)
|
||||||
|
DevMsg("enemy, ");
|
||||||
|
else
|
||||||
|
DevMsg("speaker, ");
|
||||||
|
#else
|
||||||
DevMsg( "Contexts to set '%s' on %s, ", m_szContext, m_bApplyContextToWorld ? "world" : "speaker" );
|
DevMsg( "Contexts to set '%s' on %s, ", m_szContext, m_bApplyContextToWorld ? "world" : "speaker" );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DevMsg( "response %s = '%s'\n", DescribeResponse( (ResponseType_t)m_Type ), m_szResponseName );
|
DevMsg( "response %s = '%s'\n", DescribeResponse( (ResponseType_t)m_Type ), m_szResponseName );
|
||||||
|
@ -37,6 +37,10 @@ public:
|
|||||||
const char *GetValue( int index ) const;
|
const char *GetValue( int index ) const;
|
||||||
float GetWeight( int index ) const;
|
float GetWeight( int index ) const;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void MergeSet( const AI_CriteriaSet& src );
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct CritEntry_t
|
struct CritEntry_t
|
||||||
@ -168,6 +172,24 @@ enum ResponseType_t
|
|||||||
NUM_RESPONSES,
|
NUM_RESPONSES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// I wanted to add more options to apply contexts to,
|
||||||
|
// so I replaced the existing system with a flag-based integer instead of a bunch of booleans.
|
||||||
|
//
|
||||||
|
// New ones should be implemented in:
|
||||||
|
// CResponseSystem::ParseRule() - AI_ResponseSystem.cpp
|
||||||
|
// AI_Response::Describe() - AI_Criteria.cpp
|
||||||
|
// CAI_Expresser::SpeakDispatchResponse() - ai_speech.cpp
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
APPLYCONTEXT_SELF = (1 << 0), // Included for contexts that apply to both self and something else
|
||||||
|
APPLYCONTEXT_WORLD = (1 << 1), // Apply to world
|
||||||
|
|
||||||
|
APPLYCONTEXT_SQUAD = (1 << 2), // Apply to squad
|
||||||
|
APPLYCONTEXT_ENEMY = (1 << 3), // Apply to enemy
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class AI_Response
|
class AI_Response
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -197,7 +219,12 @@ public:
|
|||||||
void SetContext( const char *context );
|
void SetContext( const char *context );
|
||||||
const char * GetContext( void ) const { return m_szContext; }
|
const char * GetContext( void ) const { return m_szContext; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int GetContextFlags() { return m_iContextFlags; }
|
||||||
|
bool IsApplyContextToWorld( void ) { return (m_iContextFlags & APPLYCONTEXT_WORLD) != 0; }
|
||||||
|
#else
|
||||||
bool IsApplyContextToWorld( void ) { return m_bApplyContextToWorld; }
|
bool IsApplyContextToWorld( void ) { return m_bApplyContextToWorld; }
|
||||||
|
#endif
|
||||||
|
|
||||||
void Describe();
|
void Describe();
|
||||||
|
|
||||||
@ -211,6 +238,16 @@ public:
|
|||||||
const char *applyContext,
|
const char *applyContext,
|
||||||
bool bApplyContextToWorld );
|
bool bApplyContextToWorld );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void Init( ResponseType_t type,
|
||||||
|
const char *responseName,
|
||||||
|
const AI_CriteriaSet& criteria,
|
||||||
|
const AI_ResponseParams& responseparams,
|
||||||
|
const char *matchingRule,
|
||||||
|
const char *applyContext,
|
||||||
|
int iContextFlags );
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *DescribeResponse( ResponseType_t type );
|
static const char *DescribeResponse( ResponseType_t type );
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -231,7 +268,11 @@ private:
|
|||||||
AI_ResponseParams m_Params;
|
AI_ResponseParams m_Params;
|
||||||
|
|
||||||
char * m_szContext;
|
char * m_szContext;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int m_iContextFlags;
|
||||||
|
#else
|
||||||
bool m_bApplyContextToWorld;
|
bool m_bApplyContextToWorld;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AI_CRITERIA_H
|
#endif // AI_CRITERIA_H
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
#include "stringpool.h"
|
#include "stringpool.h"
|
||||||
#include "fmtstr.h"
|
#include "fmtstr.h"
|
||||||
#include "multiplay_gamerules.h"
|
#include "multiplay_gamerules.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "mapbase/matchers.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
@ -57,6 +60,9 @@ public:
|
|||||||
minequals = false;
|
minequals = false;
|
||||||
usemax = false;
|
usemax = false;
|
||||||
maxequals = false;
|
maxequals = false;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
isbit = false;
|
||||||
|
#endif
|
||||||
maxval = 0.0f;
|
maxval = 0.0f;
|
||||||
minval = 0.0f;
|
minval = 0.0f;
|
||||||
|
|
||||||
@ -99,6 +105,14 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (isbit)
|
||||||
|
{
|
||||||
|
DevMsg( " matcher: &%s%s\n", notequal ? "~" : "", GetToken() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( notequal )
|
if ( notequal )
|
||||||
{
|
{
|
||||||
DevMsg( " matcher: !=%s\n", GetToken() );
|
DevMsg( " matcher: !=%s\n", GetToken() );
|
||||||
@ -118,6 +132,9 @@ public:
|
|||||||
bool minequals : 1; //5
|
bool minequals : 1; //5
|
||||||
bool usemax : 1; //6
|
bool usemax : 1; //6
|
||||||
bool maxequals : 1; //7
|
bool maxequals : 1; //7
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool isbit : 1; //8
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetToken( char const *s )
|
void SetToken( char const *s )
|
||||||
{
|
{
|
||||||
@ -461,7 +478,11 @@ struct Rule
|
|||||||
m_bMatchOnce = false;
|
m_bMatchOnce = false;
|
||||||
m_bEnabled = true;
|
m_bEnabled = true;
|
||||||
m_szContext = NULL;
|
m_szContext = NULL;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iContextFlags = 0;
|
||||||
|
#else
|
||||||
m_bApplyContextToWorld = false;
|
m_bApplyContextToWorld = false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule& operator =( const Rule& src )
|
Rule& operator =( const Rule& src )
|
||||||
@ -487,7 +508,11 @@ struct Rule
|
|||||||
SetContext( src.m_szContext );
|
SetContext( src.m_szContext );
|
||||||
m_bMatchOnce = src.m_bMatchOnce;
|
m_bMatchOnce = src.m_bMatchOnce;
|
||||||
m_bEnabled = src.m_bEnabled;
|
m_bEnabled = src.m_bEnabled;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iContextFlags = src.m_iContextFlags;
|
||||||
|
#else
|
||||||
m_bApplyContextToWorld = src.m_bApplyContextToWorld;
|
m_bApplyContextToWorld = src.m_bApplyContextToWorld;
|
||||||
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -511,7 +536,11 @@ struct Rule
|
|||||||
SetContext( src.m_szContext );
|
SetContext( src.m_szContext );
|
||||||
m_bMatchOnce = src.m_bMatchOnce;
|
m_bMatchOnce = src.m_bMatchOnce;
|
||||||
m_bEnabled = src.m_bEnabled;
|
m_bEnabled = src.m_bEnabled;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_iContextFlags = src.m_iContextFlags;
|
||||||
|
#else
|
||||||
m_bApplyContextToWorld = src.m_bApplyContextToWorld;
|
m_bApplyContextToWorld = src.m_bApplyContextToWorld;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~Rule()
|
~Rule()
|
||||||
@ -530,14 +559,22 @@ struct Rule
|
|||||||
bool IsEnabled() const { return m_bEnabled; }
|
bool IsEnabled() const { return m_bEnabled; }
|
||||||
void Disable() { m_bEnabled = false; }
|
void Disable() { m_bEnabled = false; }
|
||||||
bool IsMatchOnce() const { return m_bMatchOnce; }
|
bool IsMatchOnce() const { return m_bMatchOnce; }
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool IsApplyContextToWorld() const { return (m_iContextFlags & APPLYCONTEXT_WORLD) != 0; }
|
||||||
|
#else
|
||||||
bool IsApplyContextToWorld() const { return m_bApplyContextToWorld; }
|
bool IsApplyContextToWorld() const { return m_bApplyContextToWorld; }
|
||||||
|
#endif
|
||||||
|
|
||||||
// Indices into underlying criteria and response dictionaries
|
// Indices into underlying criteria and response dictionaries
|
||||||
CUtlVector< unsigned short > m_Criteria;
|
CUtlVector< unsigned short > m_Criteria;
|
||||||
CUtlVector< unsigned short> m_Responses;
|
CUtlVector< unsigned short> m_Responses;
|
||||||
|
|
||||||
char *m_szContext;
|
char *m_szContext;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int m_iContextFlags;
|
||||||
|
#else
|
||||||
bool m_bApplyContextToWorld : 1;
|
bool m_bApplyContextToWorld : 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool m_bMatchOnce : 1;
|
bool m_bMatchOnce : 1;
|
||||||
bool m_bEnabled : 1;
|
bool m_bEnabled : 1;
|
||||||
@ -668,7 +705,11 @@ public:
|
|||||||
|
|
||||||
void ParseOneResponse( const char *responseGroupName, ResponseGroup& group );
|
void ParseOneResponse( const char *responseGroupName, ResponseGroup& group );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void ParseInclude( CStringPool &includedFiles, const char *scriptfile = NULL );
|
||||||
|
#else
|
||||||
void ParseInclude( CStringPool &includedFiles );
|
void ParseInclude( CStringPool &includedFiles );
|
||||||
|
#endif
|
||||||
void ParseResponse( void );
|
void ParseResponse( void );
|
||||||
void ParseCriterion( void );
|
void ParseCriterion( void );
|
||||||
void ParseRule( void );
|
void ParseRule( void );
|
||||||
@ -865,6 +906,7 @@ void CResponseSystem::ResolveToken( Matcher& matcher, char *token, size_t bufsiz
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MAPBASE // Moved to matchers.h
|
||||||
static bool AppearsToBeANumber( char const *token )
|
static bool AppearsToBeANumber( char const *token )
|
||||||
{
|
{
|
||||||
if ( atof( token ) != 0.0f )
|
if ( atof( token ) != 0.0f )
|
||||||
@ -881,6 +923,7 @@ static bool AppearsToBeANumber( char const *token )
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void CResponseSystem::ComputeMatcher( Criteria *c, Matcher& matcher )
|
void CResponseSystem::ComputeMatcher( Criteria *c, Matcher& matcher )
|
||||||
{
|
{
|
||||||
@ -905,6 +948,9 @@ void CResponseSystem::ComputeMatcher( Criteria *c, Matcher& matcher )
|
|||||||
bool lt = false;
|
bool lt = false;
|
||||||
bool eq = false;
|
bool eq = false;
|
||||||
bool nt = false;
|
bool nt = false;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool bit = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while ( !done )
|
while ( !done )
|
||||||
@ -937,6 +983,17 @@ void CResponseSystem::ComputeMatcher( Criteria *c, Matcher& matcher )
|
|||||||
// Convert raw token to real token in case token is an enumerated type specifier
|
// Convert raw token to real token in case token is an enumerated type specifier
|
||||||
ResolveToken( matcher, token, sizeof( token ), rawtoken );
|
ResolveToken( matcher, token, sizeof( token ), rawtoken );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Bits are an entirely different and independent story
|
||||||
|
if (bit)
|
||||||
|
{
|
||||||
|
matcher.isbit = true;
|
||||||
|
matcher.notequal = nt;
|
||||||
|
|
||||||
|
matcher.isnumeric = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
// Fill in first data set
|
// Fill in first data set
|
||||||
if ( gt )
|
if ( gt )
|
||||||
{
|
{
|
||||||
@ -978,6 +1035,13 @@ void CResponseSystem::ComputeMatcher( Criteria *c, Matcher& matcher )
|
|||||||
case '!':
|
case '!':
|
||||||
nt = true;
|
nt = true;
|
||||||
break;
|
break;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
case '~':
|
||||||
|
nt = true;
|
||||||
|
case '&':
|
||||||
|
bit = true;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
rawtoken[ n++ ] = *in;
|
rawtoken[ n++ ] = *in;
|
||||||
break;
|
break;
|
||||||
@ -1003,6 +1067,19 @@ bool CResponseSystem::CompareUsingMatcher( const char *setValue, Matcher& m, boo
|
|||||||
v = LookupEnumeration( setValue, found );
|
v = LookupEnumeration( setValue, found );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Bits are always a different story
|
||||||
|
if (m.isbit)
|
||||||
|
{
|
||||||
|
int v1 = v;
|
||||||
|
int v2 = atoi(m.GetToken());
|
||||||
|
if (m.notequal)
|
||||||
|
return (v1 & v2) == 0;
|
||||||
|
else
|
||||||
|
return (v1 & v2) != 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int minmaxcount = 0;
|
int minmaxcount = 0;
|
||||||
|
|
||||||
if ( m.usemin )
|
if ( m.usemin )
|
||||||
@ -1052,7 +1129,11 @@ bool CResponseSystem::CompareUsingMatcher( const char *setValue, Matcher& m, boo
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( Matcher_NamesMatch(m.GetToken(), setValue) )
|
||||||
|
#else
|
||||||
if ( !Q_stricmp( setValue, m.GetToken() ) )
|
if ( !Q_stricmp( setValue, m.GetToken() ) )
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,7 +1150,12 @@ bool CResponseSystem::CompareUsingMatcher( const char *setValue, Matcher& m, boo
|
|||||||
return v == (float)atof( m.GetToken() );
|
return v == (float)atof( m.GetToken() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Wildcards.
|
||||||
|
return Matcher_NamesMatch(m.GetToken(), setValue) ? true : false;
|
||||||
|
#else
|
||||||
return !Q_stricmp( setValue, m.GetToken() ) ? true : false;
|
return !Q_stricmp( setValue, m.GetToken() ) ? true : false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CResponseSystem::Compare( const char *setValue, Criteria *c, bool verbose /*= false*/ )
|
bool CResponseSystem::Compare( const char *setValue, Criteria *c, bool verbose /*= false*/ )
|
||||||
@ -1745,11 +1831,19 @@ bool CResponseSystem::FindBestResponse( const AI_CriteriaSet& set, AI_Response&
|
|||||||
char ruleName[ 128 ];
|
char ruleName[ 128 ];
|
||||||
char responseName[ 128 ];
|
char responseName[ 128 ];
|
||||||
const char *context;
|
const char *context;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
int contextflags;
|
||||||
|
#else
|
||||||
bool bcontexttoworld;
|
bool bcontexttoworld;
|
||||||
|
#endif
|
||||||
ruleName[ 0 ] = 0;
|
ruleName[ 0 ] = 0;
|
||||||
responseName[ 0 ] = 0;
|
responseName[ 0 ] = 0;
|
||||||
context = NULL;
|
context = NULL;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
contextflags = 0;
|
||||||
|
#else
|
||||||
bcontexttoworld = false;
|
bcontexttoworld = false;
|
||||||
|
#endif
|
||||||
if ( bestRule != -1 )
|
if ( bestRule != -1 )
|
||||||
{
|
{
|
||||||
Rule *r = &m_Rules[ bestRule ];
|
Rule *r = &m_Rules[ bestRule ];
|
||||||
@ -1770,12 +1864,20 @@ bool CResponseSystem::FindBestResponse( const AI_CriteriaSet& set, AI_Response&
|
|||||||
r->Disable();
|
r->Disable();
|
||||||
}
|
}
|
||||||
context = r->GetContext();
|
context = r->GetContext();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
contextflags = r->m_iContextFlags;
|
||||||
|
#else
|
||||||
bcontexttoworld = r->IsApplyContextToWorld();
|
bcontexttoworld = r->IsApplyContextToWorld();
|
||||||
|
#endif
|
||||||
|
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
response.Init( responseType, responseName, set, rp, ruleName, context, contextflags );
|
||||||
|
#else
|
||||||
response.Init( responseType, responseName, set, rp, ruleName, context, bcontexttoworld );
|
response.Init( responseType, responseName, set, rp, ruleName, context, bcontexttoworld );
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( showResult )
|
if ( showResult )
|
||||||
{
|
{
|
||||||
@ -1894,11 +1996,42 @@ void CResponseSystem::Precache()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void CResponseSystem::ParseInclude( CStringPool &includedFiles, const char *scriptfile )
|
||||||
|
#else
|
||||||
void CResponseSystem::ParseInclude( CStringPool &includedFiles )
|
void CResponseSystem::ParseInclude( CStringPool &includedFiles )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
char includefile[ 256 ];
|
char includefile[ 256 ];
|
||||||
ParseToken();
|
ParseToken();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (scriptfile)
|
||||||
|
{
|
||||||
|
// Gets first path
|
||||||
|
// (for example, an #include from a file in resource/script/resp will return resource)
|
||||||
|
size_t len = strlen(scriptfile)-1;
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (scriptfile[i] == CORRECT_PATH_SEPARATOR || scriptfile[i] == INCORRECT_PATH_SEPARATOR)
|
||||||
|
{
|
||||||
|
len = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q_strncpy(includefile, scriptfile, len+1);
|
||||||
|
|
||||||
|
if (len+1 != strlen(scriptfile))
|
||||||
|
{
|
||||||
|
Q_snprintf(includefile, sizeof(includefile), "%s/%s", includefile, token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
includefile[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!includefile[0])
|
||||||
Q_snprintf( includefile, sizeof( includefile ), "scripts/%s", token );
|
Q_snprintf( includefile, sizeof( includefile ), "scripts/%s", token );
|
||||||
|
#else
|
||||||
|
Q_snprintf( includefile, sizeof( includefile ), "scripts/%s", token );
|
||||||
|
#endif
|
||||||
|
|
||||||
// check if the file is already included
|
// check if the file is already included
|
||||||
if ( includedFiles.Find( includefile ) != NULL )
|
if ( includedFiles.Find( includefile ) != NULL )
|
||||||
@ -1939,8 +2072,19 @@ void CResponseSystem::LoadFromBuffer( const char *scriptfile, const char *buffer
|
|||||||
|
|
||||||
if ( !Q_stricmp( token, "#include" ) )
|
if ( !Q_stricmp( token, "#include" ) )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ParseInclude( includedFiles, scriptfile );
|
||||||
|
#else
|
||||||
ParseInclude( includedFiles );
|
ParseInclude( includedFiles );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else if ( !Q_stricmp( token, "#base" ) )
|
||||||
|
{
|
||||||
|
// Actual #base in the future?
|
||||||
|
ParseInclude( includedFiles, scriptfile );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else if ( !Q_stricmp( token, "response" ) )
|
else if ( !Q_stricmp( token, "response" ) )
|
||||||
{
|
{
|
||||||
ParseResponse();
|
ParseResponse();
|
||||||
@ -2324,6 +2468,16 @@ void CResponseSystem::ParseResponse( void )
|
|||||||
ParseOneResponse( responseGroupName, newGroup );
|
ParseOneResponse( responseGroupName, newGroup );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
short existing = m_Responses.Find( responseGroupName );
|
||||||
|
if ( existing != m_Responses.InvalidIndex() )
|
||||||
|
{
|
||||||
|
//ResponseWarning( "Additional definition for response '%s', overwriting\n", responseGroupName );
|
||||||
|
m_Responses[existing] = newGroup;
|
||||||
|
m_Responses.SetElementName(existing, responseGroupName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
m_Responses.Insert( responseGroupName, newGroup );
|
m_Responses.Insert( responseGroupName, newGroup );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2405,11 +2559,22 @@ int CResponseSystem::ParseOneCriterion( const char *criterionName )
|
|||||||
ComputeMatcher( &newCriterion, newCriterion.matcher );
|
ComputeMatcher( &newCriterion, newCriterion.matcher );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
short existing = m_Criteria.Find( criterionName );
|
||||||
|
if ( existing != m_Criteria.InvalidIndex() )
|
||||||
|
{
|
||||||
|
//ResponseWarning( "Additional definition for criteria '%s', overwriting\n", criterionName );
|
||||||
|
m_Criteria[existing] = newCriterion;
|
||||||
|
m_Criteria.SetElementName(existing, criterionName);
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( m_Criteria.Find( criterionName ) != m_Criteria.InvalidIndex() )
|
if ( m_Criteria.Find( criterionName ) != m_Criteria.InvalidIndex() )
|
||||||
{
|
{
|
||||||
ResponseWarning( "Multiple definitions for criteria '%s'\n", criterionName );
|
ResponseWarning( "Multiple definitions for criteria '%s'\n", criterionName );
|
||||||
return m_Criteria.InvalidIndex();
|
return m_Criteria.InvalidIndex();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int idx = m_Criteria.Insert( criterionName, newCriterion );
|
int idx = m_Criteria.Insert( criterionName, newCriterion );
|
||||||
return idx;
|
return idx;
|
||||||
@ -2475,12 +2640,22 @@ void CResponseSystem::ParseEnumeration( void )
|
|||||||
{
|
{
|
||||||
m_Enumerations.Insert( sz, newEnum );
|
m_Enumerations.Insert( sz, newEnum );
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else
|
||||||
|
{
|
||||||
|
short existing = m_Enumerations.Find( sz );
|
||||||
|
//ResponseWarning( "Additional definition for enumeration '%s', overwriting\n", sz );
|
||||||
|
m_Enumerations[existing] = newEnum;
|
||||||
|
m_Enumerations.SetElementName(existing, sz);
|
||||||
|
}
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ResponseWarning( "Ignoring duplication enumeration '%s'\n", sz );
|
ResponseWarning( "Ignoring duplication enumeration '%s'\n", sz );
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2531,10 +2706,28 @@ void CResponseSystem::ParseRule( void )
|
|||||||
|
|
||||||
if ( !Q_stricmp( token, "applyContextToWorld" ) )
|
if ( !Q_stricmp( token, "applyContextToWorld" ) )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
newRule.m_iContextFlags |= APPLYCONTEXT_WORLD;
|
||||||
|
#else
|
||||||
newRule.m_bApplyContextToWorld = true;
|
newRule.m_bApplyContextToWorld = true;
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( !Q_stricmp( token, "applyContextToSquad" ) )
|
||||||
|
{
|
||||||
|
newRule.m_iContextFlags |= APPLYCONTEXT_SQUAD;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !Q_stricmp( token, "applyContextToEnemy" ) )
|
||||||
|
{
|
||||||
|
newRule.m_iContextFlags |= APPLYCONTEXT_ENEMY;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( !Q_stricmp( token, "applyContext" ) )
|
if ( !Q_stricmp( token, "applyContext" ) )
|
||||||
{
|
{
|
||||||
ParseToken();
|
ParseToken();
|
||||||
@ -2606,6 +2799,16 @@ void CResponseSystem::ParseRule( void )
|
|||||||
|
|
||||||
if ( validRule )
|
if ( validRule )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
short existing = m_Rules.Find( ruleName );
|
||||||
|
if ( existing != m_Rules.InvalidIndex() )
|
||||||
|
{
|
||||||
|
//ResponseWarning( "Additional definition for rule '%s', overwriting\n", ruleName );
|
||||||
|
m_Rules[existing] = newRule;
|
||||||
|
m_Rules.SetElementName(existing, ruleName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
m_Rules.Insert( ruleName, newRule );
|
m_Rules.Insert( ruleName, newRule );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2791,7 +2994,11 @@ void CResponseSystem::CopyRuleFrom( Rule *pSrcRule, int iRule, CResponseSystem *
|
|||||||
dstRule.SetContext( pSrcRule->GetContext() );
|
dstRule.SetContext( pSrcRule->GetContext() );
|
||||||
dstRule.m_bMatchOnce = pSrcRule->m_bMatchOnce;
|
dstRule.m_bMatchOnce = pSrcRule->m_bMatchOnce;
|
||||||
dstRule.m_bEnabled = pSrcRule->m_bEnabled;
|
dstRule.m_bEnabled = pSrcRule->m_bEnabled;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
dstRule.m_iContextFlags = pSrcRule->m_iContextFlags;
|
||||||
|
#else
|
||||||
dstRule.m_bApplyContextToWorld = pSrcRule->m_bApplyContextToWorld;
|
dstRule.m_bApplyContextToWorld = pSrcRule->m_bApplyContextToWorld;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copy off criteria.
|
// Copy off criteria.
|
||||||
CopyCriteriaFrom( pSrcRule, &dstRule, pCustomSystem );
|
CopyCriteriaFrom( pSrcRule, &dstRule, pCustomSystem );
|
||||||
@ -2806,6 +3013,10 @@ void CResponseSystem::CopyRuleFrom( Rule *pSrcRule, int iRule, CResponseSystem *
|
|||||||
pCustomSystem->m_Rules.Insert( m_Rules.GetElementName( iRule ), dstRule );
|
pCustomSystem->m_Rules.Insert( m_Rules.GetElementName( iRule ), dstRule );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar mapbase_rs_clear("mapbase_rs_clear", "1");
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: A special purpose response system associated with a custom entity
|
// Purpose: A special purpose response system associated with a custom entity
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -2853,6 +3064,32 @@ public:
|
|||||||
Clear();
|
Clear();
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// From an old version of Mapbase's map-specific response system stuff.
|
||||||
|
/*
|
||||||
|
#define CopyRSDict(dict) for (unsigned int i = 0; i < dict.Count(); i++) \
|
||||||
|
{ \
|
||||||
|
rs->dict.Insert(dict.GetElementName(i), dict[i]); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
bool MergeWithMain(bool bRemoveThis = true)
|
||||||
|
{
|
||||||
|
extern IResponseSystem *g_pResponseSystem;
|
||||||
|
CResponseSystem *rs = static_cast<CResponseSystem*>(g_pResponseSystem);
|
||||||
|
|
||||||
|
CopyRSDict(m_Responses);
|
||||||
|
CopyRSDict(m_Criteria);
|
||||||
|
CopyRSDict(m_Rules);
|
||||||
|
CopyRSDict(m_Enumerations);
|
||||||
|
|
||||||
|
if (mapbase_rs_clear.GetBool())
|
||||||
|
Release();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
|
|
||||||
char *m_pszScriptFile;
|
char *m_pszScriptFile;
|
||||||
@ -3051,6 +3288,254 @@ CON_COMMAND( rr_reloadresponsesystems, "Reload all response system scripts." )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Designed for extern magic, this gives the <, >, etc. of response system criteria to the outside world.
|
||||||
|
// Mostly just used for Matcher_Match in matchers.h.
|
||||||
|
bool ResponseSystemCompare(const char *criterion, const char *value)
|
||||||
|
{
|
||||||
|
Criteria criteria;
|
||||||
|
criteria.value = CopyString( criterion );
|
||||||
|
defaultresponsesytem.ComputeMatcher(&criteria, criteria.matcher);
|
||||||
|
return defaultresponsesytem.CompareUsingMatcher(value, criteria.matcher, true);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Another version that returns the criterion without the operators.
|
||||||
|
// I ended up not using this, but feel free to uncomment it.
|
||||||
|
// Just keep in mind it was scrapped before I could test it...
|
||||||
|
/*
|
||||||
|
const char *ResponseSystemCompare(const char *criterion, const char *value, bool bReturnToken)
|
||||||
|
{
|
||||||
|
CResponseSystem *responsesys = dynamic_cast<CResponseSystem*>(g_pResponseSystem);
|
||||||
|
if (responsesys)
|
||||||
|
{
|
||||||
|
Criteria criteria;
|
||||||
|
criteria.value = CopyString( criterion );
|
||||||
|
responsesys->ComputeMatcher(&criteria, criteria.matcher);
|
||||||
|
return responsesys->CompareUsingMatcher(value, criteria.matcher, true) ? criteria.matcher.GetToken() : NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// CResponseFilePrecacher
|
||||||
|
//
|
||||||
|
// Purpose: Precaches a single talker file. That's it.
|
||||||
|
//
|
||||||
|
// It copies from a bunch of the original Response System class and therefore it's really messy.
|
||||||
|
// Despite the horrors a normal programmer might find in here, I think it performs better than anything else I could've come up with.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class CResponseFilePrecacher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Stuff copied from the Response System.
|
||||||
|
// Direct copy-pastes are very compact, to say the least.
|
||||||
|
inline bool ParseToken( void )
|
||||||
|
{
|
||||||
|
if ( m_bUnget )
|
||||||
|
{ m_bUnget = false; return true; }
|
||||||
|
if ( m_ScriptStack.Count() <= 0 )
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
m_ScriptStack[ 0 ].currenttoken = engine->ParseFile( m_ScriptStack[ 0 ].currenttoken, token, sizeof( token ) );
|
||||||
|
m_ScriptStack[ 0 ].tokencount++;
|
||||||
|
return m_ScriptStack[ 0 ].currenttoken != NULL ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUtlVector< CResponseSystem::ScriptEntry > m_ScriptStack;
|
||||||
|
bool m_bUnget;
|
||||||
|
char token[ 1204 ];
|
||||||
|
|
||||||
|
|
||||||
|
void PrecacheResponse( const char *response, byte type )
|
||||||
|
{
|
||||||
|
switch ( type )
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case RESPONSE_SCENE:
|
||||||
|
{
|
||||||
|
DevMsg("Precaching scene %s...\n", response);
|
||||||
|
|
||||||
|
// fixup $gender references
|
||||||
|
char file[_MAX_PATH];
|
||||||
|
Q_strncpy( file, response, sizeof(file) );
|
||||||
|
char *gender = strstr( file, "$gender" );
|
||||||
|
if ( gender )
|
||||||
|
{
|
||||||
|
// replace with male & female
|
||||||
|
const char *postGender = gender + strlen("$gender");
|
||||||
|
*gender = 0;
|
||||||
|
char genderFile[_MAX_PATH];
|
||||||
|
|
||||||
|
Q_snprintf( genderFile, sizeof(genderFile), "%smale%s", file, postGender);
|
||||||
|
PrecacheInstancedScene( genderFile );
|
||||||
|
|
||||||
|
Q_snprintf( genderFile, sizeof(genderFile), "%sfemale%s", file, postGender);
|
||||||
|
PrecacheInstancedScene( genderFile );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrecacheInstancedScene( file );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RESPONSE_SPEAK:
|
||||||
|
{
|
||||||
|
DevMsg("Precaching sound %s...\n", response);
|
||||||
|
CBaseEntity::PrecacheScriptSound( response );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRootCommand()
|
||||||
|
{
|
||||||
|
if (!Q_stricmp( token, "#include" ) || !Q_stricmp( token, "response" )
|
||||||
|
|| !Q_stricmp( token, "enumeration" ) || !Q_stricmp( token, "criteria" )
|
||||||
|
|| !Q_stricmp( token, "criterion" ) || !Q_stricmp( token, "rule" ))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseResponse( void )
|
||||||
|
{
|
||||||
|
// Must go to response group name
|
||||||
|
ParseToken();
|
||||||
|
|
||||||
|
while ( 1 )
|
||||||
|
{
|
||||||
|
ParseToken();
|
||||||
|
|
||||||
|
if ( !Q_stricmp( token, "{" ) )
|
||||||
|
{
|
||||||
|
while ( 1 )
|
||||||
|
{
|
||||||
|
ParseToken();
|
||||||
|
if ( !Q_stricmp( token, "}" ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
byte type = ComputeResponseType( token );
|
||||||
|
if (type == RESPONSE_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ParseToken();
|
||||||
|
char *value = CopyString( token );
|
||||||
|
|
||||||
|
PrecacheResponse(value, type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte type = ComputeResponseType( token );
|
||||||
|
if (type == RESPONSE_NONE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ParseToken();
|
||||||
|
char *value = CopyString( token );
|
||||||
|
|
||||||
|
PrecacheResponse(value, type);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadFromBuffer(const char *scriptfile, unsigned char *buffer, CStringPool &includedFiles)
|
||||||
|
{
|
||||||
|
includedFiles.Allocate( scriptfile );
|
||||||
|
|
||||||
|
CResponseSystem::ScriptEntry e;
|
||||||
|
e.name = filesystem->FindOrAddFileName( scriptfile );
|
||||||
|
e.buffer = buffer;
|
||||||
|
e.currenttoken = (char *)e.buffer;
|
||||||
|
e.tokencount = 0;
|
||||||
|
m_ScriptStack.AddToHead( e );
|
||||||
|
|
||||||
|
while ( 1 )
|
||||||
|
{
|
||||||
|
ParseToken();
|
||||||
|
if ( !token[0] )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !Q_stricmp( token, "response" ) )
|
||||||
|
{
|
||||||
|
ParseResponse();
|
||||||
|
}
|
||||||
|
else if ( !Q_stricmp( token, "#include" ) || !Q_stricmp( token, "#base" ) )
|
||||||
|
{
|
||||||
|
// Compacted version of ParseInclude(), including new changes.
|
||||||
|
// Look at that if you want to read.
|
||||||
|
char includefile[ 256 ];
|
||||||
|
ParseToken();
|
||||||
|
if (scriptfile) { size_t len = strlen(scriptfile)-1;
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{ if (scriptfile[i] == CORRECT_PATH_SEPARATOR || scriptfile[i] == INCORRECT_PATH_SEPARATOR)
|
||||||
|
{ len = i; }
|
||||||
|
} Q_strncpy(includefile, scriptfile, len+1);
|
||||||
|
if (len+1 != strlen(scriptfile))
|
||||||
|
{ Q_snprintf(includefile, sizeof(includefile), "%s/%s", includefile, token); }
|
||||||
|
else includefile[0] = '\0';
|
||||||
|
} if (!includefile[0]) Q_snprintf( includefile, sizeof( includefile ), "scripts/%s", token );
|
||||||
|
|
||||||
|
if ( includedFiles.Find( includefile ) == NULL )
|
||||||
|
{
|
||||||
|
MEM_ALLOC_CREDIT();
|
||||||
|
|
||||||
|
// Try and load it
|
||||||
|
CUtlBuffer buf;
|
||||||
|
if ( filesystem->ReadFile( includefile, "GAME", buf ) )
|
||||||
|
{
|
||||||
|
LoadFromBuffer( includefile, (unsigned char *)buf.PeekGet(), includedFiles );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_ScriptStack.Count() > 0 )
|
||||||
|
m_ScriptStack.Remove( 0 );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Loads a file directly to the main response system
|
||||||
|
bool LoadResponseSystemFile(const char *scriptfile)
|
||||||
|
{
|
||||||
|
CUtlBuffer buf;
|
||||||
|
if ( !filesystem->ReadFile( scriptfile, "GAME", buf ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a really messy and specialized system that precaches the responses and only the responses of a talker file.
|
||||||
|
CStringPool includedFiles;
|
||||||
|
CResponseFilePrecacher *rs = new CResponseFilePrecacher();
|
||||||
|
if (!rs || !rs->LoadFromBuffer(scriptfile, (unsigned char *)buf.PeekGet(), includedFiles))
|
||||||
|
{
|
||||||
|
Warning( "Failed to load response system data from %s", scriptfile );
|
||||||
|
delete rs;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delete rs;
|
||||||
|
|
||||||
|
CStringPool includedFiles2;
|
||||||
|
defaultresponsesytem.LoadFromBuffer(scriptfile, (const char *)buf.PeekGet(), includedFiles2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from Mapbase manifests to flush
|
||||||
|
void ReloadResponseSystem()
|
||||||
|
{
|
||||||
|
defaultresponsesytem.ReloadAllResponseSystems();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static short RESPONSESYSTEM_SAVE_RESTORE_VERSION = 1;
|
static short RESPONSESYSTEM_SAVE_RESTORE_VERSION = 1;
|
||||||
|
|
||||||
// note: this won't save/restore settings from instanced response systems. Could add that with a CDefSaveRestoreOps implementation if needed
|
// note: this won't save/restore settings from instanced response systems. Could add that with a CDefSaveRestoreOps implementation if needed
|
||||||
|
@ -75,6 +75,10 @@ public:
|
|||||||
virtual float GetOpenInterval(void) = 0;
|
virtual float GetOpenInterval(void) = 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool PassesDoorFilter(CBaseEntity *pEntity) { return true; }
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
enum DoorState_t
|
enum DoorState_t
|
||||||
@ -163,6 +167,10 @@ private:
|
|||||||
void InputOpenAwayFrom(inputdata_t &inputdata);
|
void InputOpenAwayFrom(inputdata_t &inputdata);
|
||||||
void InputToggle(inputdata_t &inputdata);
|
void InputToggle(inputdata_t &inputdata);
|
||||||
void InputUnlock(inputdata_t &inputdata);
|
void InputUnlock(inputdata_t &inputdata);
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputAllowPlayerUse(inputdata_t &inputdata);
|
||||||
|
void InputDisallowPlayerUse(inputdata_t &inputdata);
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetDoorBlocker( CBaseEntity *pBlocker );
|
void SetDoorBlocker( CBaseEntity *pBlocker );
|
||||||
|
|
||||||
|
@ -20,10 +20,17 @@ BEGIN_DATADESC( CRagdollMagnet )
|
|||||||
DEFINE_KEYFIELD( m_force, FIELD_FLOAT, "force" ),
|
DEFINE_KEYFIELD( m_force, FIELD_FLOAT, "force" ),
|
||||||
DEFINE_KEYFIELD( m_axis, FIELD_VECTOR, "axis" ),
|
DEFINE_KEYFIELD( m_axis, FIELD_VECTOR, "axis" ),
|
||||||
DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_KEYFIELD( m_BoneTarget, FIELD_STRING, "BoneTarget" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_OUTPUT( m_OnUsed, "OnUsed" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -111,20 +118,54 @@ CRagdollMagnet *CRagdollMagnet::FindBestMagnet( CBaseEntity *pNPC )
|
|||||||
//
|
//
|
||||||
// NOTE: This function assumes pNPC is within this magnet's radius.
|
// NOTE: This function assumes pNPC is within this magnet's radius.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector CRagdollMagnet::GetForceVector( CBaseEntity *pNPC, int *pBone )
|
||||||
|
#else
|
||||||
Vector CRagdollMagnet::GetForceVector( CBaseEntity *pNPC )
|
Vector CRagdollMagnet::GetForceVector( CBaseEntity *pNPC )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
Vector vecForceToApply;
|
Vector vecForceToApply;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector vecNPCPos = pNPC->WorldSpaceCenter();
|
||||||
|
|
||||||
|
if (pBone)
|
||||||
|
{
|
||||||
|
CBaseAnimating *pAnimating = pNPC->GetBaseAnimating();
|
||||||
|
Assert( pAniamting != NULL );
|
||||||
|
|
||||||
|
const char *szBoneTarget = BoneTarget();
|
||||||
|
Assert( szBoneTarget != NULL );
|
||||||
|
|
||||||
|
int iBone = pAnimating->LookupBone( szBoneTarget );
|
||||||
|
|
||||||
|
if (iBone != -1)
|
||||||
|
{
|
||||||
|
matrix3x4_t bonetoworld;
|
||||||
|
pAnimating->GetBoneTransform( iBone, bonetoworld );
|
||||||
|
MatrixPosition( bonetoworld, vecNPCPos );
|
||||||
|
*pBone = iBone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if( IsBarMagnet() )
|
if( IsBarMagnet() )
|
||||||
{
|
{
|
||||||
CPlane axis;
|
CPlane axis;
|
||||||
Vector vecForceDir;
|
Vector vecForceDir;
|
||||||
Vector vecClosest;
|
Vector vecClosest;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CalcClosestPointOnLineSegment( vecNPCPos, GetAbsOrigin(), m_axis, vecClosest, NULL );
|
||||||
|
|
||||||
|
vecForceDir = (vecClosest - vecNPCPos );
|
||||||
|
VectorNormalize( vecForceDir );
|
||||||
|
#else
|
||||||
CalcClosestPointOnLineSegment( pNPC->WorldSpaceCenter(), GetAbsOrigin(), m_axis, vecClosest, NULL );
|
CalcClosestPointOnLineSegment( pNPC->WorldSpaceCenter(), GetAbsOrigin(), m_axis, vecClosest, NULL );
|
||||||
|
|
||||||
vecForceDir = (vecClosest - pNPC->WorldSpaceCenter() );
|
vecForceDir = (vecClosest - pNPC->WorldSpaceCenter() );
|
||||||
VectorNormalize( vecForceDir );
|
VectorNormalize( vecForceDir );
|
||||||
|
#endif
|
||||||
|
|
||||||
vecForceToApply = vecForceDir * m_force;
|
vecForceToApply = vecForceDir * m_force;
|
||||||
}
|
}
|
||||||
@ -132,7 +173,11 @@ Vector CRagdollMagnet::GetForceVector( CBaseEntity *pNPC )
|
|||||||
{
|
{
|
||||||
Vector vecForce;
|
Vector vecForce;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
vecForce = GetAbsOrigin() - vecNPCPos;
|
||||||
|
#else
|
||||||
vecForce = GetAbsOrigin() - pNPC->WorldSpaceCenter();
|
vecForce = GetAbsOrigin() - pNPC->WorldSpaceCenter();
|
||||||
|
#endif
|
||||||
VectorNormalize( vecForce );
|
VectorNormalize( vecForce );
|
||||||
|
|
||||||
vecForceToApply = vecForce * m_force;
|
vecForceToApply = vecForce * m_force;
|
||||||
|
@ -18,7 +18,11 @@ public:
|
|||||||
DECLARE_CLASS( CRagdollMagnet, CPointEntity );
|
DECLARE_CLASS( CRagdollMagnet, CPointEntity );
|
||||||
DECLARE_DATADESC();
|
DECLARE_DATADESC();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector GetForceVector( CBaseEntity *pNPC, int *pBone = NULL );
|
||||||
|
#else
|
||||||
Vector GetForceVector( CBaseEntity *pNPC );
|
Vector GetForceVector( CBaseEntity *pNPC );
|
||||||
|
#endif
|
||||||
float GetRadius( void ) { return m_radius; }
|
float GetRadius( void ) { return m_radius; }
|
||||||
Vector GetAxisVector( void ) { return m_axis - GetAbsOrigin(); }
|
Vector GetAxisVector( void ) { return m_axis - GetAbsOrigin(); }
|
||||||
float DistToPoint( const Vector &vecPoint );
|
float DistToPoint( const Vector &vecPoint );
|
||||||
@ -35,11 +39,20 @@ public:
|
|||||||
void InputEnable( inputdata_t &inputdata );
|
void InputEnable( inputdata_t &inputdata );
|
||||||
void InputDisable( inputdata_t &inputdata );
|
void InputDisable( inputdata_t &inputdata );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
const char *BoneTarget() { return STRING(m_BoneTarget); }
|
||||||
|
|
||||||
|
COutputVector m_OnUsed;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_bDisabled;
|
bool m_bDisabled;
|
||||||
float m_radius;
|
float m_radius;
|
||||||
float m_force;
|
float m_force;
|
||||||
Vector m_axis;
|
Vector m_axis;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
string_t m_BoneTarget;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //CRAGDOLLMAGNET_H
|
#endif //CRAGDOLLMAGNET_H
|
@ -22,6 +22,9 @@
|
|||||||
#include "gamestats.h"
|
#include "gamestats.h"
|
||||||
#include "ai_basenpc.h"
|
#include "ai_basenpc.h"
|
||||||
#include "Sprite.h"
|
#include "Sprite.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "mapbase/SystemConvarMod.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
@ -42,6 +45,7 @@ enum teleport_stages_t
|
|||||||
TELEPORT_FADEIN,
|
TELEPORT_FADEIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef MAPBASE // This has been moved to mapbase/SystemConvarMod.h
|
||||||
// Convar restoration save/restore
|
// Convar restoration save/restore
|
||||||
#define MAX_MODIFIED_CONVAR_STRING 128
|
#define MAX_MODIFIED_CONVAR_STRING 128
|
||||||
struct modifiedconvars_t
|
struct modifiedconvars_t
|
||||||
@ -52,6 +56,7 @@ struct modifiedconvars_t
|
|||||||
char pszCurrentValue[MAX_MODIFIED_CONVAR_STRING];
|
char pszCurrentValue[MAX_MODIFIED_CONVAR_STRING];
|
||||||
char pszOrgValue[MAX_MODIFIED_CONVAR_STRING];
|
char pszOrgValue[MAX_MODIFIED_CONVAR_STRING];
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
bool g_bInCommentaryMode = false;
|
bool g_bInCommentaryMode = false;
|
||||||
bool IsInCommentaryMode( void )
|
bool IsInCommentaryMode( void )
|
||||||
@ -663,6 +668,10 @@ public:
|
|||||||
Msg( "Commentary: Could not find commentary data file '%s'. \n", szFullName );
|
Msg( "Commentary: Could not find commentary data file '%s'. \n", szFullName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE // VDC Memory Leak Fixes
|
||||||
|
pkvFile->deleteThis();
|
||||||
|
#endif
|
||||||
|
|
||||||
engine->LockNetworkStringTables( oldLock );
|
engine->LockNetworkStringTables( oldLock );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,11 +830,13 @@ BEGIN_DATADESC_NO_BASE( CCommentarySystem )
|
|||||||
DEFINE_FIELD( m_iCommentaryNodeCount, FIELD_INTEGER ),
|
DEFINE_FIELD( m_iCommentaryNodeCount, FIELD_INTEGER ),
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
|
||||||
|
#ifndef MAPBASE // This has been moved to mapbase/SystemConvarMod.h
|
||||||
BEGIN_SIMPLE_DATADESC( modifiedconvars_t )
|
BEGIN_SIMPLE_DATADESC( modifiedconvars_t )
|
||||||
DEFINE_ARRAY( pszConvar, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ),
|
DEFINE_ARRAY( pszConvar, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ),
|
||||||
DEFINE_ARRAY( pszCurrentValue, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ),
|
DEFINE_ARRAY( pszCurrentValue, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ),
|
||||||
DEFINE_ARRAY( pszOrgValue, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ),
|
DEFINE_ARRAY( pszOrgValue, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ),
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -48,6 +48,11 @@ public:
|
|||||||
void InputTurnOff( inputdata_t &inputdata );
|
void InputTurnOff( inputdata_t &inputdata );
|
||||||
void InputToggle( inputdata_t &inputdata );
|
void InputToggle( inputdata_t &inputdata );
|
||||||
void InputStrikeOnce( inputdata_t &inputdata );
|
void InputStrikeOnce( inputdata_t &inputdata );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputAmplitude( inputdata_t &inputdata );
|
||||||
|
void InputSetStartEntity( inputdata_t &inputdata ) { m_iszStartEntity = inputdata.value.StringID(); }
|
||||||
|
void InputSetEndEntity( inputdata_t &inputdata ) { m_iszEndEntity = inputdata.value.StringID(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
void TurnOn( void );
|
void TurnOn( void );
|
||||||
void TurnOff( void );
|
void TurnOff( void );
|
||||||
@ -123,6 +128,11 @@ BEGIN_DATADESC( CEnvBeam )
|
|||||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "StrikeOnce", InputStrikeOnce ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "StrikeOnce", InputStrikeOnce ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_INPUTFUNC( FIELD_FLOAT, "Amplitude", InputAmplitude ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_STRING, "SetStartEntity", InputSetStartEntity ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_STRING, "SetEndEntity", InputSetEndEntity ),
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFINE_OUTPUT( m_OnTouchedByEntity, "OnTouchedByEntity" ),
|
DEFINE_OUTPUT( m_OnTouchedByEntity, "OnTouchedByEntity" ),
|
||||||
|
|
||||||
@ -287,6 +297,17 @@ void CEnvBeam::InputStrikeOnce( inputdata_t &inputdata )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Input handler for amplitude
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CEnvBeam::InputAmplitude( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
m_noiseAmplitude = inputdata.value.Float();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Turns the lightning on. If it is set for interval refiring, it will
|
// Purpose: Turns the lightning on. If it is set for interval refiring, it will
|
||||||
// begin doing so. If it is set to be continually on, it will do so.
|
// begin doing so. If it is set to be continually on, it will do so.
|
||||||
@ -383,11 +404,53 @@ void CEnvBeam::Strike( void )
|
|||||||
|
|
||||||
m_speed = clamp( (int) m_speed, 0, (int) MAX_BEAM_SCROLLSPEED );
|
m_speed = clamp( (int) m_speed, 0, (int) MAX_BEAM_SCROLLSPEED );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool pointStart = IsStaticPointEntity( pStart );
|
||||||
|
bool pointEnd = IsStaticPointEntity( pEnd );
|
||||||
|
#else
|
||||||
int pointStart = IsStaticPointEntity( pStart );
|
int pointStart = IsStaticPointEntity( pStart );
|
||||||
int pointEnd = IsStaticPointEntity( pEnd );
|
int pointEnd = IsStaticPointEntity( pEnd );
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( pointStart || pointEnd )
|
if ( pointStart || pointEnd )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_spawnflags & SF_BEAM_RING )
|
||||||
|
{
|
||||||
|
te->BeamRing( filter, 0.0,
|
||||||
|
pStart->entindex(),
|
||||||
|
pEnd->entindex(),
|
||||||
|
m_spriteTexture,
|
||||||
|
0, // No halo
|
||||||
|
m_frameStart,
|
||||||
|
(int)m_flFrameRate,
|
||||||
|
m_life,
|
||||||
|
m_boltWidth,
|
||||||
|
0, // No spread
|
||||||
|
m_noiseAmplitude,
|
||||||
|
m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a,
|
||||||
|
m_speed );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
te->BeamEntPoint( filter, 0.0,
|
||||||
|
pStart->entindex(),
|
||||||
|
&pStart->GetAbsOrigin(),
|
||||||
|
pEnd->entindex(),
|
||||||
|
&pEnd->GetAbsOrigin(),
|
||||||
|
m_spriteTexture,
|
||||||
|
0, // No halo
|
||||||
|
m_frameStart,
|
||||||
|
(int)m_flFrameRate,
|
||||||
|
m_life,
|
||||||
|
m_boltWidth,
|
||||||
|
m_boltWidth, // End width
|
||||||
|
0, // No fade
|
||||||
|
m_noiseAmplitude,
|
||||||
|
m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a,
|
||||||
|
m_speed );
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( m_spawnflags & SF_BEAM_RING )
|
if ( m_spawnflags & SF_BEAM_RING )
|
||||||
{
|
{
|
||||||
// don't work
|
// don't work
|
||||||
@ -410,6 +473,7 @@ void CEnvBeam::Strike( void )
|
|||||||
m_noiseAmplitude,
|
m_noiseAmplitude,
|
||||||
m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a,
|
m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a,
|
||||||
m_speed );
|
m_speed );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -58,6 +58,9 @@ END_DATADESC()
|
|||||||
#define SF_FADE_MODULATE 0x0002 // Modulate, don't blend
|
#define SF_FADE_MODULATE 0x0002 // Modulate, don't blend
|
||||||
#define SF_FADE_ONLYONE 0x0004
|
#define SF_FADE_ONLYONE 0x0004
|
||||||
#define SF_FADE_STAYOUT 0x0008
|
#define SF_FADE_STAYOUT 0x0008
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#define SF_FADE_DONT_PURGE 0x0016
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
@ -93,6 +96,13 @@ void CEnvFade::InputFade( inputdata_t &inputdata )
|
|||||||
fadeFlags |= FFADE_STAYOUT;
|
fadeFlags |= FFADE_STAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( !HasSpawnFlags(SF_FADE_DONT_PURGE) )
|
||||||
|
{
|
||||||
|
fadeFlags |= FFADE_PURGE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( m_spawnflags & SF_FADE_ONLYONE )
|
if ( m_spawnflags & SF_FADE_ONLYONE )
|
||||||
{
|
{
|
||||||
if ( inputdata.pActivator && inputdata.pActivator->IsNetClient() )
|
if ( inputdata.pActivator && inputdata.pActivator->IsNetClient() )
|
||||||
@ -102,7 +112,11 @@ void CEnvFade::InputFade( inputdata_t &inputdata )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), fadeFlags );
|
||||||
|
#else
|
||||||
UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), fadeFlags|FFADE_PURGE );
|
UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), fadeFlags|FFADE_PURGE );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
m_OnBeginFade.FireOutput( inputdata.pActivator, this );
|
m_OnBeginFade.FireOutput( inputdata.pActivator, this );
|
||||||
|
@ -32,6 +32,9 @@ private:
|
|||||||
|
|
||||||
void InputShowHudHint( inputdata_t &inputdata );
|
void InputShowHudHint( inputdata_t &inputdata );
|
||||||
void InputHideHudHint( inputdata_t &inputdata );
|
void InputHideHudHint( inputdata_t &inputdata );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputSetHudHint( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
string_t m_iszMessage;
|
string_t m_iszMessage;
|
||||||
DECLARE_DATADESC();
|
DECLARE_DATADESC();
|
||||||
};
|
};
|
||||||
@ -43,6 +46,9 @@ BEGIN_DATADESC( CEnvHudHint )
|
|||||||
DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ),
|
DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "ShowHudHint", InputShowHudHint ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "ShowHudHint", InputShowHudHint ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "HideHudHint", InputHideHudHint ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "HideHudHint", InputHideHudHint ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_INPUTFUNC( FIELD_STRING, "SetHudHint", InputSetHudHint ),
|
||||||
|
#endif
|
||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
|
||||||
@ -140,3 +146,12 @@ void CEnvHudHint::InputHideHudHint( inputdata_t &inputdata )
|
|||||||
MessageEnd();
|
MessageEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CEnvHudHint::InputSetHudHint( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
m_iszMessage = inputdata.value.StringID();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -31,6 +31,10 @@ BEGIN_DATADESC( CEnvLaser )
|
|||||||
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_OUTPUT( m_OnTouchedByEntity, "OnTouchedByEntity" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
|
||||||
|
|
||||||
@ -221,6 +225,12 @@ void CEnvLaser::FireAtPoint( trace_t &tr )
|
|||||||
// Apply damage and do sparks every 1/10th of a second.
|
// Apply damage and do sparks every 1/10th of a second.
|
||||||
if ( gpGlobals->curtime >= m_flFireTime + 0.1 )
|
if ( gpGlobals->curtime >= m_flFireTime + 0.1 )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( tr.fraction != 1.0 && tr.m_pEnt && !tr.m_pEnt->IsWorld() )
|
||||||
|
{
|
||||||
|
m_OnTouchedByEntity.FireOutput( tr.m_pEnt, this );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
BeamDamage( &tr );
|
BeamDamage( &tr );
|
||||||
DoSparks( GetAbsStartPos(), tr.endpos );
|
DoSparks( GetAbsStartPos(), tr.endpos );
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,9 @@ public:
|
|||||||
void InputTurnOn( inputdata_t &inputdata );
|
void InputTurnOn( inputdata_t &inputdata );
|
||||||
void InputTurnOff( inputdata_t &inputdata );
|
void InputTurnOff( inputdata_t &inputdata );
|
||||||
void InputToggle( inputdata_t &inputdata );
|
void InputToggle( inputdata_t &inputdata );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputSetTarget( inputdata_t &inputdata ) { m_iszLaserTarget = inputdata.value.StringID(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
DECLARE_DATADESC();
|
DECLARE_DATADESC();
|
||||||
|
|
||||||
@ -45,6 +48,10 @@ public:
|
|||||||
string_t m_iszSpriteName;
|
string_t m_iszSpriteName;
|
||||||
Vector m_firePosition;
|
Vector m_firePosition;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
COutputEvent m_OnTouchedByEntity;
|
||||||
|
#endif
|
||||||
|
|
||||||
float m_flStartFrame;
|
float m_flStartFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -168,6 +168,11 @@ private:
|
|||||||
|
|
||||||
bool m_bRolledOutroCredits;
|
bool m_bRolledOutroCredits;
|
||||||
float m_flLogoLength;
|
float m_flLogoLength;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Custom credits.txt, defaults to that
|
||||||
|
string_t m_iszCreditsFile;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
LINK_ENTITY_TO_CLASS( env_credits, CCredits );
|
LINK_ENTITY_TO_CLASS( env_credits, CCredits );
|
||||||
@ -179,6 +184,10 @@ BEGIN_DATADESC( CCredits )
|
|||||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetLogoLength", InputSetLogoLength ),
|
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetLogoLength", InputSetLogoLength ),
|
||||||
DEFINE_OUTPUT( m_OnCreditsDone, "OnCreditsDone"),
|
DEFINE_OUTPUT( m_OnCreditsDone, "OnCreditsDone"),
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_KEYFIELD( m_iszCreditsFile, FIELD_STRING, "CreditsFile" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFINE_FIELD( m_bRolledOutroCredits, FIELD_BOOLEAN ),
|
DEFINE_FIELD( m_bRolledOutroCredits, FIELD_BOOLEAN ),
|
||||||
DEFINE_FIELD( m_flLogoLength, FIELD_FLOAT )
|
DEFINE_FIELD( m_flLogoLength, FIELD_FLOAT )
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
@ -226,6 +235,9 @@ void CCredits::RollOutroCredits()
|
|||||||
|
|
||||||
UserMessageBegin( user, "CreditsMsg" );
|
UserMessageBegin( user, "CreditsMsg" );
|
||||||
WRITE_BYTE( 3 );
|
WRITE_BYTE( 3 );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||||
|
#endif
|
||||||
MessageEnd();
|
MessageEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,12 +262,18 @@ void CCredits::InputShowLogo( inputdata_t &inputdata )
|
|||||||
{
|
{
|
||||||
UserMessageBegin( user, "LogoTimeMsg" );
|
UserMessageBegin( user, "LogoTimeMsg" );
|
||||||
WRITE_FLOAT( m_flLogoLength );
|
WRITE_FLOAT( m_flLogoLength );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||||
|
#endif
|
||||||
MessageEnd();
|
MessageEnd();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UserMessageBegin( user, "CreditsMsg" );
|
UserMessageBegin( user, "CreditsMsg" );
|
||||||
WRITE_BYTE( 1 );
|
WRITE_BYTE( 1 );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||||
|
#endif
|
||||||
MessageEnd();
|
MessageEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,5 +292,8 @@ void CCredits::InputRollCredits( inputdata_t &inputdata )
|
|||||||
|
|
||||||
UserMessageBegin( user, "CreditsMsg" );
|
UserMessageBegin( user, "CreditsMsg" );
|
||||||
WRITE_BYTE( 2 );
|
WRITE_BYTE( 2 );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
WRITE_STRING( STRING(m_iszCreditsFile) );
|
||||||
|
#endif
|
||||||
MessageEnd();
|
MessageEnd();
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
#include "effect_dispatch_data.h"
|
#include "effect_dispatch_data.h"
|
||||||
#include "te_effect_dispatch.h"
|
#include "te_effect_dispatch.h"
|
||||||
#include "IEffects.h"
|
#include "IEffects.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "saverestore_utlvector.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
@ -266,3 +269,137 @@ void CRagdollBoogie::BoogieThink( void )
|
|||||||
|
|
||||||
SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
|
SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Allows mappers to control ragdoll dancing
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
class CPointRagdollBoogie : public CBaseEntity
|
||||||
|
{
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
DECLARE_CLASS( CPointRagdollBoogie, CBaseEntity );
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool ApplyBoogie(CBaseEntity *pTarget, CBaseEntity *pActivator);
|
||||||
|
|
||||||
|
void InputActivate( inputdata_t &inputdata );
|
||||||
|
void InputDeactivate( inputdata_t &inputdata );
|
||||||
|
void InputBoogieTarget( inputdata_t &inputdata );
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_flStartTime;
|
||||||
|
float m_flBoogieLength;
|
||||||
|
float m_flMagnitude;
|
||||||
|
|
||||||
|
// This allows us to remove active boogies later.
|
||||||
|
CUtlVector<EHANDLE> m_Boogies;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Save/load
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
BEGIN_DATADESC( CPointRagdollBoogie )
|
||||||
|
|
||||||
|
DEFINE_KEYFIELD( m_flStartTime, FIELD_FLOAT, "StartTime" ),
|
||||||
|
DEFINE_KEYFIELD( m_flBoogieLength, FIELD_FLOAT, "BoogieLength" ),
|
||||||
|
DEFINE_KEYFIELD( m_flMagnitude, FIELD_FLOAT, "Magnitude" ),
|
||||||
|
|
||||||
|
// Think this should be handled by StartTouch/etc.
|
||||||
|
// DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ),
|
||||||
|
|
||||||
|
DEFINE_UTLVECTOR( m_Boogies, FIELD_EHANDLE ),
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_STRING, "BoogieTarget", InputBoogieTarget ),
|
||||||
|
|
||||||
|
END_DATADESC()
|
||||||
|
|
||||||
|
LINK_ENTITY_TO_CLASS( point_ragdollboogie, CPointRagdollBoogie );
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : &inputdata -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CPointRagdollBoogie::ApplyBoogie( CBaseEntity *pTarget, CBaseEntity *pActivator )
|
||||||
|
{
|
||||||
|
if (dynamic_cast<CRagdollProp*>(pTarget))
|
||||||
|
{
|
||||||
|
m_Boogies.AddToTail(CRagdollBoogie::Create(pTarget, m_flMagnitude, gpGlobals->curtime + m_flStartTime, m_flBoogieLength, GetSpawnFlags()));
|
||||||
|
}
|
||||||
|
else if (pTarget->MyCombatCharacterPointer())
|
||||||
|
{
|
||||||
|
// Basically CBaseCombatCharacter::BecomeRagdollBoogie(), but adjusted to our needs
|
||||||
|
CTakeDamageInfo info(this, pActivator, 1.0f, DMG_GENERIC);
|
||||||
|
|
||||||
|
CBaseEntity *pRagdoll = CreateServerRagdoll(pTarget->MyCombatCharacterPointer(), 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS, true);
|
||||||
|
|
||||||
|
pRagdoll->SetCollisionBounds(CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs());
|
||||||
|
|
||||||
|
m_Boogies.AddToTail(CRagdollBoogie::Create(pRagdoll, m_flMagnitude, gpGlobals->curtime + m_flStartTime, m_flBoogieLength, GetSpawnFlags()));
|
||||||
|
|
||||||
|
CTakeDamageInfo ragdollInfo(this, pActivator, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL);
|
||||||
|
ragdollInfo.SetDamagePosition(WorldSpaceCenter());
|
||||||
|
ragdollInfo.SetDamageForce(Vector(0, 0, 1));
|
||||||
|
ragdollInfo.SetForceFriendlyFire(true);
|
||||||
|
pTarget->TakeDamage(ragdollInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : &inputdata -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CPointRagdollBoogie::InputActivate( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
CBaseEntity *pEnt = gEntList.FindEntityByName(NULL, STRING(m_target), this, inputdata.pActivator, inputdata.pCaller);
|
||||||
|
while (pEnt)
|
||||||
|
{
|
||||||
|
ApplyBoogie(pEnt, inputdata.pActivator);
|
||||||
|
|
||||||
|
pEnt = gEntList.FindEntityByName(pEnt, STRING(m_target), this, inputdata.pActivator, inputdata.pCaller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : &inputdata -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CPointRagdollBoogie::InputDeactivate( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
if (m_Boogies.Count() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < m_Boogies.Count(); i++)
|
||||||
|
{
|
||||||
|
UTIL_Remove(m_Boogies[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//m_Boogies.RemoveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : &inputdata -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CPointRagdollBoogie::InputBoogieTarget( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
CBaseEntity *pEnt = gEntList.FindEntityByName(NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller);
|
||||||
|
while (pEnt)
|
||||||
|
{
|
||||||
|
if (!ApplyBoogie(pEnt, inputdata.pActivator))
|
||||||
|
{
|
||||||
|
Warning("%s was unable to apply ragdoll boogie to %s, classname %s.\n", GetDebugName(), pEnt->GetDebugName(), pEnt->GetClassname());
|
||||||
|
}
|
||||||
|
|
||||||
|
pEnt = gEntList.FindEntityByName(pEnt, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -15,13 +15,24 @@
|
|||||||
// automatically hooks in the system's callbacks
|
// automatically hooks in the system's callbacks
|
||||||
CEntityClassList<CSkyCamera> g_SkyList;
|
CEntityClassList<CSkyCamera> g_SkyList;
|
||||||
template <> CSkyCamera *CEntityClassList<CSkyCamera>::m_pClassList = NULL;
|
template <> CSkyCamera *CEntityClassList<CSkyCamera>::m_pClassList = NULL;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CHandle<CSkyCamera> g_hActiveSkybox = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Retrives the current skycamera
|
// Retrives the current skycamera
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CSkyCamera* GetCurrentSkyCamera()
|
CSkyCamera* GetCurrentSkyCamera()
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( g_hActiveSkybox.Get() == NULL )
|
||||||
|
{
|
||||||
|
g_hActiveSkybox = GetSkyCameraList();
|
||||||
|
}
|
||||||
|
return g_hActiveSkybox.Get();
|
||||||
|
#else
|
||||||
return g_SkyList.m_pClassList;
|
return g_SkyList.m_pClassList;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CSkyCamera* GetSkyCameraList()
|
CSkyCamera* GetSkyCameraList()
|
||||||
@ -38,6 +49,10 @@ BEGIN_DATADESC( CSkyCamera )
|
|||||||
DEFINE_KEYFIELD( m_skyboxData.scale, FIELD_INTEGER, "scale" ),
|
DEFINE_KEYFIELD( m_skyboxData.scale, FIELD_INTEGER, "scale" ),
|
||||||
DEFINE_FIELD( m_skyboxData.origin, FIELD_VECTOR ),
|
DEFINE_FIELD( m_skyboxData.origin, FIELD_VECTOR ),
|
||||||
DEFINE_FIELD( m_skyboxData.area, FIELD_INTEGER ),
|
DEFINE_FIELD( m_skyboxData.area, FIELD_INTEGER ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_KEYFIELD( m_skyboxData.skycolor, FIELD_COLOR32, "skycolor" ),
|
||||||
|
DEFINE_KEYFIELD( m_bUseAnglesForSky, FIELD_BOOLEAN, "use_angles_for_sky" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
// Quiet down classcheck
|
// Quiet down classcheck
|
||||||
// DEFINE_FIELD( m_skyboxData, sky3dparams_t ),
|
// DEFINE_FIELD( m_skyboxData, sky3dparams_t ),
|
||||||
@ -55,6 +70,32 @@ BEGIN_DATADESC( CSkyCamera )
|
|||||||
DEFINE_KEYFIELD( m_skyboxData.fog.start, FIELD_FLOAT, "fogstart" ),
|
DEFINE_KEYFIELD( m_skyboxData.fog.start, FIELD_FLOAT, "fogstart" ),
|
||||||
DEFINE_KEYFIELD( m_skyboxData.fog.end, FIELD_FLOAT, "fogend" ),
|
DEFINE_KEYFIELD( m_skyboxData.fog.end, FIELD_FLOAT, "fogend" ),
|
||||||
DEFINE_KEYFIELD( m_skyboxData.fog.maxdensity, FIELD_FLOAT, "fogmaxdensity" ),
|
DEFINE_KEYFIELD( m_skyboxData.fog.maxdensity, FIELD_FLOAT, "fogmaxdensity" ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_KEYFIELD( m_skyboxData.fog.farz, FIELD_FLOAT, "farz" ),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "ForceUpdate", InputForceUpdate ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "StartUpdating", InputStartUpdating ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "StopUpdating", InputStopUpdating ),
|
||||||
|
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "ActivateSkybox", InputActivateSkybox ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "DeactivateSkybox", InputDeactivateSkybox ),
|
||||||
|
|
||||||
|
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFogStartDist", InputSetFogStartDist ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFogEndDist", InputSetFogEndDist ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFogMaxDensity", InputSetFogMaxDensity ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOnFog", InputTurnOnFog ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "TurnOffFog", InputTurnOffFog ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_COLOR32, "SetFogColor", InputSetFogColor ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_COLOR32, "SetFogColorSecondary", InputSetFogColorSecondary ),
|
||||||
|
|
||||||
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFarZ", InputSetFarZ ),
|
||||||
|
|
||||||
|
DEFINE_INPUTFUNC( FIELD_COLOR32, "SetSkyColor", InputSetSkyColor ),
|
||||||
|
|
||||||
|
DEFINE_THINKFUNC( Update ),
|
||||||
|
#endif
|
||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
|
|
||||||
@ -93,6 +134,9 @@ CSkyCamera::CSkyCamera()
|
|||||||
{
|
{
|
||||||
g_SkyList.Insert( this );
|
g_SkyList.Insert( this );
|
||||||
m_skyboxData.fog.maxdensity = 1.0f;
|
m_skyboxData.fog.maxdensity = 1.0f;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_skyboxData.skycolor.Init(0, 0, 0, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CSkyCamera::~CSkyCamera()
|
CSkyCamera::~CSkyCamera()
|
||||||
@ -102,7 +146,23 @@ CSkyCamera::~CSkyCamera()
|
|||||||
|
|
||||||
void CSkyCamera::Spawn( void )
|
void CSkyCamera::Spawn( void )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (HasSpawnFlags(SF_SKY_MASTER))
|
||||||
|
g_hActiveSkybox = this;
|
||||||
|
|
||||||
|
if (HasSpawnFlags(SF_SKY_START_UPDATING) && GetCurrentSkyCamera() == this)
|
||||||
|
{
|
||||||
|
SetThink( &CSkyCamera::Update );
|
||||||
|
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must be absolute now that the sky_camera can be parented
|
||||||
|
m_skyboxData.origin = GetAbsOrigin();
|
||||||
|
if (m_bUseAnglesForSky)
|
||||||
|
m_skyboxData.angles = GetAbsAngles();
|
||||||
|
#else
|
||||||
m_skyboxData.origin = GetLocalOrigin();
|
m_skyboxData.origin = GetLocalOrigin();
|
||||||
|
#endif
|
||||||
m_skyboxData.area = engine->GetArea( m_skyboxData.origin );
|
m_skyboxData.area = engine->GetArea( m_skyboxData.origin );
|
||||||
|
|
||||||
Precache();
|
Precache();
|
||||||
@ -145,3 +205,152 @@ void CSkyCamera::Activate( )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CSkyCamera::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID )
|
||||||
|
{
|
||||||
|
if (!BaseClass::AcceptInput( szInputName, pActivator, pCaller, Value, outputID ))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (g_hActiveSkybox == this)
|
||||||
|
{
|
||||||
|
// Most inputs require an update
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Update sky position mid-game
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CSkyCamera::Update()
|
||||||
|
{
|
||||||
|
m_skyboxData.origin = GetAbsOrigin();
|
||||||
|
if (m_bUseAnglesForSky)
|
||||||
|
m_skyboxData.angles = GetAbsAngles();
|
||||||
|
|
||||||
|
// Getting into another area is unlikely, but if it's not expensive, I guess it's okay.
|
||||||
|
m_skyboxData.area = engine->GetArea( m_skyboxData.origin );
|
||||||
|
|
||||||
|
if ( m_bUseAngles )
|
||||||
|
{
|
||||||
|
AngleVectors( GetAbsAngles(), &m_skyboxData.fog.dirPrimary.GetForModify() );
|
||||||
|
m_skyboxData.fog.dirPrimary.GetForModify() *= -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE_MP
|
||||||
|
// Updates client data, this completely ignores m_pOldSkyCamera
|
||||||
|
CBasePlayer *pPlayer = NULL;
|
||||||
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||||
|
{
|
||||||
|
pPlayer = UTIL_PlayerByIndex(i);
|
||||||
|
if (pPlayer)
|
||||||
|
pPlayer->m_Local.m_skybox3d.CopyFrom(m_skyboxData);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Updates client data, this completely ignores m_pOldSkyCamera
|
||||||
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex(1);
|
||||||
|
if (pPlayer)
|
||||||
|
{
|
||||||
|
pPlayer->m_Local.m_skybox3d.CopyFrom(m_skyboxData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSkyCamera::InputForceUpdate( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
Update();
|
||||||
|
|
||||||
|
// Updates client data, this completely ignores m_pOldSkyCamera
|
||||||
|
CBasePlayer *pPlayer = NULL;
|
||||||
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||||
|
{
|
||||||
|
pPlayer = UTIL_PlayerByIndex( i );
|
||||||
|
if (pPlayer)
|
||||||
|
pPlayer->m_Local.m_skybox3d.CopyFrom( m_skyboxData );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CSkyCamera::InputStartUpdating( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
if (GetCurrentSkyCamera() == this)
|
||||||
|
{
|
||||||
|
SetThink( &CSkyCamera::Update );
|
||||||
|
SetNextThink( gpGlobals->curtime + TICK_INTERVAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we become the current sky camera later, remember that we want to update
|
||||||
|
AddSpawnFlags( SF_SKY_START_UPDATING );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSkyCamera::InputStopUpdating( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
SetThink( NULL );
|
||||||
|
SetNextThink( TICK_NEVER_THINK );
|
||||||
|
RemoveSpawnFlags( SF_SKY_START_UPDATING );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Activate!
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CSkyCamera::InputActivateSkybox( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
CSkyCamera *pActiveSky = GetCurrentSkyCamera();
|
||||||
|
if (pActiveSky && pActiveSky->GetNextThink() != TICK_NEVER_THINK && pActiveSky != this)
|
||||||
|
{
|
||||||
|
// Deactivate that skybox
|
||||||
|
pActiveSky->SetThink( NULL );
|
||||||
|
pActiveSky->SetNextThink( TICK_NEVER_THINK );
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hActiveSkybox = this;
|
||||||
|
|
||||||
|
if (HasSpawnFlags( SF_SKY_START_UPDATING ))
|
||||||
|
InputStartUpdating( inputdata );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Deactivate!
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CSkyCamera::InputDeactivateSkybox( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
if (GetCurrentSkyCamera() == this)
|
||||||
|
{
|
||||||
|
g_hActiveSkybox = NULL;
|
||||||
|
|
||||||
|
// ClientData doesn't catch this immediately
|
||||||
|
CBasePlayer *pPlayer = NULL;
|
||||||
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||||
|
{
|
||||||
|
pPlayer = UTIL_PlayerByIndex( i );
|
||||||
|
if (pPlayer)
|
||||||
|
pPlayer->m_Local.m_skybox3d.area = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetThink( NULL );
|
||||||
|
SetNextThink( TICK_NEVER_THINK );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose: Input handlers for setting fog stuff.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void CSkyCamera::InputSetFogStartDist( inputdata_t &inputdata ) { m_skyboxData.fog.start = inputdata.value.Float(); }
|
||||||
|
void CSkyCamera::InputSetFogEndDist( inputdata_t &inputdata ) { m_skyboxData.fog.end = inputdata.value.Float(); }
|
||||||
|
void CSkyCamera::InputSetFogMaxDensity( inputdata_t &inputdata ) { m_skyboxData.fog.maxdensity = inputdata.value.Float(); }
|
||||||
|
void CSkyCamera::InputTurnOnFog( inputdata_t &inputdata ) { m_skyboxData.fog.enable = true; }
|
||||||
|
void CSkyCamera::InputTurnOffFog( inputdata_t &inputdata ) { m_skyboxData.fog.enable = false; }
|
||||||
|
void CSkyCamera::InputSetFogColor( inputdata_t &inputdata ) { m_skyboxData.fog.colorPrimary = inputdata.value.Color32(); }
|
||||||
|
void CSkyCamera::InputSetFogColorSecondary( inputdata_t &inputdata ) { m_skyboxData.fog.colorSecondary = inputdata.value.Color32(); }
|
||||||
|
|
||||||
|
void CSkyCamera::InputSetFarZ( inputdata_t &inputdata ) { m_skyboxData.fog.farz = inputdata.value.Int(); }
|
||||||
|
#endif
|
||||||
|
@ -14,13 +14,30 @@
|
|||||||
|
|
||||||
class CSkyCamera;
|
class CSkyCamera;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#define SF_SKY_MASTER (1 << 0)
|
||||||
|
#define SF_SKY_START_UPDATING (1 << 1)
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// Sky Camera Class
|
||||||
|
// Now derived directly from CBaseEntity for parenting and angles! (please don't break anything)
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
class CSkyCamera : public CBaseEntity
|
||||||
|
#else
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// Sky Camera Class
|
// Sky Camera Class
|
||||||
//
|
//
|
||||||
class CSkyCamera : public CLogicalEntity
|
class CSkyCamera : public CLogicalEntity
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DECLARE_CLASS( CSkyCamera, CBaseEntity );
|
||||||
|
#else
|
||||||
DECLARE_CLASS( CSkyCamera, CLogicalEntity );
|
DECLARE_CLASS( CSkyCamera, CLogicalEntity );
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -30,9 +47,37 @@ public:
|
|||||||
virtual void Spawn( void );
|
virtual void Spawn( void );
|
||||||
virtual void Activate();
|
virtual void Activate();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID );
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
void InputForceUpdate( inputdata_t &inputdata );
|
||||||
|
void InputStartUpdating( inputdata_t &inputdata );
|
||||||
|
void InputStopUpdating( inputdata_t &inputdata );
|
||||||
|
|
||||||
|
void InputActivateSkybox( inputdata_t &inputdata );
|
||||||
|
void InputDeactivateSkybox( inputdata_t &inputdata );
|
||||||
|
|
||||||
|
void InputSetFogStartDist( inputdata_t &data );
|
||||||
|
void InputSetFogEndDist( inputdata_t &data );
|
||||||
|
void InputTurnOnFog( inputdata_t &data );
|
||||||
|
void InputTurnOffFog( inputdata_t &data );
|
||||||
|
void InputSetFogColor( inputdata_t &data );
|
||||||
|
void InputSetFogColorSecondary( inputdata_t &data );
|
||||||
|
void InputSetFogMaxDensity( inputdata_t &inputdata );
|
||||||
|
|
||||||
|
void InputSetFarZ( inputdata_t &data );
|
||||||
|
|
||||||
|
void InputSetSkyColor( inputdata_t &inputdata ) { m_skyboxData.skycolor = inputdata.value.Color32(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sky3dparams_t m_skyboxData;
|
sky3dparams_t m_skyboxData;
|
||||||
bool m_bUseAngles;
|
bool m_bUseAngles;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Uses angles for actual skybox
|
||||||
|
bool m_bUseAnglesForSky;
|
||||||
|
#endif
|
||||||
CSkyCamera *m_pNext;
|
CSkyCamera *m_pNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -157,6 +157,10 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
|||||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_LOW );
|
ADD_ACTIVITY_TO_SR( ACT_RELOAD_LOW );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_ARM );
|
ADD_ACTIVITY_TO_SR( ACT_ARM );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_DISARM );
|
ADD_ACTIVITY_TO_SR( ACT_DISARM );
|
||||||
|
#ifdef COMPANION_HOLSTER_WORKAROUND
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_ARM_RIFLE );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_DISARM_RIFLE );
|
||||||
|
#endif
|
||||||
ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON );
|
ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON_SHOTGUN );
|
ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON_SHOTGUN );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_PICKUP_GROUND );
|
ADD_ACTIVITY_TO_SR( ACT_PICKUP_GROUND );
|
||||||
@ -396,6 +400,11 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
|||||||
ADD_ACTIVITY_TO_SR( ACT_SMG2_TOAUTO );
|
ADD_ACTIVITY_TO_SR( ACT_SMG2_TOAUTO );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_SMG2_TOBURST );
|
ADD_ACTIVITY_TO_SR( ACT_SMG2_TOBURST );
|
||||||
|
|
||||||
|
#ifdef SHARED_COMBINE_ACTIVITIES
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_COMBINE_THROW_GRENADE );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_COMBINE_AR2_ALTFIRE );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Physcannon special activities
|
// Physcannon special activities
|
||||||
ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_UPGRADE );
|
ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_UPGRADE );
|
||||||
|
|
||||||
@ -447,6 +456,10 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
|||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_RIFLE );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_RIFLE );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG1 );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG1 );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SMG1 );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SMG1 );
|
||||||
|
#if AR2_ACTIVITY_FIX == 1
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2 );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_AR2 );
|
||||||
|
#endif
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_PISTOL );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_PISTOL );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SHOTGUN );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SHOTGUN );
|
||||||
@ -465,10 +478,26 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
|||||||
ADD_ACTIVITY_TO_SR( ACT_WALK_RIFLE_STIMULATED );
|
ADD_ACTIVITY_TO_SR( ACT_WALK_RIFLE_STIMULATED );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_RUN_RIFLE_STIMULATED );
|
ADD_ACTIVITY_TO_SR( ACT_RUN_RIFLE_STIMULATED );
|
||||||
|
|
||||||
|
#if AR2_ACTIVITY_FIX == 1
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2_RELAXED );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR2_STIMULATED );
|
||||||
|
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_WALK_AR2_RELAXED );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_RUN_AR2_RELAXED );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_WALK_AR2_STIMULATED );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_RUN_AR2_STIMULATED );
|
||||||
|
#endif
|
||||||
|
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_RIFLE_STIMULATED );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_RIFLE_STIMULATED );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_RIFLE_STIMULATED );
|
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_RIFLE_STIMULATED );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_RIFLE_STIMULATED );
|
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_RIFLE_STIMULATED );
|
||||||
|
|
||||||
|
#if AR2_ACTIVITY_FIX == 1
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_AR2_STIMULATED );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR2_STIMULATED );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2_STIMULATED );
|
||||||
|
#endif
|
||||||
|
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_RELAXED );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_RELAXED );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_STIMULATED );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_STIMULATED );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_AGITATED );
|
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_AGITATED );
|
||||||
@ -518,6 +547,13 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
|||||||
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_STEALTH_PISTOL );
|
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_STEALTH_PISTOL );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_STEALTH_PISTOL );
|
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_STEALTH_PISTOL );
|
||||||
|
|
||||||
|
#if AR2_ACTIVITY_FIX == 1
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_WALK_AR2 );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR2 );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_RUN_AR2 );
|
||||||
|
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2 );
|
||||||
|
#endif
|
||||||
|
|
||||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL );
|
ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL_LOW );
|
ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL_LOW );
|
||||||
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG1 );
|
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG1 );
|
||||||
|
@ -230,6 +230,13 @@ void CAI_BaseActor::SetModel( const char *szModelName )
|
|||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Half-Laugh had a nasty way of implementing CSceneEntity into StartSceneEvent and I'm both afraid to do it here
|
||||||
|
// and I don't remember exactly how I did it. This is extremely important because
|
||||||
|
// it's the only way we can access !target1, !target2, etc. Please revisit this later.
|
||||||
|
#define STARTSCENEEVENT_HAS_CSCENEENTITY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget )
|
bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget )
|
||||||
{
|
{
|
||||||
Assert( info );
|
Assert( info );
|
||||||
@ -314,6 +321,116 @@ bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene,
|
|||||||
{
|
{
|
||||||
info->m_nType = SCENE_AI_DISABLEAI;
|
info->m_nType = SCENE_AI_DISABLEAI;
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else if (stricmp(event->GetParameters(), "AI_ADDCONTEXT") == 0)
|
||||||
|
{
|
||||||
|
// Adds a response context to the caller in place of the target field.
|
||||||
|
// This is supposed to be used with the talker system.
|
||||||
|
if (event->GetParameters2())
|
||||||
|
{
|
||||||
|
info->m_nType = SCENE_AI_ADDCONTEXT;
|
||||||
|
AddContext(event->GetParameters2());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (stricmp(event->GetParameters(), "AI_INPUT") == 0)
|
||||||
|
{
|
||||||
|
// Fires an input on an entity in place of the target field.
|
||||||
|
// This is supposed to be used with the talker system.
|
||||||
|
if (event->GetParameters2())
|
||||||
|
{
|
||||||
|
info->m_nType = SCENE_AI_INPUT;
|
||||||
|
|
||||||
|
const char *raw = event->GetParameters2();
|
||||||
|
char sTarget[128];
|
||||||
|
char sInput[128];
|
||||||
|
char sParameter[128];
|
||||||
|
char *colon1 = Q_strstr( raw, ":" );
|
||||||
|
if (!colon1)
|
||||||
|
{
|
||||||
|
Warning("%s (%s) AI_INPUT missing colon separator!\n", GetClassname(), GetDebugName());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = colon1 - raw;
|
||||||
|
Q_strncpy( sTarget, raw, MIN( len + 1, sizeof(sTarget) ) );
|
||||||
|
sTarget[MIN(len, sizeof(sTarget) - 1)] = 0;
|
||||||
|
|
||||||
|
bool bParameter = true;
|
||||||
|
char *colon2 = Q_strstr(colon1 + 1, ":");
|
||||||
|
if (!colon2)
|
||||||
|
{
|
||||||
|
DevMsg("Assuming no parameter\n");
|
||||||
|
colon2 = colon1 + 1;
|
||||||
|
bParameter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bParameter)
|
||||||
|
{
|
||||||
|
len = MIN(colon2 - (colon1 + 1), sizeof(sInput) - 1);
|
||||||
|
Q_strncpy(sInput, colon1 + 1, MIN(len + 1, sizeof(sInput)));
|
||||||
|
sInput[MIN(len, sizeof(sInput) - 1)] = 0;
|
||||||
|
|
||||||
|
Q_strncpy(sParameter, colon2 + 1, sizeof(sInput));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = colon2 - raw;
|
||||||
|
Q_strncpy(sInput, colon2, sizeof(sInput));
|
||||||
|
}
|
||||||
|
|
||||||
|
CBaseEntity *pEnt = gEntList.FindEntityByName(NULL, sTarget, this);
|
||||||
|
if (!pEnt)
|
||||||
|
{
|
||||||
|
#if STARTSCENEEVENT_HAS_CSCENEENTITY
|
||||||
|
DevMsg("%s not found with normal search, slamming to scene ent\n", sTarget);
|
||||||
|
pEnt = UTIL_FindNamedSceneEntity(sTarget, this, csceneent);
|
||||||
|
if (!pEnt)
|
||||||
|
{
|
||||||
|
DevWarning("%s slammed to self!\n", sTarget);
|
||||||
|
pEnt = this;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
DevWarning("%s slammed to self!\n", sTarget);
|
||||||
|
pEnt = this;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pEnt && sInput)
|
||||||
|
{
|
||||||
|
variant_t variant;
|
||||||
|
if (bParameter && sParameter)
|
||||||
|
{
|
||||||
|
const char *strParam = sParameter;
|
||||||
|
#if STARTSCENEEVENT_HAS_CSCENEENTITY
|
||||||
|
if (strParam[0] == '!')
|
||||||
|
{
|
||||||
|
CBaseEntity *pParamEnt = UTIL_FindNamedSceneEntity(strParam, this, csceneent);
|
||||||
|
if (pParamEnt && pParamEnt->GetEntityName() != NULL_STRING && !gEntList.FindEntityProcedural(strParam))
|
||||||
|
{
|
||||||
|
// We make sure it's a scene entity that can't be found with entlist procedural so we can translate !target# without messing with !activators, etc.
|
||||||
|
//const char *newname = pParamEnt->GetEntityName().ToCStr();
|
||||||
|
strParam = pParamEnt->GetEntityName().ToCStr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (strParam)
|
||||||
|
{
|
||||||
|
variant.SetString(MAKE_STRING(strParam));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pEnt->AcceptInput(sInput, this, this, variant, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Warning("%s (%s) AI_INPUT cannot find entity %s!\n", GetClassname(), GetDebugName(), sTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return BaseClass::StartSceneEvent( info, scene, event, actor, pTarget );
|
return BaseClass::StartSceneEvent( info, scene, event, actor, pTarget );
|
||||||
@ -508,6 +625,11 @@ bool CAI_BaseActor::ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scen
|
|||||||
Vector vecAimTargetLoc = info->m_hTarget->EyePosition();
|
Vector vecAimTargetLoc = info->m_hTarget->EyePosition();
|
||||||
Vector vecAimDir = vecAimTargetLoc - EyePosition();
|
Vector vecAimDir = vecAimTargetLoc - EyePosition();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Mind the ramp
|
||||||
|
vecAimDir *= event->GetIntensity(scene->GetTime());
|
||||||
|
#endif
|
||||||
|
|
||||||
VectorNormalize( vecAimDir );
|
VectorNormalize( vecAimDir );
|
||||||
SetAim( vecAimDir);
|
SetAim( vecAimDir);
|
||||||
}
|
}
|
||||||
@ -548,6 +670,16 @@ bool CAI_BaseActor::ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scen
|
|||||||
EnterSceneSequence( scene, event );
|
EnterSceneSequence( scene, event );
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
case SCENE_AI_ADDCONTEXT:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case SCENE_AI_INPUT:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,11 @@ public:
|
|||||||
SCENE_AI_RANDOMHEADFLEX,
|
SCENE_AI_RANDOMHEADFLEX,
|
||||||
SCENE_AI_IGNORECOLLISION,
|
SCENE_AI_IGNORECOLLISION,
|
||||||
SCENE_AI_DISABLEAI
|
SCENE_AI_DISABLEAI
|
||||||
|
#ifdef MAPBASE
|
||||||
|
,
|
||||||
|
SCENE_AI_ADDCONTEXT,
|
||||||
|
SCENE_AI_INPUT,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -95,6 +95,36 @@ extern bool AIStrongOpt( void );
|
|||||||
// Max's of the box used to search for a weapon to pick up. 45x45x~8 ft.
|
// Max's of the box used to search for a weapon to pick up. 45x45x~8 ft.
|
||||||
#define WEAPON_SEARCH_DELTA Vector( 540, 540, 100 )
|
#define WEAPON_SEARCH_DELTA Vector( 540, 540, 100 )
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Defines Mapbase's extended NPC response system usage.
|
||||||
|
#define EXPANDED_RESPONSE_SYSTEM_USAGE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EXPANDED_RESPONSE_SYSTEM_USAGE
|
||||||
|
|
||||||
|
// This macro implements the response system on any NPC, particularly non-actors that can't use CAI_ExpresserHost.
|
||||||
|
// NOTE: Because of the lack of CAI_ExpresserHost, some Response System settings like odds, delays, etc. cannot be used.
|
||||||
|
// It's recommended to just use CAI_ExpresserHost if possible.
|
||||||
|
#define DeclareResponseSystem IResponseSystem *GetResponseSystem() { extern IResponseSystem *g_pResponseSystem; return g_pResponseSystem; }
|
||||||
|
|
||||||
|
// Default CAI_ExpresserHost implementation for NPCs using CAI_ExpresserHost.
|
||||||
|
#define DeclareDefaultExpresser() virtual CAI_Expresser *CreateExpresser( void ) { m_pExpresser = new CAI_Expresser(this); if (!m_pExpresser) return NULL; m_pExpresser->Connect(this); return m_pExpresser; } \\
|
||||||
|
virtual CAI_Expresser *GetExpresser() { return m_pExpresser; } \\
|
||||||
|
virtual void PostConstructor(const char *szClassname) { BaseClass::PostConstructor(szClassname); CreateExpresser(); } \\
|
||||||
|
private: \\
|
||||||
|
CAI_Expresser *m_pExpresser; \\
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Variant of DeclareDefaultExpresser() that doesn't implement its own PostConstructor.
|
||||||
|
// CreateExpresser() should still be called from there.
|
||||||
|
#define DeclareDefaultExpresser_ExistingPC() virtual CAI_Expresser *CreateExpresser( void ) { m_pExpresser = new CAI_Expresser(this); if (!m_pExpresser) return NULL; m_pExpresser->Connect(this); return m_pExpresser; } \\
|
||||||
|
virtual CAI_Expresser *GetExpresser() { return m_pExpresser; } \\
|
||||||
|
private: \\
|
||||||
|
CAI_Expresser *m_pExpresser; \\
|
||||||
|
public:
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
enum Interruptability_t
|
enum Interruptability_t
|
||||||
{
|
{
|
||||||
GENERAL_INTERRUPTABILITY,
|
GENERAL_INTERRUPTABILITY,
|
||||||
@ -316,6 +346,10 @@ struct UnreachableEnt_t
|
|||||||
#define SCNPC_FLAG_NEEDS_WEAPON_THEM ( 1 << 5 )
|
#define SCNPC_FLAG_NEEDS_WEAPON_THEM ( 1 << 5 )
|
||||||
#define SCNPC_FLAG_DONT_TELEPORT_AT_END_ME ( 1 << 6 )
|
#define SCNPC_FLAG_DONT_TELEPORT_AT_END_ME ( 1 << 6 )
|
||||||
#define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 )
|
#define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 )
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#define SCNPC_FLAG_MAPBASE_ADDITION ( 1 << 8 )
|
||||||
|
#define SCNPC_FLAG_TEST_END_POSITION ( 1 << 9 )
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Scripted NPC interaction trigger methods
|
// Scripted NPC interaction trigger methods
|
||||||
@ -387,6 +421,10 @@ struct ScriptedNPCInteraction_t
|
|||||||
flNextAttemptTime = 0;
|
flNextAttemptTime = 0;
|
||||||
iszMyWeapon = NULL_STRING;
|
iszMyWeapon = NULL_STRING;
|
||||||
iszTheirWeapon = NULL_STRING;
|
iszTheirWeapon = NULL_STRING;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
vecRelativeEndPos = vec3_origin;
|
||||||
|
MiscCriteria = NULL_STRING;
|
||||||
|
#endif
|
||||||
|
|
||||||
for ( int i = 0; i < SNPCINT_NUM_PHASES; i++)
|
for ( int i = 0; i < SNPCINT_NUM_PHASES; i++)
|
||||||
{
|
{
|
||||||
@ -403,6 +441,9 @@ struct ScriptedNPCInteraction_t
|
|||||||
Vector vecRelativeOrigin; // (forward, right, up)
|
Vector vecRelativeOrigin; // (forward, right, up)
|
||||||
QAngle angRelativeAngles;
|
QAngle angRelativeAngles;
|
||||||
Vector vecRelativeVelocity; // Desired relative velocity of the other NPC
|
Vector vecRelativeVelocity; // Desired relative velocity of the other NPC
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Vector vecRelativeEndPos; // Relative position that the NPC must fit in
|
||||||
|
#endif
|
||||||
float flDelay; // Delay before interaction can be used again
|
float flDelay; // Delay before interaction can be used again
|
||||||
float flDistSqr; // Max distance sqr from the relative origin the NPC is allowed to be to trigger
|
float flDistSqr; // Max distance sqr from the relative origin the NPC is allowed to be to trigger
|
||||||
string_t iszMyWeapon; // Classname of the weapon I'm holding, if any
|
string_t iszMyWeapon; // Classname of the weapon I'm holding, if any
|
||||||
@ -415,6 +456,13 @@ struct ScriptedNPCInteraction_t
|
|||||||
|
|
||||||
float flNextAttemptTime;
|
float flNextAttemptTime;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Unrecognized keyvalues are tested against response criteria later.
|
||||||
|
// This was originally a CUtlVector that carries response contexts, but I couldn't get it working due to some CUtlVector-struct shenanigans.
|
||||||
|
// It works when we use a single string_t that's split and read each time the code runs, but feel free to improve on this.
|
||||||
|
string_t MiscCriteria; // CUtlVector<ResponseContext_t>
|
||||||
|
#endif
|
||||||
|
|
||||||
DECLARE_SIMPLE_DATADESC();
|
DECLARE_SIMPLE_DATADESC();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -510,6 +558,9 @@ public:
|
|||||||
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
|
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
|
||||||
|
|
||||||
virtual bool KeyValue( const char *szKeyName, const char *szValue );
|
virtual bool KeyValue( const char *szKeyName, const char *szValue );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen );
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
|
||||||
@ -565,6 +616,10 @@ public:
|
|||||||
// Thinking, including core thinking, movement, animation
|
// Thinking, including core thinking, movement, animation
|
||||||
virtual void NPCThink( void );
|
virtual void NPCThink( void );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputSetThinkNPC( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Core thinking (schedules & tasks)
|
// Core thinking (schedules & tasks)
|
||||||
virtual void RunAI( void );// core ai function!
|
virtual void RunAI( void );// core ai function!
|
||||||
|
|
||||||
@ -853,6 +908,11 @@ public:
|
|||||||
|
|
||||||
bool DidChooseEnemy() const { return !m_bSkippedChooseEnemy; }
|
bool DidChooseEnemy() const { return !m_bSkippedChooseEnemy; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputSetCondition( inputdata_t &inputdata );
|
||||||
|
void InputClearCondition( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CAI_ScheduleBits m_Conditions;
|
CAI_ScheduleBits m_Conditions;
|
||||||
CAI_ScheduleBits m_CustomInterruptConditions; //Bit string assembled by the schedule running, then
|
CAI_ScheduleBits m_CustomInterruptConditions; //Bit string assembled by the schedule running, then
|
||||||
@ -897,6 +957,10 @@ public:
|
|||||||
|
|
||||||
void UpdateSleepState( bool bInPVS );
|
void UpdateSleepState( bool bInPVS );
|
||||||
virtual void Wake( bool bFireOutput = true );
|
virtual void Wake( bool bFireOutput = true );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// A version of Wake() that takes an activator
|
||||||
|
virtual void Wake( CBaseEntity *pActivator );
|
||||||
|
#endif
|
||||||
void Sleep();
|
void Sleep();
|
||||||
bool WokeThisTick() const;
|
bool WokeThisTick() const;
|
||||||
|
|
||||||
@ -926,6 +990,10 @@ public:
|
|||||||
|
|
||||||
Activity TranslateActivity( Activity idealActivity, Activity *pIdealWeaponActivity = NULL );
|
Activity TranslateActivity( Activity idealActivity, Activity *pIdealWeaponActivity = NULL );
|
||||||
Activity NPC_TranslateActivity( Activity eNewActivity );
|
Activity NPC_TranslateActivity( Activity eNewActivity );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Activity TranslateCrouchActivity( Activity baseAct );
|
||||||
|
virtual Activity NPC_BackupActivity( Activity eNewActivity );
|
||||||
|
#endif
|
||||||
Activity GetActivity( void ) { return m_Activity; }
|
Activity GetActivity( void ) { return m_Activity; }
|
||||||
virtual void SetActivity( Activity NewActivity );
|
virtual void SetActivity( Activity NewActivity );
|
||||||
Activity GetIdealActivity( void ) { return m_IdealActivity; }
|
Activity GetIdealActivity( void ) { return m_IdealActivity; }
|
||||||
@ -1122,6 +1190,19 @@ private:
|
|||||||
public:
|
public:
|
||||||
CAI_MoveMonitor m_CommandMoveMonitor;
|
CAI_MoveMonitor m_CommandMoveMonitor;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ThreeState_t m_FriendlyFireOverride = TRS_NONE;
|
||||||
|
virtual bool FriendlyFireEnabled();
|
||||||
|
void InputSetFriendlyFire( inputdata_t &inputdata );
|
||||||
|
|
||||||
|
// Grenade-related functions from Combine soldiers ported to ai_basenpc so they could be shared.
|
||||||
|
//
|
||||||
|
// This is necessary because other NPCs can use them now and many instances where they were used relied on dynamic_casts.
|
||||||
|
virtual Vector GetAltFireTarget() { return GetEnemy() ? GetEnemy()->BodyTarget(Weapon_ShootPosition()) : vec3_origin; }
|
||||||
|
virtual void DelayGrenadeCheck(float delay) { ; }
|
||||||
|
virtual void AddGrenades( int inc, CBaseEntity *pLastGrenade = NULL ) { ; }
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
// Dynamic scripted NPC interactions
|
// Dynamic scripted NPC interactions
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
@ -1137,6 +1218,11 @@ protected:
|
|||||||
void CheckForScriptedNPCInteractions( void );
|
void CheckForScriptedNPCInteractions( void );
|
||||||
void CalculateValidEnemyInteractions( void );
|
void CalculateValidEnemyInteractions( void );
|
||||||
void CheckForcedNPCInteractions( void );
|
void CheckForcedNPCInteractions( void );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// This is checked during automatic dynamic interactions, but not during forced interactions.
|
||||||
|
// This is so we can control interaction permissions while still letting forced interactions play when needed.
|
||||||
|
virtual bool InteractionIsAllowed( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction );
|
||||||
|
#endif
|
||||||
bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles );
|
bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles );
|
||||||
virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
|
virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
|
||||||
bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); }
|
bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); }
|
||||||
@ -1162,10 +1248,20 @@ private:
|
|||||||
bool m_bCannotDieDuringInteraction;
|
bool m_bCannotDieDuringInteraction;
|
||||||
int m_iInteractionState;
|
int m_iInteractionState;
|
||||||
int m_iInteractionPlaying;
|
int m_iInteractionPlaying;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
CUtlVector<ScriptedNPCInteraction_t> m_ScriptedInteractions;
|
CUtlVector<ScriptedNPCInteraction_t> m_ScriptedInteractions;
|
||||||
|
|
||||||
float m_flInteractionYaw;
|
float m_flInteractionYaw;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Allows mappers to control dynamic interactions.
|
||||||
|
// DI added by Mapbase requires this to be on TRS_TRUE (1). Others, like Alyx's interactions, only require TRS_NONE (2).
|
||||||
|
// TRS_FALSE (0) disables all dynamic interactions, including existing ones.
|
||||||
|
ThreeState_t m_iDynamicInteractionsAllowed;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
@ -1209,6 +1305,10 @@ public:
|
|||||||
virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot );
|
virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot );
|
||||||
|
|
||||||
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set );
|
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void ModifyOrAppendEnemyCriteria( AI_CriteriaSet& set, CBaseEntity *pEnemy );
|
||||||
|
virtual void ModifyOrAppendDamageCriteria( AI_CriteriaSet& set, const CTakeDamageInfo &info );
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float SoundWaitTime() const { return m_flSoundWaitTime; }
|
float SoundWaitTime() const { return m_flSoundWaitTime; }
|
||||||
@ -1226,6 +1326,11 @@ public:
|
|||||||
int CapabilitiesRemove( int capabilities );
|
int CapabilitiesRemove( int capabilities );
|
||||||
void CapabilitiesClear( void );
|
void CapabilitiesClear( void );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputAddCapabilities( inputdata_t &inputdata );
|
||||||
|
void InputRemoveCapabilities( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_afCapability; // tells us what a npc can/can't do.
|
int m_afCapability; // tells us what a npc can/can't do.
|
||||||
|
|
||||||
@ -1562,8 +1667,25 @@ public:
|
|||||||
bool IsWeaponStateChanging( void );
|
bool IsWeaponStateChanging( void );
|
||||||
void SetDesiredWeaponState( DesiredWeaponState_t iState ) { m_iDesiredWeaponState = iState; }
|
void SetDesiredWeaponState( DesiredWeaponState_t iState ) { m_iDesiredWeaponState = iState; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool DoHolster(void);
|
||||||
|
virtual bool DoUnholster(void);
|
||||||
|
|
||||||
|
virtual bool ShouldUnholsterWeapon() { return GetState() == NPC_STATE_COMBAT && CanUnholsterWeapon(); }
|
||||||
|
virtual bool CanUnholsterWeapon() { return IsWeaponHolstered(); }
|
||||||
|
|
||||||
|
void InputGiveWeaponHolstered( inputdata_t &inputdata );
|
||||||
|
void InputChangeWeapon( inputdata_t &inputdata );
|
||||||
|
void InputPickupWeapon( inputdata_t &inputdata );
|
||||||
|
void InputPickupItem( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTE: The Shot Regulator is used to manage the RangeAttack1 weapon.
|
// NOTE: The Shot Regulator is used to manage the RangeAttack1 weapon.
|
||||||
inline CAI_ShotRegulator* GetShotRegulator() { return &m_ShotRegulator; }
|
inline CAI_ShotRegulator* GetShotRegulator() { return &m_ShotRegulator; }
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// A special function for ai_weaponmodifier.
|
||||||
|
inline void SetShotRegulator(CAI_ShotRegulator NewRegulator) { m_ShotRegulator = NewRegulator; }
|
||||||
|
#endif
|
||||||
virtual void OnRangeAttack1();
|
virtual void OnRangeAttack1();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -1582,6 +1704,10 @@ protected:
|
|||||||
float m_flLastAttackTime; // Last time that I attacked my current enemy
|
float m_flLastAttackTime; // Last time that I attacked my current enemy
|
||||||
float m_flLastEnemyTime;
|
float m_flLastEnemyTime;
|
||||||
float m_flNextWeaponSearchTime; // next time to search for a better weapon
|
float m_flNextWeaponSearchTime; // next time to search for a better weapon
|
||||||
|
#ifdef MAPBASE
|
||||||
|
public:
|
||||||
|
int m_iLastHolsteredWeapon;
|
||||||
|
#endif
|
||||||
string_t m_iszPendingWeapon; // THe NPC should create and equip this weapon.
|
string_t m_iszPendingWeapon; // THe NPC should create and equip this weapon.
|
||||||
bool m_bIgnoreUnseenEnemies;
|
bool m_bIgnoreUnseenEnemies;
|
||||||
|
|
||||||
@ -1624,6 +1750,10 @@ public:
|
|||||||
void SetHintGroup( string_t name, bool bHintGroupNavLimiting = false );
|
void SetHintGroup( string_t name, bool bHintGroupNavLimiting = false );
|
||||||
bool IsLimitingHintGroups( void ) { return m_bHintGroupNavLimiting; }
|
bool IsLimitingHintGroups( void ) { return m_bHintGroupNavLimiting; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputSetHintGroup( inputdata_t &inputdata ) { SetHintGroup(inputdata.value.StringID()); }
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
|
||||||
CAI_TacticalServices *GetTacticalServices() { return m_pTacticalServices; }
|
CAI_TacticalServices *GetTacticalServices() { return m_pTacticalServices; }
|
||||||
@ -1663,7 +1793,9 @@ public:
|
|||||||
//-----------------------------------------------------
|
//-----------------------------------------------------
|
||||||
|
|
||||||
void InitRelationshipTable( void );
|
void InitRelationshipTable( void );
|
||||||
|
#ifndef MAPBASE
|
||||||
void AddRelationship( const char *pszRelationship, CBaseEntity *pActivator );
|
void AddRelationship( const char *pszRelationship, CBaseEntity *pActivator );
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
|
virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
|
||||||
virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority );
|
virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority );
|
||||||
@ -1695,7 +1827,9 @@ public:
|
|||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
|
||||||
|
#ifndef MAPBASE // Moved to CBaseCombatCharacter
|
||||||
virtual CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL );
|
virtual CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL );
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
// States
|
// States
|
||||||
@ -1706,7 +1840,12 @@ public:
|
|||||||
virtual bool ShouldLookForBetterWeapon();
|
virtual bool ShouldLookForBetterWeapon();
|
||||||
bool Weapon_IsBetterAvailable ( void ) ;
|
bool Weapon_IsBetterAvailable ( void ) ;
|
||||||
virtual Vector Weapon_ShootPosition( void );
|
virtual Vector Weapon_ShootPosition( void );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual CBaseCombatWeapon* GiveWeapon( string_t iszWeaponName, bool bDiscardCurrent = true );
|
||||||
|
virtual CBaseCombatWeapon* GiveWeaponHolstered( string_t iszWeaponName );
|
||||||
|
#else
|
||||||
virtual void GiveWeapon( string_t iszWeaponName );
|
virtual void GiveWeapon( string_t iszWeaponName );
|
||||||
|
#endif
|
||||||
virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) { }
|
virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) { }
|
||||||
bool IsMovingToPickupWeapon();
|
bool IsMovingToPickupWeapon();
|
||||||
virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions);
|
virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions);
|
||||||
@ -1804,16 +1943,27 @@ public:
|
|||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
|
||||||
virtual void PickupWeapon( CBaseCombatWeapon *pWeapon );
|
virtual void PickupWeapon( CBaseCombatWeapon *pWeapon );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void PickupItem( CBaseEntity *pItem );
|
||||||
|
#else
|
||||||
virtual void PickupItem( CBaseEntity *pItem ) { };
|
virtual void PickupItem( CBaseEntity *pItem ) { };
|
||||||
|
#endif
|
||||||
CBaseEntity* DropItem( const char *pszItemName, Vector vecPos, QAngle vecAng );// drop an item.
|
CBaseEntity* DropItem( const char *pszItemName, Vector vecPos, QAngle vecAng );// drop an item.
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
// Inputs
|
// Inputs
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
#ifndef MAPBASE // Moved to CBaseCombatCharacter
|
||||||
void InputSetRelationship( inputdata_t &inputdata );
|
void InputSetRelationship( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
void InputSetEnemyFilter( inputdata_t &inputdata );
|
void InputSetEnemyFilter( inputdata_t &inputdata );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// This is virtual so npc_helicopter can override it
|
||||||
|
virtual void InputSetHealthFraction( inputdata_t &inputdata );
|
||||||
|
#else
|
||||||
void InputSetHealth( inputdata_t &inputdata );
|
void InputSetHealth( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
void InputBeginRappel( inputdata_t &inputdata );
|
void InputBeginRappel( inputdata_t &inputdata );
|
||||||
void InputSetSquad( inputdata_t &inputdata );
|
void InputSetSquad( inputdata_t &inputdata );
|
||||||
void InputWake( inputdata_t &inputdata );
|
void InputWake( inputdata_t &inputdata );
|
||||||
@ -1904,6 +2054,13 @@ public:
|
|||||||
COutputEvent m_OnForcedInteractionAborted;
|
COutputEvent m_OnForcedInteractionAborted;
|
||||||
COutputEvent m_OnForcedInteractionFinished;
|
COutputEvent m_OnForcedInteractionFinished;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
COutputEHANDLE m_OnHolsterWeapon;
|
||||||
|
COutputEHANDLE m_OnUnholsterWeapon;
|
||||||
|
|
||||||
|
COutputEHANDLE m_OnItemPickup;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// use this to shrink the bbox temporarily
|
// use this to shrink the bbox temporarily
|
||||||
void SetHullSizeNormal( bool force = false );
|
void SetHullSizeNormal( bool force = false );
|
||||||
@ -3059,10 +3216,19 @@ public:
|
|||||||
// NOTE: YOU MUST DEFINE THE OUTPUTS IN YOUR CLASS'S DATADESC!
|
// NOTE: YOU MUST DEFINE THE OUTPUTS IN YOUR CLASS'S DATADESC!
|
||||||
// THE DO SO, INSERT THE FOLLOWING MACRO INTO YOUR CLASS'S DATADESC.
|
// THE DO SO, INSERT THE FOLLOWING MACRO INTO YOUR CLASS'S DATADESC.
|
||||||
//
|
//
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#define DEFINE_BASENPCINTERACTABLE_DATADESC() \
|
||||||
|
DEFINE_OUTPUT( m_OnAlyxStartedInteraction, "OnAlyxStartedInteraction" ), \
|
||||||
|
DEFINE_OUTPUT( m_OnAlyxFinishedInteraction, "OnAlyxFinishedInteraction" ), \
|
||||||
|
DEFINE_OUTPUT( m_OnHacked, "OnHacked" ), \
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "InteractivePowerDown", InputPowerdown ), \
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Hack", InputDoInteraction )
|
||||||
|
#else
|
||||||
#define DEFINE_BASENPCINTERACTABLE_DATADESC() \
|
#define DEFINE_BASENPCINTERACTABLE_DATADESC() \
|
||||||
DEFINE_OUTPUT( m_OnAlyxStartedInteraction, "OnAlyxStartedInteraction" ), \
|
DEFINE_OUTPUT( m_OnAlyxStartedInteraction, "OnAlyxStartedInteraction" ), \
|
||||||
DEFINE_OUTPUT( m_OnAlyxFinishedInteraction, "OnAlyxFinishedInteraction" ), \
|
DEFINE_OUTPUT( m_OnAlyxFinishedInteraction, "OnAlyxFinishedInteraction" ), \
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "InteractivePowerDown", InputPowerdown )
|
DEFINE_INPUTFUNC( FIELD_VOID, "InteractivePowerDown", InputPowerdown )
|
||||||
|
#endif
|
||||||
|
|
||||||
template <class NPC_CLASS>
|
template <class NPC_CLASS>
|
||||||
class CNPCBaseInteractive : public NPC_CLASS, public INPCInteractive
|
class CNPCBaseInteractive : public NPC_CLASS, public INPCInteractive
|
||||||
@ -3078,6 +3244,13 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual void InputDoInteraction( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
NotifyInteraction(inputdata.pActivator ? inputdata.pActivator->MyNPCPointer() : NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Alyx specific interactions
|
// Alyx specific interactions
|
||||||
virtual void AlyxStartedInteraction( void )
|
virtual void AlyxStartedInteraction( void )
|
||||||
{
|
{
|
||||||
@ -3093,6 +3266,9 @@ public:
|
|||||||
// Alyx specific interactions
|
// Alyx specific interactions
|
||||||
COutputEvent m_OnAlyxStartedInteraction;
|
COutputEvent m_OnAlyxStartedInteraction;
|
||||||
COutputEvent m_OnAlyxFinishedInteraction;
|
COutputEvent m_OnAlyxFinishedInteraction;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
COutputEvent m_OnHacked;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -981,6 +981,9 @@ bool CAI_BaseNPC::FindCoverFromEnemy( bool bNodesOnly, float flMinDistance, floa
|
|||||||
if (GetHintNode())
|
if (GetHintNode())
|
||||||
{
|
{
|
||||||
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
|
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (GetHintNode()->GetIgnoreFacing() != HIF_NO)
|
||||||
|
#endif
|
||||||
GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() );
|
GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1585,6 +1588,39 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
|||||||
SetWait( pTask->flTaskData );
|
SetWait( pTask->flTaskData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
case TASK_FACE_INTERACTION_ANGLES:
|
||||||
|
{
|
||||||
|
if ( !m_hForcedInteractionPartner )
|
||||||
|
{
|
||||||
|
TaskFail( FAIL_NO_TARGET );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our running interaction from our partner,
|
||||||
|
// as this should only run with the NPC "receiving" the interaction
|
||||||
|
ScriptedNPCInteraction_t *pInteraction = m_hForcedInteractionPartner->GetRunningDynamicInteraction();
|
||||||
|
|
||||||
|
// Get our target's origin
|
||||||
|
Vector vecTarget = m_hForcedInteractionPartner->GetAbsOrigin();
|
||||||
|
|
||||||
|
// Face the angles the interaction actually wants us at, opposite to the partner
|
||||||
|
float angInteractionAngle = pInteraction->angRelativeAngles.y;
|
||||||
|
angInteractionAngle += 180.0f;
|
||||||
|
|
||||||
|
GetMotor()->SetIdealYaw( CalcIdealYaw( vecTarget ) + angInteractionAngle );
|
||||||
|
|
||||||
|
if (FacingIdeal())
|
||||||
|
TaskComplete();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) );
|
||||||
|
SetTurnActivity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case TASK_FACE_ENEMY:
|
case TASK_FACE_ENEMY:
|
||||||
{
|
{
|
||||||
Vector vecEnemyLKP = GetEnemyLKP();
|
Vector vecEnemyLKP = GetEnemyLKP();
|
||||||
@ -2767,6 +2803,13 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
|||||||
|
|
||||||
string_t iszArrivalText;
|
string_t iszArrivalText;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if ( m_hCine->m_iszPreIdle != NULL_STRING )
|
||||||
|
{
|
||||||
|
iszArrivalText = m_hCine->m_iszPreIdle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if ( m_hCine->m_iszEntry != NULL_STRING )
|
if ( m_hCine->m_iszEntry != NULL_STRING )
|
||||||
{
|
{
|
||||||
iszArrivalText = m_hCine->m_iszEntry;
|
iszArrivalText = m_hCine->m_iszEntry;
|
||||||
@ -3380,6 +3423,36 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
case TASK_FACE_INTERACTION_ANGLES:
|
||||||
|
{
|
||||||
|
if ( !m_hForcedInteractionPartner )
|
||||||
|
{
|
||||||
|
TaskFail( FAIL_NO_TARGET );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our running interaction from our partner,
|
||||||
|
// as this should only run with the NPC "receiving" the interaction
|
||||||
|
ScriptedNPCInteraction_t *pInteraction = m_hForcedInteractionPartner->GetRunningDynamicInteraction();
|
||||||
|
|
||||||
|
// Get our target's origin
|
||||||
|
Vector vecTarget = m_hForcedInteractionPartner->GetAbsOrigin();
|
||||||
|
|
||||||
|
// Face the angles the interaction actually wants us at, opposite to the partner
|
||||||
|
float angInteractionAngle = pInteraction->angRelativeAngles.y;
|
||||||
|
angInteractionAngle += 180.0f;
|
||||||
|
|
||||||
|
GetMotor()->SetIdealYawAndUpdate( CalcIdealYaw( vecTarget ) + angInteractionAngle, AI_KEEP_YAW_SPEED );
|
||||||
|
|
||||||
|
if (IsWaitFinished())
|
||||||
|
{
|
||||||
|
TaskComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case TASK_FIND_COVER_FROM_BEST_SOUND:
|
case TASK_FIND_COVER_FROM_BEST_SOUND:
|
||||||
{
|
{
|
||||||
switch( GetTaskInterrupt() )
|
switch( GetTaskInterrupt() )
|
||||||
@ -3668,10 +3741,25 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
|||||||
{
|
{
|
||||||
if( GetNavigator()->SetGoal(vecGoal) )
|
if( GetNavigator()->SetGoal(vecGoal) )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Pushaway destinations could be an entire floor above.
|
||||||
|
// That would get frustrating. Only go to hints within a path distance of 300 units,
|
||||||
|
// only slightly above our initial search conditions.
|
||||||
|
if (GetNavigator()->BuildAndGetPathDistToGoal() < 300.0f)
|
||||||
|
{
|
||||||
|
// NOTE: Remove this DevMsg() when this is tested!
|
||||||
|
DevMsg("Player Withdrawal Destination Dist: %f\n", GetNavigator()->GetPathDistToGoal());
|
||||||
|
pHint->NPCHandleStartNav(this, false);
|
||||||
pHint->DisableForSeconds( 0.1f ); // Force others to find their own.
|
pHint->DisableForSeconds( 0.1f ); // Force others to find their own.
|
||||||
TaskComplete();
|
TaskComplete();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
pHint->DisableForSeconds( 0.1f ); // Force others to find their own.
|
||||||
|
TaskComplete();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3881,7 +3969,11 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
|
|||||||
if ( m_hCine && m_hCine->IsTimeToStart() )
|
if ( m_hCine && m_hCine->IsTimeToStart() )
|
||||||
{
|
{
|
||||||
TaskComplete();
|
TaskComplete();
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_hCine->OnBeginSequence(this);
|
||||||
|
#else
|
||||||
m_hCine->OnBeginSequence();
|
m_hCine->OnBeginSequence();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If we have an entry, we have to play it first
|
// If we have an entry, we have to play it first
|
||||||
if ( m_hCine->m_iszEntry != NULL_STRING )
|
if ( m_hCine->m_iszEntry != NULL_STRING )
|
||||||
|
@ -411,6 +411,17 @@ void CAI_BehaviorBase::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
m_pBackBridge->BackBridge_HandleAnimEvent( pEvent );
|
m_pBackBridge->BackBridge_HandleAnimEvent( pEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-------------------------------------
|
||||||
|
|
||||||
|
bool CAI_BehaviorBase::CanUnholsterWeapon( void )
|
||||||
|
{
|
||||||
|
Assert( m_pBackBridge != NULL );
|
||||||
|
|
||||||
|
return m_pBackBridge->BackBridge_CanUnholsterWeapon();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
||||||
bool CAI_BehaviorBase::NotifyChangeBehaviorStatus( bool fCanFinishSchedule )
|
bool CAI_BehaviorBase::NotifyChangeBehaviorStatus( bool fCanFinishSchedule )
|
||||||
|
@ -130,6 +130,9 @@ public:
|
|||||||
void BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
|
void BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
|
||||||
void BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
|
void BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
|
||||||
void BridgeHandleAnimEvent( animevent_t *pEvent );
|
void BridgeHandleAnimEvent( animevent_t *pEvent );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool BridgeCanUnholsterWeapon( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual void GatherConditions();
|
virtual void GatherConditions();
|
||||||
virtual void GatherConditionsNotActive() { return; } // Override this and your behavior will call this in place of GatherConditions() when your behavior is NOT the active one.
|
virtual void GatherConditionsNotActive() { return; } // Override this and your behavior will call this in place of GatherConditions() when your behavior is NOT the active one.
|
||||||
@ -215,6 +218,9 @@ protected:
|
|||||||
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
|
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet );
|
||||||
virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
|
virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
|
||||||
virtual void HandleAnimEvent( animevent_t *pEvent );
|
virtual void HandleAnimEvent( animevent_t *pEvent );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool CanUnholsterWeapon( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual bool ShouldAlwaysThink();
|
virtual bool ShouldAlwaysThink();
|
||||||
|
|
||||||
@ -361,6 +367,11 @@ public:
|
|||||||
|
|
||||||
virtual void BackBridge_HandleAnimEvent( animevent_t *pEvent ) = 0;
|
virtual void BackBridge_HandleAnimEvent( animevent_t *pEvent ) = 0;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// For func_tank behavior
|
||||||
|
virtual bool BackBridge_CanUnholsterWeapon( void ) = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -457,6 +468,9 @@ public:
|
|||||||
Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
|
Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture );
|
||||||
bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
|
bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
|
||||||
void HandleAnimEvent( animevent_t *pEvent );
|
void HandleAnimEvent( animevent_t *pEvent );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool CanUnholsterWeapon( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
bool ShouldAlwaysThink();
|
bool ShouldAlwaysThink();
|
||||||
|
|
||||||
@ -517,6 +531,11 @@ private:
|
|||||||
|
|
||||||
void BackBridge_HandleAnimEvent( animevent_t *pEvent );
|
void BackBridge_HandleAnimEvent( animevent_t *pEvent );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// For func_tank behavior
|
||||||
|
bool BackBridge_CanUnholsterWeapon( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
CAI_BehaviorBase **AccessBehaviors();
|
CAI_BehaviorBase **AccessBehaviors();
|
||||||
int NumBehaviors();
|
int NumBehaviors();
|
||||||
|
|
||||||
@ -887,6 +906,15 @@ inline void CAI_BehaviorBase::BridgeHandleAnimEvent( animevent_t *pEvent )
|
|||||||
HandleAnimEvent( pEvent );
|
HandleAnimEvent( pEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline bool CAI_BehaviorBase::BridgeCanUnholsterWeapon( void )
|
||||||
|
{
|
||||||
|
return CanUnholsterWeapon();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
template <class BASE_NPC>
|
template <class BASE_NPC>
|
||||||
@ -1462,6 +1490,16 @@ inline void CAI_BehaviorHost<BASE_NPC>::BackBridge_HandleAnimEvent( animevent_t
|
|||||||
BaseClass::HandleAnimEvent( pEvent );
|
BaseClass::HandleAnimEvent( pEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-------------------------------------
|
||||||
|
|
||||||
|
template <class BASE_NPC>
|
||||||
|
inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanUnholsterWeapon( void )
|
||||||
|
{
|
||||||
|
return BaseClass::CanUnholsterWeapon();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
||||||
template <class BASE_NPC>
|
template <class BASE_NPC>
|
||||||
@ -1865,6 +1903,19 @@ inline void CAI_BehaviorHost<BASE_NPC>::HandleAnimEvent( animevent_t *pEvent )
|
|||||||
return BaseClass::HandleAnimEvent( pEvent );
|
return BaseClass::HandleAnimEvent( pEvent );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-------------------------------------
|
||||||
|
|
||||||
|
template <class BASE_NPC>
|
||||||
|
inline bool CAI_BehaviorHost<BASE_NPC>::CanUnholsterWeapon( void )
|
||||||
|
{
|
||||||
|
if ( m_pCurBehavior )
|
||||||
|
return m_pCurBehavior->BridgeCanUnholsterWeapon();
|
||||||
|
|
||||||
|
return BaseClass::CanUnholsterWeapon();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
||||||
template <class BASE_NPC>
|
template <class BASE_NPC>
|
||||||
|
@ -251,7 +251,12 @@ CAssaultPoint *CAI_AssaultBehavior::FindAssaultPoint( string_t iszAssaultPointNa
|
|||||||
CUtlVector<CAssaultPoint*>pAssaultPoints;
|
CUtlVector<CAssaultPoint*>pAssaultPoints;
|
||||||
CUtlVector<CAssaultPoint*>pClearAssaultPoints;
|
CUtlVector<CAssaultPoint*>pClearAssaultPoints;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Prevents non-assault points (e.g. rally points) from crashing the game
|
||||||
|
CAssaultPoint *pAssaultEnt = dynamic_cast<CAssaultPoint*>(gEntList.FindEntityByName( NULL, iszAssaultPointName ));
|
||||||
|
#else
|
||||||
CAssaultPoint *pAssaultEnt = (CAssaultPoint *)gEntList.FindEntityByName( NULL, iszAssaultPointName );
|
CAssaultPoint *pAssaultEnt = (CAssaultPoint *)gEntList.FindEntityByName( NULL, iszAssaultPointName );
|
||||||
|
#endif
|
||||||
|
|
||||||
while( pAssaultEnt != NULL )
|
while( pAssaultEnt != NULL )
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,9 @@ BEGIN_DATADESC( CAI_FearBehavior )
|
|||||||
DEFINE_FIELD( m_hMovingToHint, FIELD_EHANDLE ),
|
DEFINE_FIELD( m_hMovingToHint, FIELD_EHANDLE ),
|
||||||
DEFINE_EMBEDDED( m_SafePlaceMoveMonitor ),
|
DEFINE_EMBEDDED( m_SafePlaceMoveMonitor ),
|
||||||
DEFINE_FIELD( m_flDeferUntil, FIELD_TIME ),
|
DEFINE_FIELD( m_flDeferUntil, FIELD_TIME ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_FIELD( m_hFearGoal, FIELD_EHANDLE ),
|
||||||
|
#endif
|
||||||
END_DATADESC();
|
END_DATADESC();
|
||||||
|
|
||||||
#define BEHAVIOR_FEAR_SAFETY_TIME 5
|
#define BEHAVIOR_FEAR_SAFETY_TIME 5
|
||||||
@ -61,6 +64,11 @@ void CAI_FearBehavior::StartTask( const Task_t *pTask )
|
|||||||
m_hSafePlaceHint = m_hMovingToHint;
|
m_hSafePlaceHint = m_hMovingToHint;
|
||||||
m_hSafePlaceHint->Lock( GetOuter() );
|
m_hSafePlaceHint->Lock( GetOuter() );
|
||||||
m_SafePlaceMoveMonitor.SetMark( GetOuter(), FEAR_SAFE_PLACE_TOLERANCE );
|
m_SafePlaceMoveMonitor.SetMark( GetOuter(), FEAR_SAFE_PLACE_TOLERANCE );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_hSafePlaceHint->NPCStartedUsing( GetOuter() );
|
||||||
|
if (m_hFearGoal)
|
||||||
|
m_hFearGoal->m_OnArriveAtFearNode.FireOutput(m_hSafePlaceHint, GetOuter());
|
||||||
|
#endif
|
||||||
TaskComplete();
|
TaskComplete();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -149,7 +157,11 @@ void CAI_FearBehavior::RunTask( const Task_t *pTask )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_hMovingToHint->NPCHandleStartNav( GetOuter(), true );
|
||||||
|
#else
|
||||||
GetNavigator()->SetArrivalDirection( m_hMovingToHint->GetAbsAngles() );
|
GetNavigator()->SetArrivalDirection( m_hMovingToHint->GetAbsAngles() );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -231,6 +243,10 @@ void CAI_FearBehavior::ReleaseAllHints()
|
|||||||
// If I have a safe place, unlock it for others.
|
// If I have a safe place, unlock it for others.
|
||||||
m_hSafePlaceHint->Unlock();
|
m_hSafePlaceHint->Unlock();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_hSafePlaceHint->NPCStoppedUsing(GetOuter());
|
||||||
|
#endif
|
||||||
|
|
||||||
// Don't make it available right away. I probably left for a good reason.
|
// Don't make it available right away. I probably left for a good reason.
|
||||||
// We also don't want to oscillate
|
// We also don't want to oscillate
|
||||||
m_hSafePlaceHint->DisableForSeconds( 4.0f );
|
m_hSafePlaceHint->DisableForSeconds( 4.0f );
|
||||||
@ -274,6 +290,22 @@ bool CAI_FearBehavior::CanSelectSchedule()
|
|||||||
if( GetOuter()->IRelationType(pEnemy) != D_FR )
|
if( GetOuter()->IRelationType(pEnemy) != D_FR )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Don't run fear behavior if we've been ordered somewhere
|
||||||
|
if (GetOuter()->GetCommandGoal() != vec3_invalid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't run fear behavior if we're running any non-follow behaviors
|
||||||
|
if (GetOuter()->GetRunningBehavior() && GetOuter()->GetRunningBehavior() != this && !FStrEq(GetOuter()->GetRunningBehavior()->GetName(), "Follow"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m_hFearGoal && m_iszFearTarget != NULL_STRING)
|
||||||
|
{
|
||||||
|
if (pEnemy->NameMatches(m_iszFearTarget) || pEnemy->ClassMatches(m_iszFearTarget))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if( !pEnemy->ClassMatches("npc_hunter") )
|
if( !pEnemy->ClassMatches("npc_hunter") )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -457,6 +489,9 @@ CAI_Hint *CAI_FearBehavior::FindFearWithdrawalDest()
|
|||||||
|
|
||||||
hintCriteria.AddHintType( HINT_PLAYER_ALLY_FEAR_DEST );
|
hintCriteria.AddHintType( HINT_PLAYER_ALLY_FEAR_DEST );
|
||||||
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER | bits_HINT_NOT_CLOSE_TO_ENEMY /*| bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV*/ );
|
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER | bits_HINT_NOT_CLOSE_TO_ENEMY /*| bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV*/ );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
hintCriteria.SetFlag(bits_HINT_NODE_USE_GROUP);
|
||||||
|
#endif
|
||||||
hintCriteria.AddIncludePosition( AI_GetSinglePlayer()->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) );
|
hintCriteria.AddIncludePosition( AI_GetSinglePlayer()->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) );
|
||||||
|
|
||||||
pHint = CAI_HintManager::FindHint( pOuter, hintCriteria );
|
pHint = CAI_HintManager::FindHint( pOuter, hintCriteria );
|
||||||
@ -478,6 +513,108 @@ CAI_Hint *CAI_FearBehavior::FindFearWithdrawalDest()
|
|||||||
return pHint;
|
return pHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
Activity CAI_FearBehavior::NPC_TranslateActivity( Activity activity )
|
||||||
|
{
|
||||||
|
if ( activity == ACT_IDLE && m_hSafePlaceHint && m_hSafePlaceHint->HintActivityName() != NULL_STRING )
|
||||||
|
{
|
||||||
|
return GetOuter()->GetHintActivity(m_hSafePlaceHint->HintType(), (Activity)CAI_BaseNPC::GetActivityID( STRING(m_hSafePlaceHint->HintActivityName()) ) );
|
||||||
|
}
|
||||||
|
return BaseClass::NPC_TranslateActivity( activity );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Updates the fear goal's target.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_FearBehavior::OnRestore()
|
||||||
|
{
|
||||||
|
BaseClass::OnRestore();
|
||||||
|
|
||||||
|
if (m_hFearGoal.Get() != NULL)
|
||||||
|
{
|
||||||
|
m_iszFearTarget = m_hFearGoal->m_target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_FearBehavior::SetParameters( CAI_FearGoal *pGoal, string_t target )
|
||||||
|
{
|
||||||
|
m_hFearGoal = pGoal;
|
||||||
|
m_iszFearTarget = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
// >AI_GOAL_FEAR
|
||||||
|
//=============================================================================
|
||||||
|
//=============================================================================
|
||||||
|
LINK_ENTITY_TO_CLASS( ai_goal_fear, CAI_FearGoal );
|
||||||
|
|
||||||
|
BEGIN_DATADESC( CAI_FearGoal )
|
||||||
|
//DEFINE_KEYFIELD( m_iSomething, FIELD_INTEGER, "something" ),
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ),
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
//DEFINE_OUTPUT( m_OnSeeFearEntity, "OnSeeFearEntity" ),
|
||||||
|
DEFINE_OUTPUT( m_OnArriveAtFearNode, "OnArrivedAtNode" ),
|
||||||
|
END_DATADESC()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_FearGoal::EnableGoal( CAI_BaseNPC *pAI )
|
||||||
|
{
|
||||||
|
CAI_FearBehavior *pBehavior;
|
||||||
|
|
||||||
|
if ( !pAI->GetBehavior( &pBehavior ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pBehavior->SetParameters(this, m_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_FearGoal::DisableGoal( CAI_BaseNPC *pAI )
|
||||||
|
{
|
||||||
|
CAI_FearBehavior *pBehavior;
|
||||||
|
|
||||||
|
if ( !pAI->GetBehavior( &pBehavior ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pBehavior->SetParameters(NULL, NULL_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : &inputdata -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_FearGoal::InputActivate( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
BaseClass::InputActivate( inputdata );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
// Input : &inputdata -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_FearGoal::InputDeactivate( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
BaseClass::InputDeactivate( inputdata );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_FearBehavior )
|
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_FearBehavior )
|
||||||
|
|
||||||
DECLARE_TASK( TASK_FEAR_GET_PATH_TO_SAFETY_HINT )
|
DECLARE_TASK( TASK_FEAR_GET_PATH_TO_SAFETY_HINT )
|
||||||
@ -531,6 +668,25 @@ AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_FearBehavior )
|
|||||||
|
|
||||||
//===============================================
|
//===============================================
|
||||||
//===============================================
|
//===============================================
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_SCHEDULE
|
||||||
|
(
|
||||||
|
SCHED_FEAR_STAY_IN_SAFE_PLACE,
|
||||||
|
|
||||||
|
" Tasks"
|
||||||
|
" TASK_FEAR_WAIT_FOR_SAFETY 0"
|
||||||
|
""
|
||||||
|
" Interrupts"
|
||||||
|
""
|
||||||
|
" COND_NEW_ENEMY"
|
||||||
|
" COND_HEAR_DANGER"
|
||||||
|
" COND_FEAR_ENEMY_CLOSE"
|
||||||
|
" COND_FEAR_ENEMY_TOO_CLOSE"
|
||||||
|
" COND_CAN_RANGE_ATTACK1"
|
||||||
|
" COND_FEAR_SEPARATED_FROM_PLAYER"
|
||||||
|
" COND_ENEMY_DEAD" // Allows the fearful to follow the player when enemy dies
|
||||||
|
);
|
||||||
|
#else
|
||||||
DEFINE_SCHEDULE
|
DEFINE_SCHEDULE
|
||||||
(
|
(
|
||||||
SCHED_FEAR_STAY_IN_SAFE_PLACE,
|
SCHED_FEAR_STAY_IN_SAFE_PLACE,
|
||||||
@ -547,6 +703,7 @@ AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_FearBehavior )
|
|||||||
" COND_CAN_RANGE_ATTACK1"
|
" COND_CAN_RANGE_ATTACK1"
|
||||||
" COND_FEAR_SEPARATED_FROM_PLAYER"
|
" COND_FEAR_SEPARATED_FROM_PLAYER"
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
AI_END_CUSTOM_SCHEDULE_PROVIDER()
|
AI_END_CUSTOM_SCHEDULE_PROVIDER()
|
||||||
|
@ -20,6 +20,37 @@
|
|||||||
|
|
||||||
#include "ai_behavior.h"
|
#include "ai_behavior.h"
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "ai_goalentity.h"
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
//=========================================================
|
||||||
|
class CAI_FearGoal : public CAI_GoalEntity
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( CAI_FearGoal, CAI_GoalEntity );
|
||||||
|
public:
|
||||||
|
CAI_FearGoal()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnableGoal( CAI_BaseNPC *pAI );
|
||||||
|
void DisableGoal( CAI_BaseNPC *pAI );
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
virtual void InputActivate( inputdata_t &inputdata );
|
||||||
|
virtual void InputDeactivate( inputdata_t &inputdata );
|
||||||
|
|
||||||
|
// Note that the outer is the caller in these outputs
|
||||||
|
//COutputEvent m_OnSeeFearEntity;
|
||||||
|
COutputEvent m_OnArriveAtFearNode;
|
||||||
|
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Put something here
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class CAI_FearBehavior : public CAI_SimpleBehavior
|
class CAI_FearBehavior : public CAI_SimpleBehavior
|
||||||
{
|
{
|
||||||
DECLARE_CLASS( CAI_FearBehavior, CAI_SimpleBehavior );
|
DECLARE_CLASS( CAI_FearBehavior, CAI_SimpleBehavior );
|
||||||
@ -56,6 +87,17 @@ public:
|
|||||||
void BuildScheduleTestBits();
|
void BuildScheduleTestBits();
|
||||||
int TranslateSchedule( int scheduleType );
|
int TranslateSchedule( int scheduleType );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual Activity NPC_TranslateActivity( Activity activity );
|
||||||
|
|
||||||
|
virtual void OnRestore();
|
||||||
|
virtual void SetParameters( CAI_FearGoal *pGoal, string_t target );
|
||||||
|
CHandle<CAI_FearGoal> m_hFearGoal;
|
||||||
|
|
||||||
|
// Points to goal's fear target
|
||||||
|
string_t m_iszFearTarget;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
|
|
||||||
#ifdef HL2_EPISODIC
|
#ifdef HL2_EPISODIC
|
||||||
#include "info_darknessmode_lightsource.h"
|
#include "info_darknessmode_lightsource.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "globalstate.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
@ -403,7 +406,11 @@ bool CAI_FollowBehavior::SetFollowGoal( CAI_FollowGoal *pGoal, bool fFinishCurSc
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetFollowTarget( pGoal->GetGoalEntity() );
|
SetFollowTarget( pGoal->GetGoalEntity() );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
Assert( pGoal->m_iFormation < AIF_NUM_FORMATIONS );
|
||||||
|
#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 );
|
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 ) );
|
SetParameters( AI_FollowParams_t( (AI_Formations_t)pGoal->m_iFormation ) );
|
||||||
m_hFollowGoalEnt = pGoal;
|
m_hFollowGoalEnt = pGoal;
|
||||||
m_flTimeUpdatedFollowPosition = 0;
|
m_flTimeUpdatedFollowPosition = 0;
|
||||||
@ -764,7 +771,12 @@ void CAI_FollowBehavior::GatherConditions( void )
|
|||||||
|
|
||||||
#ifdef HL2_EPISODIC
|
#ifdef HL2_EPISODIC
|
||||||
// Let followers know if the player is lit in the darkness
|
// Let followers know if the player is lit in the darkness
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// If the darkness mode counter is 1, follow behavior is not affected by darkness.
|
||||||
|
if ( GetFollowTarget()->IsPlayer() && HL2GameRules()->IsAlyxInDarknessMode() && GlobalEntity_GetCounter("ep_alyx_darknessmode") != 1 )
|
||||||
|
#else
|
||||||
if ( GetFollowTarget()->IsPlayer() && HL2GameRules()->IsAlyxInDarknessMode() )
|
if ( GetFollowTarget()->IsPlayer() && HL2GameRules()->IsAlyxInDarknessMode() )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if ( LookerCouldSeeTargetInDarkness( GetOuter(), GetFollowTarget() ) )
|
if ( LookerCouldSeeTargetInDarkness( GetOuter(), GetFollowTarget() ) )
|
||||||
{
|
{
|
||||||
@ -907,6 +919,11 @@ void CAI_FollowBehavior::ClearFollowPoint()
|
|||||||
{
|
{
|
||||||
if ( GetHintNode() && GetHintNode()->HintType() == HINT_FOLLOW_WAIT_POINT )
|
if ( GetHintNode() && GetHintNode()->HintType() == HINT_FOLLOW_WAIT_POINT )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// If we were in range, we were probably already using it
|
||||||
|
if ((GetHintNode()->GetAbsOrigin() - GetFollowTarget()->GetAbsOrigin()).LengthSqr() < Square(MAX(m_FollowNavGoal.followPointTolerance, GetGoalRange())))
|
||||||
|
GetHintNode()->NPCStoppedUsing(GetOuter());
|
||||||
|
#endif
|
||||||
GetHintNode()->Unlock();
|
GetHintNode()->Unlock();
|
||||||
SetHintNode( NULL );
|
SetHintNode( NULL );
|
||||||
}
|
}
|
||||||
@ -931,7 +948,14 @@ CAI_Hint *CAI_FollowBehavior::FindFollowPoint()
|
|||||||
|
|
||||||
CHintCriteria hintCriteria;
|
CHintCriteria hintCriteria;
|
||||||
hintCriteria.SetHintType( HINT_FOLLOW_WAIT_POINT );
|
hintCriteria.SetHintType( HINT_FOLLOW_WAIT_POINT );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// NOTE: Does this make them stop following?
|
||||||
|
hintCriteria.SetGroup( GetOuter()->GetHintGroup() );
|
||||||
|
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_NEAREST | bits_HINT_NODE_USE_GROUP );
|
||||||
|
//hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_NEAREST );
|
||||||
|
#else
|
||||||
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_NEAREST );
|
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_NEAREST );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Add the search position
|
// Add the search position
|
||||||
hintCriteria.AddIncludePosition( GetGoalPosition(), MAX( m_FollowNavGoal.followPointTolerance, GetGoalRange() ) );
|
hintCriteria.AddIncludePosition( GetGoalPosition(), MAX( m_FollowNavGoal.followPointTolerance, GetGoalRange() ) );
|
||||||
@ -1033,6 +1057,9 @@ int CAI_FollowBehavior::SelectScheduleFollowPoints()
|
|||||||
{
|
{
|
||||||
if ( bNewHint || distSqToPoint > WAIT_HINT_MIN_DIST )
|
if ( bNewHint || distSqToPoint > WAIT_HINT_MIN_DIST )
|
||||||
return SCHED_FOLLOWER_GO_TO_WAIT_POINT;
|
return SCHED_FOLLOWER_GO_TO_WAIT_POINT;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
GetHintNode()->NPCStartedUsing(GetOuter());
|
||||||
|
#endif
|
||||||
if ( !ShouldIgnoreFollowPointFacing() )
|
if ( !ShouldIgnoreFollowPointFacing() )
|
||||||
return SCHED_FOLLOWER_STAND_AT_WAIT_POINT;
|
return SCHED_FOLLOWER_STAND_AT_WAIT_POINT;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@ enum AI_Formations_t
|
|||||||
AIF_SIDEKICK,
|
AIF_SIDEKICK,
|
||||||
AIF_HUNTER,
|
AIF_HUNTER,
|
||||||
AIF_VORTIGAUNT,
|
AIF_VORTIGAUNT,
|
||||||
|
#ifdef MAPBASE
|
||||||
|
AIF_NUM_FORMATIONS,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AI_FollowFormationFlags_t
|
enum AI_FollowFormationFlags_t
|
||||||
|
@ -543,8 +543,12 @@ int CAI_LeadBehavior::SelectSchedule()
|
|||||||
if ( !m_flWeaponSafetyTimeOut || (m_flWeaponSafetyTimeOut > gpGlobals->curtime) )
|
if ( !m_flWeaponSafetyTimeOut || (m_flWeaponSafetyTimeOut > gpGlobals->curtime) )
|
||||||
return SCHED_LEAD_PLAYERNEEDSWEAPON;
|
return SCHED_LEAD_PLAYERNEEDSWEAPON;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
pFollower->GiveNamedItem( STRING(m_weaponname) );
|
||||||
|
#else
|
||||||
string_t iszItem = AllocPooledString( "weapon_bugbait" );
|
string_t iszItem = AllocPooledString( "weapon_bugbait" );
|
||||||
pFollower->GiveNamedItem( STRING(iszItem) );
|
pFollower->GiveNamedItem( STRING(iszItem) );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1649,6 +1653,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
string_t m_iszWeaponName;
|
string_t m_iszWeaponName;
|
||||||
|
#ifdef MAPBASE
|
||||||
|
float m_flTimeoutTime = 60;
|
||||||
|
#endif
|
||||||
string_t m_iszMissingWeaponConceptModifier;
|
string_t m_iszMissingWeaponConceptModifier;
|
||||||
|
|
||||||
DECLARE_DATADESC();
|
DECLARE_DATADESC();
|
||||||
@ -1664,6 +1671,9 @@ LINK_ENTITY_TO_CLASS( ai_goal_lead_weapon, CAI_LeadGoal_Weapon );
|
|||||||
BEGIN_DATADESC( CAI_LeadGoal_Weapon )
|
BEGIN_DATADESC( CAI_LeadGoal_Weapon )
|
||||||
|
|
||||||
DEFINE_KEYFIELD( m_iszWeaponName, FIELD_STRING, "WeaponName"),
|
DEFINE_KEYFIELD( m_iszWeaponName, FIELD_STRING, "WeaponName"),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_KEYFIELD( m_flTimeoutTime, FIELD_FLOAT, "TimeoutTime" ),
|
||||||
|
#endif
|
||||||
DEFINE_KEYFIELD( m_iszMissingWeaponConceptModifier, FIELD_STRING, "MissingWeaponConceptModifier"),
|
DEFINE_KEYFIELD( m_iszMissingWeaponConceptModifier, FIELD_STRING, "MissingWeaponConceptModifier"),
|
||||||
|
|
||||||
END_DATADESC()
|
END_DATADESC()
|
||||||
@ -1688,6 +1698,10 @@ void CAI_LeadGoal_Weapon::InputActivate( inputdata_t &inputdata )
|
|||||||
CAI_LeadBehavior *pBehavior = GetLeadBehavior();
|
CAI_LeadBehavior *pBehavior = GetLeadBehavior();
|
||||||
if ( pBehavior )
|
if ( pBehavior )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
pBehavior->SetWaitForWeapon( m_iszWeaponName, m_flTimeoutTime );
|
||||||
|
#else
|
||||||
pBehavior->SetWaitForWeapon( m_iszWeaponName );
|
pBehavior->SetWaitForWeapon( m_iszWeaponName );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,11 @@ public:
|
|||||||
bool Connect( CAI_LeadBehaviorHandler *);
|
bool Connect( CAI_LeadBehaviorHandler *);
|
||||||
bool Disconnect( CAI_LeadBehaviorHandler *);
|
bool Disconnect( CAI_LeadBehaviorHandler *);
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void SetWaitForWeapon( string_t iszWeaponName, float flTimeout = 60 ) { m_weaponname = iszWeaponName; m_flWeaponSafetyTimeOut = gpGlobals->curtime + flTimeout; }
|
||||||
|
#else
|
||||||
void SetWaitForWeapon( string_t iszWeaponName ) { m_weaponname = iszWeaponName; m_flWeaponSafetyTimeOut = gpGlobals->curtime + 60; }
|
void SetWaitForWeapon( string_t iszWeaponName ) { m_weaponname = iszWeaponName; m_flWeaponSafetyTimeOut = gpGlobals->curtime + 60; }
|
||||||
|
#endif
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -516,7 +516,11 @@ int CAI_StandoffBehavior::SelectScheduleCheckCover( void )
|
|||||||
if ( GetOuter()->GetShotRegulator()->IsInRestInterval() )
|
if ( GetOuter()->GetShotRegulator()->IsInRestInterval() )
|
||||||
{
|
{
|
||||||
StandoffMsg( "Regulated to not shoot\n" );
|
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_LOW )
|
||||||
|
#endif
|
||||||
SetPosture( AIP_CROUCHING );
|
SetPosture( AIP_CROUCHING );
|
||||||
else
|
else
|
||||||
SetPosture( AIP_STANDING );
|
SetPosture( AIP_STANDING );
|
||||||
@ -1067,10 +1071,18 @@ void CAI_StandoffBehavior::UnlockHintNode()
|
|||||||
|
|
||||||
Activity CAI_StandoffBehavior::GetCoverActivity()
|
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;
|
||||||
|
#else
|
||||||
CAI_Hint *pHintNode = GetHintNode();
|
CAI_Hint *pHintNode = GetHintNode();
|
||||||
if ( pHintNode && pHintNode->HintType() == HINT_TACTICAL_COVER_LOW )
|
if ( pHintNode && pHintNode->HintType() == HINT_TACTICAL_COVER_LOW )
|
||||||
return GetOuter()->GetCoverActivity( pHintNode );
|
return GetOuter()->GetCoverActivity( pHintNode );
|
||||||
return ACT_INVALID;
|
return ACT_INVALID;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1114,7 +1126,12 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
|
|||||||
{
|
{
|
||||||
if ( !mappings[i].pszWeapon || stricmp( mappings[i].pszWeapon, pszWeaponClass ) == 0 )
|
if ( !mappings[i].pszWeapon || stricmp( mappings[i].pszWeapon, pszWeaponClass ) == 0 )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Check 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 ) ) )
|
if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() );
|
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 );
|
m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].translation );
|
||||||
|
@ -411,6 +411,20 @@ void CC_NPC_Create( const CCommand &args )
|
|||||||
{
|
{
|
||||||
baseNPC->SetName( AllocPooledString( args[2] ) );
|
baseNPC->SetName( AllocPooledString( args[2] ) );
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
else if ( args.ArgC() > 3 )
|
||||||
|
{
|
||||||
|
baseNPC->SetName( AllocPooledString( args[2] ) );
|
||||||
|
|
||||||
|
// Pass in any additional parameters.
|
||||||
|
for ( int i = 3; i + 1 < args.ArgC(); i += 2 )
|
||||||
|
{
|
||||||
|
const char *pKeyName = args[i];
|
||||||
|
const char *pValue = args[i+1];
|
||||||
|
baseNPC->KeyValue( pKeyName, pValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DispatchSpawn(baseNPC);
|
DispatchSpawn(baseNPC);
|
||||||
// Now attempt to drop into the world
|
// Now attempt to drop into the world
|
||||||
|
@ -1774,6 +1774,24 @@ AI_DEFINE_SCHEDULE
|
|||||||
// Run to cover, but don't turn to face enemy and upon
|
// Run to cover, but don't turn to face enemy and upon
|
||||||
// fail run around randomly
|
// fail run around randomly
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
#ifdef MAPBASE
|
||||||
|
AI_DEFINE_SCHEDULE
|
||||||
|
(
|
||||||
|
SCHED_RUN_FROM_ENEMY,
|
||||||
|
|
||||||
|
" Tasks"
|
||||||
|
" TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RUN_FROM_ENEMY_FALLBACK"
|
||||||
|
" TASK_STOP_MOVING 0"
|
||||||
|
" TASK_FIND_COVER_FROM_ENEMY 0"
|
||||||
|
" TASK_RUN_PATH 0"
|
||||||
|
" TASK_WAIT_FOR_MOVEMENT 0"
|
||||||
|
" TASK_REMEMBER MEMORY:INCOVER" // Now that crouch nodes are fixed, this is necessary in case cover leads to a crouch node
|
||||||
|
""
|
||||||
|
" Interrupts"
|
||||||
|
" COND_NEW_ENEMY"
|
||||||
|
" COND_ENEMY_DEAD"
|
||||||
|
);
|
||||||
|
#else
|
||||||
AI_DEFINE_SCHEDULE
|
AI_DEFINE_SCHEDULE
|
||||||
(
|
(
|
||||||
SCHED_RUN_FROM_ENEMY,
|
SCHED_RUN_FROM_ENEMY,
|
||||||
@ -1789,6 +1807,7 @@ AI_DEFINE_SCHEDULE
|
|||||||
" COND_NEW_ENEMY"
|
" COND_NEW_ENEMY"
|
||||||
" COND_ENEMY_DEAD"
|
" COND_ENEMY_DEAD"
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
AI_DEFINE_SCHEDULE
|
AI_DEFINE_SCHEDULE
|
||||||
(
|
(
|
||||||
@ -2351,6 +2370,19 @@ AI_DEFINE_SCHEDULE
|
|||||||
//=========================================================
|
//=========================================================
|
||||||
// > SCHED_INTERACTION_WAIT_FOR_PARTNER
|
// > SCHED_INTERACTION_WAIT_FOR_PARTNER
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
#ifdef MAPBASE
|
||||||
|
AI_DEFINE_SCHEDULE
|
||||||
|
(
|
||||||
|
SCHED_INTERACTION_WAIT_FOR_PARTNER,
|
||||||
|
|
||||||
|
" Tasks"
|
||||||
|
" TASK_FACE_INTERACTION_ANGLES 0" // New task to fix forced interaction anomalies
|
||||||
|
" TASK_WAIT 1"
|
||||||
|
""
|
||||||
|
" Interrupts"
|
||||||
|
" COND_NO_CUSTOM_INTERRUPTS"
|
||||||
|
);
|
||||||
|
#else
|
||||||
AI_DEFINE_SCHEDULE
|
AI_DEFINE_SCHEDULE
|
||||||
(
|
(
|
||||||
SCHED_INTERACTION_WAIT_FOR_PARTNER,
|
SCHED_INTERACTION_WAIT_FOR_PARTNER,
|
||||||
@ -2362,6 +2394,7 @@ AI_DEFINE_SCHEDULE
|
|||||||
" Interrupts"
|
" Interrupts"
|
||||||
" COND_NO_CUSTOM_INTERRUPTS"
|
" COND_NO_CUSTOM_INTERRUPTS"
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// > SCHED_SLEEP
|
// > SCHED_SLEEP
|
||||||
|
@ -15,6 +15,14 @@
|
|||||||
#include "ai_link.h"
|
#include "ai_link.h"
|
||||||
#include "ai_network.h"
|
#include "ai_network.h"
|
||||||
#include "ai_networkmanager.h"
|
#include "ai_networkmanager.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "ai_hint.h"
|
||||||
|
#include "ai_basenpc.h"
|
||||||
|
#include "filters.h"
|
||||||
|
#include "point_template.h"
|
||||||
|
#include "TemplateEntities.h"
|
||||||
|
#include "mapentities.h"
|
||||||
|
#endif
|
||||||
#include "saverestore_utlvector.h"
|
#include "saverestore_utlvector.h"
|
||||||
#include "editor_sendcommand.h"
|
#include "editor_sendcommand.h"
|
||||||
#include "bitstring.h"
|
#include "bitstring.h"
|
||||||
@ -169,6 +177,156 @@ void CAI_DynamicLinkController::InputSetInvert( inputdata_t &inputdata )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//=============================================================================
|
||||||
|
// >> CAI_CustomLinkController
|
||||||
|
// Uses the specified link class
|
||||||
|
//=============================================================================
|
||||||
|
class CAI_CustomLinkController : public CAI_DynamicLinkController
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( CAI_CustomLinkController, CAI_DynamicLinkController );
|
||||||
|
public:
|
||||||
|
CAI_CustomLinkController();
|
||||||
|
|
||||||
|
void GenerateLinksFromVolume();
|
||||||
|
int GetReferenceLinkIndex();
|
||||||
|
|
||||||
|
string_t m_iszReferenceLinkTemplate;
|
||||||
|
int m_iReferenceLink;
|
||||||
|
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
};
|
||||||
|
|
||||||
|
LINK_ENTITY_TO_CLASS(info_template_link_controller, CAI_CustomLinkController);
|
||||||
|
|
||||||
|
BEGIN_DATADESC( CAI_CustomLinkController )
|
||||||
|
|
||||||
|
DEFINE_KEYFIELD( m_iszReferenceLinkTemplate, FIELD_STRING, "ReferenceTemplate" ),
|
||||||
|
//DEFINE_FIELD( m_iReferenceLink, FIELD_INTEGER ), // I don't know if this should be saved. It's only a cached variable, so not saving it shouldn't hurt anything.
|
||||||
|
|
||||||
|
END_DATADESC()
|
||||||
|
|
||||||
|
CAI_CustomLinkController::CAI_CustomLinkController()
|
||||||
|
{
|
||||||
|
m_iReferenceLink = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CAI_CustomLinkController::GetReferenceLinkIndex()
|
||||||
|
{
|
||||||
|
if (m_iReferenceLink != -1)
|
||||||
|
return m_iReferenceLink;
|
||||||
|
|
||||||
|
CBaseEntity *pEnt = gEntList.FindEntityByName(NULL, STRING(m_iszReferenceLinkTemplate), this);
|
||||||
|
if (CPointTemplate *pTemplate = dynamic_cast<CPointTemplate*>(pEnt))
|
||||||
|
{
|
||||||
|
Assert(pTemplate->GetTemplateEntity(0));
|
||||||
|
|
||||||
|
m_iReferenceLink = pTemplate->GetTemplateIndexForTemplate(0);
|
||||||
|
return m_iReferenceLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAI_CustomLinkController::GenerateLinksFromVolume()
|
||||||
|
{
|
||||||
|
Assert( m_ControlledLinks.Count() == 0 );
|
||||||
|
|
||||||
|
int nNodes = g_pBigAINet->NumNodes();
|
||||||
|
CAI_Node **ppNodes = g_pBigAINet->AccessNodes();
|
||||||
|
|
||||||
|
float MinDistCareSq = 0;
|
||||||
|
if (m_bUseAirLinkRadius)
|
||||||
|
{
|
||||||
|
MinDistCareSq = Square(MAX_AIR_NODE_LINK_DIST + 0.1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MinDistCareSq = Square(MAX_NODE_LINK_DIST + 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector &origin = WorldSpaceCenter();
|
||||||
|
Vector vAbsMins, vAbsMaxs;
|
||||||
|
CollisionProp()->WorldSpaceAABB( &vAbsMins, &vAbsMaxs );
|
||||||
|
vAbsMins -= Vector( 1, 1, 1 );
|
||||||
|
vAbsMaxs += Vector( 1, 1, 1 );
|
||||||
|
|
||||||
|
int iReference = GetReferenceLinkIndex();
|
||||||
|
if (iReference == -1)
|
||||||
|
{
|
||||||
|
Warning("WARNING! %s reference link is invalid!\n", GetDebugName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the map data before the loop
|
||||||
|
char *pMapData = (char*)STRING( Templates_FindByIndex( iReference ) );
|
||||||
|
|
||||||
|
// Make sure the entity is a dynamic link before doing anything
|
||||||
|
CBaseEntity *pEntity = NULL;
|
||||||
|
MapEntity_ParseEntity( pEntity, pMapData, NULL );
|
||||||
|
if ( !dynamic_cast<CAI_DynamicLink*>(pEntity) )
|
||||||
|
{
|
||||||
|
Warning("WARNING! %s reference link is not a node link!\n", GetDebugName());
|
||||||
|
UTIL_RemoveImmediate(pEntity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTIL_RemoveImmediate(pEntity);
|
||||||
|
|
||||||
|
for ( int i = 0; i < nNodes; i++ )
|
||||||
|
{
|
||||||
|
CAI_Node *pNode = ppNodes[i];
|
||||||
|
const Vector &nodeOrigin = pNode->GetOrigin();
|
||||||
|
if ( origin.DistToSqr(nodeOrigin) < MinDistCareSq )
|
||||||
|
{
|
||||||
|
int nLinks = pNode->NumLinks();
|
||||||
|
for ( int j = 0; j < nLinks; j++ )
|
||||||
|
{
|
||||||
|
CAI_Link *pLink = pNode->GetLinkByIndex( j );
|
||||||
|
int iLinkDest = pLink->DestNodeID( i );
|
||||||
|
if ( iLinkDest > i )
|
||||||
|
{
|
||||||
|
const Vector &originOther = ppNodes[iLinkDest]->GetOrigin();
|
||||||
|
if ( origin.DistToSqr(originOther) < MinDistCareSq )
|
||||||
|
{
|
||||||
|
if ( IsBoxIntersectingRay( vAbsMins, vAbsMaxs, nodeOrigin, originOther - nodeOrigin ) )
|
||||||
|
{
|
||||||
|
Assert( IsBoxIntersectingRay( vAbsMins, vAbsMaxs, originOther, nodeOrigin - originOther ) );
|
||||||
|
|
||||||
|
CBaseEntity *pEntity = NULL;
|
||||||
|
|
||||||
|
// Create the entity from the mapdata
|
||||||
|
MapEntity_ParseEntity( pEntity, pMapData, NULL );
|
||||||
|
if ( pEntity == NULL )
|
||||||
|
{
|
||||||
|
Msg("%s failed to initialize templated link with mapdata: %s\n", GetDebugName(), pMapData );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We already made sure it was an info_node_link template earlier.
|
||||||
|
CAI_DynamicLink *pLink = static_cast<CAI_DynamicLink*>(pEntity);
|
||||||
|
|
||||||
|
pLink->m_nSrcID = i;
|
||||||
|
pLink->m_nDestID = iLinkDest;
|
||||||
|
pLink->m_nSrcEditID = g_pAINetworkManager->GetEditOps()->GetWCIdFromNodeId( pLink->m_nSrcID );
|
||||||
|
pLink->m_nDestEditID = g_pAINetworkManager->GetEditOps()->GetWCIdFromNodeId( pLink->m_nDestID );
|
||||||
|
pLink->m_nLinkState = m_nLinkState;
|
||||||
|
pLink->m_strAllowUse = m_strAllowUse;
|
||||||
|
pLink->m_bInvertAllow = m_bInvertAllow;
|
||||||
|
pLink->m_bFixedUpIds = true;
|
||||||
|
pLink->m_bNotSaved = true;
|
||||||
|
|
||||||
|
pLink->Spawn();
|
||||||
|
m_ControlledLinks.AddToTail( pLink );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
LINK_ENTITY_TO_CLASS(info_node_link, CAI_DynamicLink);
|
LINK_ENTITY_TO_CLASS(info_node_link, CAI_DynamicLink);
|
||||||
@ -579,6 +737,242 @@ CAI_DynamicLink::~CAI_DynamicLink(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose : Determines if usage is allowed by a NPC, whether the link is disabled or not.
|
||||||
|
// This was created for info_node_link derivatives.
|
||||||
|
// Input :
|
||||||
|
// Output :
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool CAI_DynamicLink::UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd)
|
||||||
|
{
|
||||||
|
if (!(FindLink()->m_LinkInfo & bits_LINK_OFF))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ( m_strAllowUse == NULL_STRING )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *pszAllowUse = STRING( m_strAllowUse );
|
||||||
|
if ( m_bInvertAllow )
|
||||||
|
{
|
||||||
|
// Exlude only the specified entity name or classname
|
||||||
|
if ( !pNPC->NameMatches(pszAllowUse) && !pNPC->ClassMatches( pszAllowUse ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Exclude everything but the allowed entity name or classname
|
||||||
|
if ( pNPC->NameMatches( pszAllowUse) || pNPC->ClassMatches( pszAllowUse ) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// >> CAI_DynanicLinkOneWay
|
||||||
|
//=============================================================================
|
||||||
|
class CAI_DynamicLinkOneWay : public CAI_DynamicLink
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( CAI_DynamicLinkOneWay, CAI_DynamicLink );
|
||||||
|
public:
|
||||||
|
virtual bool UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd);
|
||||||
|
//virtual void SetLinkState( void );
|
||||||
|
|
||||||
|
bool m_bNormalWhenEnabled;
|
||||||
|
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
};
|
||||||
|
|
||||||
|
LINK_ENTITY_TO_CLASS(info_node_link_oneway, CAI_DynamicLinkOneWay);
|
||||||
|
|
||||||
|
BEGIN_DATADESC( CAI_DynamicLinkOneWay )
|
||||||
|
|
||||||
|
DEFINE_KEYFIELD( m_bNormalWhenEnabled, FIELD_BOOLEAN, "Usage" ),
|
||||||
|
|
||||||
|
END_DATADESC()
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose : Determines if usage is allowed by a NPC.
|
||||||
|
// This was created for info_node_link derivatives.
|
||||||
|
// Input :
|
||||||
|
// Output :
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool CAI_DynamicLinkOneWay::UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd)
|
||||||
|
{
|
||||||
|
if (m_bNormalWhenEnabled)
|
||||||
|
return (m_nLinkState == LINK_OFF && bFromEnd) ? BaseClass::UseAllowed(pNPC, bFromEnd) : true;
|
||||||
|
|
||||||
|
if (bFromEnd || m_nLinkState == LINK_OFF)
|
||||||
|
return BaseClass::UseAllowed(pNPC, bFromEnd);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose : Updates network link state if dynamic link state has changed
|
||||||
|
// Input :
|
||||||
|
// Output :
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void CAI_DynamicLinkOneWay::SetLinkState(void)
|
||||||
|
{
|
||||||
|
if (m_bNormalWhenEnabled)
|
||||||
|
return BaseClass::SetLinkState();
|
||||||
|
|
||||||
|
if ( !gm_bInitialized )
|
||||||
|
{
|
||||||
|
// Safe to quietly return. Consistency will be enforced when InitDynamicLinks() is called
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_nSrcID == NO_NODE || m_nDestID == NO_NODE)
|
||||||
|
{
|
||||||
|
Vector pos = GetAbsOrigin();
|
||||||
|
DevWarning("ERROR: Dynamic link at %f %f %f pointing to invalid node ID!!\n", pos.x, pos.y, pos.z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAI_Node * pSrcNode = g_pBigAINet->GetNode(m_nSrcID, false);
|
||||||
|
if ( pSrcNode )
|
||||||
|
{
|
||||||
|
CAI_Link* pLink = FindLink();
|
||||||
|
if ( pLink )
|
||||||
|
{
|
||||||
|
// One-way always registers as off so it always calls UseAllowed()
|
||||||
|
pLink->m_pDynamicLink = this;
|
||||||
|
pLink->m_LinkInfo |= bits_LINK_OFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DevMsg("Dynamic Link Error: (%s) unable to form between nodes %d and %d\n", GetDebugName(), m_nSrcID, m_nDestID );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// >> CAI_DynamicLinkFilter
|
||||||
|
//=============================================================================
|
||||||
|
class CAI_DynamicLinkFilter : public CAI_DynamicLink
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( CAI_DynamicLinkFilter, CAI_DynamicLink );
|
||||||
|
public:
|
||||||
|
virtual bool UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd);
|
||||||
|
//virtual void SetLinkState( void );
|
||||||
|
|
||||||
|
bool m_bNormalWhenEnabled;
|
||||||
|
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
};
|
||||||
|
|
||||||
|
LINK_ENTITY_TO_CLASS(info_node_link_filtered, CAI_DynamicLinkFilter);
|
||||||
|
|
||||||
|
BEGIN_DATADESC( CAI_DynamicLinkFilter )
|
||||||
|
|
||||||
|
DEFINE_KEYFIELD( m_bNormalWhenEnabled, FIELD_BOOLEAN, "Usage" ),
|
||||||
|
DEFINE_INPUTFUNC( FIELD_STRING, "SetLinkFilter", InputSetDamageFilter ),
|
||||||
|
|
||||||
|
END_DATADESC()
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose : Determines if usage is allowed by a NPC.
|
||||||
|
// This was created for info_node_link derivatives.
|
||||||
|
// Input :
|
||||||
|
// Output :
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool CAI_DynamicLinkFilter::UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd)
|
||||||
|
{
|
||||||
|
if ( !m_hDamageFilter )
|
||||||
|
{
|
||||||
|
m_hDamageFilter = gEntList.FindEntityByName( NULL, m_iszDamageFilterName );
|
||||||
|
if (!m_hDamageFilter)
|
||||||
|
{
|
||||||
|
Warning("%s (%s) couldn't find filter \"%s\"!\n", GetClassname(), GetDebugName(), STRING(m_iszDamageFilterName));
|
||||||
|
return BaseClass::UseAllowed(pNPC, bFromEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CBaseFilter *pFilter = (CBaseFilter *)(m_hDamageFilter.Get());
|
||||||
|
|
||||||
|
if (m_bNormalWhenEnabled)
|
||||||
|
return (m_nLinkState == LINK_OFF) ? (pFilter->PassesFilter(this, pNPC) || BaseClass::UseAllowed(pNPC, bFromEnd)) : true;
|
||||||
|
|
||||||
|
if (m_nLinkState == LINK_OFF)
|
||||||
|
return BaseClass::UseAllowed(pNPC, bFromEnd);
|
||||||
|
|
||||||
|
return pFilter->PassesFilter(this, pNPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// >> CAI_DynamicLinkLogic
|
||||||
|
//=============================================================================
|
||||||
|
class CAI_DynamicLinkLogic : public CAI_DynamicLink
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( CAI_DynamicLinkLogic, CAI_DynamicLink );
|
||||||
|
public:
|
||||||
|
virtual bool UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd);
|
||||||
|
virtual bool FinalUseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd);
|
||||||
|
|
||||||
|
COutputEvent m_OnUsageAccepted;
|
||||||
|
COutputEvent m_OnUsageAcceptedWhileDisabled;
|
||||||
|
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
};
|
||||||
|
|
||||||
|
LINK_ENTITY_TO_CLASS(info_node_link_logic, CAI_DynamicLinkLogic);
|
||||||
|
|
||||||
|
BEGIN_DATADESC( CAI_DynamicLinkLogic )
|
||||||
|
|
||||||
|
DEFINE_OUTPUT( m_OnUsageAccepted, "OnUsageAccepted" ),
|
||||||
|
DEFINE_OUTPUT( m_OnUsageAcceptedWhileDisabled, "OnUsageAcceptedWhileDisabled" ),
|
||||||
|
|
||||||
|
END_DATADESC()
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose : Determines if usage is allowed by a NPC.
|
||||||
|
// This was created for info_node_link derivatives.
|
||||||
|
// Input :
|
||||||
|
// Output :
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool CAI_DynamicLinkLogic::UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// If the link is off, we want to fire "OnUsageAcceptedWhileDisabled", but we have to make sure
|
||||||
|
// the rest of the pathfinding calculations work. Yes, they might do all of this just to find a disabled link,
|
||||||
|
// but we have to fire the output somehow.
|
||||||
|
//
|
||||||
|
// Links already enabled go through regular usage rules.
|
||||||
|
//
|
||||||
|
if (m_nLinkState == LINK_OFF)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return BaseClass::UseAllowed( pNPC, bFromEnd );
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Purpose : After nothing else is left, finally determines if usage is allowed by a NPC.
|
||||||
|
// This was created for info_node_link derivatives.
|
||||||
|
// Input :
|
||||||
|
// Output :
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
bool CAI_DynamicLinkLogic::FinalUseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd)
|
||||||
|
{
|
||||||
|
if (m_nLinkState == LINK_ON)
|
||||||
|
{
|
||||||
|
m_OnUsageAccepted.FireOutput(pNPC, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_OnUsageAcceptedWhileDisabled.FireOutput(pNPC, this);
|
||||||
|
|
||||||
|
// We skipped the usage rules before. Do them now.
|
||||||
|
return BaseClass::UseAllowed(pNPC, bFromEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LINK_ENTITY_TO_CLASS(info_radial_link_controller, CAI_RadialLinkController);
|
LINK_ENTITY_TO_CLASS(info_radial_link_controller, CAI_RadialLinkController);
|
||||||
|
|
||||||
BEGIN_DATADESC( CAI_RadialLinkController )
|
BEGIN_DATADESC( CAI_RadialLinkController )
|
||||||
|
@ -65,6 +65,13 @@ public:
|
|||||||
|
|
||||||
int ObjectCaps();
|
int ObjectCaps();
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool UseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd);
|
||||||
|
|
||||||
|
// Called after we know the NPC meets all of the node's criteria
|
||||||
|
virtual bool FinalUseAllowed(CAI_BaseNPC *pNPC, bool bFromEnd) { return true; }
|
||||||
|
#endif
|
||||||
|
|
||||||
// ----------------
|
// ----------------
|
||||||
// Inputs
|
// Inputs
|
||||||
// ----------------
|
// ----------------
|
||||||
@ -83,6 +90,9 @@ class CAI_DynamicLinkController : public CServerOnlyEntity
|
|||||||
{
|
{
|
||||||
DECLARE_CLASS( CAI_DynamicLinkController, CServerOnlyEntity );
|
DECLARE_CLASS( CAI_DynamicLinkController, CServerOnlyEntity );
|
||||||
public:
|
public:
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual
|
||||||
|
#endif
|
||||||
void GenerateLinksFromVolume();
|
void GenerateLinksFromVolume();
|
||||||
|
|
||||||
// ----------------
|
// ----------------
|
||||||
|
@ -890,6 +890,9 @@ BEGIN_DATADESC( CAI_Hint )
|
|||||||
// Inputs
|
// Inputs
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "EnableHint", InputEnableHint ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "EnableHint", InputEnableHint ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "DisableHint", InputDisableHint ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "DisableHint", InputDisableHint ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_INPUTFUNC( FIELD_STRING, "SetHintGroup", InputSetHintGroup ),
|
||||||
|
#endif
|
||||||
|
|
||||||
// Outputs
|
// Outputs
|
||||||
DEFINE_OUTPUT( m_OnNPCStartedUsing, "OnNPCStartedUsing" ),
|
DEFINE_OUTPUT( m_OnNPCStartedUsing, "OnNPCStartedUsing" ),
|
||||||
@ -913,6 +916,18 @@ void CAI_Hint::InputDisableHint( inputdata_t &inputdata )
|
|||||||
m_NodeData.iDisabled = true;
|
m_NodeData.iDisabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void CAI_Hint::SetGroup( string_t iszNewGroup )
|
||||||
|
{
|
||||||
|
m_NodeData.strGroup = iszNewGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAI_Hint::InputSetHintGroup( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
SetGroup(inputdata.value.StringID());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Purpose :
|
// Purpose :
|
||||||
@ -1075,6 +1090,40 @@ bool CAI_Hint::IsInNodeFOV( CBaseEntity *pOther )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// An easy way of engaging certain hint parameters on certain hint types that didn't use it before.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_Hint::NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing )
|
||||||
|
{
|
||||||
|
Assert( pNPC != NULL );
|
||||||
|
|
||||||
|
HintIgnoreFacing_t facing = GetIgnoreFacing();
|
||||||
|
if (facing == HIF_DEFAULT)
|
||||||
|
facing = bDefaultFacing ? HIF_YES : HIF_NO;
|
||||||
|
|
||||||
|
if (facing == HIF_YES)
|
||||||
|
pNPC->GetNavigator()->SetArrivalDirection(GetDirection());
|
||||||
|
|
||||||
|
if (HintActivityName() != NULL_STRING)
|
||||||
|
{
|
||||||
|
Activity hintActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(HintActivityName()) );
|
||||||
|
if ( hintActivity != ACT_INVALID )
|
||||||
|
{
|
||||||
|
pNPC->GetNavigator()->SetArrivalActivity( pNPC->GetHintActivity(HintType(), hintActivity) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int iSequence = pNPC->LookupSequence(STRING(HintActivityName()));
|
||||||
|
if ( iSequence != ACT_INVALID )
|
||||||
|
{
|
||||||
|
pNPC->GetNavigator()->SetArrivalSequence( iSequence );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Locks the node for use by an AI for hints
|
// Purpose: Locks the node for use by an AI for hints
|
||||||
// Output : Returns true if the node was available for locking, false on failure.
|
// Output : Returns true if the node was available for locking, false on failure.
|
||||||
@ -1426,6 +1475,15 @@ int CAI_Hint::DrawDebugTextOverlays(void)
|
|||||||
EntityText(text_offset,tempstr,0);
|
EntityText(text_offset,tempstr,0);
|
||||||
text_offset++;
|
text_offset++;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_NodeData.strGroup != NULL_STRING)
|
||||||
|
{
|
||||||
|
Q_snprintf(tempstr,sizeof(tempstr),"hintgroup %s", STRING(m_NodeData.strGroup) ) ;
|
||||||
|
EntityText(text_offset,tempstr,0);
|
||||||
|
text_offset++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( m_NodeData.iDisabled )
|
if ( m_NodeData.iDisabled )
|
||||||
{
|
{
|
||||||
Q_snprintf(tempstr,sizeof(tempstr),"DISABLED" );
|
Q_snprintf(tempstr,sizeof(tempstr),"DISABLED" );
|
||||||
|
@ -281,6 +281,9 @@ public:
|
|||||||
float Yaw( void );
|
float Yaw( void );
|
||||||
CAI_Node *GetNode( void );
|
CAI_Node *GetNode( void );
|
||||||
string_t GetGroup( void ) const { return m_NodeData.strGroup; }
|
string_t GetGroup( void ) const { return m_NodeData.strGroup; }
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void SetGroup( string_t iszNewGroup );
|
||||||
|
#endif
|
||||||
CBaseEntity *User( void ) const { return m_hHintOwner; };
|
CBaseEntity *User( void ) const { return m_hHintOwner; };
|
||||||
Hint_e HintType( void ) const { return (Hint_e)m_NodeData.nHintType; };
|
Hint_e HintType( void ) const { return (Hint_e)m_NodeData.nHintType; };
|
||||||
void SetHintType( int hintType, bool force = false );
|
void SetHintType( int hintType, bool force = false );
|
||||||
@ -305,6 +308,10 @@ public:
|
|||||||
bool HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false );
|
bool HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false );
|
||||||
bool IsInNodeFOV( CBaseEntity *pOther );
|
bool IsInNodeFOV( CBaseEntity *pOther );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void NPCHandleStartNav( CAI_BaseNPC *pNPC, bool bDefaultFacing );
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Spawn( void );
|
void Spawn( void );
|
||||||
virtual void Activate();
|
virtual void Activate();
|
||||||
@ -317,6 +324,9 @@ private:
|
|||||||
// Input handlers
|
// Input handlers
|
||||||
void InputEnableHint( inputdata_t &inputdata );
|
void InputEnableHint( inputdata_t &inputdata );
|
||||||
void InputDisableHint( inputdata_t &inputdata );
|
void InputDisableHint( inputdata_t &inputdata );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputSetHintGroup( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -94,10 +94,16 @@ bool CAI_MoveProbe::ShouldBrushBeIgnored( CBaseEntity *pEntity )
|
|||||||
CFuncBrush *pFuncBrush = assert_cast<CFuncBrush *>(pEntity);
|
CFuncBrush *pFuncBrush = assert_cast<CFuncBrush *>(pEntity);
|
||||||
|
|
||||||
// this is true if my class or entity name matches the exclusion name on the func brush
|
// this is true if my class or entity name matches the exclusion name on the func brush
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// The only way it could conflict is if a map has a NPC using a classname as its targetname, like a single npc_fastzombie entity referred to as "npc_zombie".
|
||||||
|
// I doubt anyone's doing that unless they don't know what they're doing, and even then this still shouldn't be barred from plain-HL2 mappers.
|
||||||
|
bool nameMatches = GetOuter()->ClassMatches(pFuncBrush->m_iszExcludedClass) || GetOuter()->NameMatches(pFuncBrush->m_iszExcludedClass);
|
||||||
|
#else
|
||||||
#if HL2_EPISODIC
|
#if HL2_EPISODIC
|
||||||
bool nameMatches = ( pFuncBrush->m_iszExcludedClass == GetOuter()->m_iClassname ) || GetOuter()->NameMatches(pFuncBrush->m_iszExcludedClass);
|
bool nameMatches = ( pFuncBrush->m_iszExcludedClass == GetOuter()->m_iClassname ) || GetOuter()->NameMatches(pFuncBrush->m_iszExcludedClass);
|
||||||
#else // do not match against entity name in base HL2 (just in case there is some case somewhere that might be broken by this)
|
#else // do not match against entity name in base HL2 (just in case there is some case somewhere that might be broken by this)
|
||||||
bool nameMatches = ( pFuncBrush->m_iszExcludedClass == GetOuter()->m_iClassname );
|
bool nameMatches = ( pFuncBrush->m_iszExcludedClass == GetOuter()->m_iClassname );
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// return true (ignore brush) if the name matches, or, if exclusion is inverted, if the name does not match
|
// return true (ignore brush) if the name matches, or, if exclusion is inverted, if the name does not match
|
||||||
|
@ -597,6 +597,17 @@ bool CAI_Pathfinder::IsLinkUsable(CAI_Link *pLink, int startID)
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Skip if link turned off
|
// Skip if link turned off
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (pLink->m_pDynamicLink)
|
||||||
|
{
|
||||||
|
if (!pLink->m_pDynamicLink->UseAllowed(GetOuter(), startID == pLink->m_pDynamicLink->m_nDestID))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (pLink->m_LinkInfo & bits_LINK_OFF)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (pLink->m_LinkInfo & bits_LINK_OFF)
|
if (pLink->m_LinkInfo & bits_LINK_OFF)
|
||||||
{
|
{
|
||||||
CAI_DynamicLink *pDynamicLink = pLink->m_pDynamicLink;
|
CAI_DynamicLink *pDynamicLink = pLink->m_pDynamicLink;
|
||||||
@ -618,6 +629,7 @@ bool CAI_Pathfinder::IsLinkUsable(CAI_Link *pLink, int startID)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Get the destination nodeID
|
// Get the destination nodeID
|
||||||
@ -691,6 +703,12 @@ bool CAI_Pathfinder::IsLinkUsable(CAI_Link *pLink, int startID)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (pLink->m_pDynamicLink)
|
||||||
|
{
|
||||||
|
return pLink->m_pDynamicLink->FinalUseAllowed(GetOuter(), startID == pLink->m_pDynamicLink->m_nDestID);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
#include "eventqueue.h"
|
#include "eventqueue.h"
|
||||||
#include "ai_behavior_lead.h"
|
#include "ai_behavior_lead.h"
|
||||||
#include "gameinterface.h"
|
#include "gameinterface.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "mapbase/matchers.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
@ -338,6 +341,9 @@ BEGIN_DATADESC( CAI_PlayerAlly )
|
|||||||
DEFINE_INPUTFUNC( FIELD_STRING, "SpeakResponseConcept", InputSpeakResponseConcept ),
|
DEFINE_INPUTFUNC( FIELD_STRING, "SpeakResponseConcept", InputSpeakResponseConcept ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "MakeGameEndAlly", InputMakeGameEndAlly ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "MakeGameEndAlly", InputMakeGameEndAlly ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "MakeRegularAlly", InputMakeRegularAlly ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "MakeRegularAlly", InputMakeRegularAlly ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_INPUTFUNC( FIELD_STRING, "AskQuestion", InputAskQuestion ),
|
||||||
|
#endif
|
||||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "AnswerQuestion", InputAnswerQuestion ),
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "AnswerQuestion", InputAnswerQuestion ),
|
||||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "AnswerQuestionHello", InputAnswerQuestionHello ),
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "AnswerQuestionHello", InputAnswerQuestionHello ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "EnableSpeakWhileScripting", InputEnableSpeakWhileScripting ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "EnableSpeakWhileScripting", InputEnableSpeakWhileScripting ),
|
||||||
@ -725,8 +731,13 @@ bool CAI_PlayerAlly::SelectQuestionAndAnswerSpeech( AISpeechSelection_t *pSelect
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// if there is a friend nearby to speak to, play sentence, set friend's response time, return
|
// if there is a friend nearby to speak to, play sentence, set friend's response time, return
|
||||||
|
#ifdef MAPBASE
|
||||||
|
CAI_PlayerAlly *pFriend = dynamic_cast<CAI_PlayerAlly *>(FindSpeechTarget( AIST_NPCS | AIST_NOT_GAGGED ));
|
||||||
|
if ( pFriend && !pFriend->IsMoving() )
|
||||||
|
#else
|
||||||
CAI_PlayerAlly *pFriend = dynamic_cast<CAI_PlayerAlly *>(FindSpeechTarget( AIST_NPCS ));
|
CAI_PlayerAlly *pFriend = dynamic_cast<CAI_PlayerAlly *>(FindSpeechTarget( AIST_NPCS ));
|
||||||
if ( pFriend && !pFriend->IsMoving() && !pFriend->HasSpawnFlags(SF_NPC_GAG) )
|
if ( pFriend && !pFriend->IsMoving() && !pFriend->HasSpawnFlags(SF_NPC_GAG) )
|
||||||
|
#endif
|
||||||
return SelectQuestionFriend( pFriend, pSelection );
|
return SelectQuestionFriend( pFriend, pSelection );
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -816,7 +827,17 @@ bool CAI_PlayerAlly::SelectQuestionFriend( CBaseEntity *pFriend, AISpeechSelecti
|
|||||||
|
|
||||||
// If we haven't said hello, say hello first.
|
// If we haven't said hello, say hello first.
|
||||||
// Only ever say hello to NPCs other than my type.
|
// Only ever say hello to NPCs other than my type.
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Why only say hello to NPCs other than my type?
|
||||||
|
// Are citizens a hivemind? Do they not greet each other?
|
||||||
|
// They don't have any responses for it anyway, so SelectSpeechResponse() will fail
|
||||||
|
// and TLK_HELLO_NPC will be marked as spoken.
|
||||||
|
//
|
||||||
|
// Responses could be added so modders/mappers can take advantage of this.
|
||||||
|
if ( !GetExpresser()->SpokeConcept( TLK_HELLO_NPC ) )
|
||||||
|
#else
|
||||||
if ( !GetExpresser()->SpokeConcept( TLK_HELLO_NPC ) && !FClassnameIs( this, pFriend->GetClassname()) )
|
if ( !GetExpresser()->SpokeConcept( TLK_HELLO_NPC ) && !FClassnameIs( this, pFriend->GetClassname()) )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if ( SelectSpeechResponse( TLK_HELLO_NPC, NULL, pFriend, pSelection ) )
|
if ( SelectSpeechResponse( TLK_HELLO_NPC, NULL, pFriend, pSelection ) )
|
||||||
return true;
|
return true;
|
||||||
@ -844,6 +865,74 @@ bool CAI_PlayerAlly::SelectAnswerFriend( CBaseEntity *pFriend, AISpeechSelection
|
|||||||
return SelectSpeechResponse( TLK_ANSWER, NULL, pFriend, pSelection );
|
return SelectSpeechResponse( TLK_ANSWER, NULL, pFriend, pSelection );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Asks a question now.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CAI_PlayerAlly::AskQuestionNow( CBaseEntity *pSpeechTarget, int iQARandomNumber, const char *concept )
|
||||||
|
{
|
||||||
|
m_hPotentialSpeechTarget = pSpeechTarget;
|
||||||
|
m_iQARandomNumber = iQARandomNumber;
|
||||||
|
|
||||||
|
if (!m_hPotentialSpeechTarget)
|
||||||
|
m_hPotentialSpeechTarget = /*dynamic_cast<CAI_PlayerAlly *>*/(FindSpeechTarget( AIST_NPCS | AIST_NOT_GAGGED ));
|
||||||
|
|
||||||
|
if (m_iQARandomNumber == -1)
|
||||||
|
m_iQARandomNumber = RandomInt(0, 100);
|
||||||
|
|
||||||
|
AISpeechSelection_t selection;
|
||||||
|
SelectSpeechResponse( concept, NULL, m_hPotentialSpeechTarget.Get(), &selection );
|
||||||
|
|
||||||
|
SetSpeechTarget( selection.hSpeechTarget );
|
||||||
|
ClearPendingSpeech();
|
||||||
|
|
||||||
|
if (!selection.pResponse)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Speak immediately
|
||||||
|
return SpeakDispatchResponse( selection.concept.c_str(), selection.pResponse );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_PlayerAlly::InputAskQuestion( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
CBaseEntity *pSpeechTarget = NULL;
|
||||||
|
int iQARandomNumber = 0;
|
||||||
|
const char *concept = TLK_QUESTION;
|
||||||
|
|
||||||
|
// I didn't feel like using strtok today.
|
||||||
|
CUtlStringList vecStrings;
|
||||||
|
V_SplitString(inputdata.value.String(), " ", vecStrings);
|
||||||
|
FOR_EACH_VEC( vecStrings, i )
|
||||||
|
{
|
||||||
|
// 0 : QA Number (-1 for N/A)
|
||||||
|
// 1 : Speech Target
|
||||||
|
// 2 : Concept
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0: iQARandomNumber = atoi(vecStrings[i]); break;
|
||||||
|
case 1: pSpeechTarget = gEntList.FindEntityByName(NULL, vecStrings[i], this, inputdata.pActivator, inputdata.pCaller); break;
|
||||||
|
case 2: concept = vecStrings[i]; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSpeechTarget == NULL)
|
||||||
|
{
|
||||||
|
CAI_PlayerAlly *pFriend = dynamic_cast<CAI_PlayerAlly *>(FindSpeechTarget( AIST_NPCS | AIST_NOT_GAGGED ));
|
||||||
|
if ( pFriend )
|
||||||
|
pSpeechTarget = pFriend;
|
||||||
|
}
|
||||||
|
else if (pSpeechTarget == this)
|
||||||
|
{
|
||||||
|
pSpeechTarget = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AskQuestionNow(pSpeechTarget, iQARandomNumber, concept);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1077,6 +1166,24 @@ void CAI_PlayerAlly::Touch( CBaseEntity *pOther )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
ConVar mapbase_ally_flinching("mapbase_ally_flinching", "1", FCVAR_ARCHIVE, "Enables/disables the new flinching animations.");
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: This is to adjust for the new citizen flinching animations,
|
||||||
|
// as they would exist on all NPCs that use citizen animations.
|
||||||
|
//
|
||||||
|
// Vortigaunts and Alyx in the Episodes are the only ones who can flinch normally,
|
||||||
|
// and that's been rectified with their own functions. (they currently skip CAI_PlayerAlly's implementation)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CAI_PlayerAlly::CanFlinch( void )
|
||||||
|
{
|
||||||
|
if (mapbase_ally_flinching.GetBool() != true)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return BaseClass::CanFlinch();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CAI_PlayerAlly::OnKilledNPC( CBaseCombatCharacter *pKilled )
|
void CAI_PlayerAlly::OnKilledNPC( CBaseCombatCharacter *pKilled )
|
||||||
@ -1087,6 +1194,10 @@ void CAI_PlayerAlly::OnKilledNPC( CBaseCombatCharacter *pKilled )
|
|||||||
( pKilled->MyNPCPointer()->GetLastPlayerDamageTime() == 0 ||
|
( pKilled->MyNPCPointer()->GetLastPlayerDamageTime() == 0 ||
|
||||||
gpGlobals->curtime - pKilled->MyNPCPointer()->GetLastPlayerDamageTime() > 5 ) )
|
gpGlobals->curtime - pKilled->MyNPCPointer()->GetLastPlayerDamageTime() > 5 ) )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
m_hPotentialSpeechTarget = pKilled;
|
||||||
|
SetSpeechTarget(pKilled);
|
||||||
|
#endif
|
||||||
SpeakIfAllowed( TLK_ENEMY_DEAD );
|
SpeakIfAllowed( TLK_ENEMY_DEAD );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1174,8 +1285,14 @@ void CAI_PlayerAlly::Event_Killed( const CTakeDamageInfo &info )
|
|||||||
CBasePlayer *player = AI_GetSinglePlayer();
|
CBasePlayer *player = AI_GetSinglePlayer();
|
||||||
if ( player )
|
if ( player )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
variant_t variant;
|
||||||
|
variant.SetEntity(this);
|
||||||
|
player->AcceptInput( "OnSquadMemberKilled", info.GetAttacker(), this, variant, 0 );
|
||||||
|
#else
|
||||||
variant_t emptyVariant;
|
variant_t emptyVariant;
|
||||||
player->AcceptInput( "OnSquadMemberKilled", this, this, emptyVariant, 0 );
|
player->AcceptInput( "OnSquadMemberKilled", this, this, emptyVariant, 0 );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1185,6 +1302,10 @@ void CAI_PlayerAlly::Event_Killed( const CTakeDamageInfo &info )
|
|||||||
CAI_PlayerAlly *pMourner = dynamic_cast<CAI_PlayerAlly *>(FindSpeechTarget( AIST_NPCS ));
|
CAI_PlayerAlly *pMourner = dynamic_cast<CAI_PlayerAlly *>(FindSpeechTarget( AIST_NPCS ));
|
||||||
if ( pMourner )
|
if ( pMourner )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
pMourner->m_hPotentialSpeechTarget = this;
|
||||||
|
pMourner->SetSpeechTarget(this);
|
||||||
|
#endif
|
||||||
pMourner->SpeakIfAllowed( TLK_ALLY_KILLED );
|
pMourner->SpeakIfAllowed( TLK_ALLY_KILLED );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1286,6 +1407,11 @@ bool CAI_PlayerAlly::IsValidSpeechTarget( int flags, CBaseEntity *pEntity )
|
|||||||
// Don't bother people who don't want to be bothered
|
// Don't bother people who don't want to be bothered
|
||||||
if ( !pNPC->CanBeUsedAsAFriend() )
|
if ( !pNPC->CanBeUsedAsAFriend() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (flags & AIST_NOT_GAGGED && pNPC->HasSpawnFlags(SF_NPC_GAG))
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( flags & AIST_FACING_TARGET )
|
if ( flags & AIST_FACING_TARGET )
|
||||||
@ -1591,6 +1717,19 @@ bool CAI_PlayerAlly::SpeakIfAllowed( AIConcept_t concept, const char *modifiers,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CAI_PlayerAlly::SpeakIfAllowed( AIConcept_t concept, AI_CriteriaSet& modifiers, bool bRespondingToPlayer, char *pszOutResponseChosen, size_t bufsize )
|
||||||
|
{
|
||||||
|
if ( IsAllowedToSpeak( concept, bRespondingToPlayer ) )
|
||||||
|
{
|
||||||
|
return Speak( concept, modifiers, pszOutResponseChosen, bufsize );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CAI_PlayerAlly::ModifyOrAppendCriteria( AI_CriteriaSet& set )
|
void CAI_PlayerAlly::ModifyOrAppendCriteria( AI_CriteriaSet& set )
|
||||||
@ -1602,6 +1741,11 @@ void CAI_PlayerAlly::ModifyOrAppendCriteria( AI_CriteriaSet& set )
|
|||||||
set.AppendCriteria( "speechtarget", m_hPotentialSpeechTarget->GetClassname() );
|
set.AppendCriteria( "speechtarget", m_hPotentialSpeechTarget->GetClassname() );
|
||||||
set.AppendCriteria( "speechtargetname", STRING(m_hPotentialSpeechTarget->GetEntityName()) );
|
set.AppendCriteria( "speechtargetname", STRING(m_hPotentialSpeechTarget->GetEntityName()) );
|
||||||
set.AppendCriteria( "randomnum", UTIL_VarArgs("%d", m_iQARandomNumber) );
|
set.AppendCriteria( "randomnum", UTIL_VarArgs("%d", m_iQARandomNumber) );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Speech target contexts.
|
||||||
|
m_hPotentialSpeechTarget->AppendContextToCriteria(set, "speechtarget_");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we have a speech filter? If so, append it's criteria too
|
// Do we have a speech filter? If so, append it's criteria too
|
||||||
@ -1618,11 +1762,13 @@ void CAI_PlayerAlly::OnSpokeConcept( AIConcept_t concept, AI_Response *response
|
|||||||
CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager();
|
CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager();
|
||||||
pSpeechManager->OnSpokeConcept( this, concept, response );
|
pSpeechManager->OnSpokeConcept( this, concept, response );
|
||||||
|
|
||||||
|
#ifndef MAPBASE // This has been moved directly to CAI_Expresser
|
||||||
if( response != NULL && (response->GetParams()->flags & AI_ResponseParams::RG_WEAPONDELAY) )
|
if( response != NULL && (response->GetParams()->flags & AI_ResponseParams::RG_WEAPONDELAY) )
|
||||||
{
|
{
|
||||||
// Stop shooting, as instructed, so that my speech can be heard.
|
// Stop shooting, as instructed, so that my speech can be heard.
|
||||||
GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + response->GetWeaponDelay() );
|
GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + response->GetWeaponDelay() );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -244,6 +244,10 @@ enum AISpeechTargetSearchFlags_t
|
|||||||
AIST_IGNORE_RELATIONSHIP = (1<<2),
|
AIST_IGNORE_RELATIONSHIP = (1<<2),
|
||||||
AIST_ANY_QUALIFIED = (1<<3),
|
AIST_ANY_QUALIFIED = (1<<3),
|
||||||
AIST_FACING_TARGET = (1<<4),
|
AIST_FACING_TARGET = (1<<4),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// I needed this for something
|
||||||
|
AIST_NOT_GAGGED = (1<<5),
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AISpeechSelection_t
|
struct AISpeechSelection_t
|
||||||
@ -296,6 +300,10 @@ public:
|
|||||||
void ClearTransientConditions();
|
void ClearTransientConditions();
|
||||||
void Touch( CBaseEntity *pOther );
|
void Touch( CBaseEntity *pOther );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool CanFlinch( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
// Combat
|
// Combat
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
@ -326,6 +334,12 @@ public:
|
|||||||
CBaseEntity *GetSpeechTarget() { return m_hTalkTarget.Get(); }
|
CBaseEntity *GetSpeechTarget() { return m_hTalkTarget.Get(); }
|
||||||
void SetSpeechTarget( CBaseEntity *pSpeechTarget ) { m_hTalkTarget = pSpeechTarget; }
|
void SetSpeechTarget( CBaseEntity *pSpeechTarget ) { m_hTalkTarget = pSpeechTarget; }
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Needed for additional speech target responses
|
||||||
|
CBaseEntity *GetPotentialSpeechTarget() { return m_hPotentialSpeechTarget.Get(); }
|
||||||
|
void SetPotentialSpeechTarget( CBaseEntity *pSpeechTarget ) { m_hPotentialSpeechTarget = pSpeechTarget; }
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetSpeechFilter( CAI_SpeechFilter *pFilter ) { m_hSpeechFilter = pFilter; }
|
void SetSpeechFilter( CAI_SpeechFilter *pFilter ) { m_hSpeechFilter = pFilter; }
|
||||||
CAI_SpeechFilter *GetSpeechFilter( void ) { return m_hSpeechFilter; }
|
CAI_SpeechFilter *GetSpeechFilter( void ) { return m_hSpeechFilter; }
|
||||||
|
|
||||||
@ -373,6 +387,9 @@ public:
|
|||||||
bool ShouldSpeakRandom( AIConcept_t concept, int iChance );
|
bool ShouldSpeakRandom( AIConcept_t concept, int iChance );
|
||||||
bool IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPlayer = false );
|
bool IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPlayer = false );
|
||||||
virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
|
virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual bool SpeakIfAllowed( AIConcept_t concept, AI_CriteriaSet& modifiers, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 );
|
||||||
|
#endif
|
||||||
void ModifyOrAppendCriteria( AI_CriteriaSet& set );
|
void ModifyOrAppendCriteria( AI_CriteriaSet& set );
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
@ -398,6 +415,10 @@ public:
|
|||||||
virtual const char *GetDeathMessageText( void ) { return "GAMEOVER_ALLY"; }
|
virtual const char *GetDeathMessageText( void ) { return "GAMEOVER_ALLY"; }
|
||||||
void InputMakeGameEndAlly( inputdata_t &inputdata );
|
void InputMakeGameEndAlly( inputdata_t &inputdata );
|
||||||
void InputMakeRegularAlly( inputdata_t &inputdata );
|
void InputMakeRegularAlly( inputdata_t &inputdata );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool AskQuestionNow( CBaseEntity *pSpeechTarget = NULL, int iQARandomNumber = -1, const char *concept = TLK_QUESTION );
|
||||||
|
void InputAskQuestion( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
void InputAnswerQuestion( inputdata_t &inputdata );
|
void InputAnswerQuestion( inputdata_t &inputdata );
|
||||||
void InputAnswerQuestionHello( inputdata_t &inputdata );
|
void InputAnswerQuestionHello( inputdata_t &inputdata );
|
||||||
void InputEnableSpeakWhileScripting( inputdata_t &inputdata );
|
void InputEnableSpeakWhileScripting( inputdata_t &inputdata );
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#include "cbase.h"
|
#include "cbase.h"
|
||||||
#include "ndebugoverlay.h"
|
#include "ndebugoverlay.h"
|
||||||
#include "ai_basenpc.h"
|
#include "ai_basenpc.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "mapbase/matchers.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include "tier0/memdbgon.h"
|
#include "tier0/memdbgon.h"
|
||||||
@ -34,6 +37,9 @@ public:
|
|||||||
void Activate();
|
void Activate();
|
||||||
|
|
||||||
void SetActive( bool bActive );
|
void SetActive( bool bActive );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
virtual
|
||||||
|
#endif
|
||||||
void ChangeRelationships( int disposition, int iReverting, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
void ChangeRelationships( int disposition, int iReverting, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||||
|
|
||||||
void ApplyRelationship( CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
void ApplyRelationship( CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||||
@ -45,11 +51,20 @@ public:
|
|||||||
|
|
||||||
bool IsASubject( CBaseEntity *pEntity );
|
bool IsASubject( CBaseEntity *pEntity );
|
||||||
bool IsATarget( CBaseEntity *pEntity );
|
bool IsATarget( CBaseEntity *pEntity );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Assume no insane person already has "CLASS_" at the beginning of an entity's (class)name.
|
||||||
|
inline bool IsSubjectClassify() { return Q_strncmp(STRING(m_target), "CLASS_", 6) == 0; }
|
||||||
|
inline bool IsTargetClassify() { return Q_strncmp(STRING(m_target), "CLASS_", 6) == 0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
void OnEntitySpawned( CBaseEntity *pEntity );
|
void OnEntitySpawned( CBaseEntity *pEntity );
|
||||||
void OnEntityDeleted( CBaseEntity *pEntity );
|
void OnEntityDeleted( CBaseEntity *pEntity );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
protected:
|
||||||
|
#else
|
||||||
private:
|
private:
|
||||||
|
#endif
|
||||||
|
|
||||||
void ApplyRelationshipThink( void );
|
void ApplyRelationshipThink( void );
|
||||||
CBaseEntity *FindEntityForProceduralName( string_t iszName, CBaseEntity *pActivator, CBaseEntity *pCaller );
|
CBaseEntity *FindEntityForProceduralName( string_t iszName, CBaseEntity *pActivator, CBaseEntity *pCaller );
|
||||||
@ -259,6 +274,12 @@ bool CAI_Relationship::IsASubject( CBaseEntity *pEntity )
|
|||||||
if( pEntity->ClassMatches( m_iszSubject ) )
|
if( pEntity->ClassMatches( m_iszSubject ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Hopefully doesn't impact performance.
|
||||||
|
if (Matcher_NamesMatch(STRING(m_iszSubject), g_pGameRules->AIClassText((pEntity->Classify()))))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +293,12 @@ bool CAI_Relationship::IsATarget( CBaseEntity *pEntity )
|
|||||||
if( pEntity->ClassMatches( m_target ) )
|
if( pEntity->ClassMatches( m_target ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// Hopefully doesn't impact performance.
|
||||||
|
if (Matcher_NamesMatch(STRING(m_target), g_pGameRules->AIClassText((pEntity->Classify()))))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,3 +521,133 @@ void CAI_Relationship::ChangeRelationships( int disposition, int iReverting, CBa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//=========================================================
|
||||||
|
//=========================================================
|
||||||
|
class CAI_ClassRelationship : public CAI_Relationship
|
||||||
|
{
|
||||||
|
DECLARE_CLASS( CAI_ClassRelationship, CAI_Relationship );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Must override CAI_Relationship
|
||||||
|
void Spawn() { m_bIsActive = false; }
|
||||||
|
|
||||||
|
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||||
|
|
||||||
|
void ChangeRelationships( int disposition, int iReverting, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
||||||
|
|
||||||
|
inline bool SubjectUsingClassify() { return m_iSubjectClass != NUM_AI_CLASSES; }
|
||||||
|
inline bool TargetUsingClassify() { return m_iTargetClass != NUM_AI_CLASSES; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Class_T m_iSubjectClass;
|
||||||
|
Class_T m_iTargetClass;
|
||||||
|
|
||||||
|
DECLARE_DATADESC();
|
||||||
|
};
|
||||||
|
|
||||||
|
LINK_ENTITY_TO_CLASS( ai_relationship_classify, CAI_ClassRelationship );
|
||||||
|
|
||||||
|
BEGIN_DATADESC( CAI_ClassRelationship )
|
||||||
|
|
||||||
|
DEFINE_FIELD( m_iSubjectClass, FIELD_INTEGER ),
|
||||||
|
DEFINE_FIELD( m_iTargetClass, FIELD_INTEGER ),
|
||||||
|
|
||||||
|
END_DATADESC()
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Caches entity key values until spawn is called.
|
||||||
|
// Input : szKeyName -
|
||||||
|
// szValue -
|
||||||
|
// Output :
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CAI_ClassRelationship::KeyValue( const char *szKeyName, const char *szValue )
|
||||||
|
{
|
||||||
|
// Override regular subject and target from ai_relationship
|
||||||
|
if (FStrEq(szKeyName, "subject"))
|
||||||
|
{
|
||||||
|
m_iSubjectClass = (Class_T)atoi(szValue);
|
||||||
|
|
||||||
|
// Direct string maybe
|
||||||
|
if (m_iSubjectClass == CLASS_NONE)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_AI_CLASSES; i++)
|
||||||
|
{
|
||||||
|
if (FStrEq(szValue, g_pGameRules->AIClassText(i)))
|
||||||
|
{
|
||||||
|
m_iSubjectClass = (Class_T)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FStrEq(szKeyName, "target"))
|
||||||
|
{
|
||||||
|
m_iTargetClass = (Class_T)atoi(szValue);
|
||||||
|
|
||||||
|
// Direct string maybe
|
||||||
|
if (m_iTargetClass == CLASS_NONE)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_AI_CLASSES; i++)
|
||||||
|
{
|
||||||
|
if (FStrEq(szValue, g_pGameRules->AIClassText(i)))
|
||||||
|
{
|
||||||
|
m_iTargetClass = (Class_T)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return BaseClass::KeyValue(szKeyName, szValue);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
//---------------------------------------------------------
|
||||||
|
void CAI_ClassRelationship::ChangeRelationships( int disposition, int iReverting, CBaseEntity *pActivator, CBaseEntity *pCaller )
|
||||||
|
{
|
||||||
|
if( iReverting != NOT_REVERTING && m_iPreviousDisposition == -1 )
|
||||||
|
{
|
||||||
|
// Trying to revert without having ever set the relationships!
|
||||||
|
DevMsg( 2, "ai_relationship cannot revert changes before they are applied!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_iPreviousDisposition == -1 && iReverting == NOT_REVERTING )
|
||||||
|
{
|
||||||
|
// Set previous disposition.
|
||||||
|
m_iPreviousDisposition = CBaseCombatCharacter::GetDefaultRelationshipDisposition( m_iSubjectClass, m_iTargetClass );
|
||||||
|
m_iPreviousRank = CBaseCombatCharacter::GetDefaultRelationshipPriority( m_iSubjectClass, m_iTargetClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can't actually reset to "default" without resetting all class relationships period, so we just use the previous disposition.
|
||||||
|
// There probably wouldn't be much overlap with this entity anyway.
|
||||||
|
if ( iReverting == REVERTING_TO_PREV || iReverting == REVERTING_TO_DEFAULT )
|
||||||
|
{
|
||||||
|
CBaseCombatCharacter::SetDefaultRelationship(m_iSubjectClass, m_iTargetClass, (Disposition_t)m_iPreviousDisposition, m_iPreviousRank );
|
||||||
|
|
||||||
|
if( m_bReciprocal )
|
||||||
|
{
|
||||||
|
CBaseCombatCharacter::SetDefaultRelationship(m_iTargetClass, m_iSubjectClass, (Disposition_t)m_iPreviousDisposition, m_iPreviousRank );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( CBaseCombatCharacter::GetDefaultRelationshipDisposition( m_iSubjectClass, m_iTargetClass ) != disposition ||
|
||||||
|
CBaseCombatCharacter::GetDefaultRelationshipPriority( m_iSubjectClass, m_iTargetClass ) != m_iRank )
|
||||||
|
{
|
||||||
|
// Apply the relationship to the subject
|
||||||
|
CBaseCombatCharacter::SetDefaultRelationship(m_iSubjectClass, m_iTargetClass, (Disposition_t)disposition, m_iRank );
|
||||||
|
|
||||||
|
// Notification flags can't be used here. Sorry.
|
||||||
|
|
||||||
|
// This relationship is applied to target and subject alike
|
||||||
|
if ( m_bReciprocal )
|
||||||
|
{
|
||||||
|
// Apply the relationship to the target
|
||||||
|
CBaseCombatCharacter::SetDefaultRelationship(m_iTargetClass, m_iSubjectClass, (Disposition_t)disposition, m_iRank );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -52,6 +52,9 @@ BEGIN_DATADESC( CAI_ScriptConditions )
|
|||||||
|
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||||
|
#ifdef MAPBASE
|
||||||
|
DEFINE_INPUTFUNC( FIELD_EHANDLE, "SatisfyConditions", InputSatisfyConditions ),
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------
|
//---------------------------------
|
||||||
|
|
||||||
@ -195,12 +198,20 @@ bool CAI_ScriptConditions::EvalState( const EvalArgs_t &args )
|
|||||||
-1, // NPC_STATE_PLAYDEAD
|
-1, // NPC_STATE_PLAYDEAD
|
||||||
-1, // NPC_STATE_PRONE
|
-1, // NPC_STATE_PRONE
|
||||||
-1, // NPC_STATE_DEAD
|
-1, // NPC_STATE_DEAD
|
||||||
|
#ifdef MAPBASE
|
||||||
|
3, // A "Don't care" for the maximum value
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int valState = stateVals[pNpc->m_NPCState];
|
int valState = stateVals[pNpc->m_NPCState];
|
||||||
|
|
||||||
if ( valState < 0 )
|
if ( valState < 0 )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (m_fMinState == 0)
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( pNpc->m_NPCState == NPC_STATE_SCRIPT && m_fScriptStatus >= TRS_TRUE )
|
if ( pNpc->m_NPCState == NPC_STATE_SCRIPT && m_fScriptStatus >= TRS_TRUE )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -676,6 +687,25 @@ void CAI_ScriptConditions::InputDisable( inputdata_t &inputdata )
|
|||||||
Disable();
|
Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void CAI_ScriptConditions::InputSatisfyConditions( inputdata_t &inputdata )
|
||||||
|
{
|
||||||
|
// This satisfies things.
|
||||||
|
CBaseEntity *pActivator = HasSpawnFlags(SF_ACTOR_AS_ACTIVATOR) ? inputdata.value.Entity() : this;
|
||||||
|
m_OnConditionsSatisfied.FireOutput(pActivator, this);
|
||||||
|
|
||||||
|
|
||||||
|
//All done!
|
||||||
|
if ( m_ElementList.Count() == 1 )
|
||||||
|
{
|
||||||
|
Disable();
|
||||||
|
m_ElementList.Purge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool CAI_ScriptConditions::IsInFOV( CBaseEntity *pViewer, CBaseEntity *pViewed, float fov, bool bTrueCone )
|
bool CAI_ScriptConditions::IsInFOV( CBaseEntity *pViewer, CBaseEntity *pViewed, float fov, bool bTrueCone )
|
||||||
|
@ -159,6 +159,9 @@ private:
|
|||||||
// Input handlers
|
// Input handlers
|
||||||
void InputEnable( inputdata_t &inputdata );
|
void InputEnable( inputdata_t &inputdata );
|
||||||
void InputDisable( inputdata_t &inputdata );
|
void InputDisable( inputdata_t &inputdata );
|
||||||
|
#ifdef MAPBASE
|
||||||
|
void InputSatisfyConditions( inputdata_t &inputdata );
|
||||||
|
#endif
|
||||||
|
|
||||||
// Output handlers
|
// Output handlers
|
||||||
COutputEvent m_OnConditionsSatisfied;
|
COutputEvent m_OnConditionsSatisfied;
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
#include "AI_Criteria.h"
|
#include "AI_Criteria.h"
|
||||||
#include "isaverestore.h"
|
#include "isaverestore.h"
|
||||||
#include "sceneentity.h"
|
#include "sceneentity.h"
|
||||||
|
#ifdef MAPBASE
|
||||||
|
#include "ai_squad.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// memdbgon must be the last include file in a .cpp file!!!
|
// memdbgon must be the last include file in a .cpp file!!!
|
||||||
#include <tier0/memdbgon.h>
|
#include <tier0/memdbgon.h>
|
||||||
@ -275,6 +278,17 @@ static const int LEN_SPECIFIC_SCENE_MODIFIER = strlen( AI_SPECIFIC_SCENE_MODIFIE
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char *modifiers /*= NULL*/ )
|
AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char *modifiers /*= NULL*/ )
|
||||||
{
|
{
|
||||||
|
#ifdef MAPBASE
|
||||||
|
AI_CriteriaSet set;
|
||||||
|
|
||||||
|
if (modifiers)
|
||||||
|
{
|
||||||
|
MergeModifiers(set, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now return the code in the new function.
|
||||||
|
return SpeakFindResponse(concept, set);
|
||||||
|
#else
|
||||||
IResponseSystem *rs = GetOuter()->GetResponseSystem();
|
IResponseSystem *rs = GetOuter()->GetResponseSystem();
|
||||||
if ( !rs )
|
if ( !rs )
|
||||||
{
|
{
|
||||||
@ -319,6 +333,131 @@ AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char *
|
|||||||
pPlayer->ModifyOrAppendPlayerCriteria( set );
|
pPlayer->ModifyOrAppendPlayerCriteria( set );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
GetOuter()->ReAppendContextCriteria( set );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Now that we have a criteria set, ask for a suitable response
|
||||||
|
AI_Response *result = new AI_Response;
|
||||||
|
Assert( result && "new AI_Response: Returned a NULL AI_Response!" );
|
||||||
|
bool found = rs->FindBestResponse( set, *result, this );
|
||||||
|
|
||||||
|
if ( rr_debugresponses.GetInt() == 3 )
|
||||||
|
{
|
||||||
|
if ( ( GetOuter()->MyNPCPointer() && GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) || GetOuter()->IsPlayer() )
|
||||||
|
{
|
||||||
|
const char *pszName;
|
||||||
|
if ( GetOuter()->IsPlayer() )
|
||||||
|
{
|
||||||
|
pszName = ((CBasePlayer*)GetOuter())->GetPlayerName();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pszName = GetOuter()->GetDebugName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( found )
|
||||||
|
{
|
||||||
|
char response[ 256 ];
|
||||||
|
result->GetResponse( response, sizeof( response ) );
|
||||||
|
|
||||||
|
Warning( "RESPONSERULES: %s spoke '%s'. Found response '%s'.\n", pszName, concept, response );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Warning( "RESPONSERULES: %s spoke '%s'. Found no matching response.\n", pszName, concept );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !found )
|
||||||
|
{
|
||||||
|
//Assert( !"rs->FindBestResponse: Returned a NULL AI_Response!" );
|
||||||
|
delete result;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char response[ 256 ];
|
||||||
|
result->GetResponse( response, sizeof( response ) );
|
||||||
|
|
||||||
|
if ( !response[0] )
|
||||||
|
{
|
||||||
|
delete result;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( result->GetOdds() < 100 && random->RandomInt( 1, 100 ) <= result->GetOdds() )
|
||||||
|
{
|
||||||
|
delete result;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Merges modifiers with set.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CAI_Expresser::MergeModifiers( AI_CriteriaSet& set, const char *modifiers )
|
||||||
|
{
|
||||||
|
char copy_modifiers[ 255 ];
|
||||||
|
const char *pCopy;
|
||||||
|
char key[ 128 ] = { 0 };
|
||||||
|
char value[ 128 ] = { 0 };
|
||||||
|
|
||||||
|
Q_strncpy( copy_modifiers, modifiers, sizeof( copy_modifiers ) );
|
||||||
|
pCopy = copy_modifiers;
|
||||||
|
|
||||||
|
while( pCopy )
|
||||||
|
{
|
||||||
|
pCopy = SplitContext( pCopy, key, sizeof( key ), value, sizeof( value ), NULL );
|
||||||
|
|
||||||
|
if( *key && *value )
|
||||||
|
{
|
||||||
|
set.AppendCriteria( key, value, CONCEPT_WEIGHT );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Searches for a possible response, takes an AI_CriteriaSet instead.
|
||||||
|
// Input : concept -
|
||||||
|
// NULL -
|
||||||
|
// Output : AI_Response
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, AI_CriteriaSet &modifiers )
|
||||||
|
{
|
||||||
|
IResponseSystem *rs = GetOuter()->GetResponseSystem();
|
||||||
|
if ( !rs )
|
||||||
|
{
|
||||||
|
Assert( !"No response system installed for CAI_Expresser::GetOuter()!!!" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AI_CriteriaSet set;
|
||||||
|
// Always include the concept name
|
||||||
|
set.AppendCriteria( "concept", concept, CONCEPT_WEIGHT );
|
||||||
|
|
||||||
|
// Tier 1: Criteria
|
||||||
|
// Let our outer fill in most match criteria
|
||||||
|
GetOuter()->ModifyOrAppendCriteria( set );
|
||||||
|
|
||||||
|
// Append local player criteria to set, but not if this is a player doing the talking
|
||||||
|
if ( !GetOuter()->IsPlayer() )
|
||||||
|
{
|
||||||
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 );
|
||||||
|
if( pPlayer )
|
||||||
|
pPlayer->ModifyOrAppendPlayerCriteria( set );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tier 2: Modifiers
|
||||||
|
set.MergeSet(modifiers);
|
||||||
|
|
||||||
|
// Tier 3: Contexts
|
||||||
|
GetOuter()->ReAppendContextCriteria( set );
|
||||||
|
|
||||||
// Now that we have a criteria set, ask for a suitable response
|
// Now that we have a criteria set, ask for a suitable response
|
||||||
AI_Response *result = new AI_Response;
|
AI_Response *result = new AI_Response;
|
||||||
Assert( result && "new AI_Response: Returned a NULL AI_Response!" );
|
Assert( result && "new AI_Response: Returned a NULL AI_Response!" );
|
||||||
@ -376,16 +515,45 @@ AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char *
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Dispatches the result
|
// Purpose: Dispatches the result
|
||||||
// Input : *response -
|
// Input : *response -
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef MAPBASE
|
||||||
|
bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *result, IRecipientFilter *filter, const char *modifiers )
|
||||||
|
#else
|
||||||
bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *result, IRecipientFilter *filter /* = NULL */ )
|
bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *result, IRecipientFilter *filter /* = NULL */ )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
char response[ 256 ];
|
char response[ 256 ];
|
||||||
result->GetResponse( response, sizeof( response ) );
|
result->GetResponse( response, sizeof( response ) );
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (response[0] == '$')
|
||||||
|
{
|
||||||
|
response[0] = '\0';
|
||||||
|
const char *replace = GetOuter()->GetContextValue(response);
|
||||||
|
if (!replace)
|
||||||
|
{
|
||||||
|
replace = modifiers;
|
||||||
|
|
||||||
|
char key[128] = { 0 };
|
||||||
|
char value[128] = { 0 };
|
||||||
|
replace = SplitContext(replace, key, sizeof(key), value, sizeof(value), NULL);
|
||||||
|
replace = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replace)
|
||||||
|
{
|
||||||
|
DevMsg("Replacing %s with %s...\n", response, GetOuter()->GetContextValue(response));
|
||||||
|
Q_strncpy(response, replace, sizeof(response));
|
||||||
|
GetOuter()->PrecacheScriptSound( response );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
float delay = result->GetDelay();
|
float delay = result->GetDelay();
|
||||||
|
|
||||||
bool spoke = false;
|
bool spoke = false;
|
||||||
@ -475,6 +643,57 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res
|
|||||||
NDebugOverlay::Text( vPrintPos, CFmtStr( "%s: %s", concept, response ), true, 1.5 );
|
NDebugOverlay::Text( vPrintPos, CFmtStr( "%s: %s", concept, response ), true, 1.5 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
if (result->GetContext())
|
||||||
|
{
|
||||||
|
const char *pszContext = result->GetContext();
|
||||||
|
|
||||||
|
// Check for operators
|
||||||
|
char *pOperator = Q_strstr(pszContext, ":")+1;
|
||||||
|
if (pOperator && (pOperator[0] == '+' || pOperator[0] == '-' ||
|
||||||
|
pOperator[0] == '*' || pOperator[0] == '/'))
|
||||||
|
{
|
||||||
|
pszContext = ParseApplyContext(pszContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iContextFlags = result->GetContextFlags();
|
||||||
|
if ( iContextFlags & APPLYCONTEXT_SQUAD )
|
||||||
|
{
|
||||||
|
CAI_BaseNPC *pNPC = GetOuter()->MyNPCPointer();
|
||||||
|
if (pNPC && pNPC->GetSquad())
|
||||||
|
{
|
||||||
|
AISquadIter_t iter;
|
||||||
|
CAI_BaseNPC *pSquadmate = pNPC->GetSquad()->GetFirstMember( &iter );
|
||||||
|
while ( pSquadmate )
|
||||||
|
{
|
||||||
|
pSquadmate->AddContext( pszContext );
|
||||||
|
|
||||||
|
pSquadmate = pNPC->GetSquad()->GetNextMember( &iter );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( iContextFlags & APPLYCONTEXT_ENEMY )
|
||||||
|
{
|
||||||
|
CBaseEntity *pEnemy = GetOuter()->GetEnemy();
|
||||||
|
if ( pEnemy )
|
||||||
|
{
|
||||||
|
pEnemy->AddContext( pszContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( iContextFlags & APPLYCONTEXT_WORLD )
|
||||||
|
{
|
||||||
|
CBaseEntity *pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex( 0 ) );
|
||||||
|
if ( pEntity )
|
||||||
|
{
|
||||||
|
pEntity->AddContext( pszContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( iContextFlags == 0 || iContextFlags & APPLYCONTEXT_SELF )
|
||||||
|
{
|
||||||
|
GetOuter()->AddContext( pszContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( result->IsApplyContextToWorld() )
|
if ( result->IsApplyContextToWorld() )
|
||||||
{
|
{
|
||||||
CBaseEntity *pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex( 0 ) );
|
CBaseEntity *pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex( 0 ) );
|
||||||
@ -487,6 +706,7 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res
|
|||||||
{
|
{
|
||||||
GetOuter()->AddContext( result->GetContext() );
|
GetOuter()->AddContext( result->GetContext() );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
SetSpokeConcept( concept, result );
|
SetSpokeConcept( concept, result );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -569,6 +789,32 @@ bool CAI_Expresser::Speak( AIConcept_t concept, const char *modifiers /*= NULL*/
|
|||||||
return spoke;
|
return spoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Uses an AI_CriteriaSet directly instead of using context-format modifier text.
|
||||||
|
// Input : concept -
|
||||||
|
// Output : Returns true on success, false on failure.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool CAI_Expresser::Speak( AIConcept_t concept, AI_CriteriaSet& modifiers, char *pszOutResponseChosen /* = NULL*/, size_t bufsize /* = 0 */, IRecipientFilter *filter /* = NULL */ )
|
||||||
|
{
|
||||||
|
AI_Response *result = SpeakFindResponse( concept, modifiers );
|
||||||
|
if ( !result )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpeechMsg( GetOuter(), "%s (%p) spoke %s (%f)\n", STRING(GetOuter()->GetEntityName()), GetOuter(), concept, gpGlobals->curtime );
|
||||||
|
|
||||||
|
bool spoke = SpeakDispatchResponse( concept, result, filter );
|
||||||
|
if ( pszOutResponseChosen )
|
||||||
|
{
|
||||||
|
result->GetResponse( pszOutResponseChosen, bufsize );
|
||||||
|
}
|
||||||
|
|
||||||
|
return spoke;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
// Purpose:
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -821,8 +1067,32 @@ void CAI_Expresser::SetSpokeConcept( AIConcept_t concept, AI_Response *response,
|
|||||||
slot->response = response;
|
slot->response = response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
// This "weapondelay" was just in player allies before.
|
||||||
|
// Putting it here eliminates the need to implement OnSpokeConcept on all NPCs for weapondelay.
|
||||||
|
if ( bCallback )
|
||||||
|
{
|
||||||
|
if( response != NULL && (response->GetParams()->flags & AI_ResponseParams::RG_WEAPONDELAY) )
|
||||||
|
{
|
||||||
|
if ( GetOuter()->IsNPC() )
|
||||||
|
{
|
||||||
|
// Stop shooting, as instructed, so that my speech can be heard.
|
||||||
|
GetOuter()->MyNPCPointer()->GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + response->GetWeaponDelay() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char szResponse[64];
|
||||||
|
response->GetName(szResponse, sizeof(szResponse));
|
||||||
|
Warning("%s response %s wants to use weapondelay, but %s is not a NPC!\n", GetOuter()->GetDebugName(), szResponse, GetOuter()->GetDebugName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GetSink()->OnSpokeConcept( concept, response );
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ( bCallback )
|
if ( bCallback )
|
||||||
GetSink()->OnSpokeConcept( concept, response );
|
GetSink()->OnSpokeConcept( concept, response );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
@ -894,6 +1164,66 @@ void CAI_Expresser::SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... )
|
|||||||
UTIL_LogPrintf( string );
|
UTIL_LogPrintf( string );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAPBASE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose:
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
char *CAI_Expresser::ParseApplyContext( const char *szContext )
|
||||||
|
{
|
||||||
|
char szKey[128];
|
||||||
|
char szValue[128];
|
||||||
|
float flDuration = 0.0;
|
||||||
|
|
||||||
|
SplitContext(szContext, szKey, sizeof(szKey), szValue, sizeof(szValue), &flDuration);
|
||||||
|
|
||||||
|
// This is the value without the operator
|
||||||
|
const char *pszValue = szValue + 1;
|
||||||
|
|
||||||
|
// This is the operator itself
|
||||||
|
char cOperator = szValue[0];
|
||||||
|
|
||||||
|
// This is the value to operate with (e.g. the "7" in "+7")
|
||||||
|
float flNewValue = atof( pszValue );
|
||||||
|
|
||||||
|
if (flNewValue == 0.0f)
|
||||||
|
{
|
||||||
|
// If it's really 0, then this is a waste of time
|
||||||
|
Warning("\"%s\" was detected by applyContext operators as an operable number, but it's not.\n", szValue);
|
||||||
|
return strdup(szContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the existing value; will be operated upon and become the final assignment
|
||||||
|
float flValue = 0.0f;
|
||||||
|
const char *szExistingValue = GetOuter()->GetContextValue(szKey);
|
||||||
|
if (szExistingValue)
|
||||||
|
flValue = atof(szExistingValue);
|
||||||
|
|
||||||
|
// Do the operation based on what the character was
|
||||||
|
switch (cOperator)
|
||||||
|
{
|
||||||
|
case '+': flValue += flNewValue; break;
|
||||||
|
case '-': flValue -= flNewValue; break;
|
||||||
|
case '*': flValue *= flNewValue; break;
|
||||||
|
case '/': flValue /= flNewValue; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_snprintf(szValue, sizeof(szValue), "%f", flValue);
|
||||||
|
|
||||||
|
// Remove all trailing 0's from the float to maintain whole integers
|
||||||
|
int i;
|
||||||
|
for (i = strlen(szValue)-1; szValue[i] == '0'; i--)
|
||||||
|
{
|
||||||
|
szValue[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there were only zeroes past the period, this is a whole number. Remove the period
|
||||||
|
if (szValue[i] == '.')
|
||||||
|
szValue[i] = '\0';
|
||||||
|
|
||||||
|
return UTIL_VarArgs("%s:%s:%f", szKey, szValue, flDuration);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -912,6 +1242,7 @@ void CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria( CAI_BaseNPC *pSpeaker, AI_C
|
|||||||
set.AppendCriteria( "npcstate", UTIL_VarArgs( "[NPCState::%s]", pStateNames[pSpeaker->m_NPCState] ) );
|
set.AppendCriteria( "npcstate", UTIL_VarArgs( "[NPCState::%s]", pStateNames[pSpeaker->m_NPCState] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MAPBASE
|
||||||
if ( pSpeaker->GetEnemy() )
|
if ( pSpeaker->GetEnemy() )
|
||||||
{
|
{
|
||||||
set.AppendCriteria( "enemy", pSpeaker->GetEnemy()->GetClassname() );
|
set.AppendCriteria( "enemy", pSpeaker->GetEnemy()->GetClassname() );
|
||||||
@ -924,6 +1255,7 @@ void CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria( CAI_BaseNPC *pSpeaker, AI_C
|
|||||||
else
|
else
|
||||||
set.AppendCriteria( "timesincecombat", UTIL_VarArgs( "%f", gpGlobals->curtime - pSpeaker->GetLastEnemyTime() ) );
|
set.AppendCriteria( "timesincecombat", UTIL_VarArgs( "%f", gpGlobals->curtime - pSpeaker->GetLastEnemyTime() ) );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
set.AppendCriteria( "speed", UTIL_VarArgs( "%.3f", pSpeaker->GetSmoothedVelocity().Length() ) );
|
set.AppendCriteria( "speed", UTIL_VarArgs( "%.3f", pSpeaker->GetSmoothedVelocity().Length() ) );
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user