Updated Mapbase MP port to Mapbase v7.1

This commit is contained in:
ALLEN-PC\acj30 2023-01-18 11:58:02 -06:00
parent 9cf5381ef1
commit c19dccff63
466 changed files with 44286 additions and 5102 deletions

View File

@ -6,10 +6,11 @@ MAKEFILE_LINK:=$(THISFILE).link
-include $(MAKEFILE_LINK)
$(MAKEFILE_LINK): $(shell which $(CC)) $(THISFILE)
if [ "$(shell printf "$(shell $(CC) -dumpversion)\n8" | sort -Vr | head -1)" = 8 ]; then \
$(COMPILE.cpp) -o gcc9+support.o gcc9+support.c ;\
# depend on CXX so the correct makefile can be selected when the system is updated
$(MAKEFILE_LINK): $(shell which $(CXX)) $(THISFILE) $(SRCROOT)/devtools/gcc9+support.cpp
@ if [ "$(shell printf "$(shell $(CXX) -dumpversion)\n8" | sort -Vr | head -1)" = 8 ]; then \
ln -sf $(MAKEFILE_BASE).default $@ ;\
else \
$(COMPILE.cpp) -m32 -o $(SRCROOT)/devtools/gcc9+support.o $(SRCROOT)/devtools/gcc9+support.cpp &&\
ln -sf $(MAKEFILE_BASE).gcc8 $@ ;\
fi

View File

@ -813,7 +813,11 @@ bool GameData::RemapNameField( const char *pszInValue, char *pszOutValue, TNameF
{
strcpy( pszOutValue, pszInValue );
#ifdef MAPBASE
if ( pszInValue[ 0 ] && pszInValue[ 0 ] != '@' && pszInValue[ 0 ] != '!' )
#else
if ( pszInValue[ 0 ] && pszInValue[ 0 ] != '@' )
#endif
{ // ! at the start of a value means it is global and should not be remaped
switch( NameFixup )
{

View File

@ -92,6 +92,7 @@ private:
float m_flLinearAtten;
float m_flQuadraticAtten;
float m_flShadowAtten;
float m_flShadowFilter;
bool m_bAlwaysDraw;
//bool m_bProjectedTextureVersion;

View File

@ -264,6 +264,9 @@ LINK_ENTITY_TO_CLASS( client_ragdoll, C_ClientRagdoll );
BEGIN_DATADESC( C_ClientRagdoll )
DEFINE_FIELD( m_bFadeOut, FIELD_BOOLEAN ),
DEFINE_FIELD( m_bImportant, FIELD_BOOLEAN ),
#ifdef MAPBASE
DEFINE_FIELD( m_flForcedRetireTime, FIELD_FLOAT ),
#endif
DEFINE_FIELD( m_iCurrentFriction, FIELD_INTEGER ),
DEFINE_FIELD( m_iMinFriction, FIELD_INTEGER ),
DEFINE_FIELD( m_iMaxFriction, FIELD_INTEGER ),
@ -286,6 +289,22 @@ BEGIN_DATADESC( C_ClientRagdoll )
END_DATADESC()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( C_ClientRagdoll, C_BaseAnimating, "Client-side ragdolls" )
DEFINE_SCRIPTFUNC_NAMED( SUB_Remove, "FadeOut", "Fades out the ragdoll and removes it from the client." )
// TODO: Proper shared ragdoll funcs?
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRagdollObject, "GetRagdollObject", "Gets the ragdoll object of the specified index." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRagdollObjectCount, "GetRagdollObjectCount", "Gets the number of ragdoll objects on this ragdoll." )
END_SCRIPTDESC();
ScriptHook_t C_BaseAnimating::g_Hook_OnClientRagdoll;
ScriptHook_t C_BaseAnimating::g_Hook_FireEvent;
//ScriptHook_t C_BaseAnimating::g_Hook_BuildTransformations;
#endif
BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-side" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC_NAMED( ScriptGetPoseParameter, "GetPoseParameter", "Get the specified pose parameter's value" )
@ -293,6 +312,22 @@ BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-si
DEFINE_SCRIPTFUNC_NAMED( ScriptSetPoseParameter, "SetPoseParameter", "Set the specified pose parameter to the specified value" )
DEFINE_SCRIPTFUNC( IsSequenceFinished, "Ask whether the main sequence is done playing" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC_NAMED( ScriptLookupAttachment, "LookupAttachment", "Get the named attachement id" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentOrigin, "GetAttachmentOrigin", "Get the attachement id's origin vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentAngles, "GetAttachmentAngles", "Get the attachement id's angles as a p,y,r vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentMatrix, "GetAttachmentMatrix", "Get the attachement id's matrix transform" )
DEFINE_SCRIPTFUNC( LookupBone, "Get the named bone id" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoneTransform, "GetBoneTransform", "Get the transform for the specified bone" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetBoneTransform, "SetBoneTransform", "Set the transform for the specified bone" )
DEFINE_SCRIPTFUNC_NAMED( ScriptAttachEntityToBone, "AttachEntityToBone", "Attaches this entity to the specified target and bone. Also allows for optional local position offset" )
DEFINE_SCRIPTFUNC_NAMED( ScriptRemoveBoneAttachment, "RemoveBoneAttachment", "Removes the specified bone attachment" )
//DEFINE_SCRIPTFUNC( RemoveBoneAttachments, "Removes all bone attachments" )
DEFINE_SCRIPTFUNC( DestroyBoneAttachments, "Destroys all bone attachments" )
DEFINE_SCRIPTFUNC( GetNumBoneAttachments, "Gets the number of bone attachments" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoneAttachment, "GetBoneAttachment", "Gets the specified bone attachment" )
DEFINE_SCRIPTFUNC( SetBodygroup, "Sets a bodygroup")
DEFINE_SCRIPTFUNC( GetBodygroup, "Gets a bodygroup" )
DEFINE_SCRIPTFUNC( GetBodygroupName, "Gets a bodygroup name" )
@ -302,12 +337,43 @@ BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-si
DEFINE_SCRIPTFUNC( GetSequence, "Gets the current sequence" )
DEFINE_SCRIPTFUNC( SetSequence, "Sets the current sequence" )
DEFINE_SCRIPTFUNC( SequenceLoops, "Loops the current sequence" )
DEFINE_SCRIPTFUNC( SequenceLoops, "Does the current sequence loop?" )
DEFINE_SCRIPTFUNC( LookupSequence, "Gets the index of the specified sequence name" )
DEFINE_SCRIPTFUNC( LookupActivity, "Gets the ID of the specified activity name" )
DEFINE_SCRIPTFUNC( GetSequenceName, "Gets the name of the specified sequence index" )
DEFINE_SCRIPTFUNC( GetSequenceActivityName, "Gets the activity name of the specified sequence index" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceMoveDist, "GetSequenceMoveDist", "Gets the move distance of the specified sequence" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceActivity, "GetSequenceActivity", "Gets the activity ID of the specified sequence index" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectWeightedSequence, "SelectWeightedSequence", "Selects a sequence for the specified activity ID" )
DEFINE_SCRIPTFUNC( GetPlaybackRate, "" )
DEFINE_SCRIPTFUNC( SetPlaybackRate, "" )
DEFINE_SCRIPTFUNC( GetCycle, "" )
DEFINE_SCRIPTFUNC( SetCycle, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSkin, "GetSkin", "Gets the model's skin" )
DEFINE_SCRIPTFUNC( SetSkin, "Sets the model's skin" )
DEFINE_SCRIPTFUNC( GetForceBone, "Gets the entity's force bone, which is used to determine which bone a ragdoll should apply its force to." )
DEFINE_SCRIPTFUNC( SetForceBone, "Sets the entity's force bone, which is used to determine which bone a ragdoll should apply its force to." )
DEFINE_SCRIPTFUNC( GetRagdollForce, "Gets the entity's ragdoll force, which is used to apply velocity to a ragdoll." )
DEFINE_SCRIPTFUNC( SetRagdollForce, "Sets the entity's ragdoll force, which is used to apply velocity to a ragdoll." )
DEFINE_SCRIPTFUNC_NAMED( ScriptBecomeRagdollOnClient, "BecomeRagdollOnClient", "" )
DEFINE_SCRIPTFUNC( IsRagdoll, "" )
BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_OnClientRagdoll, "OnClientRagdoll", FIELD_VOID, "Called when this entity turns into a client-side ragdoll." )
DEFINE_SCRIPTHOOK_PARAM( "ragdoll", FIELD_HSCRIPT )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_FireEvent, "FireEvent", FIELD_BOOLEAN, "Called when handling animation events. Return false to cancel base handling." )
DEFINE_SCRIPTHOOK_PARAM( "origin", FIELD_VECTOR )
DEFINE_SCRIPTHOOK_PARAM( "angles", FIELD_VECTOR )
DEFINE_SCRIPTHOOK_PARAM( "event", FIELD_INTEGER )
DEFINE_SCRIPTHOOK_PARAM( "options", FIELD_CSTRING )
END_SCRIPTHOOK()
//BEGIN_SCRIPTHOOK( C_BaseAnimating::g_Hook_BuildTransformations, "BuildTransformations", FIELD_VOID, "Called when building bone transformations. Allows VScript to read/write any bone with Get/SetBoneTransform." )
//END_SCRIPTHOOK()
#endif
END_SCRIPTDESC();
@ -319,6 +385,9 @@ C_ClientRagdoll::C_ClientRagdoll( bool bRestoring )
m_bFadeOut = false;
m_bFadingOut = false;
m_bImportant = false;
#ifdef MAPBASE
m_flForcedRetireTime = 0.0f;
#endif
m_bNoModelParticles = false;
SetClassname("client_ragdoll");
@ -399,7 +468,11 @@ void C_ClientRagdoll::OnRestore( void )
if ( m_bFadeOut == true )
{
#ifdef MAPBASE
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant, m_flForcedRetireTime );
#else
s_RagdollLRU.MoveToTopOfLRU( this, m_bImportant );
#endif
}
NoteRagdollCreationTick( this );
@ -674,6 +747,24 @@ void C_ClientRagdoll::Release( void )
BaseClass::Release();
}
#ifdef MAPBASE_VSCRIPT
HSCRIPT C_ClientRagdoll::ScriptGetRagdollObject( int iIndex )
{
if (iIndex < 0 || iIndex > m_pRagdoll->RagdollBoneCount())
{
Warning("%s GetRagdollObject: Index %i not valid (%i objects)\n", GetDebugName(), iIndex, m_pRagdoll->RagdollBoneCount());
return NULL;
}
return g_pScriptVM->RegisterInstance( m_pRagdoll->GetElement(iIndex) );
}
int C_ClientRagdoll::ScriptGetRagdollObjectCount()
{
return m_pRagdoll->RagdollBoneCount();
}
#endif
//-----------------------------------------------------------------------------
// Incremented each frame in InvalidateModelBones. Models compare this value to what it
// was last time they setup their bones to determine if they need to re-setup their bones.
@ -711,6 +802,10 @@ C_BaseAnimating::C_BaseAnimating() :
m_nPrevSequence = -1;
m_nRestoreSequence = -1;
m_pRagdoll = NULL;
m_pClientsideRagdoll = NULL;
#ifdef MAPBASE
m_pServerRagdoll = NULL;
#endif
m_builtRagdoll = false;
m_hitboxBoneCacheHandle = 0;
int i;
@ -1461,6 +1556,94 @@ float C_BaseAnimating::ClampCycle( float flCycle, bool isLooping )
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
// Purpose: Returns the world location and world angles of an attachment to vscript caller
// Input : attachment name
// Output : location and angles
//-----------------------------------------------------------------------------
const Vector& C_BaseAnimating::ScriptGetAttachmentOrigin( int iAttachment )
{
static Vector absOrigin;
static QAngle qa;
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
return absOrigin;
}
const Vector& C_BaseAnimating::ScriptGetAttachmentAngles( int iAttachment )
{
static Vector absOrigin;
static Vector absAngles;
static QAngle qa;
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
absAngles.x = qa.x;
absAngles.y = qa.y;
absAngles.z = qa.z;
return absAngles;
}
HSCRIPT C_BaseAnimating::ScriptGetAttachmentMatrix( int iAttachment )
{
static matrix3x4_t matrix;
C_BaseAnimating::GetAttachment( iAttachment, matrix );
return g_pScriptVM->RegisterInstance( &matrix );
}
void C_BaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform )
{
matrix3x4_t *matTransform = HScriptToClass<matrix3x4_t>( hTransform );
if (matTransform == NULL)
return;
GetBoneTransform( iBone, *matTransform );
}
void C_BaseAnimating::ScriptSetBoneTransform( int iBone, HSCRIPT hTransform )
{
matrix3x4_t *matTransform = HScriptToClass<matrix3x4_t>( hTransform );
if (matTransform == NULL)
return;
MatrixCopy( *matTransform, GetBoneForWrite( iBone ) );
}
void C_BaseAnimating::ScriptAttachEntityToBone( HSCRIPT attachTarget, int boneIndexAttached, const Vector &bonePosition, const QAngle &boneAngles )
{
C_BaseEntity *pTarget = ToEnt( attachTarget );
if (pTarget == NULL)
return;
AttachEntityToBone( pTarget->GetBaseAnimating(), boneIndexAttached, bonePosition, boneAngles );
}
void C_BaseAnimating::ScriptRemoveBoneAttachment( HSCRIPT boneAttachment )
{
C_BaseEntity *pTarget = ToEnt( boneAttachment );
if (pTarget == NULL)
return;
RemoveBoneAttachment( pTarget->GetBaseAnimating() );
}
HSCRIPT C_BaseAnimating::ScriptGetBoneAttachment( int i )
{
return ToHScript( GetBoneAttachment( i ) );
}
HSCRIPT C_BaseAnimating::ScriptBecomeRagdollOnClient()
{
C_BaseAnimating *pRagdoll = BecomeRagdollOnClient();
if (!pRagdoll)
return NULL;
return pRagdoll->GetScriptInstance();
}
float C_BaseAnimating::ScriptGetPoseParameter( const char* szName )
{
CStudioHdr* pHdr = GetModelPtr();
@ -1638,7 +1821,23 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater
}
}
#ifdef MAPBASE_VSCRIPT
//if (m_ScriptScope.IsInitialized() && g_Hook_BuildTransformations.CanRunInScope(m_ScriptScope))
//{
// int oldWritableBones = m_BoneAccessor.GetWritableBones();
// int oldReadableBones = m_BoneAccessor.GetReadableBones();
// m_BoneAccessor.SetWritableBones( BONE_USED_BY_ANYTHING );
// m_BoneAccessor.SetReadableBones( BONE_USED_BY_ANYTHING );
//
// // No parameters
// //ScriptVariant_t args[] = {};
// //ScriptVariant_t returnValue;
// g_Hook_BuildTransformations.Call( m_ScriptScope, NULL, NULL /*&returnValue, args*/ );
//
// m_BoneAccessor.SetWritableBones( oldWritableBones );
// m_BoneAccessor.SetReadableBones( oldReadableBones );
//}
#endif
}
//-----------------------------------------------------------------------------
@ -1844,6 +2043,10 @@ CollideType_t C_BaseAnimating::GetCollideType( void )
return BaseClass::GetCollideType();
}
#ifdef MAPBASE
ConVar ai_death_pose_enabled( "ai_death_pose_enabled", "1", FCVAR_NONE, "Toggles the death pose fix code, which cancels sequence transitions while a NPC is ragdolling." );
#endif
//-----------------------------------------------------------------------------
// Purpose: if the active sequence changes, keep track of the previous ones and decay them based on their decay rate
//-----------------------------------------------------------------------------
@ -1860,6 +2063,14 @@ void C_BaseAnimating::MaintainSequenceTransitions( IBoneSetup &boneSetup, float
return;
}
#ifdef MAPBASE
if ( IsAboutToRagdoll() && ai_death_pose_enabled.GetBool() )
{
m_nPrevNewSequenceParity = m_nNewSequenceParity;
return;
}
#endif
m_SequenceTransitioner.CheckForSequenceChange(
boneSetup.GetStudioHdr(),
GetSequence(),
@ -2659,14 +2870,29 @@ void C_BaseAnimating::CalculateIKLocks( float currentTime )
// debugoverlay->AddBoxOverlay( origin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 0 );
float d = (pTarget->est.pos - origin).Length();
Vector vecDelta = (origin - pTarget->est.pos);
float d = vecDelta.Length();
if ( d >= flDist)
continue;
flDist = d;
pTarget->SetPos( origin );
pTarget->SetAngles( angles );
#ifdef MAPBASE
// For blending purposes, IK attachments should obey weight
if ( pTarget->est.flWeight < 1.0f )
{
Quaternion qTarget;
AngleQuaternion( angles, qTarget );
QuaternionSlerp( pTarget->est.q, qTarget, pTarget->est.flWeight, pTarget->est.q );
pTarget->SetPos( pTarget->est.pos + (vecDelta * pTarget->est.flWeight) );
}
else
#endif
{
pTarget->SetPos( origin );
pTarget->SetAngles( angles );
}
// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
}
@ -3611,7 +3837,11 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
flEventCycle,
gpGlobals->curtime );
}
#ifdef MAPBASE_VSCRIPT
if (ScriptHookFireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() ) == false)
continue;
#endif
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
@ -3644,6 +3874,11 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
gpGlobals->curtime );
}
#ifdef MAPBASE_VSCRIPT
if (ScriptHookFireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() ) == false)
continue;
#endif
FireEvent( GetAbsOrigin(), GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() );
}
}
@ -3651,6 +3886,26 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr )
m_flPrevEventCycle = flEventCycle;
}
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool C_BaseAnimating::ScriptHookFireEvent( const Vector& origin, const QAngle& angles, int event, const char *options )
{
if (m_ScriptScope.IsInitialized() && g_Hook_FireEvent.CanRunInScope(m_ScriptScope))
{
// origin, angles, event, options
ScriptVariant_t args[] = { origin, angles, event, options };
ScriptVariant_t returnValue = true;
g_Hook_FireEvent.Call( m_ScriptScope, &returnValue, args );
return returnValue.m_bool;
}
return true;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Parses a muzzle effect event and sends it out for drawing
// Input : *options - event parameters in text format
@ -4716,12 +4971,18 @@ bool C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matri
return bSuccess;
}
C_ClientRagdoll *C_BaseAnimating::CreateClientRagdoll( bool bRestoring )
{
//DevMsg( "Creating ragdoll at tick %d\n", gpGlobals->tickcount );
return new C_ClientRagdoll( bRestoring );
}
C_BaseAnimating *C_BaseAnimating::CreateRagdollCopy()
{
//Adrian: We now create a separate entity that becomes this entity's ragdoll.
//That way the server side version of this entity can go away.
//Plus we can hook save/restore code to these ragdolls so they don't fall on restore anymore.
C_ClientRagdoll *pRagdoll = new C_ClientRagdoll( false );
C_ClientRagdoll *pRagdoll = CreateClientRagdoll( false );
if ( pRagdoll == NULL )
return NULL;
@ -4789,9 +5050,9 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
{
MoveToLastReceivedPosition( true );
GetAbsOrigin();
m_pClientsideRagdoll = CreateRagdollCopy();
C_BaseAnimating *pRagdoll = CreateRagdollCopy();
if ( pRagdoll )
if ( m_pClientsideRagdoll )
{
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
@ -4803,19 +5064,29 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
if ( bInitBoneArrays )
{
bInitAsClient = pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
bInitAsClient = m_pClientsideRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
}
if ( !bInitAsClient || !bInitBoneArrays )
{
Warning( "C_BaseAnimating::BecomeRagdollOnClient failed. pRagdoll:%p bInitBoneArrays:%d bInitAsClient:%d\n",
pRagdoll, bInitBoneArrays, bInitAsClient );
pRagdoll->Release();
m_pClientsideRagdoll, bInitBoneArrays, bInitAsClient );
m_pClientsideRagdoll->Release();
return NULL;
}
#ifdef MAPBASE_VSCRIPT
// Hook for ragdolling
if (m_ScriptScope.IsInitialized() && g_Hook_OnClientRagdoll.CanRunInScope( m_ScriptScope ))
{
// ragdoll
ScriptVariant_t args[] = { ScriptVariant_t( m_pClientsideRagdoll->GetScriptInstance() ) };
g_Hook_OnClientRagdoll.Call( m_ScriptScope, NULL, args );
}
#endif
}
return pRagdoll;
return m_pClientsideRagdoll;
}
bool C_BaseAnimating::InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt, bool bFixedConstraints )
@ -5281,6 +5552,11 @@ void C_BaseAnimating::StudioFrameAdvance()
if ( flNewCycle < 0.0f || flNewCycle >= 1.0f )
{
if (flNewCycle >= 1.0f)
{
ReachedEndOfSequence();
}
if ( IsSequenceLooping( hdr, GetSequence() ) )
{
flNewCycle -= (int)(flNewCycle);

View File

@ -38,6 +38,7 @@ class C_BaseClientShader
*/
class IRagdoll;
class C_ClientRagdoll;
class CIKContext;
class CIKState;
class ConVar;
@ -79,7 +80,7 @@ public:
QAngle m_angRotation;
Vector m_vOriginVelocity;
int m_nLastFramecount : 31;
int m_bAnglesComputed : 1;
bool m_bAnglesComputed : 1;
};
@ -164,6 +165,10 @@ public:
virtual void FireObsoleteEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
virtual const char* ModifyEventParticles( const char* token ) { return token; }
#ifdef MAPBASE_VSCRIPT
bool ScriptHookFireEvent( const Vector& origin, const QAngle& angles, int event, const char *options );
#endif
#if defined ( SDK_DLL ) || defined ( HL2MP )
virtual void ResetEventsParity() { m_nPrevResetEventsParity = -1; } // used to force animation events to function on players so the muzzleflashes and other events occur
// so new functions don't have to be made to parse the models like CSS does in ProcessMuzzleFlashEvent
@ -297,6 +302,7 @@ public:
bool IsRagdoll() const;
bool IsAboutToRagdoll() const;
virtual C_BaseAnimating *BecomeRagdollOnClient();
virtual C_ClientRagdoll *CreateClientRagdoll( bool bRestoring = false );
C_BaseAnimating *CreateRagdollCopy();
bool InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt, bool bFixedConstraints=false );
void IgniteRagdoll( C_BaseAnimating *pSource );
@ -350,6 +356,8 @@ public:
void ClientSideAnimationChanged();
virtual unsigned int ComputeClientSideAnimationFlags();
virtual void ReachedEndOfSequence() { return; }
virtual void ResetClientsideFrame( void ) { SetCycle( 0 ); }
void SetCycle( float flCycle );
@ -456,6 +464,37 @@ public:
virtual void UpdateOnRemove( void );
#ifdef MAPBASE_VSCRIPT
int ScriptLookupAttachment( const char *pAttachmentName ) { return LookupAttachment( pAttachmentName ); }
const Vector& ScriptGetAttachmentOrigin(int iAttachment);
const Vector& ScriptGetAttachmentAngles(int iAttachment);
HSCRIPT ScriptGetAttachmentMatrix(int iAttachment);
void ScriptGetBoneTransform( int iBone, HSCRIPT hTransform );
void ScriptSetBoneTransform( int iBone, HSCRIPT hTransform );
void ScriptAttachEntityToBone( HSCRIPT attachTarget, int boneIndexAttached, const Vector &bonePosition, const QAngle &boneAngles );
void ScriptRemoveBoneAttachment( HSCRIPT boneAttachment );
HSCRIPT ScriptGetBoneAttachment( int i );
int ScriptGetSequenceActivity( int iSequence ) { return GetSequenceActivity( iSequence ); }
float ScriptGetSequenceMoveDist( int iSequence ) { return GetSequenceMoveDist( GetModelPtr(), iSequence ); }
int ScriptSelectWeightedSequence( int activity ) { return SelectWeightedSequence( (Activity)activity ); }
// For VScript
int ScriptGetSkin() { return GetSkin(); }
void SetSkin( int iSkin ) { m_nSkin = iSkin; }
int GetForceBone() { return m_nForceBone; }
void SetForceBone( int iBone ) { m_nForceBone = iBone; }
const Vector& GetRagdollForce() { return m_vecForce; }
void SetRagdollForce( const Vector &vecForce ) { m_vecForce = vecForce; }
HSCRIPT ScriptBecomeRagdollOnClient();
static ScriptHook_t g_Hook_OnClientRagdoll;
static ScriptHook_t g_Hook_FireEvent;
//static ScriptHook_t g_Hook_BuildTransformations; // UNDONE: Thread access issues
float ScriptGetPoseParameter(const char* szName);
#endif
void ScriptSetPoseParameter(const char* szName, float fValue);
@ -477,10 +516,6 @@ protected:
virtual bool CalcAttachments();
#ifdef MAPBASE_VSCRIPT
int ScriptGetSequenceActivity( int iSequence ) { return GetSequenceActivity( iSequence ); }
#endif
private:
// This method should return true if the bones have changed + SetupBones needs to be called
virtual float LastBoneChangedTime() { return FLT_MAX; }
@ -498,6 +533,10 @@ private:
public:
CRagdoll *m_pRagdoll;
C_BaseAnimating *m_pClientsideRagdoll; // From Alien Swarm SDK
#ifdef MAPBASE
C_BaseAnimating *m_pServerRagdoll; // Not from Alien Swarm SDK (note that this can exist without the entity having died)
#endif
// Texture group to use
int m_nSkin;
@ -669,6 +708,9 @@ public:
C_ClientRagdoll( bool bRestoring = true );
DECLARE_CLASS( C_ClientRagdoll, C_BaseAnimating );
DECLARE_DATADESC();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
// inherited from IPVSNotify
virtual void OnPVSStatusChanged( bool bInPVS );
@ -690,8 +732,17 @@ public:
void FadeOut( void );
virtual float LastBoneChangedTime();
#ifdef MAPBASE_VSCRIPT
HSCRIPT ScriptGetRagdollObject( int iIndex );
int ScriptGetRagdollObjectCount();
#endif
bool m_bFadeOut;
bool m_bImportant;
#ifdef MAPBASE
// Required to save/restore Alien Swarm SDK ragdoll LRU forced fade
float m_flForcedRetireTime;
#endif
float m_flEffectTime;
private:

View File

@ -195,3 +195,39 @@ BEGIN_PREDICTION_DATA( C_BaseCombatCharacter )
DEFINE_PRED_ARRAY( m_hMyWeapons, FIELD_EHANDLE, MAX_WEAPONS, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( C_BaseCombatCharacter, CBaseEntity, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAmmoCount, "GetAmmoCount", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetActiveWeapon, "GetActiveWeapon", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetWeapon, "GetWeapon", "" )
END_SCRIPTDESC();
int C_BaseCombatCharacter::ScriptGetAmmoCount( int i )
{
Assert( i == -1 || i < MAX_AMMO_SLOTS );
if ( i < 0 || i >= MAX_AMMO_SLOTS )
return NULL;
return GetAmmoCount( i );
}
HSCRIPT C_BaseCombatCharacter::ScriptGetActiveWeapon()
{
return ToHScript( GetActiveWeapon() );
}
HSCRIPT C_BaseCombatCharacter::ScriptGetWeapon( int i )
{
Assert( i >= 0 && i < MAX_WEAPONS );
if ( i < 0 || i >= MAX_WEAPONS )
return NULL;
return ToHScript( GetWeapon(i) );
}
#endif

View File

@ -29,6 +29,9 @@ class C_BaseCombatCharacter : public C_BaseFlex
public:
DECLARE_CLIENTCLASS();
DECLARE_PREDICTABLE();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
C_BaseCombatCharacter( void );
virtual ~C_BaseCombatCharacter( void );
@ -103,6 +106,12 @@ public:
bool IsClientSideGlowEnabled( void ){ return m_bClientSideGlowEnabled; }
#endif // GLOWS_ENABLE
#ifdef MAPBASE_VSCRIPT
int ScriptGetAmmoCount( int i );
HSCRIPT ScriptGetActiveWeapon();
HSCRIPT ScriptGetWeapon( int i );
#endif
public:
float m_flNextAttack;

View File

@ -125,9 +125,15 @@ void C_BaseCombatWeapon::OnRestore()
int C_BaseCombatWeapon::GetWorldModelIndex( void )
{
#ifdef MAPBASE
int iIndex = GetOwner() ? m_iWorldModelIndex.Get() : m_iDroppedModelIndex.Get();
#else
int iIndex = m_iWorldModelIndex.Get();
#endif
if ( GameRules() )
{
const char *pBaseName = modelinfo->GetModelName( modelinfo->GetModel( m_iWorldModelIndex ) );
const char *pBaseName = modelinfo->GetModelName( modelinfo->GetModel( iIndex ) );
const char *pTranslatedName = GameRules()->TranslateEffectForVisionFilter( "weapons", pBaseName );
if ( pTranslatedName != pBaseName )
@ -136,7 +142,7 @@ int C_BaseCombatWeapon::GetWorldModelIndex( void )
}
}
return m_iWorldModelIndex;
return iIndex;
}
//-----------------------------------------------------------------------------
@ -505,25 +511,44 @@ int C_BaseCombatWeapon::DrawModel( int flags )
// check if local player chases owner of this weapon in first person
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
if ( localplayer && localplayer->IsObserver() && GetOwner() )
if ( localplayer )
{
#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 );
if ( (!localplayer->InFirstPersonView() || (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)) && (viewID != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)) )
{
// TODO: Is this inefficient?
int nModelIndex = GetModelIndex();
int nWorldModelIndex = GetWorldModelIndex();
if (nModelIndex != nWorldModelIndex)
{
SetModelIndex(nWorldModelIndex);
}
int iDraw = BaseClass::DrawModel(flags);
if (nModelIndex != nWorldModelIndex)
{
SetModelIndex(nModelIndex);
}
return iDraw;
}
}
#endif
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
if ( localplayer->IsObserver() && GetOwner() )
{
// don't draw weapon if chasing this guy as spectator
// we don't check that in ShouldDraw() since this may change
// without notification
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() )
return false;
if ( localplayer->GetObserverMode() == OBS_MODE_IN_EYE &&
localplayer->GetObserverTarget() == GetOwner() )
return false;
}
}
return BaseClass::DrawModel( flags );

View File

@ -428,7 +428,13 @@ BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_AnimTimeMustBeFirst )
RecvPropInt( RECVINFO(m_flAnimTime), 0, RecvProxy_AnimTime ),
END_RECV_TABLE()
#ifdef MAPBASE_VSCRIPT
ScriptHook_t C_BaseEntity::g_Hook_UpdateOnRemove;
ScriptHook_t C_BaseEntity::g_Hook_ModifyEmitSoundParams;
#endif
BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" )
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetForward, "GetForwardVector", "Get the forward vector of the entity" )
#ifdef MAPBASE_VSCRIPT
@ -442,6 +448,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC( ValidateScriptScope, "Ensure that an entity's script scope has been created" )
DEFINE_SCRIPTFUNC( GetOrCreatePrivateScriptScope, "Create and retrieve the script-side data associated with an entity" )
DEFINE_SCRIPTFUNC( GetScriptScope, "Retrieve the script-side data associated with an entity" )
DEFINE_SCRIPTFUNC( GetHealth, "" )
@ -449,6 +456,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelName, "GetModelName", "Returns the name of the model" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopSound, "StopSound", "Stops a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptEmitSound, "EmitSound", "Plays a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( VScriptPrecacheScriptSound, "PrecacheSoundScript", "Precache a sound for later playing." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSoundDuration, "GetSoundDuration", "Returns float duration of the sound. Takes soundname and optional actormodelname." )
@ -456,23 +464,106 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC( GetClassname, "" )
DEFINE_SCRIPTFUNC_NAMED( GetEntityName, "GetName", "" )
DEFINE_SCRIPTFUNC_NAMED( SetAbsOrigin, "SetOrigin", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetForward, "SetForwardVector", "Set the orientation of the entity to have this forward vector" )
DEFINE_SCRIPTFUNC( GetLocalOrigin, "GetLocalOrigin" )
DEFINE_SCRIPTFUNC( SetLocalOrigin, "SetLocalOrigin" )
DEFINE_SCRIPTFUNC( GetLocalAngles, "GetLocalAngles" )
DEFINE_SCRIPTFUNC( SetLocalAngles, "SetLocalAngles" )
DEFINE_SCRIPTFUNC_NAMED( WorldSpaceCenter, "GetCenter", "Get vector to center of object - absolute coords" )
DEFINE_SCRIPTFUNC_NAMED( ScriptEyePosition, "EyePosition", "Get vector to eye position - absolute coords" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAngles, "GetAngles", "Get entity pitch, yaw, roll as a vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptEyeAngles, "EyeAngles", "Get eye pitch, yaw, roll as a vector" )
DEFINE_SCRIPTFUNC_NAMED( GetAbsAngles, "GetAngles", "Get entity pitch, yaw, roll as a vector" )
DEFINE_SCRIPTFUNC_NAMED( SetAbsAngles, "SetAngles", "Set entity pitch, yaw, roll" )
DEFINE_SCRIPTFUNC( SetSize, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMins, "GetBoundingMins", "Get a vector containing min bounds, centered on object" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMaxs, "GetBoundingMaxs", "Get a vector containing max bounds, centered on object" )
DEFINE_SCRIPTFUNC_NAMED( ScriptEntityToWorldTransform, "EntityToWorldTransform", "Get the entity's transform" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetPhysicsObject, "GetPhysicsObject", "Get the entity's physics object if it has one" )
DEFINE_SCRIPTFUNC( GetWaterLevel, "Get current level of water submergence" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetParent, "SetParent", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetMoveParent, "GetMoveParent", "If in hierarchy, retrieves the entity's parent" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRootMoveParent, "GetRootMoveParent", "If in hierarchy, walks up the hierarchy to find the root parent" )
DEFINE_SCRIPTFUNC_NAMED( ScriptFirstMoveChild, "FirstMoveChild", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptNextMovePeer, "NextMovePeer", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptFollowEntity, "FollowEntity", "Begin following the specified entity. This makes this entity non-solid, parents it to the target entity, and teleports it to the specified entity's origin. The second parameter is whether or not to use bonemerging while following." )
DEFINE_SCRIPTFUNC( StopFollowingEntity, "Stops following an entity if we're following one." )
DEFINE_SCRIPTFUNC( IsFollowingEntity, "Returns true if this entity is following another entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFollowedEntity, "GetFollowedEntity", "Get the entity we're following." )
DEFINE_SCRIPTFUNC_NAMED( GetScriptOwnerEntity, "GetOwner", "Gets this entity's owner" )
DEFINE_SCRIPTFUNC_NAMED( SetScriptOwnerEntity, "SetOwner", "Sets this entity's owner" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorVector, "GetRenderColorVector", "Get the render color as a vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorR, "GetRenderColorR", "Get the render color's R value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorG, "GetRenderColorG", "Get the render color's G value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetColorB, "GetRenderColorB", "Get the render color's B value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAlpha, "GetRenderAlpha", "Get the render color's alpha value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorVector, "SetRenderColorVector", "Set the render color as a vector" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColor, "SetRenderColor", "Set the render color" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorR, "SetRenderColorR", "Set the render color's R value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorG, "SetRenderColorG", "Set the render color's G value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetColorB, "SetRenderColorB", "Set the render color's B value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetAlpha, "SetRenderAlpha", "Set the render color's alpha value" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRenderMode, "GetRenderMode", "Get render mode" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetRenderMode, "SetRenderMode", "Set render mode" )
DEFINE_SCRIPTFUNC( GetEffects, "Get effects" )
DEFINE_SCRIPTFUNC( AddEffects, "Add effect(s)" )
DEFINE_SCRIPTFUNC( RemoveEffects, "Remove effect(s)" )
DEFINE_SCRIPTFUNC( ClearEffects, "Clear effect(s)" )
DEFINE_SCRIPTFUNC( SetEffects, "Set effect(s)" )
DEFINE_SCRIPTFUNC( IsEffectActive, "Check if an effect is active" )
DEFINE_SCRIPTFUNC( GetFlags, "Get flags" )
DEFINE_SCRIPTFUNC( AddFlag, "Add flag" )
DEFINE_SCRIPTFUNC( RemoveFlag, "Remove flag" )
DEFINE_SCRIPTFUNC( GetEFlags, "Get Eflags" )
DEFINE_SCRIPTFUNC( AddEFlags, "Add Eflags" )
DEFINE_SCRIPTFUNC( RemoveEFlags, "Remove Eflags" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetMoveType, "GetMoveType", "Get the move type" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetMoveType, "SetMoveType", "Set the move type" )
DEFINE_SCRIPTFUNC( GetCollisionGroup, "Get the collision group" )
DEFINE_SCRIPTFUNC( SetCollisionGroup, "Set the collision group" )
DEFINE_SCRIPTFUNC( GetSolidFlags, "Get solid flags" )
DEFINE_SCRIPTFUNC( AddSolidFlags, "Add solid flags" )
DEFINE_SCRIPTFUNC( RemoveSolidFlags, "Remove solid flags" )
DEFINE_SCRIPTFUNC( IsPlayer, "Returns true if this entity is a player." )
DEFINE_SCRIPTFUNC( IsNPC, "Returns true if this entity is a NPC." )
//DEFINE_SCRIPTFUNC( IsCombatCharacter, "Returns true if this entity is a combat character (player or NPC)." )
DEFINE_SCRIPTFUNC_NAMED( IsBaseCombatWeapon, "IsWeapon", "Returns true if this entity is a weapon." )
DEFINE_SCRIPTFUNC( IsWorld, "Returns true if this entity is the world." )
DEFINE_SCRIPTFUNC( SetModel, "Set client-only entity model" )
//DEFINE_SCRIPTFUNC_NAMED( ScriptInitializeAsClientEntity, "InitializeAsClientEntity", "" )
DEFINE_SCRIPTFUNC_NAMED( Remove, "Destroy", "Remove clientside entity" )
DEFINE_SCRIPTFUNC_NAMED( GetEntityIndex, "entindex", "" )
#endif
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
DEFINE_SIMPLE_SCRIPTHOOK( C_BaseEntity::g_Hook_UpdateOnRemove, "UpdateOnRemove", FIELD_VOID, "Called when the entity is being removed." )
BEGIN_SCRIPTHOOK( C_BaseEntity::g_Hook_ModifyEmitSoundParams, "ModifyEmitSoundParams", FIELD_VOID, "Called every time a sound is emitted on this entity, allowing for its parameters to be modified." )
DEFINE_SCRIPTHOOK_PARAM( "params", FIELD_HSCRIPT )
END_SCRIPTHOOK()
#endif // MAPBASE_VSCRIPT
END_SCRIPTDESC();
#ifndef NO_ENTITY_PREDICTION
@ -507,6 +598,7 @@ BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
RecvPropInt(RECVINFO(m_clrRender)),
#ifdef MAPBASE
RecvPropInt(RECVINFO(m_iViewHideFlags)),
RecvPropBool(RECVINFO(m_bDisableFlashlight)),
#endif
RecvPropInt(RECVINFO(m_iTeamNum)),
RecvPropInt(RECVINFO(m_CollisionGroup)),
@ -1272,8 +1364,23 @@ void C_BaseEntity::Term()
if ( m_hScriptInstance )
{
#ifdef MAPBASE_VSCRIPT
if ( m_ScriptScope.IsInitialized() && g_Hook_UpdateOnRemove.CanRunInScope( m_ScriptScope ) )
{
g_Hook_UpdateOnRemove.Call( m_ScriptScope, NULL, NULL );
}
#endif
g_pScriptVM->RemoveInstance( m_hScriptInstance );
m_hScriptInstance = NULL;
#ifdef MAPBASE_VSCRIPT
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
if ( h ) g_pScriptVM->ReleaseScript( h );
}
m_ScriptThinkFuncs.PurgeAndDeleteElements();
#endif
}
}
@ -1611,6 +1718,11 @@ bool C_BaseEntity::ShouldReceiveProjectedTextures( int flags )
if ( IsEffectActive( EF_NODRAW ) )
return false;
#ifdef MAPBASE
if ( m_bDisableFlashlight )
return false;
#endif
if( flags & SHADOW_FLAGS_FLASHLIGHT )
{
if ( GetRenderMode() > kRenderNormal && GetRenderColor().a == 0 )
@ -4829,9 +4941,15 @@ C_BaseEntity *C_BaseEntity::Instance( int iEnt )
}
#ifdef WIN32
#if _MSC_VER < 1900
#pragma warning( push )
#include <typeinfo.h>
#pragma warning( pop )
#else
#include <typeinfo>
#endif
#endif
//-----------------------------------------------------------------------------
@ -6069,6 +6187,9 @@ BEGIN_DATADESC_NO_BASE( C_BaseEntity )
DEFINE_FIELD( m_angAbsRotation, FIELD_VECTOR ),
DEFINE_ARRAY( m_rgflCoordinateFrame, FIELD_FLOAT, 12 ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore)
DEFINE_FIELD( m_fFlags, FIELD_INTEGER ),
#ifdef MAPBASE_VSCRIPT
DEFINE_FIELD( m_iszScriptId, FIELD_STRING ),
#endif
END_DATADESC()
//-----------------------------------------------------------------------------

View File

@ -162,6 +162,15 @@ struct thinkfunc_t
int m_nLastThinkTick;
};
#ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t
{
float m_flNextThink;
HSCRIPT m_hfnThink;
unsigned m_iContextHash;
};
#endif
#define CREATE_PREDICTED_ENTITY( className ) \
C_BaseEntity::CreatePredictedEntityByName( className, __FILE__, __LINE__ );
@ -267,6 +276,7 @@ public:
bool ValidateScriptScope();
bool CallScriptFunction( const char* pFunctionName, ScriptVariant_t* pFunctionReturn );
HSCRIPT GetOrCreatePrivateScriptScope();
HSCRIPT GetScriptScope() { return m_ScriptScope; }
HSCRIPT LookupScriptFunction(const char* pFunctionName);
@ -276,12 +286,18 @@ public:
bool RunScript( const char* pScriptText, const char* pDebugFilename = "C_BaseEntity::RunScript" );
#endif
HSCRIPT GetScriptOwnerEntity();
virtual void SetScriptOwnerEntity(HSCRIPT pOwner);
HSCRIPT GetScriptInstance();
HSCRIPT m_hScriptInstance;
string_t m_iszScriptId;
#ifdef MAPBASE_VSCRIPT
CScriptScope m_ScriptScope;
static ScriptHook_t g_Hook_UpdateOnRemove;
static ScriptHook_t g_Hook_ModifyEmitSoundParams;
#endif
// IClientUnknown overrides.
@ -388,7 +404,7 @@ public:
#ifdef MAPBASE_VSCRIPT
// "I don't know why but wrapping entindex() works, while calling it directly crashes."
inline int C_BaseEntity::GetEntityIndex() const { return entindex(); }
inline int GetEntityIndex() const { return entindex(); }
#endif
// This works for client-only entities and returns the GetEntryIndex() of the entity's handle,
@ -1153,6 +1169,11 @@ public:
bool IsFollowingEntity();
CBaseEntity *GetFollowedEntity();
#ifdef MAPBASE_VSCRIPT
void ScriptFollowEntity( HSCRIPT hBaseEntity, bool bBoneMerge );
HSCRIPT ScriptGetFollowedEntity();
#endif
// For shadows rendering the correct body + sequence...
virtual int GetBody() { return 0; }
virtual int GetSkin() { return 0; }
@ -1168,21 +1189,46 @@ public:
#ifdef MAPBASE_VSCRIPT
const char* ScriptGetModelName( void ) const { return STRING(GetModelName()); }
void ScriptStopSound(const char* soundname);
void ScriptEmitSound(const char* soundname);
float ScriptSoundDuration(const char* soundname, const char* actormodel);
void VScriptPrecacheScriptSound(const char* soundname);
const Vector& ScriptEyePosition(void) { static Vector vec; vec = EyePosition(); return vec; }
const Vector& ScriptGetAngles(void) { static Vector vec; QAngle qa = GetAbsAngles(); vec.x = qa.x; vec.y = qa.y; vec.z = qa.z; return vec; }
const QAngle& ScriptEyeAngles(void) { static QAngle ang; ang = EyeAngles(); return ang; }
void ScriptSetForward( const Vector& v ) { QAngle angles; VectorAngles( v, angles ); SetAbsAngles( angles ); }
const Vector& ScriptGetBoundingMins( void ) { return m_Collision.OBBMins(); }
const Vector& ScriptGetBoundingMaxs( void ) { return m_Collision.OBBMaxs(); }
HSCRIPT ScriptEntityToWorldTransform( void );
HSCRIPT ScriptGetPhysicsObject( void );
void ScriptSetParent( HSCRIPT hParent, const char *szAttachment );
HSCRIPT ScriptGetMoveParent( void );
HSCRIPT ScriptGetRootMoveParent();
HSCRIPT ScriptFirstMoveChild( void );
HSCRIPT ScriptNextMovePeer( void );
const Vector& ScriptGetColorVector();
int ScriptGetColorR() { return m_clrRender.GetR(); }
int ScriptGetColorG() { return m_clrRender.GetG(); }
int ScriptGetColorB() { return m_clrRender.GetB(); }
int ScriptGetAlpha() { return m_clrRender.GetA(); }
void ScriptSetColorVector( const Vector& vecColor );
void ScriptSetColor( int r, int g, int b );
void ScriptSetColorR( int iVal ) { SetRenderColorR( iVal ); }
void ScriptSetColorG( int iVal ) { SetRenderColorG( iVal ); }
void ScriptSetColorB( int iVal ) { SetRenderColorB( iVal ); }
void ScriptSetAlpha( int iVal ) { SetRenderColorA( iVal ); }
int ScriptGetRenderMode() { return GetRenderMode(); }
void ScriptSetRenderMode( int nRenderMode ) { SetRenderMode( (RenderMode_t)nRenderMode ); }
int ScriptGetMoveType() { return GetMoveType(); }
void ScriptSetMoveType( int iMoveType ) { SetMoveType( (MoveType_t)iMoveType ); }
#endif
// Stubs on client
@ -1222,7 +1268,7 @@ public:
#ifdef _DEBUG
void FunctionCheck( void *pFunction, const char *name );
ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name )
ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, const char *name )
{
//COMPILE_TIME_ASSERT( sizeof(func) == 4 );
m_pfnTouch = func;
@ -1359,6 +1405,7 @@ public:
#ifdef MAPBASE
int m_iViewHideFlags;
bool m_bDisableFlashlight;
#endif
private:
@ -1500,6 +1547,15 @@ protected:
CUtlVector< thinkfunc_t > m_aThinkFunctions;
int m_iCurrentThinkContext;
#ifdef MAPBASE_VSCRIPT
public:
void ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float time );
void ScriptContextThink();
private:
CUtlVector< scriptthinkfunc_t* > m_ScriptThinkFuncs;
public:
#endif
// Object eye position
Vector m_vecViewOffset;

View File

@ -15,7 +15,7 @@
#include "ammodef.h"
#include "vprof.h"
#include "view.h"
#include "vstdlib/ikeyvaluessystem.h"
#include "vstdlib/IKeyValuesSystem.h"
#ifdef MAPBASE
#include "usermessages.h"
#endif
@ -666,7 +666,8 @@ void CIconLesson::UpdateInactive()
CUtlBuffer msg_data;
msg_data.PutChar( 1 );
msg_data.PutString( m_szHudHint.String() );
usermessages->DispatchUserMessage( usermessages->LookupUserMessage( "KeyHintText" ), bf_read( msg_data.Base(), msg_data.TellPut() ) );
bf_read msg( msg_data.Base(), msg_data.TellPut() );
usermessages->DispatchUserMessage( usermessages->LookupUserMessage( "KeyHintText" ), msg );
}
#endif
@ -1039,40 +1040,40 @@ Vector CIconLesson::GetIconTargetPosition( C_BaseEntity *pIconTarget )
#define LESSON_VARIABLE_INIT_SYMBOL( _varEnum, _varName, _varType ) g_n##_varEnum##Symbol = KeyValuesSystem()->GetSymbolForString( #_varEnum );
#define LESSON_SCRIPT_STRING_ADD_TO_MAP( _varEnum, _varName, _varType ) g_NameToTypeMap.Insert( #_varEnum, LESSON_VARIABLE_##_varEnum## );
#define LESSON_SCRIPT_STRING_ADD_TO_MAP( _varEnum, _varName, _varType ) g_NameToTypeMap.Insert( #_varEnum, LESSON_VARIABLE_##_varEnum );
// Create enum value
#define LESSON_VARIABLE_ENUM( _varEnum, _varName, _varType ) LESSON_VARIABLE_##_varEnum##,
#define LESSON_VARIABLE_ENUM( _varEnum, _varName, _varType ) LESSON_VARIABLE_##_varEnum,
// Init info call
#define LESSON_VARIABLE_INIT_INFO_CALL( _varEnum, _varName, _varType ) g_pLessonVariableInfo[ LESSON_VARIABLE_##_varEnum## ].Init_##_varEnum##();
#define LESSON_VARIABLE_INIT_INFO_CALL( _varEnum, _varName, _varType ) g_pLessonVariableInfo[ LESSON_VARIABLE_##_varEnum ].Init_##_varEnum();
// Init info
#define LESSON_VARIABLE_INIT_INFO( _varEnum, _varName, _varType ) \
void Init_##_varEnum##() \
void Init_##_varEnum() \
{ \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::##_varName## ); \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
varType = LessonParamTypeFromString( #_varType ); \
}
#define LESSON_VARIABLE_INIT_INFO_BOOL( _varEnum, _varName, _varType ) \
void Init_##_varEnum##() \
void Init_##_varEnum() \
{ \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::##_varName## ); \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
varType = FIELD_BOOLEAN; \
}
#define LESSON_VARIABLE_INIT_INFO_EHANDLE( _varEnum, _varName, _varType ) \
void Init_##_varEnum##() \
void Init_##_varEnum() \
{ \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::##_varName## ); \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
varType = FIELD_EHANDLE; \
}
#define LESSON_VARIABLE_INIT_INFO_STRING( _varEnum, _varName, _varType ) \
void Init_##_varEnum##() \
void Init_##_varEnum() \
{ \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::##_varName## ); \
iOffset = offsetof( CScriptedIconLesson, CScriptedIconLesson::_varName ); \
varType = FIELD_STRING; \
}
@ -1094,15 +1095,15 @@ Vector CIconLesson::GetIconTargetPosition( C_BaseEntity *pIconTarget )
// Process the element action on this variable
#define PROCESS_LESSON_ACTION( _varEnum, _varName, _varType ) \
case LESSON_VARIABLE_##_varEnum##:\
case LESSON_VARIABLE_##_varEnum:\
return ProcessElementAction( pLessonElement->iAction, pLessonElement->bNot, #_varName, _varName, &pLessonElement->szParam, eventParam_float );
#define PROCESS_LESSON_ACTION_EHANDLE( _varEnum, _varName, _varType ) \
case LESSON_VARIABLE_##_varEnum##:\
case LESSON_VARIABLE_##_varEnum:\
return ProcessElementAction( pLessonElement->iAction, pLessonElement->bNot, #_varName, _varName, &pLessonElement->szParam, eventParam_float, eventParam_BaseEntity, eventParam_string );
#define PROCESS_LESSON_ACTION_STRING( _varEnum, _varName, _varType ) \
case LESSON_VARIABLE_##_varEnum##:\
case LESSON_VARIABLE_##_varEnum:\
return ProcessElementAction( pLessonElement->iAction, pLessonElement->bNot, #_varName, &_varName, &pLessonElement->szParam, eventParam_string );
// Init the variable from the script (or a convar)
@ -2957,7 +2958,7 @@ bool CScriptedIconLesson::ProcessElementAction( int iAction, bool bNot, const ch
{
if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
{
ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->HealthFraction() ", pchVarName, pchVarName );
ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->HealthFraction() ", pchVarName );
ConColorMsg( CBaseLesson::m_rgbaVerboseName, "... " );
ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );
@ -2969,7 +2970,7 @@ bool CScriptedIconLesson::ProcessElementAction( int iAction, bool bNot, const ch
if ( gameinstructor_verbose.GetInt() > 0 && ShouldShowSpew() )
{
ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->HealthFraction() ", pchVarName, pchVarName );
ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, "\t[%s]->HealthFraction() ", pchVarName );
ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f ", pVar->HealthFraction() );
ConColorMsg( CBaseLesson::m_rgbaVerbosePlain, ( bNot ) ? ( ">= [%s] " ) : ( "< [%s] " ), pchParamName->String() );
ConColorMsg( CBaseLesson::m_rgbaVerboseName, "%f\n", fParam );

View File

@ -426,7 +426,7 @@ private:
LessonEvent_t * AddUpdateEvent( void );
private:
static CUtlDict< int, int > CScriptedIconLesson::LessonActionMap;
static CUtlDict< int, int > LessonActionMap;
EHANDLE m_hLocalPlayer;
float m_fOutput;

View File

@ -284,6 +284,7 @@ END_RECV_TABLE()
RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ),
RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ),
RecvPropBool ( RECVINFO( m_bInTriggerFall ) ),
#endif
END_RECV_TABLE()
@ -334,7 +335,10 @@ END_RECV_TABLE()
RecvPropString( RECVINFO(m_szLastPlaceName) ),
RecvPropEHandle(RECVINFO(m_hPostProcessCtrl)), // Send to everybody - for spectating
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropEHandle( RECVINFO( m_hPostProcessCtrl ) ), // Send to everybody - for spectating
RecvPropEHandle( RECVINFO( m_hColorCorrectionCtrl ) ), // Send to everybody - for spectating
#endif
#if defined USES_ECON_ITEMS
RecvPropUtlVector( RECVINFO_UTLVECTOR( m_hMyWearables ), MAX_WEARABLES_SENT_FROM_SERVER, RecvPropEHandle(NULL, 0, 0) ),
@ -496,14 +500,14 @@ C_BasePlayer::~C_BasePlayer()
if ( this == s_pLocalPlayer )
{
s_pLocalPlayer = NULL;
}
#ifdef MAPBASE_VSCRIPT
if ( IsLocalPlayer() && g_pScriptVM )
{
g_pScriptVM->SetValue( "player", SCRIPT_VARIANT_NULL );
}
if ( g_pScriptVM )
{
g_pScriptVM->SetValue( "player", SCRIPT_VARIANT_NULL );
}
#endif
}
delete m_pFlashlight;
}
@ -861,6 +865,14 @@ void C_BasePlayer::PostDataUpdate( DataUpdateType_t updateType )
// changed level, which would cause the snd_soundmixer to be left modified.
ConVar *pVar = (ConVar *)cvar->FindVar( "snd_soundmixer" );
pVar->Revert();
#ifdef MAPBASE_VSCRIPT
// Moved here from LevelInitPostEntity, which is executed before local player is spawned.
if ( g_pScriptVM )
{
g_pScriptVM->SetValue( "player", GetScriptInstance() );
}
#endif
}
}
@ -1373,6 +1385,10 @@ void C_BasePlayer::AddEntity( void )
// Add in lighting effects
CreateLightEffects();
#ifdef MAPBASE
SetLocalAnglesDim( X_INDEX, 0 );
#endif
}
extern float UTIL_WaterLevel( const Vector &position, float minz, float maxz );
@ -1495,8 +1511,9 @@ int C_BasePlayer::DrawModel( int flags )
if (m_bDrawPlayerModelExternally)
{
// Draw the player in any view except the main or "intro" view, both of which are default first-person views.
// HACKHACK: Also don't draw in shadow depth textures if the player's flashlight is on, as that causes the playermodel to block it.
view_id_t viewID = CurrentViewID();
if (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA)
if (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA || (viewID == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT)))
{
// Make sure the player model wouldn't draw anyway...
if (!ShouldDrawThisPlayer())
@ -1519,6 +1536,38 @@ int C_BasePlayer::DrawModel( int flags )
return BaseClass::DrawModel( flags );
}
#ifdef MAPBASE
ConVar cl_player_allow_thirdperson_projtex( "cl_player_allow_thirdperson_projtex", "1", FCVAR_NONE, "Allows players to receive projected textures if they're non-local or in third person." );
ConVar cl_player_allow_thirdperson_rttshadows( "cl_player_allow_thirdperson_rttshadows", "0", FCVAR_NONE, "Allows players to cast RTT shadows if they're non-local or in third person." );
ConVar cl_player_allow_firstperson_projtex( "cl_player_allow_firstperson_projtex", "1", FCVAR_NONE, "Allows players to receive projected textures even if they're in first person." );
ConVar cl_player_allow_firstperson_rttshadows( "cl_player_allow_firstperson_rttshadows", "0", FCVAR_NONE, "Allows players to cast RTT shadows even if they're in first person." );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ShadowType_t C_BasePlayer::ShadowCastType()
{
if ( (!IsLocalPlayer() || ShouldDraw()) ? !cl_player_allow_thirdperson_rttshadows.GetBool() : !cl_player_allow_firstperson_rttshadows.GetBool() )
return SHADOWS_NONE;
if ( !IsVisible() )
return SHADOWS_NONE;
return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC;
}
//-----------------------------------------------------------------------------
// Should this object receive shadows?
//-----------------------------------------------------------------------------
bool C_BasePlayer::ShouldReceiveProjectedTextures( int flags )
{
if ( (!IsLocalPlayer() || ShouldDraw()) ? !cl_player_allow_thirdperson_projtex.GetBool() : !cl_player_allow_firstperson_projtex.GetBool() )
return false;
return BaseClass::ShouldReceiveProjectedTextures( flags );
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -2934,6 +2983,7 @@ void C_BasePlayer::UpdateFogBlend( void )
}
}
#ifdef MAPBASE // From Alien Swarm SDK
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
@ -2942,6 +2992,15 @@ C_PostProcessController* C_BasePlayer::GetActivePostProcessController() const
return m_hPostProcessCtrl.Get();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
C_ColorCorrection* C_BasePlayer::GetActiveColorCorrection() const
{
return m_hColorCorrectionCtrl.Get();
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------

View File

@ -23,7 +23,10 @@
#include "hintsystem.h"
#include "SoundEmitterSystem/isoundemittersystembase.h"
#include "c_env_fog_controller.h"
#ifdef MAPBASE // From Alien Swarm SDK
#include "c_postprocesscontroller.h"
#include "c_colorcorrection.h"
#endif
#include "igameevents.h"
#include "GameEventListener.h"
@ -204,6 +207,11 @@ public:
void SetMaxSpeed( float flMaxSpeed ) { m_flMaxspeed = flMaxSpeed; }
float MaxSpeed() const { return m_flMaxspeed; }
#ifdef MAPBASE
// See c_baseplayer.cpp
virtual ShadowType_t ShadowCastType();
virtual bool ShouldReceiveProjectedTextures( int flags );
#else
// Should this object cast shadows?
virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; }
@ -211,6 +219,7 @@ public:
{
return false;
}
#endif
bool IsLocalPlayer( void ) const;
@ -381,7 +390,10 @@ public:
void UpdateFogController( void );
void UpdateFogBlend( void );
#ifdef MAPBASE // From Alien Swarm SDK
C_PostProcessController* GetActivePostProcessController() const;
C_ColorCorrection* GetActiveColorCorrection() const;
#endif
float GetFOVTime( void ){ return m_flFOVTime; }
@ -458,6 +470,8 @@ public:
// Allows the player's model to draw on non-main views, like monitors or mirrors.
bool m_bDrawPlayerModelExternally;
bool m_bInTriggerFall;
#endif
protected:
@ -646,7 +660,10 @@ private:
// One for left and one for right side of step
StepSoundCache_t m_StepSoundCache[ 2 ];
CNetworkHandle(C_PostProcessController, m_hPostProcessCtrl); // active postprocessing controller
#ifdef MAPBASE // From Alien Swarm SDK
CNetworkHandle( C_PostProcessController, m_hPostProcessCtrl ); // active postprocessing controller
CNetworkHandle( C_ColorCorrection, m_hColorCorrectionCtrl ); // active FXVolume color correction
#endif
public:

View File

@ -35,7 +35,7 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef CSTRIKE_DLL
#if defined(CSTRIKE_DLL) || defined (MAPBASE)
ConVar cl_righthand( "cl_righthand", "1", FCVAR_ARCHIVE, "Use right-handed view models." );
#endif
@ -197,7 +197,7 @@ bool C_BaseViewModel::Interpolate( float currentTime )
bool C_BaseViewModel::ShouldFlipViewModel()
{
#ifdef CSTRIKE_DLL
#if defined(CSTRIKE_DLL) || defined (MAPBASE)
// If cl_righthand is set, then we want them all right-handed.
CBaseCombatWeapon *pWeapon = m_hWeapon.Get();
if ( pWeapon )

View File

@ -6,6 +6,7 @@
//===========================================================================//
#include "cbase.h"
#include "c_colorcorrection.h"
#include "filesystem.h"
#include "cdll_client_int.h"
#include "colorcorrectionmgr.h"
@ -17,45 +18,27 @@
static ConVar mat_colcorrection_disableentities( "mat_colcorrection_disableentities", "0", FCVAR_NONE, "Disable map color-correction entities" );
//------------------------------------------------------------------------------
// Purpose : Color correction entity with radial falloff
//------------------------------------------------------------------------------
class C_ColorCorrection : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_ColorCorrection();
virtual ~C_ColorCorrection();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
void ClientThink();
private:
Vector m_vecOrigin;
float m_minFalloff;
float m_maxFalloff;
float m_flCurWeight;
char m_netLookupFilename[MAX_PATH];
bool m_bEnabled;
ClientCCHandle_t m_CCHandle;
};
#ifdef MAPBASE // From Alien Swarm SDK
static ConVar mat_colcorrection_forceentitiesclientside( "mat_colcorrection_forceentitiesclientside", "0", FCVAR_CHEAT, "Forces color correction entities to be updated on the client" );
#endif
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrection, DT_ColorCorrection, CColorCorrection)
RecvPropVector( RECVINFO(m_vecOrigin) ),
RecvPropFloat( RECVINFO(m_minFalloff) ),
RecvPropFloat( RECVINFO(m_maxFalloff) ),
RecvPropFloat( RECVINFO(m_flCurWeight) ),
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropFloat( RECVINFO(m_flMaxWeight) ),
RecvPropFloat( RECVINFO(m_flFadeInDuration) ),
RecvPropFloat( RECVINFO(m_flFadeOutDuration) ),
#endif
RecvPropString( RECVINFO(m_netLookupFilename) ),
RecvPropBool( RECVINFO(m_bEnabled) ),
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropBool( RECVINFO(m_bMaster) ),
RecvPropBool( RECVINFO(m_bClientSide) ),
RecvPropBool( RECVINFO(m_bExclusive) )
#endif
END_RECV_TABLE()
@ -65,14 +48,43 @@ END_RECV_TABLE()
//------------------------------------------------------------------------------
C_ColorCorrection::C_ColorCorrection()
{
#ifdef MAPBASE // From Alien Swarm SDK
m_minFalloff = -1.0f;
m_maxFalloff = -1.0f;
m_flFadeInDuration = 0.0f;
m_flFadeOutDuration = 0.0f;
m_flCurWeight = 0.0f;
m_flMaxWeight = 1.0f;
m_netLookupFilename[0] = '\0';
m_bEnabled = false;
m_bMaster = false;
m_bExclusive = false;
#endif
m_CCHandle = INVALID_CLIENT_CCHANDLE;
#ifdef MAPBASE // From Alien Swarm SDK
m_bFadingIn = false;
m_flFadeStartWeight = 0.0f;
m_flFadeStartTime = 0.0f;
m_flFadeDuration = 0.0f;
#endif
}
C_ColorCorrection::~C_ColorCorrection()
{
#ifdef MAPBASE // From Alien Swarm SDK
g_pColorCorrectionMgr->RemoveColorCorrectionEntity( this, m_CCHandle );
#else
g_pColorCorrectionMgr->RemoveColorCorrection( m_CCHandle );
#endif
}
#ifdef MAPBASE // From Alien Swarm SDK
bool C_ColorCorrection::IsClientSide() const
{
return m_bClientSide || mat_colcorrection_forceentitiesclientside.GetBool();
}
#endif
//------------------------------------------------------------------------------
// Purpose :
@ -87,11 +99,21 @@ void C_ColorCorrection::OnDataChanged(DataUpdateType_t updateType)
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
#ifdef MAPBASE // From Alien Swarm SDK
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_netLookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionEntity( this, name, m_netLookupFilename );
#else
char filename[MAX_PATH];
Q_strncpy( filename, m_netLookupFilename, MAX_PATH );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrection( filename );
SetNextClientThink( ( m_CCHandle != INVALID_CLIENT_CCHANDLE ) ? CLIENT_THINK_ALWAYS : CLIENT_THINK_NEVER );
#endif
}
}
}
@ -104,6 +126,129 @@ bool C_ColorCorrection::ShouldDraw()
return false;
}
#ifdef MAPBASE // From Alien Swarm SDK
void C_ColorCorrection::Update( C_BasePlayer *pPlayer, float ccScale )
{
Assert( m_CCHandle != INVALID_CLIENT_CCHANDLE );
if ( mat_colcorrection_disableentities.GetInt() )
{
// Allow the colorcorrectionui panel (or user) to turn off color-correction entities
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
// fade weight on client
if ( IsClientSide() )
{
m_flCurWeight = Lerp( GetFadeRatio(), m_flFadeStartWeight, m_bFadingIn ? m_flMaxWeight : 0.0f );
}
if( !m_bEnabled && m_flCurWeight == 0.0f )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, 0.0f, m_bExclusive );
return;
}
Vector playerOrigin = pPlayer->GetAbsOrigin();
float weight = 0;
if ( ( m_minFalloff != -1 ) && ( m_maxFalloff != -1 ) && m_minFalloff != m_maxFalloff )
{
float dist = (playerOrigin - m_vecOrigin).Length();
weight = (dist-m_minFalloff) / (m_maxFalloff-m_minFalloff);
if ( weight<0.0f ) weight = 0.0f;
if ( weight>1.0f ) weight = 1.0f;
}
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_flCurWeight * ( 1.0 - weight ) * ccScale, m_bExclusive );
}
void C_ColorCorrection::EnableOnClient( bool bEnable, bool bSkipFade )
{
if ( !IsClientSide() )
{
return;
}
m_bFadingIn = bEnable;
// initialize countdown timer
m_flFadeStartWeight = m_flCurWeight;
float flFadeTimeScale = 1.0f;
if ( m_flMaxWeight != 0.0f )
{
flFadeTimeScale = m_flCurWeight / m_flMaxWeight;
}
if ( m_bFadingIn )
{
flFadeTimeScale = 1.0f - flFadeTimeScale;
}
if ( bSkipFade )
{
flFadeTimeScale = 0.0f;
}
StartFade( flFadeTimeScale * ( m_bFadingIn ? m_flFadeInDuration : m_flFadeOutDuration ) );
// update the clientside weight once here, in case the fade duration is 0
m_flCurWeight = Lerp( GetFadeRatio(), m_flFadeStartWeight, m_bFadingIn ? m_flMaxWeight : 0.0f );
}
Vector C_ColorCorrection::GetOrigin()
{
return m_vecOrigin;
}
float C_ColorCorrection::GetMinFalloff()
{
return m_minFalloff;
}
float C_ColorCorrection::GetMaxFalloff()
{
return m_maxFalloff;
}
void C_ColorCorrection::SetWeight( float fWeight )
{
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, fWeight, false );
}
void C_ColorCorrection::StartFade( float flDuration )
{
m_flFadeStartTime = gpGlobals->curtime;
m_flFadeDuration = MAX( flDuration, 0.0f );
}
float C_ColorCorrection::GetFadeRatio() const
{
float flRatio = 1.0f;
if ( m_flFadeDuration != 0.0f )
{
flRatio = ( gpGlobals->curtime - m_flFadeStartTime ) / m_flFadeDuration;
flRatio = clamp( flRatio, 0.0f, 1.0f );
}
return flRatio;
}
bool C_ColorCorrection::IsFadeTimeElapsed() const
{
return ( ( gpGlobals->curtime - m_flFadeStartTime ) > m_flFadeDuration ) ||
( ( gpGlobals->curtime - m_flFadeStartTime ) < 0.0f );
}
void UpdateColorCorrectionEntities( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrection **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}
#else
void C_ColorCorrection::ClientThink()
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
@ -141,6 +286,7 @@ void C_ColorCorrection::ClientThink()
BaseClass::ClientThink();
}
#endif

View File

@ -0,0 +1,88 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Note that this header exists in the Alien Swarm SDK, but not in stock Source SDK 2013.
// Although technically a new Mapbase file, it only serves to move otherwise identical code,
// so most code and repo conventions will pretend it was always there.
//
// --------------------------------------------------------------------
//
// Purpose: Color correction entity with simple radial falloff
//
//=============================================================================//
#ifndef C_COLORCORRECTION_H
#define C_COLORCORRECTION_H
#ifdef _WIN32
#pragma once
#endif
#include "colorcorrectionmgr.h"
//------------------------------------------------------------------------------
// Purpose : Color correction entity with radial falloff
//------------------------------------------------------------------------------
class C_ColorCorrection : public C_BaseEntity
{
public:
DECLARE_CLASS( C_ColorCorrection, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_ColorCorrection();
virtual ~C_ColorCorrection();
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
#ifdef MAPBASE // From Alien Swarm SDK
virtual void Update(C_BasePlayer *pPlayer, float ccScale);
bool IsMaster() const { return m_bMaster; }
bool IsClientSide() const;
bool IsExclusive() const { return m_bExclusive; }
void EnableOnClient( bool bEnable, bool bSkipFade = false );
Vector GetOrigin();
float GetMinFalloff();
float GetMaxFalloff();
void SetWeight( float fWeight );
protected:
void StartFade( float flDuration );
float GetFadeRatio() const;
bool IsFadeTimeElapsed() const;
#else
void ClientThink();
private:
#endif
Vector m_vecOrigin;
float m_minFalloff;
float m_maxFalloff;
float m_flCurWeight;
char m_netLookupFilename[MAX_PATH];
bool m_bEnabled;
#ifdef MAPBASE // From Alien Swarm SDK
float m_flFadeInDuration;
float m_flFadeOutDuration;
float m_flMaxWeight;
bool m_bMaster;
bool m_bClientSide;
bool m_bExclusive;
bool m_bFadingIn;
float m_flFadeStartWeight;
float m_flFadeStartTime;
float m_flFadeDuration;
#endif
ClientCCHandle_t m_CCHandle;
};
#endif

View File

@ -36,9 +36,26 @@ public:
void OnDataChanged(DataUpdateType_t updateType);
bool ShouldDraw();
#ifdef MAPBASE // From Alien Swarm SDK
void Update( C_BasePlayer *pPlayer, float ccScale );
void StartTouch( C_BaseEntity *pOther );
void EndTouch( C_BaseEntity *pOther );
#else
void ClientThink();
#endif
private:
#ifdef MAPBASE // From Alien Swarm SDK
float m_LastEnterWeight;
float m_LastEnterTime;
float m_LastExitWeight;
float m_LastExitTime;
bool m_bEnabled;
float m_MaxWeight;
float m_FadeDuration;
#endif
float m_Weight;
char m_lookupFilename[MAX_PATH];
@ -46,6 +63,11 @@ private:
};
IMPLEMENT_CLIENTCLASS_DT(C_ColorCorrectionVolume, DT_ColorCorrectionVolume, CColorCorrectionVolume)
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropBool( RECVINFO( m_bEnabled ) ),
RecvPropFloat( RECVINFO( m_MaxWeight ) ),
RecvPropFloat( RECVINFO( m_FadeDuration ) ),
#endif
RecvPropFloat( RECVINFO(m_Weight) ),
RecvPropString( RECVINFO(m_lookupFilename) ),
END_RECV_TABLE()
@ -82,11 +104,21 @@ void C_ColorCorrectionVolume::OnDataChanged(DataUpdateType_t updateType)
{
if ( m_CCHandle == INVALID_CLIENT_CCHANDLE )
{
#ifdef MAPBASE // From Alien Swarm SDK
// forming a unique name without extension
char cleanName[MAX_PATH];
V_StripExtension( m_lookupFilename, cleanName, sizeof( cleanName ) );
char name[MAX_PATH];
Q_snprintf( name, MAX_PATH, "%s_%d", cleanName, entindex() );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrectionVolume( this, name, m_lookupFilename );
#else
char filename[MAX_PATH];
Q_strncpy( filename, m_lookupFilename, MAX_PATH );
m_CCHandle = g_pColorCorrectionMgr->AddColorCorrection( filename );
SetNextClientThink( ( m_CCHandle != INVALID_CLIENT_CCHANDLE ) ? CLIENT_THINK_ALWAYS : CLIENT_THINK_NEVER );
#endif
}
}
}
@ -99,11 +131,95 @@ bool C_ColorCorrectionVolume::ShouldDraw()
return false;
}
#ifdef MAPBASE // From Alien Swarm SDK
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::StartTouch( CBaseEntity *pEntity )
{
m_LastEnterTime = gpGlobals->curtime;
m_LastEnterWeight = m_Weight;
}
//--------------------------------------------------------------------------------------------------------
void C_ColorCorrectionVolume::EndTouch( CBaseEntity *pEntity )
{
m_LastExitTime = gpGlobals->curtime;
m_LastExitWeight = m_Weight;
}
void C_ColorCorrectionVolume::Update( C_BasePlayer *pPlayer, float ccScale )
{
if ( pPlayer )
{
bool isTouching = CollisionProp()->IsPointInBounds( pPlayer->EyePosition() );
bool wasTouching = m_LastEnterTime > m_LastExitTime;
if ( isTouching && !wasTouching )
{
StartTouch( pPlayer );
}
else if ( !isTouching && wasTouching )
{
EndTouch( pPlayer );
}
}
if( !m_bEnabled )
{
m_Weight = 0.0f;
}
else
{
if( m_LastEnterTime > m_LastExitTime )
{
// we most recently entered the volume
if( m_Weight < 1.0f )
{
float dt = gpGlobals->curtime - m_LastEnterTime;
float weight = m_LastEnterWeight + dt / ((1.0f-m_LastEnterWeight)*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = weight;
}
}
else
{
// we most recently exitted the volume
if( m_Weight > 0.0f )
{
float dt = gpGlobals->curtime - m_LastExitTime;
float weight = (1.0f-m_LastExitWeight) + dt / (m_LastExitWeight*m_FadeDuration);
if( weight>1.0f )
weight = 1.0f;
m_Weight = 1.0f - weight;
}
}
}
// Vector entityPosition = GetAbsOrigin();
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight * ccScale );
}
void UpdateColorCorrectionVolumes( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrectionVolume **pList, int listCount )
{
for ( int i = 0; i < listCount; i++ )
{
pList[i]->Update(pPlayer, ccScale);
}
}
#else
void C_ColorCorrectionVolume::ClientThink()
{
Vector entityPosition = GetAbsOrigin();
g_pColorCorrectionMgr->SetColorCorrectionWeight( m_CCHandle, m_Weight );
}
#endif

View File

@ -40,7 +40,10 @@ ConVar r_RainSplashPercentage( "r_RainSplashPercentage", "20", FCVAR_CHEAT ); //
ConVar r_RainParticleDensity( "r_RainParticleDensity", "1", FCVAR_NONE, "Density of Particle Rain 0-1" );
#ifdef MAPBASE
ConVar r_RainParticleClampOffset( "r_RainParticleClampOffset", "112", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems" );
ConVar r_RainParticleClampOffset_Rain( "r_RainParticleClampOffset_Rain", "120", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Rain' type." );
ConVar r_RainParticleClampOffset_Ash( "r_RainParticleClampOffset_Ash", "300", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Ash' type." );
ConVar r_RainParticleClampOffset_RainStorm( "r_RainParticleClampOffset_RainStorm", "112", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Rain Storm' type." );
ConVar r_RainParticleClampOffset_Snow( "r_RainParticleClampOffset_Snow", "300", FCVAR_NONE, "How far inward or outward to extrude clamped precipitation particle systems using the 'Particle Snow' type." );
ConVar r_RainParticleClampDebug( "r_RainParticleClampDebug", "0", FCVAR_NONE, "Enables debug code for precipitation particle system clamping" );
#endif
@ -951,6 +954,70 @@ void CClient_Precipitation::CreateParticlePrecip( void )
UpdateParticlePrecip( pPlayer );
}
#ifdef MAPBASE
void CClient_Precipitation::ClampParticlePosition( Vector &vPlayerPos, Vector &vOffsetPos, Vector &vOffsetPosNear, Vector &vOffsetPosFar )
{
Vector mins, maxs;
modelinfo->GetModelBounds( GetModel(), mins, maxs );
// Account for precipitation height
maxs.z += 180;
Vector vecOrigin; //= WorldSpaceCenter();
VectorLerp( mins, maxs, 0.5f, vecOrigin );
maxs -= vecOrigin;
mins -= vecOrigin;
//float flMax = r_RainParticleClampOffset.GetFloat();
float flMax = 0;
switch (m_nPrecipType)
{
case PRECIPITATION_TYPE_PARTICLERAIN:
flMax = r_RainParticleClampOffset_Rain.GetFloat();
break;
case PRECIPITATION_TYPE_PARTICLEASH:
flMax = r_RainParticleClampOffset_Ash.GetFloat();
break;
case PRECIPITATION_TYPE_PARTICLERAINSTORM:
flMax = r_RainParticleClampOffset_RainStorm.GetFloat();
break;
case PRECIPITATION_TYPE_PARTICLESNOW:
flMax = r_RainParticleClampOffset_Snow.GetFloat();
break;
}
Vector addend( flMax, flMax, 0 );
mins += addend;
maxs -= addend;
if (flMax > 0)
{
// Unless this is extruding outwards, make sure the offset isn't inverting the bounds.
// This means precipitation triggers with bounds less than offset*2 will turn into a thin line
// and the involved precipitation will pretty much be spatial at all times, which is okay.
mins.x = clamp( mins.x, -FLT_MAX, -1 );
mins.y = clamp( mins.y, -FLT_MAX, -1 );
maxs.x = clamp( maxs.x, 1, FLT_MAX );
maxs.y = clamp( maxs.y, 1, FLT_MAX );
}
if (r_RainParticleClampDebug.GetBool())
debugoverlay->AddBoxOverlay( vecOrigin, mins, maxs, vec3_angle, 255, 0, 0, 128, 0.15f );
maxs += vecOrigin;
mins += vecOrigin;
CalcClosestPointOnAABB( mins, maxs, vPlayerPos, vPlayerPos );
CalcClosestPointOnAABB( mins, maxs, vOffsetPos, vOffsetPos );
CalcClosestPointOnAABB( mins, maxs, vOffsetPosNear, vOffsetPosNear );
CalcClosestPointOnAABB( mins, maxs, vOffsetPosFar, vOffsetPosFar );
}
#endif
void CClient_Precipitation::UpdateParticlePrecip( C_BasePlayer *pPlayer )
{
if ( !pPlayer )
@ -980,44 +1047,7 @@ void CClient_Precipitation::UpdateParticlePrecip( C_BasePlayer *pPlayer )
#ifdef MAPBASE
if (m_spawnflags & SF_PRECIP_PARTICLE_CLAMP)
{
Vector mins, maxs;
modelinfo->GetModelBounds( GetModel(), mins, maxs );
// Account for precipitation height
maxs.z += 180;
Vector vecOrigin; //= WorldSpaceCenter();
VectorLerp( mins, maxs, 0.5f, vecOrigin );
maxs -= vecOrigin;
mins -= vecOrigin;
float flMax = r_RainParticleClampOffset.GetFloat();
Vector addend( flMax, flMax, 0 );
mins += addend;
maxs -= addend;
if (flMax > 0)
{
// Unless this is extruding outwards, make sure the offset isn't inverting the bounds.
// This means precipitation triggers with bounds less than offset*2 will turn into a thin line
// and the involved precipitation will pretty much be spatial at all times, which is okay.
mins.x = clamp( mins.x, -FLT_MAX, -1 );
mins.y = clamp( mins.y, -FLT_MAX, -1 );
maxs.x = clamp( maxs.x, 1, FLT_MAX );
maxs.y = clamp( maxs.y, 1, FLT_MAX );
}
if (r_RainParticleClampDebug.GetBool())
debugoverlay->AddBoxOverlay( vecOrigin, mins, maxs, vec3_angle, 255, 0, 0, 128, 0.15f );
maxs += vecOrigin;
mins += vecOrigin;
CalcClosestPointOnAABB( mins, maxs, vPlayerPos, vPlayerPos );
CalcClosestPointOnAABB( mins, maxs, vOffsetPos, vOffsetPos );
CalcClosestPointOnAABB( mins, maxs, vOffsetPosNear, vOffsetPosNear );
CalcClosestPointOnAABB( mins, maxs, vOffsetPosFar, vOffsetPosFar );
ClampParticlePosition( vPlayerPos, vOffsetPos, vOffsetPosNear, vOffsetPosFar );
}
#endif
@ -1236,6 +1266,13 @@ void CClient_Precipitation::DispatchInnerParticlePrecip( C_BasePlayer *pPlayer,
Vector vOffsetPosFar = vPlayerPos + Vector ( 0, 0, 180 ) + ( vForward * m_flParticleInnerDist ); // 100.0
Vector vDensity = Vector( r_RainParticleDensity.GetFloat(), 0, 0 ) * m_flDensity;
#ifdef MAPBASE
if (m_spawnflags & SF_PRECIP_PARTICLE_CLAMP)
{
ClampParticlePosition( vPlayerPos, vOffsetPos, vOffsetPosNear, vOffsetPosFar );
}
#endif
#ifdef MAPBASE
if (!(m_spawnflags & SF_PRECIP_PARTICLE_NO_OUTER))
#endif

View File

@ -130,6 +130,10 @@ private:
void CreateAshParticle( void );
void CreateRainOrSnowParticle( Vector vSpawnPosition, Vector vVelocity );
#ifdef MAPBASE
void ClampParticlePosition( Vector &vPlayerPos, Vector &vOffsetPos, Vector &vOffsetPosNear, Vector &vOffsetPosFar );
#endif
// Information helpful in creating and rendering particles
IMaterial *m_MatHandle; // material used

View File

@ -25,6 +25,11 @@ ConVar cl_globallight_freeze( "cl_globallight_freeze", "0" );
// You can set these as KV anyway.
ConVar cl_globallight_xoffset( "cl_globallight_xoffset", "0" );
ConVar cl_globallight_yoffset( "cl_globallight_yoffset", "0" );
static ConVar cl_globallight_slopescaledepthbias_shadowmap( "cl_globallight_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
static ConVar cl_globallight_shadowfiltersize( "cl_globallight_shadowfiltersize", "0.1", FCVAR_CHEAT );
static ConVar cl_globallight_depthbias_shadowmap( "cl_globallight_depthbias_shadowmap", "0.00001", FCVAR_CHEAT );
static ConVar cl_globallight_depthres( "cl_globallight_depthres", "8192", FCVAR_CHEAT );
#else
ConVar cl_globallight_xoffset( "cl_globallight_xoffset", "-800" );
ConVar cl_globallight_yoffset( "cl_globallight_yoffset", "1600" );
@ -286,16 +291,21 @@ void C_GlobalLight::ClientThink()
state.m_bOrtho = false;
}
#ifndef MAPBASE // Don't draw that huge debug thing
#ifdef MAPBASE
//state.m_bDrawShadowFrustum = true; // Don't draw that huge debug thing
state.m_flShadowMapResolution = cl_globallight_depthres.GetFloat();
state.m_flShadowFilterSize = cl_globallight_shadowfiltersize.GetFloat();
state.m_flShadowSlopeScaleDepthBias = cl_globallight_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = cl_globallight_depthbias_shadowmap.GetFloat();
state.m_bEnableShadows = m_bEnableShadows;
state.m_pSpotlightTexture = m_SpotlightTexture;
state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
#else
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

View File

@ -25,8 +25,8 @@
#include "tier0/memdbgon.h"
#ifdef ASW_PROJECTED_TEXTURES
static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT );
static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.00001", FCVAR_CHEAT );
extern ConVarRef mat_slopescaledepthbias_shadowmap;
extern ConVarRef mat_depthbias_shadowmap;
float C_EnvProjectedTexture::m_flVisibleBBoxMinHeight = -FLT_MAX;
@ -60,6 +60,7 @@ IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvPro
RecvPropFloat( RECVINFO( m_flLinearAtten ) ),
RecvPropFloat( RECVINFO( m_flQuadraticAtten ) ),
RecvPropFloat( RECVINFO( m_flShadowAtten ) ),
RecvPropFloat( RECVINFO( m_flShadowFilter ) ),
RecvPropBool( RECVINFO( m_bAlwaysDraw ) ),
// Not needed on the client right now, change when it actually is needed
@ -97,6 +98,7 @@ C_EnvProjectedTexture *C_EnvProjectedTexture::Create( )
pEnt->m_flLinearAtten = 100.0f;
pEnt->m_flQuadraticAtten = 0.0f;
pEnt->m_flShadowAtten = 0.0f;
pEnt->m_flShadowFilter = 0.5f;
//pEnt->m_bProjectedTextureVersion = 1;
#endif
@ -283,6 +285,8 @@ void C_EnvProjectedTexture::UpdateLight( void )
// VectorNormalize( vRight );
// VectorNormalize( vUp );
VectorVectors( vForward, vRight, vUp );
}
}
else
@ -401,6 +405,7 @@ void C_EnvProjectedTexture::UpdateLight( void )
state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
state.m_flShadowAtten = m_flShadowAtten;
state.m_flShadowFilterSize = m_flShadowFilter;
#else
state.m_fQuadraticAtten = 0.0;
state.m_fLinearAtten = 100;

View File

@ -48,6 +48,9 @@ protected:
int m_iCachedDesiredOverlay;
int m_iCurrentOverlay;
float m_flCurrentOverlayTime;
#ifdef MAPBASE
int m_iOverlayIndex;
#endif
};
IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOverlay )
@ -56,6 +59,9 @@ IMPLEMENT_CLIENTCLASS_DT( C_EnvScreenOverlay, DT_EnvScreenOverlay, CEnvScreenOve
RecvPropFloat( RECVINFO( m_flStartTime ) ),
RecvPropInt( RECVINFO( m_iDesiredOverlay ) ),
RecvPropBool( RECVINFO( m_bIsActive ) ),
#ifdef MAPBASE
RecvPropInt( RECVINFO( m_iOverlayIndex ) ),
#endif
END_RECV_TABLE()
//-----------------------------------------------------------------------------
@ -77,7 +83,11 @@ void C_EnvScreenOverlay::PostDataUpdate( DataUpdateType_t updateType )
BaseClass::PostDataUpdate( updateType );
// If we have a start time now, start the overlays going
#ifdef MAPBASE
if ( m_bIsActive && m_flStartTime > 0 && (view->GetScreenOverlayMaterial() == NULL || (m_iOverlayIndex != -1 && view->GetIndexedScreenOverlayMaterial(m_iOverlayIndex) == NULL)) )
#else
if ( m_bIsActive && m_flStartTime > 0 && view->GetScreenOverlayMaterial() == NULL )
#endif
{
StartOverlays();
}
@ -111,7 +121,16 @@ void C_EnvScreenOverlay::StopOverlays( void )
if ( m_bWasActive && !m_bIsActive )
{
view->SetScreenOverlayMaterial( NULL );
#ifdef MAPBASE
if (m_iOverlayIndex != -1)
{
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, NULL );
}
else
#endif
{
view->SetScreenOverlayMaterial( NULL );
}
}
}
@ -163,7 +182,16 @@ void C_EnvScreenOverlay::StartCurrentOverlay( void )
IMaterial *pMaterial = materials->FindMaterial( m_iszOverlayNames[m_iCurrentOverlay], TEXTURE_GROUP_CLIENT_EFFECTS, false );
if ( !IsErrorMaterial( pMaterial ) )
{
view->SetScreenOverlayMaterial( pMaterial );
#ifdef MAPBASE
if (m_iOverlayIndex != -1)
{
view->SetIndexedScreenOverlayMaterial( m_iOverlayIndex, pMaterial );
}
else
#endif
{
view->SetScreenOverlayMaterial( pMaterial );
}
}
else
{

View File

@ -9,7 +9,7 @@
#include "GameEventListener.h"
#include "vgui_controls/phandle.h"
#include "vgui_controls/PHandle.h"
class CBaseLesson;

View File

@ -0,0 +1,27 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//
//=====================================================================================//
#include "cbase.h"
#include "c_movie_display.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
IMPLEMENT_CLIENTCLASS_DT( C_MovieDisplay, DT_MovieDisplay, CMovieDisplay )
RecvPropBool( RECVINFO( m_bEnabled ) ),
RecvPropBool( RECVINFO( m_bLooping ) ),
RecvPropBool( RECVINFO( m_bMuted ) ),
RecvPropString( RECVINFO( m_szMovieFilename ) ),
RecvPropString( RECVINFO( m_szGroupName ) ),
END_RECV_TABLE()
C_MovieDisplay::C_MovieDisplay()
{
}
C_MovieDisplay::~C_MovieDisplay()
{
}

View File

@ -0,0 +1,36 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#ifndef C_MOVIE_DISPLAY_H
#define C_MOVIE_DISPLAY_H
#include "cbase.h"
class C_MovieDisplay : public C_BaseEntity
{
public:
DECLARE_CLASS( C_MovieDisplay, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_MovieDisplay();
~C_MovieDisplay();
bool IsEnabled( void ) const { return m_bEnabled; }
bool IsLooping( void ) const { return m_bLooping; }
bool IsMuted(void) const { return m_bMuted; }
const char *GetMovieFilename( void ) const { return m_szMovieFilename; }
const char *GetGroupName( void ) const { return m_szGroupName; }
private:
bool m_bEnabled;
bool m_bLooping;
bool m_bMuted;
char m_szMovieFilename[128];
char m_szGroupName[128];
};
#endif //C_MOVIE_DISPLAY_H

View File

@ -42,6 +42,7 @@ protected:
EHANDLE m_hControlPointEnts[kMAXCONTROLPOINTS];
Vector m_vControlPointVecs[kMAXCONTROLPOINTS];
// SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ),
unsigned char m_iControlPointParents[kMAXCONTROLPOINTS];
@ -65,6 +66,7 @@ BEGIN_RECV_TABLE_NOBASE( C_ParticleSystem, DT_ParticleSystem )
RecvPropFloat( RECVINFO( m_flStartTime ) ),
RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY(m_vControlPointVecs), RecvPropVector( RECVINFO( m_vControlPointVecs[0] ) ) ),
RecvPropArray3( RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt( RECVINFO(m_iControlPointParents[0]))),
RecvPropBool( RECVINFO( m_bWeatherEffect ) ),
END_RECV_TABLE();
@ -150,21 +152,41 @@ void C_ParticleSystem::ClientThink( void )
AssertMsg1( pEffect, "Particle system couldn't make %s", pszName );
if (pEffect)
{
for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i )
if (m_vControlPointVecs[0] != GetAbsOrigin() && m_hControlPointEnts[0] == NULL)
{
CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get();
if ( pOnEntity )
// we are using info_particle_system_coordinate
for (int i = 0; i < kMAXCONTROLPOINTS; ++i)
{
ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
ParticleProp()->AddControlPoint(pEffect, i + 1, this, PATTACH_WORLDORIGIN, 0, m_vControlPointVecs[i] - GetAbsOrigin());
AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS,
"Particle system specified bogus control point parent (%d) for point %d.",
m_iControlPointParents[i], i);
if (m_iControlPointParents[i] != 0)
{
pEffect->SetControlPointParent(i + 1, m_iControlPointParents[i]);
}
}
AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS ,
"Particle system specified bogus control point parent (%d) for point %d.",
m_iControlPointParents[i], i );
if (m_iControlPointParents[i] != 0)
}
else
{
for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i )
{
pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]);
CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get();
if ( pOnEntity )
{
ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW );
}
AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS ,
"Particle system specified bogus control point parent (%d) for point %d.",
m_iControlPointParents[i], i );
if (m_iControlPointParents[i] != 0)
{
pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,11 @@ BEGIN_NETWORK_TABLE( CDynamicProp, DT_DynamicProp )
RecvPropBool(RECVINFO(m_bUseHitboxesForRenderBox)),
END_NETWORK_TABLE()
#ifdef MAPBASE_VSCRIPT
// Allows client-side VScript to create dynamic props via CreateProp()
LINK_ENTITY_TO_CLASS( prop_dynamic, C_DynamicProp );
#endif
C_DynamicProp::C_DynamicProp( void )
{
m_iCachedFrameCount = -1;

View File

@ -74,6 +74,27 @@ IMPLEMENT_CLIENTCLASS_DT_NOBASE( C_RopeKeyframe, DT_RopeKeyframe, CRopeKeyframe
RecvPropInt( RECVINFO( m_iParentAttachment ) ),
END_RECV_TABLE()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( C_RopeKeyframe, C_BaseEntity, "The clientside class of move_rope and keyframe_rope" )
DEFINE_SCRIPTFUNC( GetNodePosition, "Gets the position of the specified node index" )
DEFINE_SCRIPTFUNC( GetNumNodes, "Gets the number of nodes available" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetStartEntity, "GetStartEntity", "Gets the rope's start entity" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetEndEntity, "GetEndEntity", "Gets the rope's end entity" )
DEFINE_SCRIPTFUNC( SetupHangDistance, "Sets the rope's hang distance" )
DEFINE_SCRIPTFUNC( SetSlack, "Sets the rope's slack value (extra length)" )
DEFINE_SCRIPTFUNC( GetRopeFlags, "Gets the rope's flags" )
DEFINE_SCRIPTFUNC( SetRopeFlags, "Sets the rope's flags" )
DEFINE_SCRIPTFUNC( SetColorMod, "Sets the rope's color mod value" )
DEFINE_SCRIPTFUNC( ShakeRope, "Shakes the rope with the specified center, radius, and magnitude" )
DEFINE_SCRIPTFUNC( AnyPointsMoved, "Returns true if any points have moved recently" )
END_SCRIPTDESC();
#endif
#define ROPE_IMPULSE_SCALE 20
#define ROPE_IMPULSE_DECAY 0.95
@ -2032,6 +2053,25 @@ bool C_RopeKeyframe::GetAttachment( int number, Vector &origin, QAngle &angles )
return false;
}
#ifdef MAPBASE
const Vector &C_RopeKeyframe::GetNodePosition( int index )
{
int nNodes = m_RopePhysics.NumNodes();
if ( index >= nNodes || nNodes < 2 )
{
Warning( "C_RopeKeyframe::GetNodePosition(): Invalid node index %i (number of nodes is %i)\n", index, nNodes );
return vec3_origin;
}
return m_RopePhysics.GetNode( index )->m_vPredicted;
}
int C_RopeKeyframe::GetNumNodes()
{
return m_RopePhysics.NumNodes();
}
#endif
bool C_RopeKeyframe::AnyPointsMoved()
{
#ifdef MAPBASE

View File

@ -33,6 +33,9 @@ public:
DECLARE_CLASS( C_RopeKeyframe, C_BaseEntity );
DECLARE_CLIENTCLASS();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
private:
@ -142,6 +145,11 @@ public:
virtual bool GetAttachment( int number, Vector &origin );
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );
#ifdef MAPBASE
const Vector &GetNodePosition( int index );
int GetNumNodes();
#endif
private:
void FinishInit( const char *pMaterialName );
@ -166,6 +174,11 @@ private:
void ReceiveMessage( int classID, bf_read &msg );
bool CalculateEndPointAttachment( C_BaseEntity *pEnt, int iAttachment, Vector &vPos, QAngle *pAngles );
#ifdef MAPBASE_VSCRIPT
HSCRIPT ScriptGetStartEntity() { return ToHScript( GetStartEntity() ); }
HSCRIPT ScriptGetEndEntity() { return ToHScript( GetEndEntity() ); }
#endif
private:
// Track which links touched something last frame. Used to prevent wind from gusting on them.

View File

@ -112,6 +112,15 @@ public:
C_BasePlayer *GetPlayerOwner( void );
bool IsInputOnlyToOwner( void );
#ifdef MAPBASE
void GetSize( float &width, float &height ) const { width = m_flWidth; height = m_flHeight; }
void GetPixelSize( int &width, int &height ) const { width = m_nPixelWidth; height = m_nPixelHeight; }
void SetWidth( float flWidth ) { m_flWidth = flWidth; }
void SetHeight( float flHeight ) { m_flHeight = flHeight; }
void SetPixelWidth( int nWidth ) { m_nPixelWidth = nWidth; }
void SetPixelHeight( int nHeight ) { m_nPixelHeight = nHeight; }
#endif
private:
// Vgui screen management
void CreateVguiScreen( const char *pTypeName );

View File

@ -13,6 +13,9 @@
#include "ivieweffects.h"
#include "shake.h"
#include "eventlist.h"
#ifdef MAPBASE
#include "mapentities_shared.h"
#endif
// NVNT haptic include for notification of world precache
#include "haptics/haptic_utils.h"
// memdbgon must be the last include file in a .cpp file!!!
@ -62,9 +65,6 @@ BEGIN_RECV_TABLE( C_World, DT_World )
#ifdef MAPBASE
RecvPropString(RECVINFO(m_iszChapterTitle)),
#endif
#ifdef MAPBASE_VSCRIPT
RecvPropInt(RECVINFO(m_iScriptLanguageClient)),
#endif
END_RECV_TABLE()
#ifdef MAPBASE_VSCRIPT
@ -86,6 +86,11 @@ bool C_World::Init( int entnum, int iSerialNum )
ActivityList_Init();
EventList_Init();
#ifdef MAPBASE_VSCRIPT
m_iScriptLanguageServer = SL_NONE;
m_iScriptLanguageClient = SL_NONE;
#endif
return BaseClass::Init( entnum, iSerialNum );
}
@ -129,11 +134,6 @@ void C_World::OnDataChanged( DataUpdateType_t updateType )
engine->SetOcclusionParameters( params );
modelinfo->SetLevelScreenFadeRange( m_flMinPropScreenSpaceWidth, m_flMaxPropScreenSpaceWidth );
#ifdef MAPBASE_VSCRIPT
// This is now here so that C_World has time to receive the selected script language
VScriptClientInit();
#endif
}
}
@ -199,6 +199,72 @@ void C_World::Spawn( void )
Precache();
}
//-----------------------------------------------------------------------------
// Parse data from a map file
//-----------------------------------------------------------------------------
bool C_World::KeyValue( const char *szKeyName, const char *szValue )
{
#ifdef MAPBASE_VSCRIPT
if ( FStrEq( szKeyName, "vscriptlanguage" ) )
{
m_iScriptLanguageServer = atoi( szValue );
}
else if ( FStrEq( szKeyName, "vscriptlanguage_client" ) )
{
m_iScriptLanguageClient = atoi( szValue );
}
else
#endif
return BaseClass::KeyValue( szKeyName, szValue );
return true;
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Parses worldspawn data from BSP on the client
//-----------------------------------------------------------------------------
void C_World::ParseWorldMapData( const char *pMapData )
{
char szTokenBuffer[MAPKEY_MAXLENGTH];
for ( ; true; pMapData = MapEntity_SkipToNextEntity(pMapData, szTokenBuffer) )
{
//
// Parse the opening brace.
//
char token[MAPKEY_MAXLENGTH];
pMapData = MapEntity_ParseToken( pMapData, token );
//
// Check to see if we've finished or not.
//
if (!pMapData)
break;
if (token[0] != '{')
{
Error( "MapEntity_ParseAllEntities: found %s when expecting {", token);
continue;
}
CEntityMapData entData( (char*)pMapData );
char className[MAPKEY_MAXLENGTH];
if (!entData.ExtractValue( "classname", className ))
{
Error( "classname missing from entity!\n" );
}
if ( !Q_strcmp( className, "worldspawn" ) )
{
// Set up keyvalues.
ParseMapData( &entData );
return;
}
}
}
#endif
C_World *GetClientWorldEntity()

View File

@ -31,6 +31,7 @@ public:
virtual void Precache();
virtual void Spawn();
virtual bool KeyValue( const char *szKeyName, const char *szValue );
// Don't worry about adding the world to the collision list; it's already there
virtual CollideType_t GetCollideType( void ) { return ENTITY_SHOULD_NOT_COLLIDE; }
@ -41,8 +42,17 @@ public:
float GetWaveHeight() const;
const char *GetDetailSpriteMaterial() const;
#ifdef MAPBASE
// A special function which parses map data for the client world entity before LevelInitPreEntity().
// This can be used to access keyvalues early and without transmitting from the server.
void ParseWorldMapData( const char *pMapData );
#endif
#ifdef MAPBASE_VSCRIPT
ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)m_iScriptLanguageClient; }
void ClientThink() { ScriptContextThink(); }
// -2 = Use server language
ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)(m_iScriptLanguageClient != -2 ? m_iScriptLanguageClient : m_iScriptLanguageServer); }
#endif
public:
@ -64,6 +74,7 @@ public:
char m_iszChapterTitle[64];
#endif
#ifdef MAPBASE_VSCRIPT
int m_iScriptLanguageServer;
int m_iScriptLanguageClient;
#endif

View File

@ -148,6 +148,10 @@
#include "fbxsystem/fbxsystem.h"
#endif
#ifdef MAPBASE_VSCRIPT
#include "vscript_client.h"
#endif
extern vgui::IInputInternal *g_InputInternal;
//=============================================================================
@ -271,6 +275,8 @@ void ProcessCacheUsedMaterials()
}
}
void VGui_ClearVideoPanels();
// String tables
INetworkStringTable *g_pStringTableParticleEffectNames = NULL;
INetworkStringTable *g_StringTableEffectDispatch = NULL;
@ -1108,6 +1114,9 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetViewEffectsRestoreBlockHandler() );
#ifdef MAPBASE_VSCRIPT
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetVScriptSaveRestoreBlockHandler() );
#endif
ClientWorldFactoryInit();
@ -1214,12 +1223,17 @@ void CHLClient::Shutdown( void )
g_pSixenseInput = NULL;
#endif
VGui_ClearVideoPanels();
C_BaseAnimating::ShutdownBoneSetupThreadPool();
ClientWorldFactoryShutdown();
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetViewEffectsRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() );
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() );
#ifdef MAPBASE_VSCRIPT
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetVScriptSaveRestoreBlockHandler() );
#endif
ClientVoiceMgr_Shutdown();
@ -1639,6 +1653,10 @@ void CHLClient::LevelInitPreEntity( char const* pMapName )
tempents->LevelInit();
ResetToneMapping(1.0);
#ifdef MAPBASE
GetClientWorldEntity()->ParseWorldMapData( engine->GetMapEntitiesString() );
#endif
IGameSystem::LevelInitPreEntityAllSystems(pMapName);
#ifdef USES_ECON_ITEMS

View File

@ -166,7 +166,6 @@ 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 );

View File

@ -535,7 +535,6 @@ $Project
"$SRCDIR\public\dt_utlvector_recv.cpp" \
"$SRCDIR\public\filesystem_helpers.cpp" \
"$SRCDIR\public\interpolatortypes.cpp" \
"$SRCDIR\game\shared\interval.cpp" \
"$SRCDIR\common\language.cpp" \
"$SRCDIR\public\networkvar.cpp" \
"$SRCDIR\common\randoverride.cpp" \
@ -1106,6 +1105,7 @@ $Project
$File "$SRCDIR\public\vgui_controls\WizardSubPanel.h"
$File "$SRCDIR\public\worldsize.h"
$File "$SRCDIR\public\zip_uncompressed.h"
$File "$SRCDIR\public\tier1\interval.h"
//Haptics
$File "$SRCDIR\public\haptics\ihaptics.h" [$WIN32]
$File "$SRCDIR\public\haptics\haptic_utils.h" [$WIN32]
@ -1162,7 +1162,6 @@ $Project
$File "$SRCDIR\game\shared\igamesystem.h"
$File "$SRCDIR\game\shared\imovehelper.h"
$File "$SRCDIR\game\shared\in_buttons.h"
$File "$SRCDIR\game\shared\interval.h"
$File "$SRCDIR\game\shared\iplayeranimstate.h"
$File "$SRCDIR\game\shared\ipredictionsystem.h"
$File "$SRCDIR\game\shared\itempents.h"
@ -1260,6 +1259,9 @@ $Project
$Lib vtf
$ImpLib steam_api
// Discord integration
$Lib "$LIBPUBLIC\discord-rpc" [$MAPBASE_RPC]
$Libexternal $LIBCOMMON/libcrypto [$OSXALL]
$Libexternal "$SRCDIR\lib\common\$(CRYPTOPPDIR)\libcrypto" [$LINUXALL]

View File

@ -12,6 +12,7 @@ $Configuration
$PreprocessorDefinitions "$BASE;MAPBASE_RPC;DISCORD_RPC;STEAM_RPC" [$MAPBASE_RPC]
$PreprocessorDefinitions "$BASE;MAPBASE_VSCRIPT" [$MAPBASE_VSCRIPT]
$PreprocessorDefinitions "$BASE;NEW_RESPONSE_SYSTEM" [$NEW_RESPONSE_SYSTEM]
}
}
@ -31,16 +32,23 @@ $Project
$File "c_postprocesscontroller.cpp"
$File "c_postprocesscontroller.h"
$File "c_env_dof_controller.cpp"
$File "c_movie_display.cpp"
$File "c_movie_display.h"
$File "vgui_movie_display.cpp"
$File "convarproxy.cpp"
$Folder "Mapbase"
{
$File "$SRCDIR\game\shared\mapbase\mapbase_shared.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_usermessages.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_rpc.cpp"
$File "$SRCDIR\game\shared\mapbase\mapbase_game_log.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.cpp"
$File "$SRCDIR\game\shared\mapbase\MapEdit.h"
$File "$SRCDIR\game\shared\mapbase\matchers.cpp"
$File "$SRCDIR\game\shared\mapbase\matchers.h"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.cpp"
$File "$SRCDIR\game\shared\mapbase\singleplayer_animstate.h"
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.h" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\vscript_singletons.cpp" [$MAPBASE_VSCRIPT]
@ -50,11 +58,18 @@ $Project
$File "$SRCDIR\game\shared\mapbase\vscript_consts_weapons.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.cpp" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\weapon_custom_scripted.h" [$MAPBASE_VSCRIPT]
$File "$SRCDIR\game\shared\mapbase\logic_script_client.cpp" [$MAPBASE_VSCRIPT]
$File "mapbase\vscript_vgui.cpp" [$MAPBASE_VSCRIPT]
$File "mapbase\vscript_vgui.h" [$MAPBASE_VSCRIPT]
$File "mapbase\vscript_vgui.nut" [$MAPBASE_VSCRIPT]
$File "mapbase\c_func_clientclip.cpp"
$File "mapbase\c_func_fake_worldportal.cpp"
$File "mapbase\c_func_fake_worldportal.h"
$File "mapbase\c_point_glow.cpp"
$File "mapbase\c_vgui_text_display.cpp"
$File "mapbase\mapbase_autocubemap.cpp"
}
$Folder "HL2 DLL"

View File

@ -298,8 +298,11 @@ ClientModeShared::ClientModeShared()
m_pWeaponSelection = NULL;
m_nRootSize[ 0 ] = m_nRootSize[ 1 ] = -1;
#ifdef MAPBASE // From Alien Swarm SDK
m_pCurrentPostProcessController = NULL;
m_PostProcessLerpTimer.Invalidate();
m_pCurrentColorCorrection = NULL;
#endif
#if defined( REPLAY_ENABLED )
m_pReplayReminderPanel = NULL;
@ -656,6 +659,43 @@ void ClientModeShared::Update()
}
}
#ifdef MAPBASE // From Alien Swarm SDK
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ClientModeShared::OnColorCorrectionWeightsReset( void )
{
C_ColorCorrection *pNewColorCorrection = NULL;
C_ColorCorrection *pOldColorCorrection = m_pCurrentColorCorrection;
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer )
{
pNewColorCorrection = pPlayer->GetActiveColorCorrection();
}
if ( pNewColorCorrection != pOldColorCorrection )
{
if ( pOldColorCorrection )
{
pOldColorCorrection->EnableOnClient( false );
}
if ( pNewColorCorrection )
{
pNewColorCorrection->EnableOnClient( true, pOldColorCorrection == NULL );
}
m_pCurrentColorCorrection = pNewColorCorrection;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float ClientModeShared::GetColorCorrectionScale( void ) const
{
return 1.0f;
}
#endif
//-----------------------------------------------------------------------------
// This processes all input before SV Move messages are sent
//-----------------------------------------------------------------------------
@ -1280,7 +1320,7 @@ void ClientModeShared::FireGameEvent( IGameEvent *event )
}
}
if ( team == 0 && GetLocalTeam() > 0 )
if ( team == 0 && GetLocalTeam() )
{
bValidTeam = false;
}

View File

@ -91,6 +91,11 @@ public:
virtual void ProcessInput(bool bActive);
virtual bool CreateMove( float flInputSampleTime, CUserCmd *cmd );
virtual void Update();
#ifdef MAPBASE // From Alien Swarm SDK
virtual void OnColorCorrectionWeightsReset( void );
virtual float GetColorCorrectionScale( void ) const;
virtual void ClearCurrentColorCorrection() { m_pCurrentColorCorrection = NULL; }
#endif
// Input
virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding );
@ -165,12 +170,16 @@ private:
CBaseHudWeaponSelection *m_pWeaponSelection;
int m_nRootSize[2];
#ifdef MAPBASE // From Alien Swarm SDK
void UpdatePostProcessingEffects();
const C_PostProcessController* m_pCurrentPostProcessController;
PostProcessParameters_t m_CurrentPostProcessParameters;
PostProcessParameters_t m_LerpStartPostProcessParameters, m_LerpEndPostProcessParameters;
CountdownTimer m_PostProcessLerpTimer;
CHandle<C_ColorCorrection> m_pCurrentColorCorrection;
#endif
};
#endif // CLIENTMODE_NORMAL_H

View File

@ -125,6 +125,11 @@ ConVar r_threaded_client_shadow_manager( "r_threaded_client_shadow_manager", "1"
ConVar r_threaded_client_shadow_manager( "r_threaded_client_shadow_manager", "0" );
#endif
#ifdef MAPBASE
ConVarRef mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap" );
ConVarRef mat_depthbias_shadowmap( "mat_depthbias_shadowmap" );
#endif
#ifdef _WIN32
#pragma warning( disable: 4701 )
#endif
@ -1424,6 +1429,15 @@ bool CClientShadowMgr::Init()
materials->AddRestoreFunc( ShadowRestoreFunc );
#ifdef MAPBASE
// These need to be referenced here since the cvars don't exist in the initial declaration
mat_slopescaledepthbias_shadowmap = ConVarRef( "mat_slopescaledepthbias_shadowmap" );
mat_depthbias_shadowmap = ConVarRef( "mat_depthbias_shadowmap" );
mat_slopescaledepthbias_shadowmap.SetValue( "16" ); // Would do something like 2 here, but it causes citizens to look weird under flashlights
mat_depthbias_shadowmap.SetValue( "0.00005" );
#endif
return true;
}
@ -4473,13 +4487,18 @@ void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
}
CViewSetup shadowView;
#ifndef MAPBASE
shadowView.m_flAspectRatio = 1.0f;
#endif
shadowView.x = shadowView.y = 0;
shadowView.width = shadowDepthTexture->GetActualWidth();
shadowView.height = shadowDepthTexture->GetActualHeight();
#ifndef ASW_PROJECTED_TEXTURES
shadowView.m_bOrtho = false;
shadowView.m_bDoBloomAndToneMapping = false;
#ifdef MAPBASE
shadowView.m_flAspectRatio = (flashlightState.m_fHorizontalFOVDegrees / flashlightState.m_fVerticalFOVDegrees);
#endif // MAPBASE
#endif
// Copy flashlight parameters
@ -4487,6 +4506,10 @@ void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
if ( !flashlightState.m_bOrtho )
{
shadowView.m_bOrtho = false;
#ifdef MAPBASE
shadowView.m_flAspectRatio = (flashlightState.m_fHorizontalFOVDegrees / flashlightState.m_fVerticalFOVDegrees);
#endif // MAPBASE
}
else
{
@ -4495,6 +4518,10 @@ void CClientShadowMgr::ComputeShadowDepthTextures( const CViewSetup &viewSetup )
shadowView.m_OrthoTop = flashlightState.m_fOrthoTop;
shadowView.m_OrthoRight = flashlightState.m_fOrthoRight;
shadowView.m_OrthoBottom = flashlightState.m_fOrthoBottom;
#ifdef MAPBASE
shadowView.m_flAspectRatio = 1.0f;
#endif
}
shadowView.m_bDoBloomAndToneMapping = false;

View File

@ -8,6 +8,12 @@
#include "cbase.h"
#include "tier0/vprof.h"
#include "colorcorrectionmgr.h"
#ifdef MAPBASE // From Alien Swarm SDK
#include "clientmode_shared.h" //"clientmode.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
#endif
//------------------------------------------------------------------------------
@ -16,6 +22,13 @@
static CColorCorrectionMgr s_ColorCorrectionMgr;
CColorCorrectionMgr *g_pColorCorrectionMgr = &s_ColorCorrectionMgr;
#ifdef MAPBASE // From Alien Swarm SDK
static ConVar mat_colcorrection_editor( "mat_colcorrection_editor", "0" );
static CUtlVector<C_ColorCorrection *> g_ColorCorrectionList;
static CUtlVector<C_ColorCorrectionVolume *> g_ColorCorrectionVolumeList;
#endif
//------------------------------------------------------------------------------
// Constructor
@ -62,10 +75,89 @@ void CColorCorrectionMgr::RemoveColorCorrection( ClientCCHandle_t h )
}
}
#ifdef MAPBASE // From Alien Swarm SDK
ClientCCHandle_t CColorCorrectionMgr::AddColorCorrectionEntity( C_ColorCorrection *pEntity, const char *pName, const char *pFileName )
{
ClientCCHandle_t h = AddColorCorrection(pName, pFileName);
if ( h != INVALID_CLIENT_CCHANDLE )
{
Assert(g_ColorCorrectionList.Find(pEntity) == -1);
g_ColorCorrectionList.AddToTail(pEntity);
}
return h;
}
void CColorCorrectionMgr::RemoveColorCorrectionEntity( C_ColorCorrection *pEntity, ClientCCHandle_t h)
{
RemoveColorCorrection(h);
g_ColorCorrectionList.FindAndFastRemove(pEntity);
}
ClientCCHandle_t CColorCorrectionMgr::AddColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, const char *pName, const char *pFileName )
{
ClientCCHandle_t h = AddColorCorrection(pName, pFileName);
if ( h != INVALID_CLIENT_CCHANDLE )
{
Assert(g_ColorCorrectionVolumeList.Find(pVolume) == -1);
g_ColorCorrectionVolumeList.AddToTail(pVolume);
}
return h;
}
void CColorCorrectionMgr::RemoveColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, ClientCCHandle_t h)
{
RemoveColorCorrection(h);
g_ColorCorrectionVolumeList.FindAndFastRemove(pVolume);
}
#endif
//------------------------------------------------------------------------------
// Modify color correction weights
//------------------------------------------------------------------------------
#ifdef MAPBASE // From Alien Swarm SDK
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight, bool bExclusive )
{
if ( h != INVALID_CLIENT_CCHANDLE )
{
SetWeightParams_t params = { h, flWeight, bExclusive };
m_colorCorrectionWeights.AddToTail( params );
if( bExclusive && m_bHaveExclusiveWeight && ( flWeight != 0.0f ) )
{
DevWarning( "Found multiple active color_correction entities with exclusive setting enabled. This is invalid.\n" );
}
if ( bExclusive )
{
m_bHaveExclusiveWeight = true;
m_flExclusiveWeight = flWeight;
}
}
}
void CColorCorrectionMgr::CommitColorCorrectionWeights()
{
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
for ( int i = 0; i < m_colorCorrectionWeights.Count(); i++ )
{
ColorCorrectionHandle_t ccHandle = reinterpret_cast<ColorCorrectionHandle_t>( m_colorCorrectionWeights[i].handle );
float flWeight = m_colorCorrectionWeights[i].flWeight;
if ( !m_colorCorrectionWeights[i].bExclusive )
{
flWeight = (1.0f - m_flExclusiveWeight ) * m_colorCorrectionWeights[i].flWeight;
}
pRenderContext->SetLookupWeight( ccHandle, flWeight );
// FIXME: NOTE! This doesn't work if the same handle has
// its weight set twice with no intervening calls to ResetColorCorrectionWeights
// which, at the moment, is true
if ( flWeight != 0.0f )
{
++m_nActiveWeightCount;
}
}
m_colorCorrectionWeights.RemoveAll();
}
#else
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight )
{
if ( h != INVALID_CLIENT_CCHANDLE )
@ -83,6 +175,7 @@ void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float fl
}
}
}
#endif
void CColorCorrectionMgr::ResetColorCorrectionWeights()
{
@ -93,6 +186,11 @@ void CColorCorrectionMgr::ResetColorCorrectionWeights()
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->ResetLookupWeights();
m_nActiveWeightCount = 0;
#ifdef MAPBASE // From Alien Swarm SDK
m_bHaveExclusiveWeight = false;
m_flExclusiveWeight = 0.0f;
m_colorCorrectionWeights.RemoveAll();
#endif
}
void CColorCorrectionMgr::SetResetable( ClientCCHandle_t h, bool bResetable )
@ -113,7 +211,34 @@ void CColorCorrectionMgr::SetResetable( ClientCCHandle_t h, bool bResetable )
//------------------------------------------------------------------------------
// Is color correction active?
//------------------------------------------------------------------------------
#ifdef MAPBASE // From Alien Swarm SDK
bool CColorCorrectionMgr::HasNonZeroColorCorrectionWeights() const
{
return ( m_nActiveWeightCount != 0 ) || mat_colcorrection_editor.GetBool();
}
void CColorCorrectionMgr::UpdateColorCorrection()
{
ResetColorCorrectionWeights();
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
IClientMode *pClientMode = GetClientModeNormal(); //GetClientMode();
Assert( pClientMode );
if ( !pPlayer || !pClientMode )
{
return;
}
pClientMode->OnColorCorrectionWeightsReset();
float ccScale = pClientMode->GetColorCorrectionScale();
UpdateColorCorrectionEntities( pPlayer, ccScale, g_ColorCorrectionList.Base(), g_ColorCorrectionList.Count() );
UpdateColorCorrectionVolumes( pPlayer, ccScale, g_ColorCorrectionVolumeList.Base(), g_ColorCorrectionVolumeList.Count() );
CommitColorCorrectionWeights();
}
#else
bool CColorCorrectionMgr::HasNonZeroColorCorrectionWeights() const
{
return ( m_nActiveWeightCount != 0 );
}
#endif

View File

@ -14,6 +14,10 @@
#include "igamesystem.h"
#ifdef MAPBASE // From Alien Swarm SDK
class C_ColorCorrection;
class C_ColorCorrectionVolume;
#endif
//------------------------------------------------------------------------------
// Purpose : Singleton manager for color correction on the client
@ -35,8 +39,21 @@ public:
ClientCCHandle_t AddColorCorrection( const char *pName, const char *pFileName = NULL );
void RemoveColorCorrection( ClientCCHandle_t );
#ifdef MAPBASE // From Alien Swarm SDK
ClientCCHandle_t AddColorCorrectionEntity( C_ColorCorrection *pEntity, const char *pName, const char *pFileName = NULL );
void RemoveColorCorrectionEntity( C_ColorCorrection *pEntity, ClientCCHandle_t );
ClientCCHandle_t AddColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, const char *pName, const char *pFileName = NULL );
void RemoveColorCorrectionVolume( C_ColorCorrectionVolume *pVolume, ClientCCHandle_t );
#endif
// Modify color correction weights
#ifdef MAPBASE // From Alien Swarm SDK
void SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight, bool bExclusive = false );
void UpdateColorCorrection();
#else
void SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight );
#endif
void ResetColorCorrectionWeights();
void SetResetable( ClientCCHandle_t h, bool bResetable );
@ -45,8 +62,27 @@ public:
private:
int m_nActiveWeightCount;
#ifdef MAPBASE // From Alien Swarm SDK
bool m_bHaveExclusiveWeight;
float m_flExclusiveWeight;
struct SetWeightParams_t
{
ClientCCHandle_t handle;
float flWeight;
bool bExclusive;
};
CUtlVector< SetWeightParams_t > m_colorCorrectionWeights;
void CommitColorCorrectionWeights();
#endif
};
#ifdef MAPBASE // From Alien Swarm SDK
void UpdateColorCorrectionEntities( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrection **pList, int listCount );
void UpdateColorCorrectionVolumes( C_BasePlayer *pPlayer, float ccScale, C_ColorCorrectionVolume **pList, int listCount );
#endif
//------------------------------------------------------------------------------
// Singleton access

View File

@ -0,0 +1,113 @@
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
//
// Material proxy to stuff a convar into a material var.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
// identifier was truncated to '255' characters in the debug information
//#pragma warning(disable: 4786)
#include "convar.h"
#include "materialsystem/imaterialproxy.h"
#include "materialsystem/imaterialvar.h"
//#include "imaterialproxydict.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
class CConVarMaterialProxy: public IMaterialProxy
{
public:
CConVarMaterialProxy()
: m_pResult( NULL ),
m_conVarRef( "", true )
{
}
virtual ~CConVarMaterialProxy()
{
}
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
const char *pResult = pKeyValues->GetString( "resultVar" );
if ( !pResult )
return false;
bool found;
m_pResult = pMaterial->FindVar( pResult, &found );
if ( !found )
{
m_pResult = NULL;
return false;
}
/*
if ( !Q_stricmp( pResult, "$alpha" ) )
{
pMaterial->SetMaterialVarFlag( MATERIAL_VAR_ALPHA_MODIFIED_BY_PROXY, true );
}
*/
pResult = pKeyValues->GetString( "convar" );
if( !pResult )
{
return false;
}
m_conVarRef.Init( pResult, false );
if ( !m_conVarRef.IsValid() )
{
return false;
}
return true;
}
virtual void OnBind( void* )
{
switch( m_pResult->GetType() )
{
case MATERIAL_VAR_TYPE_VECTOR:
{
float f = m_conVarRef.GetFloat();
Vector4D vec( f, f, f, f );
m_pResult->SetVecValue( vec.Base(), m_pResult->VectorSize() );
}
break;
#ifdef MAPBASE
case MATERIAL_VAR_TYPE_STRING:
m_pResult->SetStringValue( m_conVarRef.GetString() );
break;
#endif
case MATERIAL_VAR_TYPE_INT:
m_pResult->SetIntValue( m_conVarRef.GetInt() );
break;
case MATERIAL_VAR_TYPE_FLOAT:
default:
m_pResult->SetFloatValue( m_conVarRef.GetFloat() );
break;
}
}
virtual IMaterial *GetMaterial()
{
return m_pResult->GetOwningMaterial();
}
virtual void Release()
{
}
protected:
IMaterialVar *m_pResult;
ConVarRef m_conVarRef;
};
EXPOSE_INTERFACE( CConVarMaterialProxy, IMaterialProxy, "ConVar" IMATERIAL_PROXY_INTERFACE_VERSION );

View File

@ -5,6 +5,10 @@
//=============================================================================
#include "cbase.h"
#ifdef MAPBASE
#include "proxyentity.h"
#include "materialsystem/imaterialvar.h"
#endif
class C_PropScalable : public C_BaseAnimating
{
@ -194,3 +198,56 @@ void C_PropScalable::GetRenderBounds( Vector &theMins, Vector &theMaxs )
Assert( theMins.IsValid() && theMaxs.IsValid() );
}
#ifdef MAPBASE
ConVar r_coreball_update_sphere_center( "r_coreball_update_sphere_center", "1", FCVAR_NONE, "Allows prop_coreball to update its center to the entity's origin" );
class CCoreBallUpdateMaterialProxy : public CEntityMaterialProxy
{
public:
CCoreBallUpdateMaterialProxy()
{
m_pMaterial = NULL;
m_pSphereCenter = NULL;
}
virtual ~CCoreBallUpdateMaterialProxy()
{
}
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
m_pMaterial = pMaterial;
bool found;
m_pSphereCenter = m_pMaterial->FindVar( "$spherecenter", &found );
if( !found )
{
m_pSphereCenter = NULL;
return false;
}
return true;
}
virtual void OnBind( C_BaseEntity *pC_BaseEntity )
{
if (r_coreball_update_sphere_center.GetBool())
{
const Vector &origin = pC_BaseEntity->GetAbsOrigin();
m_pSphereCenter->SetVecValue( origin.x, origin.y, origin.z );
}
else
{
// Just continuously bind the old hacked value (TODO: Optimize so it's not just assigning the same value constantly?)
m_pSphereCenter->SetVecValue( 2688.0, 12139.0, 5170.0 );
}
}
virtual IMaterial *GetMaterial()
{
return m_pMaterial;
}
protected:
IMaterial *m_pMaterial;
IMaterialVar *m_pSphereCenter;
};
EXPOSE_INTERFACE( CCoreBallUpdateMaterialProxy, IMaterialProxy, "CoreBallUpdate" IMATERIAL_PROXY_INTERFACE_VERSION );
#endif

View File

@ -52,8 +52,8 @@ static ConVar r_flashlightladderdist( "r_flashlightladderdist", "40.0", FCVAR_CH
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 );
extern ConVarRef mat_slopescaledepthbias_shadowmap;
extern ConVarRef mat_depthbias_shadowmap;
#endif
#ifdef MAPBASE
static ConVar r_flashlighttextureoverride( "r_flashlighttextureoverride", "", FCVAR_CHEAT );

View File

@ -25,6 +25,13 @@ extern ConVar r_drawmodeldecals;
ImpactSoundRouteFn g_pImpactSoundRouteFn = NULL;
#ifdef MAPBASE
ConVar g_ragdoll_steal_impacts_client( "g_ragdoll_steal_impacts_client", "1", FCVAR_NONE, "Allows clientside death ragdolls to \"steal\" impacts from their source entities. This fixes issues with NPCs dying before decals are applied." );
ConVar g_ragdoll_steal_impacts_server( "g_ragdoll_steal_impacts_server", "1", FCVAR_NONE, "Allows serverside death ragdolls to \"steal\" impacts from their source entities. This fixes issues with NPCs dying before decals are applied." );
ConVar g_ragdoll_client_impact_decals( "g_ragdoll_client_impact_decals", "1", FCVAR_NONE, "Applies decals to clientside ragdolls when they are hit." );
#endif
//==========================================================================================================================
// RAGDOLL ENUMERATOR
//==========================================================================================================================
@ -32,7 +39,11 @@ CRagdollEnumerator::CRagdollEnumerator( Ray_t& shot, int iDamageType )
{
m_rayShot = shot;
m_iDamageType = iDamageType;
#ifdef MAPBASE
m_pHitEnt = NULL;
#else
m_bHit = false;
#endif
}
IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity )
@ -57,7 +68,11 @@ IterationRetval_t CRagdollEnumerator::EnumElement( IHandleEntity *pHandleEntity
if ( tr.fraction < 1.0 )
{
pModel->ImpactTrace( &tr, m_iDamageType, NULL );
#ifdef MAPBASE
m_pHitEnt = pModel;
#else
m_bHit = true;
#endif
//FIXME: Yes? No?
return ITERATION_STOP;
@ -84,6 +99,22 @@ bool FX_AffectRagdolls( Vector vecOrigin, Vector vecStart, int iDamageType )
return ragdollEnum.Hit();
}
#ifdef MAPBASE
C_BaseAnimating *FX_AffectRagdolls_GetHit( Vector vecOrigin, Vector vecStart, int iDamageType )
{
// don't do this when lots of ragdolls are simulating
if ( s_RagdollLRU.CountRagdolls(true) > 1 )
return NULL;
Ray_t shotRay;
shotRay.Init( vecStart, vecOrigin );
CRagdollEnumerator ragdollEnum( shotRay, iDamageType );
partition->EnumerateElementsAlongRay( PARTITION_CLIENT_RESPONSIVE_EDICTS, shotRay, false, &ragdollEnum );
return ragdollEnum.GetHit();
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
// Input : &data -
@ -104,6 +135,22 @@ bool Impact( Vector &vecOrigin, Vector &vecStart, int iMaterial, int iDamageType
Assert ( pEntity );
#ifdef MAPBASE
// If the entity already has a ragdoll that was created on the current tick, use that ragdoll instead.
// This allows the killing damage's decals to show up on the ragdoll.
if (C_BaseAnimating *pAnimating = pEntity->GetBaseAnimating())
{
if (pAnimating->m_pClientsideRagdoll && WasRagdollCreatedOnCurrentTick( pAnimating->m_pClientsideRagdoll ) && g_ragdoll_steal_impacts_client.GetBool())
{
pEntity = pAnimating->m_pClientsideRagdoll;
}
else if (pAnimating->m_pServerRagdoll && WasRagdollCreatedOnCurrentTick( pAnimating->m_pServerRagdoll ) && g_ragdoll_steal_impacts_server.GetBool())
{
pEntity = pAnimating->m_pServerRagdoll;
}
}
#endif
// Clear out the trace
memset( &tr, 0, sizeof(trace_t));
tr.fraction = 1.0f;
@ -115,13 +162,52 @@ bool Impact( Vector &vecOrigin, Vector &vecStart, int iMaterial, int iDamageType
VectorMA( vecStart, flLength + 8.0f, shotDir, traceExt );
// Attempt to hit ragdolls
bool bHitRagdoll = false;
#ifdef MAPBASE
if ( !pEntity->IsClientCreated() )
{
C_BaseAnimating *pRagdoll = FX_AffectRagdolls_GetHit( vecOrigin, vecStart, iDamageType );
if (pRagdoll)
{
bHitRagdoll = true;
if (g_ragdoll_client_impact_decals.GetBool() && pRagdoll->IsRagdoll())
{
pEntity = pRagdoll;
// HACKHACK: Get the ragdoll's nearest bone for its material
int iNearestMaterial = 0;
float flNearestDistSqr = FLT_MAX;
IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT];
int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) );
for ( int i = 0; i < count; i++ )
{
Vector vecPosition;
QAngle angAngles;
pList[i]->GetPosition( &vecPosition, &angAngles );
float flDistSqr = (vecStart - vecPosition).LengthSqr();
if (flDistSqr < flNearestDistSqr)
{
iNearestMaterial = pList[i]->GetMaterialIndex();
flNearestDistSqr = flDistSqr;
}
}
// Get the material from the surfaceprop
surfacedata_t *psurfaceData = physprops->GetSurfaceData( iNearestMaterial );
iMaterial = psurfaceData->game.material;
}
}
}
#else
if ( !pEntity->IsClientCreated() )
{
bHitRagdoll = FX_AffectRagdolls( vecOrigin, vecStart, iDamageType );
}
#endif
if ( (nFlags & IMPACT_NODECAL) == 0 )
{

View File

@ -58,12 +58,21 @@ public:
// Actual work code
virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity );
#ifdef MAPBASE
bool Hit( void ) const { return m_pHitEnt != NULL; }
C_BaseAnimating *GetHit( void ) { return m_pHitEnt; }
#else
bool Hit( void ) const { return m_bHit; }
#endif
private:
Ray_t m_rayShot;
int m_iDamageType;
#ifdef MAPBASE
C_BaseAnimating *m_pHitEnt;
#else
bool m_bHit;
#endif
};
#endif // FX_IMPACT_H

View File

@ -156,6 +156,32 @@ bool CBaseViewport::LoadHudAnimations( void )
return true;
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Reloads HUD animations after loading a map-specific HUD animations file.
//-----------------------------------------------------------------------------
void CBaseViewport::ReloadHudAnimations( void )
{
// Force a reload
if ( LoadHudAnimations() == false )
{
// Fall back to just the main
if ( m_pAnimController->SetScriptFile( GetVPanel(), "scripts/HudAnimations.txt", true ) == false )
{
Assert(0);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Loads a map-specific HUD animations file.
//-----------------------------------------------------------------------------
bool CBaseViewport::LoadCustomHudAnimations( const char *pszFile )
{
return m_pAnimController->SetScriptFile( GetVPanel(), pszFile, true );
}
#endif
//================================================================
CBaseViewport::CBaseViewport() : vgui::EditablePanel( NULL, "CBaseViewport")
{

View File

@ -73,6 +73,10 @@ public:
public: // IGameEventListener:
virtual void FireGameEvent( IGameEvent * event);
#ifdef MAPBASE
bool LoadCustomHudAnimations( const char *pszFile );
void ReloadHudAnimations( void );
#endif
protected:

View File

@ -150,6 +150,10 @@ private:
static const int ENTRY_IN_USE = -2;
};
#ifdef MAPBASE_VSCRIPT
// For unregistration boundary check
public:
#endif
CUtlVector< GlowObjectDefinition_t > m_GlowObjectDefinitions;
int m_nFirstFreeSlot;
};

View File

@ -31,6 +31,9 @@ ConVar cl_npc_speedmod_outtime( "cl_npc_speedmod_outtime", "1.5", FCVAR_CLIENTDL
IMPLEMENT_CLIENTCLASS_DT(C_BaseHLPlayer, DT_HL2_Player, CHL2_Player)
RecvPropDataTable( RECVINFO_DT(m_HL2Local),0, &REFERENCE_RECV_TABLE(DT_HL2Local) ),
RecvPropBool( RECVINFO( m_fIsSprinting ) ),
#ifdef SP_ANIM_STATE
RecvPropFloat( RECVINFO( m_flAnimRenderYaw ) ),
#endif
END_RECV_TABLE()
BEGIN_PREDICTION_DATA( C_BaseHLPlayer )
@ -90,6 +93,13 @@ void C_BaseHLPlayer::OnDataChanged( DataUpdateType_t updateType )
SetNextClientThink( CLIENT_THINK_ALWAYS );
}
#ifdef SP_ANIM_STATE
if (m_flAnimRenderYaw != FLT_MAX)
{
m_angAnimRender = QAngle( 0, m_flAnimRenderYaw, 0 );
}
#endif
BaseClass::OnDataChanged( updateType );
}
@ -657,3 +667,21 @@ void C_BaseHLPlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quatern
BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" );
}
#ifdef SP_ANIM_STATE
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const QAngle& C_BaseHLPlayer::GetRenderAngles( void )
{
if ( m_flAnimRenderYaw != FLT_MAX )
{
return m_angAnimRender;
}
else
{
return BaseClass::GetRenderAngles();
}
}
#endif

View File

@ -15,6 +15,10 @@
#include "c_baseplayer.h"
#include "c_hl2_playerlocaldata.h"
#if !defined( HL2MP ) && defined ( MAPBASE )
#include "mapbase/singleplayer_animstate.h"
#endif
class C_BaseHLPlayer : public C_BasePlayer
{
public:
@ -58,6 +62,10 @@ public:
bool IsWeaponLowered( void ) { return m_HL2Local.m_bWeaponLowered; }
#ifdef SP_ANIM_STATE
virtual const QAngle& GetRenderAngles( void );
#endif
public:
C_HL2PlayerLocalData m_HL2Local;
@ -78,7 +86,13 @@ private:
bool m_bPlayUseDenySound; // Signaled by PlayerUse, but can be unset by HL2 ladder code...
float m_flSpeedMod;
float m_flExitSpeedMod;
#ifdef SP_ANIM_STATE
// At the moment, we network the render angles since almost none of the player anim stuff is done on the client in SP.
// If any of this is ever adapted for MP, this method should be replaced with replicating/moving the anim state to the client.
float m_flAnimRenderYaw;
QAngle m_angAnimRender;
#endif
friend class CHL2GameMovement;
};

View File

@ -32,6 +32,16 @@ struct creditname_t
float flTimeAdd;
float flTimeStart;
int iSlot;
#ifdef MAPBASE
// New credits stuff
Color cColorOverride;
// Images
int iImageID = -1;
float flImageScale = 1.0f;
#endif
};
#define CREDITS_FILE "scripts/credits.txt"
@ -47,6 +57,9 @@ enum
#define CREDITS_LOGO 1
#define CREDITS_INTRO 2
#define CREDITS_OUTRO 3
#ifdef MAPBASE
#define CREDITS_PRECACHE 4
#endif
bool g_bRollingCredits = false;
@ -93,15 +106,27 @@ private:
void DrawOutroCreditsName( void );
void DrawIntroCreditsName( void );
void DrawLogo( void );
#ifdef MAPBASE
void DrawOutroCreditFont( const char *pCreditName, float flYPos, vgui::HFont hTFont, const Color &cColor, int iScreenWidth, int iDivisor = 2 );
void DrawOutroCreditTexture( int iImageID, float flYPos, float flImageScale, const Color &cColor, int iScreenWidth, int iDivisor = 2 );
#endif
void PrepareLogo( float flTime );
void PrepareOutroCredits( void );
void PrepareIntroCredits( void );
#ifdef MAPBASE
void PrecacheCredits();
#endif
float FadeBlend( float fadein, float fadeout, float hold, float localTime );
void PrepareLine( vgui::HFont hFont, char const *pchLine );
#ifdef MAPBASE
int GetOrAllocateImageID( const char *szFileName );
#endif
CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "Default" );
CPanelAnimationVar( Color, m_TextColor, "TextColor", "FgColor" );
@ -110,7 +135,10 @@ private:
float m_flScrollTime;
float m_flSeparation;
#ifdef MAPBASE
int m_iEndLines;
int m_iEndLines;
float m_flEndLinesFadeHoldTime;
bool m_bAllowColumns;
CUtlDict<int, int> m_ImageDict;
#endif
float m_flFadeTime;
bool m_bLastOneInPlace;
@ -141,6 +169,9 @@ private:
char m_szCreditsFile[MAX_PATH];
char m_szLogoFont[64];
char m_szLogo2Font[64];
Color m_cLogoColor;
Color m_cLogo2Color;
#endif
};
@ -202,6 +233,20 @@ void CHudCredits::Clear( void )
m_bLastOneInPlace = false;
m_Alpha = m_TextColor[3];
m_iLogoState = LOGO_FADEOFF;
#ifdef MAPBASE
if ( surface() )
{
for (int i = m_ImageDict.Count()-1; i >= 0; i--)
{
if (m_ImageDict[i] != -1)
{
surface()->DestroyTextureID( m_ImageDict[i] );
m_ImageDict.RemoveAt( i );
}
}
}
#endif
}
//-----------------------------------------------------------------------------
@ -229,7 +274,11 @@ void CHudCredits::ReadNames( KeyValues *pKeyValue )
{
creditname_t Credits;
V_strcpy_safe( Credits.szCreditName, pKVNames->GetName() );
#ifdef MAPBASE
V_strcpy_safe( Credits.szFontName, pKVNames->GetString( (const char *)NULL, "Default" ) );
#else
V_strcpy_safe( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) );
#endif
m_CreditsList.AddToTail( Credits );
pKVNames = pKVNames->GetNextKey();
@ -248,6 +297,8 @@ void CHudCredits::ReadParams( KeyValues *pKeyValue )
m_flSeparation = pKeyValue->GetFloat( "separation", 5 );
#ifdef MAPBASE
m_iEndLines = pKeyValue->GetInt( "endlines", 1 );
m_flEndLinesFadeHoldTime = pKeyValue->GetFloat( "endlines_fadeholdtime", ( IsConsole() ? 2.0f : 10.0f ) ); // "360 certification requires that we not hold a static image too long."
m_bAllowColumns = pKeyValue->GetBool( "allow_columns", false );
#endif
m_flFadeInTime = pKeyValue->GetFloat( "fadeintime", 1 );
@ -268,6 +319,10 @@ void CHudCredits::ReadParams( KeyValues *pKeyValue )
#ifdef MAPBASE
Q_strncpy( m_szLogoFont, pKeyValue->GetString( "logofont", "" ), sizeof( m_szLogoFont ) );
Q_strncpy( m_szLogo2Font, pKeyValue->GetString( "logo2font", "" ), sizeof( m_szLogo2Font ) );
m_cLogoColor = pKeyValue->GetColor( "logocolor" );
m_cLogo2Color = pKeyValue->GetColor( "logo2color" );
#endif
}
@ -300,10 +355,46 @@ void CHudCredits::DrawOutroCreditsName( void )
if ( pCredit == NULL )
continue;
#ifdef MAPBASE
vgui::HScheme scheme = GetScheme();
#else
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName, true );
#endif
vgui::HFont m_hTFont = INVALID_FONT;
int iFontTall = surface()->GetFontTall ( m_hTFont );
int iFontTall = 1;
#ifdef MAPBASE
if (pCredit->iImageID != -1)
{
// Get the size of the tallest image if there's multiple
int iFontWide;
if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" ))
{
CUtlStringList outStrings;
V_SplitString( pCredit->szCreditName, "\t", outStrings );
FOR_EACH_VEC( outStrings, i )
{
int iTempTall;
surface()->DrawGetTextureSize( GetOrAllocateImageID( outStrings[i] ), iFontWide, iTempTall );
if (iTempTall > iFontTall)
iFontTall = iTempTall;
}
outStrings.PurgeAndDeleteElements();
}
else
{
surface()->DrawGetTextureSize( GetOrAllocateImageID( pCredit->szCreditName ), iFontWide, iFontTall );
}
iFontTall = ((float)iFontTall * pCredit->flImageScale);
}
else
#endif
{
m_hTFont = vgui::scheme()->GetIScheme( scheme )->GetFont( pCredit->szFontName, true );
iFontTall = surface()->GetFontTall( m_hTFont );
}
if ( pCredit->flYPos < -iFontTall || pCredit->flYPos > iTall )
{
@ -317,6 +408,9 @@ void CHudCredits::DrawOutroCreditsName( void )
Color cColor = m_TextColor;
#ifdef MAPBASE
if (pCredit->cColorOverride.a() > 0)
cColor = pCredit->cColorOverride;
// Some lines should stick around and fade out
if ( i >= m_CreditsList.Count()-m_iEndLines )
#else
@ -333,8 +427,12 @@ void CHudCredits::DrawOutroCreditsName( void )
{
m_bLastOneInPlace = true;
#ifdef MAPBASE
m_flFadeTime = gpGlobals->curtime + m_flEndLinesFadeHoldTime;
#else
// 360 certification requires that we not hold a static image too long.
m_flFadeTime = gpGlobals->curtime + ( IsConsole() ? 2.0f : 10.0f );
#endif
}
}
else
@ -364,6 +462,50 @@ void CHudCredits::DrawOutroCreditsName( void )
if ( pCredit->bActive == false )
continue;
#ifdef MAPBASE
// Credits separated by tabs should appear divided
if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" ))
{
CUtlStringList outStrings;
V_SplitString( pCredit->szCreditName, "\t", outStrings );
int iDivisor = 1 + outStrings.Count();
if (pCredit->iImageID != -1)
{
FOR_EACH_VEC( outStrings, i )
{
int iImageID = GetOrAllocateImageID( outStrings[i] );
// Center the image if needed
int iImageWide, iImageTall = 1;
surface()->DrawGetTextureSize( iImageID, iImageWide, iImageTall );
if (iImageTall < iFontTall)
{
DrawOutroCreditTexture( iImageID, pCredit->flYPos + ((iFontTall * 0.5f) - (iImageTall * 0.5f)), pCredit->flImageScale, cColor, iWidth*(i + 1), iDivisor );
}
else
{
DrawOutroCreditTexture( iImageID, pCredit->flYPos, pCredit->flImageScale, cColor, iWidth*(i + 1), iDivisor );
}
}
}
else
{
FOR_EACH_VEC( outStrings, i )
{
DrawOutroCreditFont( outStrings[i], pCredit->flYPos, m_hTFont, cColor, iWidth*(i + 1), iDivisor );
}
}
outStrings.PurgeAndDeleteElements();
}
else if (pCredit->iImageID != -1)
{
DrawOutroCreditTexture( pCredit->iImageID, pCredit->flYPos, pCredit->flImageScale, cColor, iWidth, 2 );
}
else
{
DrawOutroCreditFont( pCredit->szCreditName, pCredit->flYPos, m_hTFont, cColor, iWidth, 2 );
}
#else
surface()->DrawSetTextFont( m_hTFont );
surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], cColor[3] );
@ -382,9 +524,56 @@ void CHudCredits::DrawOutroCreditsName( void )
surface()->DrawSetTextPos( ( iWidth / 2 ) - ( iStringWidth / 2 ), pCredit->flYPos );
surface()->DrawUnicodeString( unicode );
#endif
}
}
#ifdef MAPBASE
void CHudCredits::DrawOutroCreditFont( const char *pCreditName, float flYPos, vgui::HFont hTFont, const Color &cColor, int iScreenWidth, int iDivisor )
{
surface()->DrawSetTextFont( hTFont );
surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], cColor[3] );
wchar_t unicode[256];
if ( pCreditName[0] == '#' )
{
g_pVGuiLocalize->ConstructString( unicode, sizeof(unicode), g_pVGuiLocalize->Find(pCreditName), 0 );
}
else
{
g_pVGuiLocalize->ConvertANSIToUnicode( pCreditName, unicode, sizeof( unicode ) );
}
int iStringWidth = GetStringPixelWidth( unicode, hTFont );
// ((iScreenWidth*iMultiplier) / iDivisor)
// When needed, just multiply iScreenWidth before sending to the function
surface()->DrawSetTextPos( (iScreenWidth / iDivisor) - (iStringWidth / 2), flYPos );
surface()->DrawUnicodeString( unicode );
}
void CHudCredits::DrawOutroCreditTexture( int iImageID, float flYPos, float flImageScale, const Color &cColor, int iScreenWidth, int iDivisor )
{
int iImageWide, iImageTall;
surface()->DrawGetTextureSize( iImageID, iImageWide, iImageTall );
// Scale for resolution
flImageScale *= ((float)GetTall() / 900.0f);
iImageWide = ((float)(iImageWide) * flImageScale);
iImageTall = ((float)(iImageTall) * flImageScale);
iImageWide /= 2;
//iImageTall /= 2;
iScreenWidth /= iDivisor;
surface()->DrawSetColor( cColor );
surface()->DrawSetTexture( iImageID );
surface()->DrawTexturedRect( iScreenWidth - iImageWide, flYPos, iScreenWidth + iImageWide, flYPos + iImageTall );
}
#endif
void CHudCredits::DrawLogo( void )
{
if( m_iLogoState == LOGO_FADEOFF )
@ -464,13 +653,22 @@ void CHudCredits::DrawLogo( void )
Q_snprintf( szLogoFont, sizeof( szLogoFont ), "WeaponIcons" );
}
#ifdef MAPBASE
vgui::HScheme scheme = GetScheme();
#else
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
#endif
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( szLogoFont );
int iFontTall = surface()->GetFontTall ( m_hTFont );
Color cColor = m_TextColor;
cColor[3] = m_Alpha;
#ifdef MAPBASE
if (m_cLogoColor.a() > 0)
cColor = m_cLogoColor;
#endif
surface()->DrawSetTextFont( m_hTFont );
surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], cColor[3] );
@ -485,6 +683,19 @@ void CHudCredits::DrawLogo( void )
if ( Q_strlen( m_szLogo2 ) > 0 )
{
#ifdef MAPBASE
if (m_szLogo2Font[0] != '\0')
{
m_hTFont = vgui::scheme()->GetIScheme( scheme )->GetFont( m_szLogo2Font );
iFontTall = surface()->GetFontTall( m_hTFont );
surface()->DrawSetTextFont( m_hTFont );
}
if (m_cLogo2Color.a() > 0)
{
surface()->DrawSetTextColor( m_cLogo2Color[0], m_cLogo2Color[1], m_cLogo2Color[2], m_cLogo2Color[3] );
}
#endif
g_pVGuiLocalize->ConvertANSIToUnicode( m_szLogo2, unicode, sizeof( unicode ) );
iStringWidth = GetStringPixelWidth( unicode, m_hTFont );
@ -544,14 +755,26 @@ void CHudCredits::DrawIntroCreditsName( void )
if ( pCredit->bActive == false )
continue;
#ifdef MAPBASE
vgui::HScheme scheme = GetScheme();
#else
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
#endif
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName );
float localTime = gpGlobals->curtime - pCredit->flTimeStart;
surface()->DrawSetTextFont( m_hTFont );
#ifdef MAPBASE
Color cColor = m_cColor;
if (pCredit->cColorOverride.a() > 0)
cColor = pCredit->cColorOverride;
surface()->DrawSetTextColor( cColor[0], cColor[1], cColor[2], FadeBlend( m_flFadeInTime, m_flFadeOutTime, m_flFadeHoldTime + pCredit->flTimeAdd, localTime ) * cColor[3] );
#else
surface()->DrawSetTextColor( m_cColor[0], m_cColor[1], m_cColor[2], FadeBlend( m_flFadeInTime, m_flFadeOutTime, m_flFadeHoldTime + pCredit->flTimeAdd, localTime ) * m_cColor[3] );
#endif
wchar_t unicode[256];
g_pVGuiLocalize->ConvertANSIToUnicode( pCredit->szCreditName, unicode, sizeof( unicode ) );
@ -692,17 +915,119 @@ void CHudCredits::PrepareOutroCredits( void )
if ( pCredit == NULL )
continue;
#ifdef MAPBASE
vgui::HScheme scheme = GetScheme();
#else
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName, true );
#endif
pCredit->flYPos = iHeight;
pCredit->bActive = false;
#ifdef MAPBASE
if (pCredit->szFontName[0] == '$')
{
if (V_strncmp( pCredit->szFontName + 1, "Image", 5 ) == 0)
{
if (pCredit->szFontName[6] == ';')
{
CUtlStringList outStrings;
V_SplitString( pCredit->szFontName, ";", outStrings );
FOR_EACH_VEC( outStrings, i )
{
switch (i)
{
// Get scale
case 1:
pCredit->flImageScale = atof( outStrings[i] );
break;
iHeight += surface()->GetFontTall ( m_hTFont ) + m_flSeparation;
// Get color
case 2:
int tmp[4];
UTIL_StringToIntArray( tmp, 4, outStrings[i] );
pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] );
break;
}
}
outStrings.PurgeAndDeleteElements();
}
PrepareLine( m_hTFont, pCredit->szCreditName );
// Get the size of the tallest image if there's multiple
int iFontWide, iFontTall = 1;
if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" ))
{
CUtlStringList outStrings;
V_SplitString( pCredit->szCreditName, "\t", outStrings );
FOR_EACH_VEC( outStrings, i )
{
pCredit->iImageID = GetOrAllocateImageID( outStrings[i] );
int iTempTall;
surface()->DrawGetTextureSize( pCredit->iImageID, iFontWide, iTempTall );
if (iTempTall > iFontTall)
iFontTall = iTempTall;
}
outStrings.PurgeAndDeleteElements();
}
else
{
pCredit->iImageID = GetOrAllocateImageID( pCredit->szCreditName );
surface()->DrawGetTextureSize( pCredit->iImageID, iFontWide, iFontTall );
}
pCredit->flYPos = iHeight;
pCredit->bActive = false;
iHeight += ((float)iFontTall * pCredit->flImageScale * ((float)GetTall() / 900.0f)) + m_flSeparation;
//Msg( "'%s' is image type (image scale is %f)\n", pCredit->szCreditName, pCredit->flImageScale );
}
else
{
//Msg( "'%s' is not an image type\n", pCredit->szFontName + 1 );
}
}
else
#endif
{
#ifdef MAPBASE
if (V_strstr( pCredit->szFontName, ";" ))
{
CUtlStringList outStrings;
V_SplitString( pCredit->szFontName, ";", outStrings );
FOR_EACH_VEC( outStrings, i )
{
switch (i)
{
// Get color
case 1:
int tmp[4];
UTIL_StringToIntArray( tmp, 4, outStrings[i] );
pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] );
break;
}
}
Q_strncpy( pCredit->szFontName, outStrings[0], sizeof( pCredit->szFontName ) );
outStrings.PurgeAndDeleteElements();
}
#endif
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme( scheme )->GetFont( pCredit->szFontName, true );
pCredit->flYPos = iHeight;
pCredit->bActive = false;
iHeight += surface()->GetFontTall ( m_hTFont ) + m_flSeparation;
PrepareLine( m_hTFont, pCredit->szCreditName );
}
}
#ifdef MAPBASE
// Check if the last line has a color override. If it does, use that as the alpha for the fadeout
if (m_CreditsList.Tail().cColorOverride.a() != 0)
m_Alpha = m_CreditsList.Tail().cColorOverride.a();
#endif
SetActive( true );
g_iCreditsPixelHeight = iHeight;
@ -721,7 +1046,34 @@ void CHudCredits::PrepareIntroCredits( void )
if ( pCredit == NULL )
continue;
#ifdef MAPBASE
if (V_strstr( pCredit->szFontName, ";" ))
{
CUtlStringList outStrings;
V_SplitString( pCredit->szFontName, ";", outStrings );
FOR_EACH_VEC( outStrings, i )
{
switch (i)
{
// Get color
case 1:
int tmp[4];
UTIL_StringToIntArray( tmp, 4, outStrings[i] );
pCredit->cColorOverride = Color( tmp[0], tmp[1], tmp[2], tmp[3] );
break;
}
}
Q_strncpy( pCredit->szFontName, outStrings[0], sizeof( pCredit->szFontName ) );
outStrings.PurgeAndDeleteElements();
}
#endif
#ifdef MAPBASE
vgui::HScheme scheme = GetScheme();
#else
vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" );
#endif
vgui::HFont m_hTFont = vgui::scheme()->GetIScheme(scheme)->GetFont( pCredit->szFontName );
pCredit->flYPos = m_flY + ( iSlot * surface()->GetFontTall ( m_hTFont ) );
@ -749,6 +1101,64 @@ void CHudCredits::PrepareIntroCredits( void )
SetActive( true );
}
#ifdef MAPBASE
void CHudCredits::PrecacheCredits()
{
PrepareCredits( "OutroCreditsNames" );
if ( m_CreditsList.Count() == 0 )
return;
for ( int i = 0; i < m_CreditsList.Count(); i++ )
{
creditname_t *pCredit = &m_CreditsList[i];
if ( pCredit == NULL )
continue;
if (pCredit->szFontName[0] == '$')
{
if (V_strncmp( pCredit->szFontName + 1, "Image", 5 ) == 0)
{
if (m_bAllowColumns && V_strstr( pCredit->szCreditName, "\t" ))
{
CUtlStringList outStrings;
V_SplitString( pCredit->szCreditName, "\t", outStrings );
FOR_EACH_VEC( outStrings, i )
{
GetOrAllocateImageID( outStrings[i] );
}
outStrings.PurgeAndDeleteElements();
}
else
{
GetOrAllocateImageID( pCredit->szCreditName );
}
}
else
{
//Msg( "'%s' is not an image type\n", pCredit->szFontName + 1 );
}
}
}
m_CreditsList.RemoveAll();
}
int CHudCredits::GetOrAllocateImageID( const char *szFileName )
{
int iIndex = m_ImageDict.Find( szFileName );
if (iIndex == m_ImageDict.InvalidIndex())
{
iIndex = surface()->CreateNewTextureID();
m_ImageDict.Insert( szFileName, iIndex );
surface()->DrawSetTextureFile( iIndex, szFileName, true, false );
return iIndex;
}
return m_ImageDict[iIndex];
}
#endif
void CHudCredits::MsgFunc_CreditsMsg( bf_read &msg )
{
m_iCreditsType = msg.ReadByte();
@ -777,6 +1187,13 @@ void CHudCredits::MsgFunc_CreditsMsg( bf_read &msg )
PrepareOutroCredits();
break;
}
#ifdef MAPBASE
case CREDITS_PRECACHE:
{
PrecacheCredits();
break;
}
#endif
}
}

View File

@ -644,6 +644,15 @@ void CHudWeaponSelection::Paint()
// This is a bit of a misnomer... we really are asking "Is this the selected slot"?
selectedWeapon = true;
}
#ifdef MAPBASE
else if (!hud_showemptyweaponslots.GetBool() && !pWeapon)
{
// Revert the offset
xPos -= ( m_flMediumBoxWide + 5 ) * xModifiers[ i ];
yPos -= ( m_flMediumBoxTall + 5 ) * yModifiers[ i ];
continue;
}
#endif
// Draw the box with the appropriate icon
DrawLargeWeaponBox( pWeapon,
@ -1375,6 +1384,23 @@ void CHudWeaponSelection::PlusTypeFastWeaponSwitch( int iWeaponSlot )
// Changing vertical/horizontal direction. Reset the selected box position to zero.
m_iSelectedBoxPosition = 0;
m_iSelectedSlot = iWeaponSlot;
#ifdef MAPBASE
if (!hud_showemptyweaponslots.GetBool())
{
// Skip empty slots
int i = 0;
while ( i < MAX_WEAPON_POSITIONS )
{
C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( iWeaponSlot, i );
if ( pWeapon )
break;
i++;
}
m_iSelectedBoxPosition = i;
}
#endif
}
else
{
@ -1385,6 +1411,27 @@ void CHudWeaponSelection::PlusTypeFastWeaponSwitch( int iWeaponSlot )
// Decrementing within the slot. If we're at the zero position in this slot,
// jump to the zero position of the opposite slot. This also counts as our increment.
increment = -1;
#ifdef MAPBASE
if (!hud_showemptyweaponslots.GetBool())
{
// Skip empty slots
int iZeroPos = 0;
while ( iZeroPos < MAX_WEAPON_POSITIONS )
{
C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( m_iSelectedSlot, iZeroPos );
if ( pWeapon )
break;
iZeroPos++;
}
if ( iZeroPos == m_iSelectedBoxPosition )
{
newSlot = ( m_iSelectedSlot + 2 ) % 4;
m_iSelectedBoxPosition = increment = 0;
}
}
else
#endif
if ( 0 == m_iSelectedBoxPosition )
{
newSlot = ( m_iSelectedSlot + 2 ) % 4;
@ -1402,6 +1449,35 @@ void CHudWeaponSelection::PlusTypeFastWeaponSwitch( int iWeaponSlot )
lastSlotPos = slotPos;
}
}
#ifdef MAPBASE
if (!hud_showemptyweaponslots.GetBool())
{
// Skip empty slots
int i = m_iSelectedBoxPosition + increment;
while ( i >= 0 && i < lastSlotPos )
{
C_BaseCombatWeapon *pWeapon = GetWeaponInSlot( newSlot, i );
if ( !pWeapon )
{
if (increment < 0)
{
increment--;
i--;
}
else
{
increment++;
i++;
}
}
else
{
break;
}
}
}
#endif
// Increment/Decrement the selected box position
if ( m_iSelectedBoxPosition + increment <= lastSlotPos )

View File

@ -1303,7 +1303,7 @@ void CHudCloseCaption::Reset( void )
Unlock();
}
bool CHudCloseCaption::SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t *args ) const
bool CHudCloseCaption::SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t *args, int size ) const
{
const wchar_t *in = *ppIn;
const wchar_t *oldin = in;
@ -1318,8 +1318,11 @@ bool CHudCloseCaption::SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t
cmd[ 0 ]= 0;
wchar_t *out = cmd;
in++;
while ( *in != L'\0' && *in != L':' && *in != L'>' && !isspace( *in ) )
while ( *in != L'\0' && *in != L':' && *in != L'>' && !V_isspace( *in ) )
{
if ( (int)( out - cmd ) + (int)sizeof( wchar_t ) >= size )
break;
*out++ = *in++;
}
*out = L'\0';
@ -1334,6 +1337,9 @@ bool CHudCloseCaption::SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t
out = args;
while ( *in != L'\0' && *in != L'>' )
{
if ( (int)( out - args ) + (int)sizeof( wchar_t ) >= size )
break;
*out++ = *in++;
}
*out = L'\0';
@ -1361,7 +1367,7 @@ bool CHudCloseCaption::GetFloatCommandValue( const wchar_t *stream, const wchar_
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
if ( SplitCommand( &curpos, cmd, args, sizeof( cmd ) ) )
{
if ( !wcscmp( cmd, findcmd ) )
{
@ -1385,7 +1391,7 @@ bool CHudCloseCaption::StreamHasCommand( const wchar_t *stream, const wchar_t *f
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
if ( SplitCommand( &curpos, cmd, args, sizeof( cmd ) ) )
{
if ( !wcscmp( cmd, findcmd ) )
{
@ -1424,7 +1430,7 @@ bool CHudCloseCaption::StreamHasCommand( const wchar_t *stream, const wchar_t *s
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
if ( SplitCommand( &curpos, cmd, args, sizeof( cmd ) ) )
{
if ( !wcscmp( cmd, search ) )
{
@ -1516,7 +1522,7 @@ void CHudCloseCaption::Process( const wchar_t *stream, float duration, const cha
const wchar_t *prevpos = curpos;
if ( SplitCommand( &curpos, cmd, args ) )
if ( SplitCommand( &curpos, cmd, args, sizeof( cmd ) ) )
{
if ( !wcscmp( cmd, L"delay" ) )
{
@ -1613,6 +1619,9 @@ struct WorkUnitParams
clr = Color( 255, 255, 255, 255 );
newline = false;
font = 0;
#ifdef MAPBASE
customFont = false;
#endif
}
~WorkUnitParams()
@ -1658,6 +1667,9 @@ struct WorkUnitParams
Color clr;
bool newline;
vgui::HFont font;
#ifdef MAPBASE
bool customFont;
#endif
};
void CHudCloseCaption::AddWorkUnit( CCloseCaptionItem *item,
@ -1717,7 +1729,7 @@ void CHudCloseCaption::ComputeStreamWork( int available_width, CCloseCaptionItem
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
if ( SplitCommand( &curpos, cmd, args, sizeof( cmd ) ) )
{
if ( !wcscmp( cmd, L"cr" ) )
{
@ -1772,27 +1784,58 @@ void CHudCloseCaption::ComputeStreamWork( int available_width, CCloseCaptionItem
{
AddWorkUnit( item, params );
params.italic = !params.italic;
#ifdef MAPBASE
params.customFont = false;
#endif
}
else if ( !wcscmp( cmd, L"B" ) )
{
AddWorkUnit( item, params );
params.bold = !params.bold;
#ifdef MAPBASE
params.customFont = false;
#endif
}
#ifdef MAPBASE
else if ( !wcscmp( cmd, L"font" ) )
{
AddWorkUnit( item, params );
vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() );
if ( args[0] != 0 )
{
char font[64];
g_pVGuiLocalize->ConvertUnicodeToANSI( args, font, sizeof( font ) );
params.font = pScheme->GetFont( font );
params.customFont = true;
}
else
{
params.customFont = false;
}
}
#endif
continue;
}
int font;
if ( IsPC() )
vgui::HFont useF = params.font;
#ifdef MAPBASE
if (params.customFont == false)
#endif
{
font = params.GetFontNumber();
int font;
if ( IsPC() )
{
font = params.GetFontNumber();
}
else
{
font = streamlen >= cc_smallfontlength.GetInt() ? CCFONT_SMALL : CCFONT_NORMAL;
}
useF = m_hFonts[font];
params.font = useF;
}
else
{
font = streamlen >= cc_smallfontlength.GetInt() ? CCFONT_SMALL : CCFONT_NORMAL;
}
vgui::HFont useF = m_hFonts[font];
params.font = useF;
int w, h;
@ -1940,7 +1983,7 @@ bool CHudCloseCaption::GetNoRepeatValue( const wchar_t *caption, float &retval )
wchar_t cmd[ 256 ];
wchar_t args[ 256 ];
if ( SplitCommand( &curpos, cmd, args ) )
if ( SplitCommand( &curpos, cmd, args, sizeof( cmd ) ) )
{
if ( !wcscmp( cmd, L"norepeat" ) )
{
@ -2631,6 +2674,124 @@ void CHudCloseCaption::InitCaptionDictionary( const char *dbfile )
g_AsyncCaptionResourceManager.SetDbInfo( m_AsyncCaptions );
}
#ifdef MAPBASE
void CHudCloseCaption::AddAdditionalCaptionDictionary( const char *dbfile, CUtlVector<CUtlSymbol> &outPathSymbols )
{
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Adding additional caption dictionary \"%s\"\n", dbfile );
g_AsyncCaptionResourceManager.Clear();
char searchPaths[4096];
filesystem->GetSearchPath( "MOD", true, searchPaths, sizeof( searchPaths ) );
for ( char *path = strtok( searchPaths, ";" ); path; path = strtok( NULL, ";" ) )
{
if ( IsX360() && ( filesystem->GetDVDMode() == DVDMODE_STRICT ) && !V_stristr( path, ".zip" ) )
{
// only want zip paths
continue;
}
char fullpath[MAX_PATH];
Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", path, dbfile );
Q_FixSlashes( fullpath );
if ( IsX360() )
{
char fullpath360[MAX_PATH];
UpdateOrCreateCaptionFile( fullpath, fullpath360, sizeof( fullpath360 ) );
Q_strncpy( fullpath, fullpath360, sizeof( fullpath ) );
}
// Seach for this dictionary. If it already exists, remove it.
for (int i = 0; i < m_AsyncCaptions.Count(); ++i)
{
if (FStrEq( m_AsyncCaptions[i].m_DataBaseFile.String(), fullpath ))
{
m_AsyncCaptions.Remove( i );
break;
}
}
FileHandle_t fh = filesystem->Open( fullpath, "rb" );
if ( FILESYSTEM_INVALID_HANDLE != fh )
{
MEM_ALLOC_CREDIT();
CUtlBuffer dirbuffer;
AsyncCaption_t& entry = m_AsyncCaptions[ m_AsyncCaptions.AddToTail() ];
// Read the header
filesystem->Read( &entry.m_Header, sizeof( entry.m_Header ), fh );
if ( entry.m_Header.magic != COMPILED_CAPTION_FILEID )
Error( "Invalid file id for %s\n", fullpath );
if ( entry.m_Header.version != COMPILED_CAPTION_VERSION )
Error( "Invalid file version for %s\n", fullpath );
if ( entry.m_Header.directorysize < 0 || entry.m_Header.directorysize > 64 * 1024 )
Error( "Invalid directory size %d for %s\n", entry.m_Header.directorysize, fullpath );
//if ( entry.m_Header.blocksize != MAX_BLOCK_SIZE )
// Error( "Invalid block size %d, expecting %d for %s\n", entry.m_Header.blocksize, MAX_BLOCK_SIZE, fullpath );
int directoryBytes = entry.m_Header.directorysize * sizeof( CaptionLookup_t );
entry.m_CaptionDirectory.EnsureCapacity( entry.m_Header.directorysize );
dirbuffer.EnsureCapacity( directoryBytes );
filesystem->Read( dirbuffer.Base(), directoryBytes, fh );
filesystem->Close( fh );
entry.m_CaptionDirectory.CopyArray( (const CaptionLookup_t *)dirbuffer.PeekGet(), entry.m_Header.directorysize );
entry.m_CaptionDirectory.RedoSort( true );
entry.m_DataBaseFile = fullpath;
outPathSymbols.AddToTail( entry.m_DataBaseFile );
}
}
g_AsyncCaptionResourceManager.SetDbInfo( m_AsyncCaptions );
}
void CHudCloseCaption::AddCustomCaptionFile( char const *file, CUtlVector<CUtlSymbol> &outPathSymbols )
{
//
// 'file' should be something like "maps/mapbase_demo01_closecaption_%language%"
//
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Adding custom caption file \"%s\"\n", file );
if (!IsX360())
{
g_pVGuiLocalize->AddFile( file, "MOD", true );
}
char uilanguage[64];
engine->GetUILanguage( uilanguage, sizeof( uilanguage ) );
char dbfile[512];
V_StrSubst( file, "%language%", uilanguage, dbfile, sizeof( dbfile ) );
V_SetExtension( dbfile, ".dat", sizeof( dbfile ) );
AddAdditionalCaptionDictionary( dbfile, outPathSymbols );
}
void CHudCloseCaption::RemoveCaptionDictionary( const CUtlSymbol &dbFileSymbol )
{
//
// 'file' should be something like "maps/mapbase_demo01_closecaption_%language%"
//
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Removing custom caption file \"%s\"\n", dbFileSymbol.String() );
for (int i = 0; i < m_AsyncCaptions.Count(); ++i)
{
if ( m_AsyncCaptions[i].m_DataBaseFile == dbFileSymbol )
{
m_AsyncCaptions.Remove( i );
break;
}
}
}
#endif
void CHudCloseCaption::OnFinishAsyncLoad( int nFileIndex, int nBlockNum, AsyncCaptionData_t *pData )
{
// Fill in data for all users of pData->m_nBlockNum

View File

@ -111,6 +111,11 @@ public:
void PlayRandomCaption();
void InitCaptionDictionary( char const *dbfile );
#ifdef MAPBASE
void AddAdditionalCaptionDictionary( char const *dbfile, CUtlVector<CUtlSymbol> &outPathSymbols );
void AddCustomCaptionFile( char const *file, CUtlVector<CUtlSymbol> &outPathSymbols );
void RemoveCaptionDictionary( const CUtlSymbol &dbFileSymbol );
#endif
void OnFinishAsyncLoad( int nFileIndex, int nBlockNum, AsyncCaptionData_t *pData );
void Flush();
@ -133,6 +138,11 @@ public:
void FindSound( char const *pchANSI );
#ifdef MAPBASE
inline bool IsUsingCommentaryDimensions() const { return m_bUsingCommentaryDimensions; }
inline void SetUsingCommentaryDimensions( bool bToggle ) { m_bUsingCommentaryDimensions = bToggle; }
#endif
public:
struct CaptionRepeat
@ -169,7 +179,7 @@ private:
void DrawStream( wrect_t& rect, wrect_t &rcWindow, CCloseCaptionItem *item, int iFadeLine, float flFadeLineAlpha );
void ComputeStreamWork( int available_width, CCloseCaptionItem *item );
bool SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t *args ) const;
bool SplitCommand( wchar_t const **ppIn, wchar_t *cmd, wchar_t *args, int size ) const;
bool StreamHasCommand( const wchar_t *stream, const wchar_t *findcmd ) const;
bool GetFloatCommandValue( const wchar_t *stream, const wchar_t *findcmd, float& value ) const;
@ -212,6 +222,10 @@ private:
bool m_bVisibleDueToDirect;
bool m_bPaintDebugInfo;
CUtlSymbol m_CurrentLanguage;
#ifdef MAPBASE
bool m_bUsingCommentaryDimensions;
#endif
};
#endif // HUD_CLOSECAPTION_H

View File

@ -528,15 +528,15 @@ void CLCD::ShowItems_R( CLCDPage *page, unsigned int dwCurTime, CUtlVector< CLCD
{
CLCDItem *newItem = NULL;
CLCDItem *item = ag->m_Definition[ r ];
switch ( item->m_Type )
CLCDItem *itemLocl = ag->m_Definition[ r ];
switch ( itemLocl->m_Type )
{
default:
break;
case LCDITEM_TEXT:
{
CLCDItemText *text = static_cast< CLCDItemText * >( item );
CLCDItemText *text = static_cast< CLCDItemText * >( itemLocl );
CUtlString s;
s = text->m_OriginalText;
Replace( s, prefix, s1 );
@ -551,7 +551,7 @@ void CLCD::ShowItems_R( CLCDPage *page, unsigned int dwCurTime, CUtlVector< CLCD
// text->m_OriginalText = s;
CLCDItemText *copy = static_cast< CLCDItemText * >( page->Alloc( item->m_Type ) );
CLCDItemText *copy = static_cast< CLCDItemText * >( page->Alloc( itemLocl->m_Type ) );
*copy = *text;
copy->m_bActive = true;
copy->m_OriginalText = s;
@ -564,8 +564,8 @@ void CLCD::ShowItems_R( CLCDPage *page, unsigned int dwCurTime, CUtlVector< CLCD
break;
case LCDITEM_ICON:
{
CLCDItemIcon *icon = static_cast< CLCDItemIcon * >( item );
CLCDItemIcon *copy = static_cast< CLCDItemIcon * >( page->Alloc( item->m_Type ) );
CLCDItemIcon *icon = static_cast< CLCDItemIcon * >( itemLocl );
CLCDItemIcon *copy = static_cast< CLCDItemIcon * >( page->Alloc( itemLocl->m_Type ) );
*copy = *icon;
copy->m_bActive = true;
copy->Create( m_lcd );
@ -1186,16 +1186,16 @@ void CLCD::DumpPlayer()
C_Team *team = player->GetTeam();
if ( team )
{
CDescribeData helper( team );
helper.DumpDescription( team->GetPredDescMap() );
CDescribeData helperLocl( team );
helperLocl.DumpDescription( team->GetPredDescMap() );
}
Msg( "(playerresource)\n\n" );
if ( g_PR )
{
CDescribeData helper( g_PR );
helper.DumpDescription( g_PR->GetPredDescMap() );
CDescribeData helperLocl( g_PR );
helperLocl.DumpDescription( g_PR->GetPredDescMap() );
}
Msg( "(localplayerweapon)\n\n" );
@ -1203,8 +1203,8 @@ void CLCD::DumpPlayer()
C_BaseCombatWeapon *active = player->GetActiveWeapon();
if ( active )
{
CDescribeData helper( active );
helper.DumpDescription( active->GetPredDescMap() );
CDescribeData helperLocl( active );
helperLocl.DumpDescription( active->GetPredDescMap() );
}
Msg( "Other replacements:\n\n" );

View File

@ -10,7 +10,7 @@
#include "iclientmode.h"
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IVGUI.h>
#include <vgui/IVGui.h>
#include <vgui_controls/EditablePanel.h>
#include <vgui_controls/Controls.h>
#include <vgui_controls/Label.h>

View File

@ -34,7 +34,7 @@
#define LOCATOR_ICON_FX_FADE_OUT 0x00000800 // Set when deactivated so it can smoothly vanish
#define LOCATOR_ICON_FX_FADE_IN 0x00001000 // Set when activated so it can smoothly appear
#include "tier1/UtlSymbol.h"
#include "tier1/utlsymbol.h"
// See comments in UtlSymbol on why this is useful
DECLARE_PRIVATE_SYMBOLTYPE( CGameInstructorSymbol );

View File

@ -21,9 +21,15 @@ static CPDumpPanel *g_pPDumpPanel = NULL;
// we pragma'd away in platform.h, so this little compiler specific hack will eliminate those warnings while
// retaining our own warning setup...ywb
#ifdef WIN32
#if _MSC_VER < 1900
#pragma warning( push )
#include <typeinfo.h>
#pragma warning( pop )
#else
#include <typeinfo>
#endif
#endif
using namespace vgui;

View File

@ -58,6 +58,9 @@ public:
// Hidden bits.
// HIDEHUD_ flags that note when this element should be hidden in the HUD
virtual void SetHiddenBits( int iBits );
#ifdef MAPBASE_VSCRIPT
int GetHiddenBits() const { return m_iHiddenBits; }
#endif
bool IsParentedToClientDLLRootPanel() const;
void SetParentedToClientDLLRootPanel( bool parented );

View File

@ -112,6 +112,11 @@ public:
virtual bool CanRecordDemo( char *errorMsg, int length ) const = 0;
#ifdef MAPBASE // From Alien Swarm SDK
virtual void OnColorCorrectionWeightsReset( void ) = 0;
virtual float GetColorCorrectionScale( void ) const = 0;
#endif
virtual void ComputeVguiResConditions( KeyValues *pkvConditions ) = 0;
//=============================================================================

View File

@ -25,7 +25,9 @@
#include "tier0/icommandline.h"
#include "inputsystem/iinputsystem.h"
#include "inputsystem/ButtonCode.h"
#if _MSC_VER < 1900
#include "math.h"
#endif
#include "tier1/convar_serverbounded.h"
#include "cam_thirdperson.h"

View File

@ -115,6 +115,13 @@ public:
virtual void SetScreenOverlayMaterial( IMaterial *pMaterial ) = 0;
virtual IMaterial *GetScreenOverlayMaterial( ) = 0;
#ifdef MAPBASE
virtual void SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial ) = 0;
virtual IMaterial *GetIndexedScreenOverlayMaterial( int i ) = 0;
virtual void ResetIndexedScreenOverlays() = 0;
virtual int GetMaxIndexedScreenOverlays() const = 0;
#endif
virtual void WriteSaveGameScreenshot( const char *pFilename ) = 0;
virtual void WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded = false, bool bWriteVTF = false ) = 0;

View File

@ -1,6 +1,6 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: Recreates Portal 2 linked_portal_door functionality using SDK code only.
// Purpose: Recreates Portal 2 linked_portal_door visual functionality using SDK code only.
// (basically a combination of point_camera and func_reflective_glass)
//
// $NoKeywords: $
@ -58,70 +58,11 @@ bool C_FuncFakeWorldPortal::ShouldDraw()
}
//-----------------------------------------------------------------------------
// Do we have a fake world portal in view?
//-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane )
{
// Early out if no cameras
C_FuncFakeWorldPortal *pReflectiveGlass = GetFakeWorldPortalList();
if ( !pReflectiveGlass )
return NULL;
Frustum_t frustum;
GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum );
cplane_t localPlane;
Vector vecOrigin, vecWorld, vecDelta, vecForward;
AngleVectors( view.angles, &vecForward, NULL, NULL );
for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext )
{
if ( pReflectiveGlass->IsDormant() )
continue;
if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) )
continue;
Vector vecMins, vecMaxs;
pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs );
if ( R_CullBox( vecMins, vecMaxs, frustum ) )
continue;
const model_t *pModel = pReflectiveGlass->GetModel();
const matrix3x4_t& mat = pReflectiveGlass->EntityToWorldTransform();
int nCount = modelinfo->GetBrushModelPlaneCount( pModel );
for ( int i = 0; i < nCount; ++i )
{
modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin );
MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space
VectorTransform( vecOrigin, mat, vecWorld );
if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane
continue;
VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull
if ( vecDelta.Dot( plane.normal ) >= 0 )
continue;
// Must have valid plane
if ( !pReflectiveGlass->m_hTargetPlane )
continue;
return pReflectiveGlass;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Iterates through fake world portals instead of just picking one
//-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, cplane_t &plane,
const Frustum_t &frustum )
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
Vector &vecAbsPlaneNormal, float &flLocalPlaneDist, const Frustum_t &frustum )
{
// Early out if no cameras
C_FuncFakeWorldPortal *pReflectiveGlass = NULL;
@ -130,8 +71,9 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
else
pReflectiveGlass = pStart->m_pNext;
cplane_t localPlane;
Vector vecOrigin, vecWorld, vecDelta;
cplane_t localPlane, worldPlane;
Vector vecMins, vecMaxs, vecLocalOrigin, vecAbsOrigin, vecDelta;
for ( ; pReflectiveGlass != NULL; pReflectiveGlass = pReflectiveGlass->m_pNext )
{
if ( pReflectiveGlass->IsDormant() )
@ -140,7 +82,10 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
if ( pReflectiveGlass->m_iViewHideFlags & (1 << CurrentViewID()) )
continue;
Vector vecMins, vecMaxs;
// Must have valid plane
if ( !pReflectiveGlass->m_hTargetPlane )
continue;
pReflectiveGlass->GetRenderBoundsWorldspace( vecMins, vecMaxs );
if ( R_CullBox( vecMins, vecMaxs, frustum ) )
continue;
@ -151,21 +96,21 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
int nCount = modelinfo->GetBrushModelPlaneCount( pModel );
for ( int i = 0; i < nCount; ++i )
{
modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecOrigin );
modelinfo->GetBrushModelPlane( pModel, i, localPlane, &vecLocalOrigin );
MatrixTransformPlane( mat, localPlane, plane ); // Transform to world space
VectorTransform( vecOrigin, mat, vecWorld );
MatrixTransformPlane( mat, localPlane, worldPlane ); // Transform to world space
if ( view.origin.Dot( plane.normal ) <= plane.dist ) // Check for view behind plane
if ( view.origin.Dot( worldPlane.normal ) <= worldPlane.dist ) // Check for view behind plane
continue;
VectorSubtract( vecWorld, view.origin, vecDelta ); // Backface cull
if ( vecDelta.Dot( plane.normal ) >= 0 )
VectorTransform( vecLocalOrigin, mat, vecAbsOrigin );
VectorSubtract( vecAbsOrigin, view.origin, vecDelta );
if ( vecDelta.Dot( worldPlane.normal ) >= 0 ) // Backface cull
continue;
// Must have valid plane
if ( !pReflectiveGlass->m_hTargetPlane )
continue;
flLocalPlaneDist = localPlane.dist;
vecAbsPlaneNormal = worldPlane.normal;
return pReflectiveGlass;
}

View File

@ -53,10 +53,8 @@ public:
//-----------------------------------------------------------------------------
// Do we have reflective glass in view? If so, what's the reflection plane?
//-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane );
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, cplane_t &plane,
const Frustum_t &frustum );
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
Vector &vecAbsPlaneNormal, float &flLocalPlaneDist, const Frustum_t &frustum );
#endif // C_FUNC_FAKE_WORLDPORTAL

View File

@ -0,0 +1,282 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: Displays easy, flexible VGui text. Mapbase equivalent of point_worldtext.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "panelmetaclassmgr.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include <vgui/IInput.h>
#include <vgui/IPanel.h>
#include <vgui/IVGui.h>
#include "ienginevgui.h"
#include "c_vguiscreen.h"
#include "vgui_bitmapbutton.h"
#include "vgui_bitmappanel.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// vgui_text_display
//-----------------------------------------------------------------------------
class C_VGuiTextDisplay : public C_BaseEntity
{
public:
DECLARE_CLASS( C_VGuiTextDisplay, C_BaseEntity );
DECLARE_CLIENTCLASS();
C_VGuiTextDisplay();
~C_VGuiTextDisplay();
virtual void PostDataUpdate( DataUpdateType_t updateType );
bool IsEnabled( void ) const { return m_bEnabled; }
const char *GetDisplayText( void ) const { return m_szDisplayText; }
const char *GetFontName( void ) const { return m_szFont; }
int GetResolution( void ) const { return m_iResolution; }
vgui::Label::Alignment GetContentAlignment() const { return m_iContentAlignment; }
bool NeedsTextUpdate() { return m_bTextNeedsUpdate; }
void UpdatedText() { m_bTextNeedsUpdate = false; }
private:
bool m_bEnabled;
char m_szDisplayText[256];
vgui::Label::Alignment m_iContentAlignment;
char m_szFont[64];
int m_iResolution;
bool m_bTextNeedsUpdate;
};
IMPLEMENT_CLIENTCLASS_DT( C_VGuiTextDisplay, DT_VGuiTextDisplay, CVGuiTextDisplay )
RecvPropBool( RECVINFO( m_bEnabled ) ),
RecvPropString( RECVINFO( m_szDisplayText ) ),
RecvPropInt( RECVINFO( m_iContentAlignment ) ),
RecvPropString( RECVINFO( m_szFont ) ),
RecvPropInt( RECVINFO( m_iResolution ) ),
END_RECV_TABLE()
C_VGuiTextDisplay::C_VGuiTextDisplay()
{
}
C_VGuiTextDisplay::~C_VGuiTextDisplay()
{
}
void C_VGuiTextDisplay::PostDataUpdate( DataUpdateType_t updateType )
{
BaseClass::PostDataUpdate( updateType );
// For now, always update
m_bTextNeedsUpdate = true;
}
using namespace vgui;
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class C_TextDisplayPanel : public CVGuiScreenPanel
{
DECLARE_CLASS( C_TextDisplayPanel, CVGuiScreenPanel );
public:
C_TextDisplayPanel( vgui::Panel *parent, const char *panelName );
~C_TextDisplayPanel( void );
virtual void ApplySchemeSettings( IScheme *pScheme );
void UpdateText();
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick( void );
virtual void Paint( void );
private:
CHandle<C_VGuiScreen> m_hVGUIScreen;
CHandle<C_VGuiTextDisplay> m_hScreenEntity;
// VGUI specifics
Label *m_pDisplayTextLabel;
};
DECLARE_VGUI_SCREEN_FACTORY( C_TextDisplayPanel, "text_display_panel" );
CUtlVector <C_TextDisplayPanel *> g_TextDisplays;
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
C_TextDisplayPanel::C_TextDisplayPanel( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "C_TextDisplayPanel"/*, vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/WorldTextPanel.res", "WorldTextPanel" )*/ )
{
// Add ourselves to the global list of movie displays
g_TextDisplays.AddToTail( this );
}
//-----------------------------------------------------------------------------
// Purpose: Clean up the movie
//-----------------------------------------------------------------------------
C_TextDisplayPanel::~C_TextDisplayPanel( void )
{
// Remove ourselves from the global list of movie displays
g_TextDisplays.FindAndRemove( this );
}
//-----------------------------------------------------------------------------
// Purpose: Setup our scheme
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::ApplySchemeSettings( IScheme *pScheme )
{
BaseClass::ApplySchemeSettings( pScheme );
/*
m_pDisplayTextLabel->SetFgColor( Color( 255, 255, 255, 255 ) );
m_pDisplayTextLabel->SetText( "" );
m_pDisplayTextLabel->SetVisible( false );
*/
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::UpdateText()
{
color32 clr = m_hScreenEntity->GetRenderColor();
m_pDisplayTextLabel->SetFgColor( Color( clr.r, clr.g, clr.b, clr.a ) );
m_pDisplayTextLabel->SetText( m_hScreenEntity->GetDisplayText() );
//SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
//m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
Label::Alignment iAlignment = m_hScreenEntity->GetContentAlignment();
switch (iAlignment)
{
// Use a special scaling method when using a south alignment
case Label::Alignment::a_southwest:
case Label::Alignment::a_south:
case Label::Alignment::a_southeast:
int lW, lT;
m_pDisplayTextLabel->GetContentSize( lW, lT );
SetSize( m_hScreenEntity->GetResolution(), lT );
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), lT );
float sW, sT;
m_hVGUIScreen->GetSize( sW, sT );
//Msg( "Screen width: %f, new height: %f\n", sW, sW * (lT / m_hScreenEntity->GetResolution()) );
m_hVGUIScreen->SetHeight( sW * ((float)lT / (float)m_hScreenEntity->GetResolution()) );
m_hVGUIScreen->SetPixelHeight( lT );
break;
default:
SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
break;
}
m_pDisplayTextLabel->SetContentAlignment( iAlignment );
bool bWrap = true;
bool bCenterWrap = false;
switch (iAlignment)
{
// Center wrap if centered
case Label::Alignment::a_north:
case Label::Alignment::a_center:
case Label::Alignment::a_south:
bCenterWrap = true;
break;
// HACKHACK: Don't wrap if using an east alignment
case Label::Alignment::a_northeast:
case Label::Alignment::a_east:
case Label::Alignment::a_southeast:
bWrap = false;
break;
}
m_pDisplayTextLabel->SetWrap( bWrap );
m_pDisplayTextLabel->SetCenterWrap( bCenterWrap );
//Msg( "Resolution is %i\n", m_hScreenEntity->GetResolution() );
const char *pszFontName = m_hScreenEntity->GetFontName();
if (pszFontName && pszFontName[0] != '\0')
{
HFont font = scheme()->GetIScheme( GetScheme() )->GetFont( pszFontName );
m_pDisplayTextLabel->SetFont( font );
}
m_pDisplayTextLabel->SetVisible( true );
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool C_TextDisplayPanel::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
if ( !BaseClass::Init( pKeyValues, pInitData ) )
return false;
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
m_pDisplayTextLabel = dynamic_cast<vgui::Label*>(FindChildByName( "TextDisplay" ));
// Save this for simplicity later on
m_hVGUIScreen = dynamic_cast<C_VGuiScreen *>( GetEntity() );
if ( m_hVGUIScreen != NULL )
{
// Also get the associated entity
m_hScreenEntity = dynamic_cast<C_VGuiTextDisplay *>(m_hVGUIScreen->GetOwnerEntity());
UpdateText();
}
return true;
}
//-----------------------------------------------------------------------------
// Update the display string
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::OnTick()
{
if (m_hScreenEntity->NeedsTextUpdate())
{
UpdateText();
m_hScreenEntity->UpdatedText();
}
BaseClass::OnTick();
}
ConVar r_vguitext_bg( "r_vguitext_bg", "0" );
//-----------------------------------------------------------------------------
// Purpose: Update and draw the frame
//-----------------------------------------------------------------------------
void C_TextDisplayPanel::Paint( void )
{
// Black out the background (we could omit drawing under the video surface, but this is straight-forward)
if ( r_vguitext_bg.GetBool() )
{
surface()->DrawSetColor( 0, 0, 0, 255 );
surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() );
//surface()->DrawSetColor( 64, 64, 64, 255 );
//surface()->DrawFilledRect( 0, 0, m_pDisplayTextLabel->GetWide(), m_pDisplayTextLabel->GetTall() );
}
// Parent's turn
BaseClass::Paint();
}

View File

@ -0,0 +1,280 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose: A utility which automatically generates HDR and LDR cubemaps.
// This has the following purposes:
//
// 1. Allow both HDR and LDR cubemaps to be generated automatically after a map is compiled
// 2. Have a way to batch build cubemaps for several levels at once
//
// Author: Blixibon
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "tier0/icommandline.h"
#include "igamesystem.h"
#include "filesystem.h"
#include "utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
extern const char *g_MapName;
ConVar autocubemap_hdr_do_both( "autocubemap_hdr_do_both", "1" );
ConVar autocubemap_hdr_value( "autocubemap_hdr_value", "2" );
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CAutoCubemapSystem : public CAutoGameSystem
{
public:
CAutoCubemapSystem() : CAutoGameSystem( "CAutoCubemapSystem" )
{
}
virtual bool Init()
{
const char *pszFile = NULL;
if (CommandLine()->CheckParm( "-autocubemap", &pszFile ))
{
if (!pszFile || pszFile[0] == '\0')
{
// Assume that we just want to autocubemap the first map we load
// (no code here for now)
}
else
{
LoadFile( pszFile );
}
// Begin autocubemap with the first level we load
m_bAutoCubemapOnFirstLevel = true;
}
return true;
}
virtual void LevelInitPostEntity()
{
if (m_bAutoCubemapActive)
{
if (m_bAutoCubemapBuildingCubemaps)
{
// Check if we need to do the other HDR level
if (autocubemap_hdr_do_both.GetBool() && !m_bAutoCubemapDoingBoth)
{
m_bAutoCubemapBuildingCubemaps = false;
m_bAutoCubemapDoingBoth = true;
// Change the HDR level and restart the map
//ConVarRef mat_hdr_level( "mat_hdr_level" );
engine->ClientCmd_Unrestricted( VarArgs( "toggle mat_hdr_level 0 %i; restart", autocubemap_hdr_value.GetInt() ) );
}
else
{
// Go to the next map
m_bAutoCubemapBuildingCubemaps = false;
m_bAutoCubemapDoingBoth = false;
m_AutoCubemapMapsIndex++;
if (m_AutoCubemapMapsIndex < m_AutoCubemapMaps.Count())
{
engine->ClientCmd_Unrestricted( VarArgs( "map %s", m_AutoCubemapMaps[m_AutoCubemapMapsIndex] ) );
}
else
{
// CUBEMAPPER FINISHED
m_AutoCubemapMaps.PurgeAndDeleteElements();
m_AutoCubemapMapsIndex = 0;
m_bAutoCubemapActive = false;
Msg( "CUBEMAPPER FINISHED\n" );
if (autocubemap_hdr_do_both.GetBool())
{
engine->ClientCmd_Unrestricted( VarArgs( "mat_hdr_level %i", m_iAutoCubemapUserHDRLevel ) );
}
}
}
}
else
{
// Build cubemaps for this map
m_bAutoCubemapBuildingCubemaps = true;
engine->ClientCmd_Unrestricted( "exec buildcubemaps_prep; buildcubemaps" );
}
}
else if (m_bAutoCubemapOnFirstLevel)
{
// Start autocubemap now
StartAutoCubemap();
m_bAutoCubemapOnFirstLevel = false;
}
}
//-------------------------------------------------------------------------------------
void StartAutoCubemap()
{
if (m_AutoCubemapMaps.Count() <= 0)
{
//Msg("No maps to cubemap with!\n");
//return;
// Just do this map
m_AutoCubemapMaps.AddToTail( strdup( g_MapName ) );
}
if (autocubemap_hdr_do_both.GetBool())
{
// Save the user's HDR level
ConVarRef mat_hdr_level( "mat_hdr_level" );
m_iAutoCubemapUserHDRLevel = mat_hdr_level.GetInt();
}
m_bAutoCubemapActive = true;
m_AutoCubemapMapsIndex = 0;
if (FStrEq( m_AutoCubemapMaps[m_AutoCubemapMapsIndex], g_MapName ))
{
// Build cubemaps right here, right now
m_bAutoCubemapBuildingCubemaps = true;
engine->ClientCmd_Unrestricted( "exec buildcubemaps_prep; buildcubemaps" );
}
else
{
// Go to that map
engine->ClientCmd_Unrestricted( VarArgs( "map %s", m_AutoCubemapMaps[m_AutoCubemapMapsIndex] ) );
}
}
void LoadFile( const char *pszFile )
{
KeyValues *pKV = new KeyValues( "AutoCubemap" );
if ( pKV->LoadFromFile( filesystem, pszFile, NULL ) )
{
KeyValues *pSubKey = pKV->GetFirstSubKey();
while ( pSubKey )
{
m_AutoCubemapMaps.AddToTail( strdup(pSubKey->GetName()) );
pSubKey = pSubKey->GetNextKey();
}
Msg( "Initted autocubemap\n" );
}
else
{
Warning( "Unable to load autocubemap file \"%s\"\n", pszFile );
}
pKV->deleteThis();
}
void Clear()
{
m_bAutoCubemapActive = false;
m_bAutoCubemapBuildingCubemaps = false;
m_bAutoCubemapDoingBoth = false;
m_AutoCubemapMaps.PurgeAndDeleteElements();
m_AutoCubemapMapsIndex = 0;
}
void PrintState()
{
char szCmd[1024] = { 0 };
if (m_AutoCubemapMaps.Count() > 0)
{
Q_strncpy( szCmd, "=== CUBEMAPPER MAP LIST ===\n", sizeof( szCmd ) );
FOR_EACH_VEC( m_AutoCubemapMaps, i )
{
Q_snprintf( szCmd, sizeof( szCmd ), "%s%s\n", szCmd, m_AutoCubemapMaps[i] );
}
Q_strncat( szCmd, "========================", sizeof( szCmd ), COPY_ALL_CHARACTERS );
Q_snprintf( szCmd, sizeof( szCmd ), "%s\nNumber of maps: %i (starting at %i)\n", szCmd, m_AutoCubemapMaps.Count(), m_AutoCubemapMapsIndex );
}
else
{
Q_strncat( szCmd, "========================\n", sizeof( szCmd ), COPY_ALL_CHARACTERS );
Q_strncat( szCmd, "There are no maps selected. Use 'autocubemap_init' to load a map list.\nIf 'autocubemap_start' is executed while no maps are selected, only the current map will have cubemaps generated.\n", sizeof( szCmd ), COPY_ALL_CHARACTERS );
Q_strncat( szCmd, "========================\n", sizeof( szCmd ), COPY_ALL_CHARACTERS );
}
Msg( "%s", szCmd );
}
//-------------------------------------------------------------------------------------
bool m_bAutoCubemapActive = false;
bool m_bAutoCubemapBuildingCubemaps = false;
bool m_bAutoCubemapDoingBoth = false;
int m_iAutoCubemapUserHDRLevel; // For setting the user back to the right HDR level when we're finished
// Start autocubemap with the first level we load (used for launch parameter)
bool m_bAutoCubemapOnFirstLevel = false;
CUtlVector<const char*> m_AutoCubemapMaps;
int m_AutoCubemapMapsIndex;
};
CAutoCubemapSystem g_AutoCubemapSystem;
CON_COMMAND( autocubemap_init, "Inits autocubemap" )
{
if (gpGlobals->maxClients > 1)
{
Msg( "Can't run autocubemap in multiplayer\n" );
return;
}
if (args.ArgC() <= 1)
{
Msg("Format: autocubemap_init <file name in the 'cfg' folder>\n");
return;
}
g_AutoCubemapSystem.LoadFile( args.Arg( 1 ) );
}
CON_COMMAND( autocubemap_print, "Prints current autocubemap information" )
{
if (gpGlobals->maxClients > 1)
{
Msg("Can't run autocubemap in multiplayer\n");
return;
}
g_AutoCubemapSystem.PrintState();
}
CON_COMMAND( autocubemap_clear, "Clears autocubemap stuff" )
{
if (gpGlobals->maxClients > 1)
{
Msg("Can't run autocubemap in multiplayer\n");
return;
}
g_AutoCubemapSystem.Clear();
}
CON_COMMAND( autocubemap_start, "Begins the autocubemap (it's recommended to check 'autocubemap_print' before running this command)" )
{
if (gpGlobals->maxClients > 1)
{
Msg("Can't run autocubemap in multiplayer\n");
return;
}
g_AutoCubemapSystem.StartAutoCubemap();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef VSCRIPT_VGUI_H
#define VSCRIPT_VGUI_H
#ifdef _WIN32
#pragma once
#endif
void RegisterScriptVGUI();
#endif

View File

@ -0,0 +1,394 @@
static const char* g_Script_vgui_init = R"script(
local DoCreateFont = ISurface.CreateFont;
ISurface.CreateFont <- function( name, props )
{
if ( !("name" in props) || typeof props.name != "string" )
throw "invalid parameter 'name'";
if ( !("tall" in props) || typeof props.tall != "integer" || !props.tall )
throw "invalid parameter 'tall'";
if ( !("weight" in props) || typeof props.weight != "integer" )
throw "invalid parameter 'weight'";
local yres_min = 0, yres_max = 0;
if ( "yres" in props && typeof props.yres == "string" )
{
local ss = ::split( props.yres, " " );
try
{
yres_min = ss[0].tointeger();
yres_max = ss[1].tointeger();
}
catch(x)
{
throw "invalid parameter 'yres'";
}
}
if ( ( (!("proportional" in props) || typeof props.proportional != "bool") ) && !yres_min )
{
throw "parameter 'proportional' or 'yres' not found";
}
else if ( "proportional" in props && props.proportional && yres_min )
{
throw "resolution definition on a proportional font"
}
local blur = 0, scanlines = 0, proportional = false, flags = 0;
if ( "blur" in props && typeof props.blur == "integer" )
blur = props.blur;
if ( "scanlines" in props && typeof props.scanlines == "integer" )
scanlines = props.scanlines;
if ( "proportional" in props && typeof props.proportional == "bool" )
proportional = props.proportional;
if ( "italic" in props && props.italic == true )
flags = flags | 0x001;
if ( "underline" in props && props.underline == true )
flags = flags | 0x002;
if ( "strikeout" in props && props.strikeout == true )
flags = flags | 0x004;
if ( "symbol" in props && props.symbol == true )
flags = flags | 0x008;
if ( "antialias" in props && props.antialias == true )
flags = flags | 0x010;
if ( "gaussianblur" in props && props.gaussianblur == true )
flags = flags | 0x020;
if ( "rotary" in props && props.rotary == true )
flags = flags | 0x040;
if ( "dropshadow" in props && props.dropshadow == true )
flags = flags | 0x080;
if ( "additive" in props && props.additive == true )
flags = flags | 0x100;
if ( "outline" in props && props.outline == true )
flags = flags | 0x200;
if ( "custom" in props && props.custom == true )
flags = flags | 0x400;
if ( "bitmap" in props && props.bitmap == true )
flags = flags | 0x800;
return DoCreateFont( name, props.name, props.tall, props.weight, blur, scanlines, flags, yres_min, yres_max, proportional );
}
local _Schemes = {}
local _FontTall = {}
local DoGetFont = ISurface.DoGetFont <- ISurface.GetFont;
local DoGetFontTall = ISurface.GetFontTall;
ISurface.GetFont <- function( name, proportional, sch = "" )
{
if ( sch in _Schemes )
{
local fonts = _Schemes[sch][proportional.tointeger()];
if ( name in fonts )
return fonts[name];
}
else
{
if ( typeof sch != "string" )
throw "invalid parameter 'scheme'";
_Schemes[sch] <- [{}, {}];
}
local id = DoGetFont( name, proportional, sch );
if ( id > 0 )
_Schemes[sch][proportional.tointeger()][name] <- id;
return id;
}
ISurface.GetFontTall <- function( id )
{
if ( id in _FontTall )
return _FontTall[id];
return _FontTall[id] <- DoGetFontTall( id );
}
local _Textures = {}
local DoGetTextureID = ISurface.GetTextureID;
local DoValidateTexture = ISurface.ValidateTexture;
local DoSetTextureFile = ISurface.SetTextureFile;
ISurface.ValidateTexture <- function( filename, hardwareFilter, forceReload = false, procedural = false )
{
return DoValidateTexture( filename, hardwareFilter, forceReload, procedural );
}
ISurface.SetTextureFile <- function( id, filename, hardwareFilter )
{
if ( filename in _Textures )
delete _Textures[filename];
return DoSetTextureFile( id, filename, hardwareFilter );
}
ISurface.GetTextureID <- function( name )
{
if ( name in _Textures )
return _Textures[name];
local id = DoGetTextureID( name );
if ( id > 0 )
_Textures[name] <- id;
return id;
}
// Forward compatibility
IVGui.GetRootPanel <- function() { return 1000 }
//IVGui.GetGameUIRootPanel <- function() { return 1001 }
IVGui.GetClientDLLRootPanel <- function() { return 1002 }
//IVGui.GetHudViewportPanel <- function() { return 1010 }
local CreatePanel = IVGui.CreatePanel;
IVGui.CreatePanel <- function( type, parent, name )
{
if ( !parent )
throw "invalid parent";
local root = 0;
if ( typeof parent == "integer" )
{
switch ( parent )
{
case 1000:
root = 0;
break;
case 1002:
root = 2;
break;
default:
throw "invalid parent";
}
parent = null;
}
return CreatePanel( type, parent, name, root );
}
ISurface.__OnScreenSizeChanged <- function()
{
_FontTall.clear();
}
// MAX_JOYSTICKS = 1 // ( 1 << MAX_SPLITSCREEN_CLIENT_BITS )
// MAX_JOYSTICK_AXES = 6 // X,Y,Z,R,U,V
// JOYSTICK_MAX_BUTTON_COUNT = 32
// JOYSTICK_POV_BUTTON_COUNT = 4
// JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2
enum ButtonCode
{
KEY_FIRST = 0
KEY_0 = 1
KEY_1 = 2
KEY_2 = 3
KEY_3 = 4
KEY_4 = 5
KEY_5 = 6
KEY_6 = 7
KEY_7 = 8
KEY_8 = 9
KEY_9 = 10
KEY_A = 11
KEY_B = 12
KEY_C = 13
KEY_D = 14
KEY_E = 15
KEY_F = 16
KEY_G = 17
KEY_H = 18
KEY_I = 19
KEY_J = 20
KEY_K = 21
KEY_L = 22
KEY_M = 23
KEY_N = 24
KEY_O = 25
KEY_P = 26
KEY_Q = 27
KEY_R = 28
KEY_S = 29
KEY_T = 30
KEY_U = 31
KEY_V = 32
KEY_W = 33
KEY_X = 34
KEY_Y = 35
KEY_Z = 36
KEY_PAD_0 = 37
KEY_PAD_1 = 38
KEY_PAD_2 = 39
KEY_PAD_3 = 40
KEY_PAD_4 = 41
KEY_PAD_5 = 42
KEY_PAD_6 = 43
KEY_PAD_7 = 44
KEY_PAD_8 = 45
KEY_PAD_9 = 46
KEY_PAD_DIVIDE = 47
KEY_PAD_MULTIPLY = 48
KEY_PAD_MINUS = 49
KEY_PAD_PLUS = 50
KEY_PAD_ENTER = 51
KEY_PAD_DECIMAL = 52
KEY_LBRACKET = 53
KEY_RBRACKET = 54
KEY_SEMICOLON = 55
KEY_APOSTROPHE = 56
KEY_BACKQUOTE = 57
KEY_COMMA = 58
KEY_PERIOD = 59
KEY_SLASH = 60
KEY_BACKSLASH = 61
KEY_MINUS = 62
KEY_EQUAL = 63
KEY_ENTER = 64
KEY_SPACE = 65
KEY_BACKSPACE = 66
KEY_TAB = 67
KEY_CAPSLOCK = 68
KEY_NUMLOCK = 69
KEY_ESCAPE = 70
KEY_SCROLLLOCK = 71
KEY_INSERT = 72
KEY_DELETE = 73
KEY_HOME = 74
KEY_END = 75
KEY_PAGEUP = 76
KEY_PAGEDOWN = 77
KEY_BREAK = 78
KEY_LSHIFT = 79
KEY_RSHIFT = 80
KEY_LALT = 81
KEY_RALT = 82
KEY_LCONTROL = 83
KEY_RCONTROL = 84
KEY_LWIN = 85
KEY_RWIN = 86
KEY_APP = 87
KEY_UP = 88
KEY_LEFT = 89
KEY_DOWN = 90
KEY_RIGHT = 91
KEY_F1 = 92
KEY_F2 = 93
KEY_F3 = 94
KEY_F4 = 95
KEY_F5 = 96
KEY_F6 = 97
KEY_F7 = 98
KEY_F8 = 99
KEY_F9 = 100
KEY_F10 = 101
KEY_F11 = 102
KEY_F12 = 103
KEY_CAPSLOCKTOGGLE = 104
KEY_NUMLOCKTOGGLE = 105
KEY_SCROLLLOCKTOGGLE = 106
KEY_LAST = 106
MOUSE_FIRST = 107
MOUSE_LEFT = 107
MOUSE_RIGHT = 108
MOUSE_MIDDLE = 109
MOUSE_4 = 110
MOUSE_5 = 111
MOUSE_WHEEL_UP = 112
MOUSE_WHEEL_DOWN = 113
MOUSE_LAST = 113
JOYSTICK_FIRST = 114
JOYSTICK_FIRST_BUTTON = 114
JOYSTICK_LAST_BUTTON = 145
JOYSTICK_FIRST_POV_BUTTON = 146
JOYSTICK_LAST_POV_BUTTON = 149
JOYSTICK_FIRST_AXIS_BUTTON = 150
JOYSTICK_LAST_AXIS_BUTTON = 161
JOYSTICK_LAST = 161
}
enum AnalogCode
{
MOUSE_X = 0
MOUSE_Y = 1
MOUSE_XY = 2
MOUSE_WHEEL = 3
JOYSTICK_FIRST_AXIS = 4
JOYSTICK_LAST_AXIS = 9
}
enum CursorCode
{
dc_none = 1
dc_arrow = 2
dc_ibeam = 3
dc_hourglass = 4
dc_waitarrow = 5
dc_crosshair = 6
dc_up = 7
dc_sizenwse = 8
dc_sizenesw = 9
dc_sizewe = 10
dc_sizens = 11
dc_sizeall = 12
dc_no = 13
dc_hand = 14
dc_blank = 15
}
enum Alignment
{
northwest = 0
north = 1
northeast = 2
west = 3
center = 4
east = 5
southwest = 6
south = 7
southeast = 8
}
if ( __Documentation.RegisterHelp != dummy )
{
local RegEnum = function( e )
{
local K = getconsttable()[e];
__Documentation.RegisterEnumHelp( e, K.len(), "" );
e += ".";
foreach ( s, v in K )
{
__Documentation.RegisterConstHelp( e+s, v, "" );
}
}
RegEnum( "ButtonCode" );
RegEnum( "AnalogCode" );
RegEnum( "CursorCode" );
RegEnum( "Alignment" );
__Documentation.RegisterHelp( "ISurface::CreateFont", "void ISurface::CreateFont(string, handle)", "" );
__Documentation.RegisterHelp( "IVGui::CreatePanel", "handle IVGui::CreatePanel(string, handle, string)", "" );
__Documentation.RegisterHelp( "IVGui::GetRootPanel", "handle IVGui::GetRootPanel()", "" );
__Documentation.RegisterHelp( "IVGui::GetClientDLLRootPanel", "handle IVGui::GetClientDLLRootPanel()", "" );
}
)script";

View File

@ -234,14 +234,6 @@ CPanelMetaClassMgrImp::CPanelMetaClassMgrImp() : m_PanelTypeDict( true, 0, 32 )
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
}

View File

@ -119,7 +119,7 @@ entities. Each one is useful under different conditions.
#include "tier0/fasttimer.h"
#include "utllinkedlist.h"
#include "utldict.h"
#ifdef WIN32
#if defined(WIN32) && _MSC_VER < 1900
#include <typeinfo.h>
#else
#include <typeinfo>

View File

@ -6,7 +6,7 @@
//=============================================================================//
#include "cbase.h"
#include "c_baseentity.h"
#ifdef WIN32
#if defined(WIN32) && _MSC_VER < 1900
#include <typeinfo.h>
#endif
#include "tier0/vprof.h"

View File

@ -704,9 +704,157 @@ void C_PhysPropClientside::ParseAllEntities(const char *pMapData)
}
}
#ifdef MAPBASE
CBaseAnimating *BreakModelCreate_Ragdoll( CBaseEntity *pOwnerEnt, breakmodel_t *pModel, const Vector &position, const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity )
{
C_BaseAnimating *pOwner = dynamic_cast<C_BaseAnimating *>( pOwnerEnt );
if ( !pOwner )
return NULL;
C_ClientRagdoll *pRagdoll = new C_ClientRagdoll( false );
if ( pRagdoll == NULL )
return NULL;
const char *pModelName = pModel->modelName;
if ( pRagdoll->InitializeAsClientEntity( pModelName, RENDER_GROUP_OPAQUE_ENTITY ) == false )
{
pRagdoll->Release();
return NULL;
}
pRagdoll->SetAbsOrigin( position );
pRagdoll->SetAbsAngles( angles );
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
matrix3x4_t currentBones[MAXSTUDIOBONES];
const float boneDt = 0.1f;
pRagdoll->SetParent( pOwner );
pRagdoll->ForceSetupBonesAtTime( boneDelta0, gpGlobals->curtime - boneDt );
pRagdoll->ForceSetupBonesAtTime( boneDelta1, gpGlobals->curtime );
pRagdoll->ForceSetupBonesAtTime( currentBones, gpGlobals->curtime );
pRagdoll->SetParent( NULL );
// We need to take these from the entity
//pRagdoll->SetAbsOrigin( position );
//pRagdoll->SetAbsAngles( angles );
pRagdoll->IgniteRagdoll( pOwner );
pRagdoll->TransferDissolveFrom( pOwner );
pRagdoll->InitModelEffects();
if ( pOwner->IsEffectActive( EF_NOSHADOW ) )
{
pRagdoll->AddEffects( EF_NOSHADOW );
}
pRagdoll->m_nRenderFX = kRenderFxRagdoll;
pRagdoll->SetRenderMode( pOwner->GetRenderMode() );
pRagdoll->SetRenderColor( pOwner->GetRenderColor().r, pOwner->GetRenderColor().g, pOwner->GetRenderColor().b, pOwner->GetRenderColor().a );
//pRagdoll->SetGlobalFadeScale( pOwner->GetGlobalFadeScale() );
pRagdoll->SetSkin( pOwner->GetSkin() );
//pRagdoll->m_vecForce = pOwner->m_vecForce;
//pRagdoll->m_nForceBone = 0; //pOwner->m_nForceBone;
pRagdoll->SetNextClientThink( CLIENT_THINK_ALWAYS );
pRagdoll->SetModelName( AllocPooledString( pModelName ) );
pRagdoll->ResetSequence( 0 );
pRagdoll->SetModelScale( pOwner->GetModelScale() );
pRagdoll->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
//pRagdoll->m_builtRagdoll = true;
CStudioHdr *hdr = pRagdoll->GetModelPtr();
if ( !hdr )
{
pRagdoll->Release();
Warning( "Couldn't create ragdoll gib for %s (no model pointer)\n", pModel->modelName );
return NULL;
}
pRagdoll->m_pRagdoll = CreateRagdoll(
pRagdoll,
hdr,
vec3_origin,
0,
boneDelta0,
boneDelta1,
currentBones,
boneDt );
if ( !pRagdoll->m_pRagdoll )
{
pRagdoll->Release();
Warning( "Couldn't create ragdoll gib for %s\n", pModel->modelName );
return NULL;
}
IPhysicsObject *pPhysicsObject = pRagdoll->VPhysicsGetObject();
if ( pPhysicsObject )
{
// randomize velocity by 5%
float rndf = RandomFloat( -0.025, 0.025 );
Vector rndVel = velocity + rndf*velocity;
pPhysicsObject->AddVelocity( &rndVel, &angVelocity );
}
pRagdoll->ApplyLocalAngularVelocityImpulse( angVelocity );
if ( pRagdoll->m_pRagdoll )
{
pRagdoll->m_bImportant = false;
pRagdoll->m_flForcedRetireTime = pModel->fadeTime > 0.0f ? gpGlobals->curtime + pModel->fadeTime : 0.0f;
s_RagdollLRU.MoveToTopOfLRU( pRagdoll, pRagdoll->m_bImportant, pRagdoll->m_flForcedRetireTime );
pRagdoll->m_bFadeOut = true;
}
// Cause the entity to recompute its shadow type and make a
// version which only updates when physics state changes
// NOTE: We have to do this after m_pRagdoll is assigned above
// because that's what ShadowCastType uses to figure out which type of shadow to use.
pRagdoll->DestroyShadow();
pRagdoll->CreateShadow();
pRagdoll->SetAbsOrigin( position );
pRagdoll->SetAbsAngles( angles );
pRagdoll->SetPlaybackRate( 0 );
pRagdoll->SetCycle( 0 );
// put into ACT_DIERAGDOLL if it exists, otherwise use sequence 0
int nSequence = pRagdoll->SelectWeightedSequence( ACT_DIERAGDOLL );
if ( nSequence < 0 )
{
pRagdoll->ResetSequence( 0 );
}
else
{
pRagdoll->ResetSequence( nSequence );
}
pRagdoll->UpdatePartitionListEntry();
pRagdoll->MarkRenderHandleDirty();
NoteRagdollCreationTick( pRagdoll );
//pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
return pRagdoll;
}
#endif
CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position,
const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, int nSkin, const breakablepropparams_t &params )
{
#ifdef MAPBASE
if ( pModel->isRagdoll )
{
CBaseEntity *pEntity = BreakModelCreate_Ragdoll( pOwner, pModel, position, angles, velocity, angVelocity );
return pEntity;
}
#endif
C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew();
if ( !pEntity )
@ -778,10 +926,12 @@ CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel,
pEntity->SetFadeMinMax( pModel->fadeMinDist, pModel->fadeMaxDist );
}
#ifndef MAPBASE
if ( pModel->isRagdoll )
{
DevMsg( "BreakModelCreateSingle: clientside doesn't support ragdoll breakmodels.\n" );
}
#endif
IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();

View File

@ -12,6 +12,9 @@
#include "materialsystem/imaterialsystem.h"
#include "functionproxy.h"
#include "toolframework_client.h"
#ifdef MAPBASE
#include "view.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@ -521,4 +524,100 @@ void CPlayerLogoOnModelProxy::OnBind( void *pC_BaseEntity )
}
EXPOSE_INTERFACE( CPlayerLogoOnModelProxy, IMaterialProxy, "PlayerLogoOnModel" IMATERIAL_PROXY_INTERFACE_VERSION );
*/
*/
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Returns the proximity of the current view to the entity
//-----------------------------------------------------------------------------
class CViewProximityProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
float m_Factor;
};
bool CViewProximityProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
m_Factor = pKeyValues->GetFloat( "scale", 0.002 );
return true;
}
void CViewProximityProxy::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
// Find the distance between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
Vector delta;
VectorSubtract( pEntity->WorldSpaceCenter(), CurrentViewOrigin(), delta );
Assert( m_pResult );
SetFloatResult( delta.Length() * m_Factor );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CViewProximityProxy, IMaterialProxy, "ViewProximity" IMATERIAL_PROXY_INTERFACE_VERSION );
//-----------------------------------------------------------------------------
// Returns the current view direction
//-----------------------------------------------------------------------------
class CViewDirectionProxy : public CResultProxy
{
public:
bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
void OnBind( void *pC_BaseEntity );
private:
float m_Factor;
};
bool CViewDirectionProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
if (!CResultProxy::Init( pMaterial, pKeyValues ))
return false;
m_Factor = pKeyValues->GetFloat( "scale", 2 );
return true;
}
void CViewDirectionProxy::OnBind( void *pC_BaseEntity )
{
if (!pC_BaseEntity)
return;
// Find the view angle between the player and this entity....
C_BaseEntity *pEntity = BindArgToEntity( pC_BaseEntity );
Vector delta;
Vector forward;
VectorSubtract( pEntity->WorldSpaceCenter(), CurrentViewOrigin(), delta );
VectorNormalize( delta );
forward = CurrentViewForward();
Assert( m_pResult );
SetFloatResult( DotProduct( forward, delta ) * m_Factor );
if ( ToolsEnabled() )
{
ToolFramework_RecordMaterialParams( GetMaterial() );
}
}
EXPOSE_INTERFACE( CViewDirectionProxy, IMaterialProxy, "ViewDirection" IMATERIAL_PROXY_INTERFACE_VERSION );
#endif

View File

@ -69,6 +69,16 @@ BEGIN_SIMPLE_DATADESC( CRagdoll )
DEFINE_RAGDOLL_ELEMENT( 21 ),
DEFINE_RAGDOLL_ELEMENT( 22 ),
DEFINE_RAGDOLL_ELEMENT( 23 ),
#ifdef MAPBASE
DEFINE_RAGDOLL_ELEMENT( 24 ),
DEFINE_RAGDOLL_ELEMENT( 25 ),
DEFINE_RAGDOLL_ELEMENT( 26 ),
DEFINE_RAGDOLL_ELEMENT( 27 ),
DEFINE_RAGDOLL_ELEMENT( 28 ),
DEFINE_RAGDOLL_ELEMENT( 29 ),
DEFINE_RAGDOLL_ELEMENT( 30 ),
DEFINE_RAGDOLL_ELEMENT( 31 ),
#endif
END_DATADESC()
@ -477,6 +487,9 @@ int C_ServerRagdoll::InternalDrawModel( int flags )
return ret;
}
#ifdef MAPBASE
static ConVar g_ragdoll_server_snatch_instance( "g_ragdoll_server_snatch_instance", "1", FCVAR_NONE, "Allows serverside ragdolls to snatch their source entities' model instances in the same way clientside ragdolls do, thereby retaining decals." );
#endif
CStudioHdr *C_ServerRagdoll::OnNewModel( void )
{
@ -499,6 +512,26 @@ CStudioHdr *C_ServerRagdoll::OnNewModel( void )
m_iv_ragAngles.SetMaxCount( m_elementCount );
}
#ifdef MAPBASE
if ( GetOwnerEntity() )
{
if (GetOwnerEntity()->GetModelName() == GetModelName())
{
// TODO: Is there a better place for this?
if (GetOwnerEntity()->GetBaseAnimating())
GetOwnerEntity()->GetBaseAnimating()->m_pServerRagdoll = this;
if (g_ragdoll_server_snatch_instance.GetBool())
{
GetOwnerEntity()->SnatchModelInstance( this );
}
}
}
// Add server ragdolls to the creation tick list
NoteRagdollCreationTick( this );
#endif
return hdr;
}

View File

@ -121,7 +121,7 @@ char *CHudTextMessage::BufferedLocaliseTextString( const char *msg )
char *CHudTextMessage::LookupString( const char *msg, int *msg_dest )
{
if ( !msg )
return "";
return (char*)"";
// '#' character indicates this is a reference to a string in titles.txt, and not the string itself
if ( msg[0] == '#' )

View File

@ -129,7 +129,7 @@ void CDebugOverlay::Paint()
{
float xPos = screenPos[0];
float yPos = screenPos[1]+ (pCurrText->lineOffset*13); // Line spacing;
g_pMatSystemSurface->DrawColoredText( m_hFont, xPos, yPos, r, g, b, a, pCurrText->text );
g_pMatSystemSurface->DrawColoredText( m_hFont, xPos, yPos, r, g, b, a, "%s", pCurrText->text );
}
}
else
@ -138,7 +138,7 @@ void CDebugOverlay::Paint()
{
float xPos = screenPos[0];
float yPos = screenPos[1]+ (pCurrText->lineOffset*13); // Line spacing;
g_pMatSystemSurface->DrawColoredText( m_hFont, xPos, yPos, r, g, b, a, pCurrText->text );
g_pMatSystemSurface->DrawColoredText( m_hFont, xPos, yPos, r, g, b, a, "%s", pCurrText->text );
}
}
}

View File

@ -0,0 +1,442 @@
//========= Copyright © 1996-2009, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "cbase.h"
#include "c_vguiscreen.h"
#include "vgui_controls/Label.h"
#include "vgui_bitmappanel.h"
#include <vgui/IVGui.h>
#include "c_slideshow_display.h"
#include "ienginevgui.h"
#include "fmtstr.h"
#include "vgui_controls/ImagePanel.h"
#include <vgui/ISurface.h>
#include "video/ivideoservices.h"
#include "engine/IEngineSound.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "c_movie_display.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
using namespace vgui;
struct VideoPlaybackInfo_t
{
VideoPlaybackInfo_t( void ) :
m_pMaterial ( NULL ),
m_nSourceHeight(0), m_nSourceWidth(0),
m_flU(0.0f),m_flV(0.0f) {}
IMaterial *m_pMaterial;
int m_nSourceHeight, m_nSourceWidth; // Source movie's dimensions
float m_flU, m_flV; // U,V ranges for video on its sheet
};
//-----------------------------------------------------------------------------
// Control screen
//-----------------------------------------------------------------------------
class CMovieDisplayScreen : public CVGuiScreenPanel
{
DECLARE_CLASS( CMovieDisplayScreen, CVGuiScreenPanel );
public:
CMovieDisplayScreen( vgui::Panel *parent, const char *panelName );
~CMovieDisplayScreen( void );
virtual void ApplySchemeSettings( IScheme *pScheme );
virtual bool Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData );
virtual void OnTick( void );
virtual void Paint( void );
private:
bool IsActive( void );
void SetupMovie( void );
void UpdateMovie( void );
bool BeginPlayback( const char *pFilename );
void CalculatePlaybackDimensions( int nSrcWidth, int nSrcHeight );
inline void GetPanelPos( int &xpos, int &ypos )
{
xpos = ( (float) ( GetWide() - m_nPlaybackWidth ) / 2 );
ypos = ( (float) ( GetTall() - m_nPlaybackHeight ) / 2 );
}
private:
// BINK playback info
IVideoMaterial *m_VideoMaterial;
VideoPlaybackInfo_t m_playbackInfo;
CHandle<C_VGuiScreen> m_hVGUIScreen;
CHandle<C_MovieDisplay> m_hScreenEntity;
int m_nTextureId;
int m_nPlaybackHeight; // Playback dimensions (proper ration adjustments)
int m_nPlaybackWidth;
bool m_bBlackBackground;
bool m_bSlaved;
bool m_bInitialized;
bool m_bLastActiveState; // HACK: I'd rather get a real callback...
// VGUI specifics
Label *m_pDisplayTextLabel;
Color m_cDefault;
Color m_cInvisible;
bool bIsAlreadyVisible;
};
DECLARE_VGUI_SCREEN_FACTORY( CMovieDisplayScreen, "movie_display_screen" );
CUtlVector <CMovieDisplayScreen *> g_MovieDisplays;
//-----------------------------------------------------------------------------
// Constructor:
//-----------------------------------------------------------------------------
CMovieDisplayScreen::CMovieDisplayScreen( vgui::Panel *parent, const char *panelName )
: BaseClass( parent, "CMovieDisplayScreen", vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/MovieDisplayScreen.res", "MovieDisplayScreen" ) )
{
m_pDisplayTextLabel = new vgui::Label( this, "NumberDisplay", "testing!");
m_VideoMaterial = NULL;
m_nTextureId = -1;
m_bBlackBackground = true;
m_bSlaved = false;
m_bInitialized = false;
// Add ourselves to the global list of movie displays
g_MovieDisplays.AddToTail( this );
//m_VideoMaterial->SetMuted(true);
m_bLastActiveState = IsActive();
}
//-----------------------------------------------------------------------------
// Purpose: Clean up the movie
//-----------------------------------------------------------------------------
CMovieDisplayScreen::~CMovieDisplayScreen( void )
{
if ( g_pVideo != NULL && m_VideoMaterial != NULL )
{
g_pVideo->DestroyVideoMaterial( m_VideoMaterial );
m_VideoMaterial = NULL;
}
// Clean up our texture reference
g_pMatSystemSurface->DestroyTextureID( m_nTextureId );
// Remove ourselves from the global list of movie displays
g_MovieDisplays.FindAndRemove( this );
}
//-----------------------------------------------------------------------------
// Purpose: Setup our scheme
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::ApplySchemeSettings( IScheme *pScheme )
{
assert( pScheme );
m_cDefault = Color( 255, 255, 255, 255 );
m_cInvisible = Color( 0, 0, 0, 0 );
m_pDisplayTextLabel->SetFgColor( m_cDefault );
m_pDisplayTextLabel->SetText( "" );
m_pDisplayTextLabel->SetVisible( false );
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CMovieDisplayScreen::Init( KeyValues* pKeyValues, VGuiScreenInitData_t* pInitData )
{
// Make sure we get ticked...
vgui::ivgui()->AddTickSignal( GetVPanel() );
if ( !BaseClass::Init( pKeyValues, pInitData ) )
return false;
// Save this for simplicity later on
m_hVGUIScreen = dynamic_cast<C_VGuiScreen *>( GetEntity() );
if ( m_hVGUIScreen != NULL )
{
// Also get the associated entity
m_hScreenEntity = dynamic_cast<C_MovieDisplay *>(m_hVGUIScreen->GetOwnerEntity());
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Helper function to check our active state
//-----------------------------------------------------------------------------
bool CMovieDisplayScreen::IsActive( void )
{
bool bScreenActive = false;
if ( m_hVGUIScreen != NULL )
{
bScreenActive = m_hVGUIScreen->IsActive();
}
return bScreenActive;
}
//-----------------------------------------------------------------------------
// Purpose: Either become the master of a group of screens, or become a slave to another
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::SetupMovie( void )
{
// Only bother if we haven't been setup yet
if ( m_bInitialized )
return;
const char *szGroupName = m_hScreenEntity->GetGroupName();
CMovieDisplayScreen *pMasterScreen = NULL;
for ( int i = 0; i < g_MovieDisplays.Count(); i++ )
{
// Must be valid and not us
if ( g_MovieDisplays[i] == NULL || g_MovieDisplays[i] == this )
continue;
// Must have an associated movie entity
if ( g_MovieDisplays[i]->m_hScreenEntity == NULL )
continue;
// Must have a group name to care
if ( szGroupName[0] == NULL )
continue;
// Group names must match!
// FIXME: Use an ID instead?
const char *szTestGroupName = g_MovieDisplays[i]->m_hScreenEntity->GetGroupName();
if ( Q_strnicmp( szTestGroupName, szGroupName, 128 ) )
continue;
// See if we've found a master display
if ( g_MovieDisplays[i]->m_bInitialized && g_MovieDisplays[i]->m_bSlaved == false )
{
m_bSlaved = true;
// Share the info from the master
m_playbackInfo = g_MovieDisplays[i]->m_playbackInfo;
// We need to calculate our own playback dimensions as we may be a different size than our parent
CalculatePlaybackDimensions( m_playbackInfo.m_nSourceWidth, m_playbackInfo.m_nSourceHeight );
// Bind our texture
m_nTextureId = surface()->CreateNewTextureID( true );
g_pMatSystemSurface->DrawSetTextureMaterial( m_nTextureId, m_playbackInfo.m_pMaterial );
// Hold this as the master screen
pMasterScreen = g_MovieDisplays[i];
break;
}
}
// We need to try again, we have no screen entity!
if ( m_hScreenEntity == NULL )
return;
// No master found, become one
if ( pMasterScreen == NULL )
{
const char *szFilename = m_hScreenEntity->GetMovieFilename();
BeginPlayback( szFilename );
m_bSlaved = false;
}
// Done
m_bInitialized = true;
}
//-----------------------------------------------------------------------------
// Purpose: Deal with the details of the video playback
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::UpdateMovie( void )
{
// Only the master in a group updates the bink file
if ( m_bSlaved )
return;
if ( m_VideoMaterial == NULL )
return;
// Get the current activity state of the screen
bool bScreenActive = IsActive();
// Pause if the game has paused
if ( engine->IsPaused() || engine->Con_IsVisible() )
{
bScreenActive = false;
}
// See if we've changed our activity state
if ( bScreenActive != m_bLastActiveState )
{
m_VideoMaterial->SetPaused( !bScreenActive );
}
// Updated
m_bLastActiveState = bScreenActive;
// Update the frame if we're currently enabled
if ( bScreenActive )
{
// Update our frame
if ( m_VideoMaterial->Update() == false )
{
// Issue a close command
// OnVideoOver();
// StopPlayback();
}
if (!m_hScreenEntity->IsMuted())
{
m_VideoMaterial->SetMuted(false);
}
}
}
//-----------------------------------------------------------------------------
// Update the display string
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::OnTick()
{
BaseClass::OnTick();
// Create our playback or slave to another screen already playing
SetupMovie();
// Now update the movie
UpdateMovie();
}
//-----------------------------------------------------------------------------
// Purpose: Adjust the playback dimensions to properly account for our screen dimensions
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::CalculatePlaybackDimensions( int nSrcWidth, int nSrcHeight )
{
float flFrameRatio = ( (float) GetWide() / (float) GetTall() );
float flVideoRatio = ( (float) nSrcWidth / (float) nSrcHeight );
if ( flVideoRatio > flFrameRatio )
{
m_nPlaybackWidth = GetWide();
m_nPlaybackHeight = ( GetWide() / flVideoRatio );
}
else if ( flVideoRatio < flFrameRatio )
{
m_nPlaybackWidth = ( GetTall() * flVideoRatio );
m_nPlaybackHeight = GetTall();
}
else
{
m_nPlaybackWidth = GetWide();
m_nPlaybackHeight = GetTall();
}
}
//-----------------------------------------------------------------------------
// Purpose: Begins playback of a movie
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CMovieDisplayScreen::BeginPlayback( const char *pFilename )
{
// need working video services
if ( g_pVideo == NULL )
return false;
// Create a new video material
if ( m_VideoMaterial != NULL )
{
g_pVideo->DestroyVideoMaterial( m_VideoMaterial );
m_VideoMaterial = NULL;
}
// Create a globally unique name for this material
char szMaterialName[256];
// Append our group name if we have one
const char *szGroupName = m_hScreenEntity->GetGroupName();
if ( szGroupName[0] != NULL )
{
Q_snprintf( szMaterialName, sizeof(szMaterialName), "%s_%s", pFilename, szGroupName );
}
else
{
Q_snprintf( szMaterialName, sizeof(szMaterialName), "%s_%s", pFilename, m_hScreenEntity->GetEntityName() );
}
m_VideoMaterial = g_pVideo->CreateVideoMaterial( szMaterialName, pFilename, "GAME",
VideoPlaybackFlags::DEFAULT_MATERIAL_OPTIONS,
VideoSystem::DETERMINE_FROM_FILE_EXTENSION/*, m_bAllowAlternateMedia*/ );
if ( m_VideoMaterial == NULL )
return false;
m_VideoMaterial->SetMuted(true); // FIXME: Allow?
if ( m_hScreenEntity->IsLooping() )
{
m_VideoMaterial->SetLooping( true );
}
if ( m_VideoMaterial->HasAudio())
{
// We want to be the sole audio source
enginesound->NotifyBeginMoviePlayback();
}
// Get our basic info from the movie
m_VideoMaterial->GetVideoImageSize( &m_playbackInfo.m_nSourceWidth, &m_playbackInfo.m_nSourceHeight );
m_VideoMaterial->GetVideoTexCoordRange( &m_playbackInfo.m_flU, &m_playbackInfo.m_flV );
m_playbackInfo.m_pMaterial = m_VideoMaterial->GetMaterial();
// Get our playback dimensions
CalculatePlaybackDimensions( m_playbackInfo.m_nSourceWidth, m_playbackInfo.m_nSourceHeight );
// Bind our texture
m_nTextureId = surface()->CreateNewTextureID( true );
g_pMatSystemSurface->DrawSetTextureMaterial( m_nTextureId, m_playbackInfo.m_pMaterial );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Update and draw the frame
//-----------------------------------------------------------------------------
void CMovieDisplayScreen::Paint( void )
{
// Masters must keep the video updated
if ( m_bSlaved == false && m_VideoMaterial == NULL )
{
BaseClass::Paint();
return;
}
// Sit in the "center"
int xpos, ypos;
GetPanelPos( xpos, ypos );
// Black out the background (we could omit drawing under the video surface, but this is straight-forward)
if ( m_bBlackBackground )
{
surface()->DrawSetColor( 0, 0, 0, 255 );
surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() );
}
// Draw it
surface()->DrawSetTexture( m_nTextureId );
surface()->DrawSetColor( 255, 255, 255, 255 );
surface()->DrawTexturedSubRect( xpos, ypos, xpos+m_nPlaybackWidth, ypos+m_nPlaybackHeight, 0.0f, 0.0f, m_playbackInfo.m_flU, m_playbackInfo.m_flV );
// Parent's turn
BaseClass::Paint();
}

View File

@ -16,20 +16,59 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
static CUtlVector< VideoPanel * > g_vecVideoPanels;
// Thiis is a hack due to the fact that the user can type quit with the video panel up, but it's parented to the GameUI dll root panel, which is already gone so
// we would crash in the destructor
void VGui_ClearVideoPanels()
{
for ( int i = g_vecVideoPanels.Count() - 1; i >= 0; --i )
{
if ( g_vecVideoPanels[ i ] )
{
delete g_vecVideoPanels[ i ];
}
}
g_vecVideoPanels.RemoveAll();
}
struct VideoPanelParms_t
{
VideoPanelParms_t( bool _interrupt = true, bool _loop = false, bool _mute = false )
{
bAllowInterrupt = _interrupt;
bLoop = _loop;
bMute = _mute;
}
bool bAllowInterrupt;
bool bLoop;
bool bMute;
//float flFadeIn;
//float flFadeOut;
};
VideoPanel::VideoPanel( unsigned int nXPos, unsigned int nYPos, unsigned int nHeight, unsigned int nWidth, bool allowAlternateMedia ) :
BaseClass( NULL, "VideoPanel" ),
m_VideoMaterial( NULL ),
m_nPlaybackWidth( 0 ),
m_nPlaybackHeight( 0 ),
m_bAllowAlternateMedia( allowAlternateMedia )
m_nShutdownCount( 0 ),
m_bLooping( false ),
m_bStopAllSounds( true ),
m_bAllowInterruption( true ),
m_bAllowAlternateMedia( allowAlternateMedia ),
m_bStarted( false )
{
#ifdef MAPBASE
vgui::VPANEL pParent = enginevgui->GetPanel( PANEL_ROOT );
#else
vgui::VPANEL pParent = enginevgui->GetPanel( PANEL_GAMEUIDLL );
#endif
SetParent( pParent );
SetVisible( false );
@ -53,6 +92,11 @@ VideoPanel::VideoPanel( unsigned int nXPos, unsigned int nYPos, unsigned int nHe
SetScheme(vgui::scheme()->LoadSchemeFromFile( "resource/VideoPanelScheme.res", "VideoPanelScheme"));
LoadControlSettings("resource/UI/VideoPanel.res");
// Let us update
vgui::ivgui()->AddTickSignal( GetVPanel() );
g_vecVideoPanels.AddToTail( this );
}
//-----------------------------------------------------------------------------
@ -60,6 +104,8 @@ VideoPanel::VideoPanel( unsigned int nXPos, unsigned int nYPos, unsigned int nHe
//-----------------------------------------------------------------------------
VideoPanel::~VideoPanel( void )
{
g_vecVideoPanels.FindAndRemove( this );
SetParent( (vgui::Panel *) NULL );
// Shut down this video, destroy the video material
@ -70,13 +116,39 @@ VideoPanel::~VideoPanel( void )
}
}
//-----------------------------------------------------------------------------
// Purpose: Keeps a tab on when the movie is ending and allows a frame to pass to prevent threading issues
//-----------------------------------------------------------------------------
void VideoPanel::OnTick( void )
{
if ( m_nShutdownCount > 0 )
{
m_nShutdownCount++;
if ( m_nShutdownCount > 10 )
{
OnClose();
m_nShutdownCount = 0;
}
}
BaseClass::OnTick();
}
void VideoPanel::OnVideoOver()
{
StopPlayback();
}
//-----------------------------------------------------------------------------
// Purpose: Begins playback of a movie
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool VideoPanel::BeginPlayback( const char *pFilename )
{
// Who the heck hacked this in?
if ( !pFilename || pFilename[ 0 ] == '\0' )
return false;
#ifdef _X360
XVIDEO_MODE videoMode;
XGetVideoMode( &videoMode );
@ -106,9 +178,25 @@ bool VideoPanel::BeginPlayback( const char *pFilename )
if ( m_VideoMaterial == NULL )
return false;
if ( m_bLooping )
{
m_VideoMaterial->SetLooping( true );
}
#ifdef MAPBASE
if ( m_bMuted )
{
m_VideoMaterial->SetMuted( true );
}
#endif
m_bStarted = true;
// We want to be the sole audio source
// FIXME: This may not always be true!
enginesound->NotifyBeginMoviePlayback();
if ( m_bStopAllSounds )
{
enginesound->NotifyBeginMoviePlayback();
}
int nWidth, nHeight;
m_VideoMaterial->GetVideoImageSize( &nWidth, &nHeight );
@ -168,9 +256,10 @@ void VideoPanel::DoModal( void )
//-----------------------------------------------------------------------------
void VideoPanel::OnKeyCodeTyped( vgui::KeyCode code )
{
if ( code == KEY_ESCAPE )
bool bInterruptKeyPressed = ( code == KEY_ESCAPE );
if ( m_bAllowInterruption && bInterruptKeyPressed )
{
OnClose();
StopPlayback();
}
else
{
@ -181,34 +270,54 @@ void VideoPanel::OnKeyCodeTyped( vgui::KeyCode code )
//-----------------------------------------------------------------------------
// Purpose: Handle keys that should cause us to close
//-----------------------------------------------------------------------------
void VideoPanel::OnKeyCodePressed( vgui::KeyCode code )
void VideoPanel::OnKeyCodePressed( vgui::KeyCode keycode )
{
vgui::KeyCode code = GetBaseButtonCode( keycode );
// All these keys will interrupt playback
bool bInterruptKeyPressed = ( code == KEY_ESCAPE ||
code == KEY_BACKQUOTE ||
code == KEY_SPACE ||
code == KEY_ENTER ||
code == KEY_XBUTTON_A ||
code == KEY_XBUTTON_B ||
code == KEY_XBUTTON_X ||
code == KEY_XBUTTON_Y ||
code == KEY_XBUTTON_START ||
code == KEY_XBUTTON_BACK );
// These keys cause the panel to shutdown
if ( code == KEY_ESCAPE ||
code == KEY_BACKQUOTE ||
code == KEY_SPACE ||
code == KEY_ENTER ||
code == KEY_XBUTTON_A ||
code == KEY_XBUTTON_B ||
code == KEY_XBUTTON_X ||
code == KEY_XBUTTON_Y ||
code == KEY_XBUTTON_START ||
code == KEY_XBUTTON_BACK )
if ( m_bAllowInterruption && bInterruptKeyPressed )
{
OnClose();
StopPlayback();
}
else
{
BaseClass::OnKeyCodePressed( code );
BaseClass::OnKeyCodePressed( keycode );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void VideoPanel::StopPlayback( void )
{
SetVisible( false );
// Start the deferred shutdown process
m_nShutdownCount = 1;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void VideoPanel::OnClose( void )
{
enginesound->NotifyEndMoviePlayback();
if ( m_bStopAllSounds )
{
enginesound->NotifyEndMoviePlayback();
}
BaseClass::OnClose();
if ( vgui::input()->GetAppModalSurface() == GetVPanel() )
@ -224,7 +333,6 @@ void VideoPanel::OnClose( void )
engine->ClientCmd( m_szExitCommand );
}
SetVisible( false );
MarkForDeletion();
}
@ -247,26 +355,52 @@ void VideoPanel::Paint( void )
if ( m_VideoMaterial == NULL )
return;
float alpha = ((float)GetFgColor()[3]/255.0f);
#ifdef MAPBASE
if (m_flFadeIn != 0.0f || m_flFadeOut != 0.0f)
{
// GetCurrentVideoTime() and GetVideoDuration() are borked
float flFrameCount = m_VideoMaterial->GetFrameCount();
float flEnd = flFrameCount / m_VideoMaterial->GetVideoFrameRate().GetFPS();
float flTime = ((float)(m_VideoMaterial->GetCurrentFrame()) / flFrameCount) * flEnd;
float flFadeOutDelta = (flEnd - m_flFadeOut);
if (flTime <= m_flFadeIn)
{
alpha = (flTime / m_flFadeIn);
}
else if (flTime >= flFadeOutDelta)
{
alpha = (1.0f - ((flTime - flFadeOutDelta) / m_flFadeOut));
}
}
#endif
if ( m_VideoMaterial->Update() == false )
{
// Issue a close command
OnVideoOver();
OnClose();
//OnClose();
}
// Sit in the "center"
int xpos, ypos;
GetPanelPos( xpos, ypos );
LocalToScreen( xpos, ypos );
// Black out the background (we could omit drawing under the video surface, but this is straight-forward)
if ( m_bBlackBackground )
{
vgui::surface()->DrawSetColor( 0, 0, 0, 255 );
vgui::surface()->DrawSetColor( 0, 0, 0, alpha * 255.0f );
vgui::surface()->DrawFilledRect( 0, 0, GetWide(), GetTall() );
}
// Draw the polys to draw this out
CMatRenderContextPtr pRenderContext( materials );
#ifdef MAPBASE
pRenderContext->ClearColor4ub( 255, 255, 255, alpha * 255.0f );
#endif
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
@ -306,8 +440,6 @@ void VideoPanel::Paint( void )
flTopY = FLerp( 1, -1, 0, vh ,flTopY );
flBottomY = FLerp( 1, -1, 0, vh, flBottomY );
float alpha = ((float)GetFgColor()[3]/255.0f);
for ( int corner=0; corner<4; corner++ )
{
bool bLeft = (corner==0) || (corner==3);
@ -340,16 +472,37 @@ void VideoPanel::Paint( void )
bool VideoPanel_Create( unsigned int nXPos, unsigned int nYPos,
unsigned int nWidth, unsigned int nHeight,
const char *pVideoFilename,
const char *pExitCommand /*= NULL*/)
const char *pExitCommand /*= NULL*/,
const VideoPanelParms_t &parms )
{
// Create the base video panel
VideoPanel *pVideoPanel = new VideoPanel( nXPos, nYPos, nHeight, nWidth, false );
VideoPanel *pVideoPanel = new VideoPanel( nXPos, nYPos, nHeight, nWidth );
if ( pVideoPanel == NULL )
return false;
// Toggle if we want the panel to allow interruption
pVideoPanel->SetAllowInterrupt( parms.bAllowInterrupt );
// Set the command we'll call (if any) when the video is interrupted or completes
pVideoPanel->SetExitCommand( pExitCommand );
#ifdef MAPBASE
// Toggle if we want the panel to loop (inspired by Portal 2)
pVideoPanel->SetLooping( parms.bLoop );
// Toggle if we want the panel to be muted
pVideoPanel->SetMuted( parms.bMute );
// TODO: Unique "Stop All Sounds" parameter
if (parms.bMute)
{
pVideoPanel->SetStopAllSounds( false );
}
// Fade parameters (unfinished)
//pVideoPanel->SetFade( parms.flFadeIn, parms.flFadeOut );
#endif
// Start it going
if ( pVideoPanel->BeginPlayback( pVideoFilename ) == false )
{
@ -365,8 +518,29 @@ bool VideoPanel_Create( unsigned int nXPos, unsigned int nYPos,
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback (Debug) -
// user must include file extension
// Purpose: Create a video panel with the supplied commands
//-----------------------------------------------------------------------------
void CreateVideoPanel( const char *lpszFilename, const char *lpszExitCommand, int nWidth, int nHeight, VideoPanelParms_t &parms )
{
char strFullpath[MAX_PATH];
Q_strncpy( strFullpath, "media/", MAX_PATH ); // Assume we must play out of the media directory
char strFilename[MAX_PATH];
Q_StripExtension( lpszFilename, strFilename, MAX_PATH );
Q_strncat( strFullpath, lpszFilename, MAX_PATH );
// Use the full screen size if they haven't specified an override
unsigned int nScreenWidth = ( nWidth != 0 ) ? nWidth : ScreenWidth();
unsigned int nScreenHeight = ( nHeight != 0 ) ? nHeight : ScreenHeight();
// Create the panel and go!
if ( VideoPanel_Create( 0, 0, nScreenWidth, nScreenHeight, strFullpath, lpszExitCommand, parms ) == false )
{
Warning( "Unable to play video: %s\n", strFullpath );
}
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo, "Plays a video: <filename> [width height]" )
@ -376,30 +550,32 @@ CON_COMMAND( playvideo, "Plays a video: <filename> [width height]" )
unsigned int nScreenWidth = Q_atoi( args[2] );
unsigned int nScreenHeight = Q_atoi( args[3] );
char strFullpath[MAX_PATH];
Q_strncpy( strFullpath, "media/", MAX_PATH ); // Assume we must play out of the media directory
char strFilename[MAX_PATH];
Q_StripExtension( args[1], strFilename, MAX_PATH );
Q_strncat( strFullpath, args[1], MAX_PATH );
if ( nScreenWidth == 0 )
{
nScreenWidth = ScreenWidth();
}
if ( nScreenHeight == 0 )
{
nScreenHeight = ScreenHeight();
}
// Create the panel and go!
if ( VideoPanel_Create( 0, 0, nScreenWidth, nScreenHeight, strFullpath ) == false )
{
Warning( "Unable to play video: %s\n", strFullpath );
}
// New struct; functionally identical
VideoPanelParms_t parms;
CreateVideoPanel( args[1], NULL, nScreenWidth, nScreenHeight, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo_nointerrupt, "Plays a video without ability to skip: <filename> [width height]" )
{
if ( args.ArgC() < 2 )
return;
unsigned int nScreenWidth = Q_atoi( args[2] );
unsigned int nScreenHeight = Q_atoi( args[3] );
// New struct; functionally identical
VideoPanelParms_t parms( false );
CreateVideoPanel( args[1], NULL, nScreenWidth, nScreenHeight, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback and fire a command on completion
//-----------------------------------------------------------------------------
@ -409,21 +585,78 @@ CON_COMMAND( playvideo_exitcommand, "Plays a video and fires and exit command wh
if ( args.ArgC() < 2 )
return;
unsigned int nScreenWidth = ScreenWidth();
unsigned int nScreenHeight = ScreenHeight();
char strFullpath[MAX_PATH];
Q_strncpy( strFullpath, "media/", MAX_PATH ); // Assume we must play out of the media directory
char strFilename[MAX_PATH];
Q_StripExtension( args[1], strFilename, MAX_PATH );
Q_strncat( strFullpath, args[1], MAX_PATH );
// Pull out the exit command we want to use
char *pExitCommand = Q_strstr( args.GetCommandString(), args[2] );
// Create the panel and go!
if ( VideoPanel_Create( 0, 0, nScreenWidth, nScreenHeight, strFullpath, pExitCommand ) == false )
// New struct; functionally identical
VideoPanelParms_t parms;
CreateVideoPanel( args[1], pExitCommand, 0, 0, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback and fire a command on completion
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo_exitcommand_nointerrupt, "Plays a video (without interruption) and fires and exit command when it is stopped or finishes: <filename> <exit command>" )
{
if ( args.ArgC() < 2 )
return;
// Pull out the exit command we want to use
char *pExitCommand = Q_strstr( args.GetCommandString(), args[2] );
// New struct; functionally identical
VideoPanelParms_t parms( false );
CreateVideoPanel( args[1], pExitCommand, 0, 0, parms );
}
//-----------------------------------------------------------------------------
// Purpose: Cause all playback to stop
//-----------------------------------------------------------------------------
CON_COMMAND( stopvideos, "Stops all videos playing to the screen" )
{
FOR_EACH_VEC( g_vecVideoPanels, itr )
{
Warning( "Unable to play video: %s\n", strFullpath );
engine->ClientCmd( pExitCommand );
g_vecVideoPanels[itr]->StopPlayback();
}
}
//-----------------------------------------------------------------------------
// Purpose: Used to launch a video playback and fire a command on completion
//-----------------------------------------------------------------------------
CON_COMMAND( playvideo_complex, "Plays a video with various parameters to simplify logic_playmovie: <filename> <exit command> <no interrupt> <looping> <fade in> <fade out>" )
{
if ( args.ArgC() < 2 )
return;
// Pull out the exit command we want to use
char *pExitCommand = Q_strstr( args.GetCommandString(), args[2] );
// Parameters
VideoPanelParms_t parms;
if (args.ArgC() >= 3)
parms.bAllowInterrupt = atoi( args[3] ) != 0;
if (args.ArgC() >= 4)
parms.bLoop = atoi( args[4] ) != 0;
if (args.ArgC() >= 5)
parms.bMute = atoi( args[5] ) != 0;
//if (args.ArgC() >= 5)
// parms.flFadeIn = atof( args[5] );
//if (args.ArgC() >= 6)
// parms.flFadeOut = atof( args[6] );
// Stop a softlock
if (parms.bAllowInterrupt == false && parms.bLoop)
{
Warning( "WARNING: Tried to play video set to be uninterruptible and looping. This would cause a softlock because the video loops forever and there's no way to stop it.\n" );
return;
}
CreateVideoPanel( args[1], pExitCommand, 0, 0, parms );
}

View File

@ -45,14 +45,22 @@ public:
}
bool BeginPlayback( const char *pFilename );
void StopPlayback( void );
void SetBlackBackground( bool bBlack ){ m_bBlackBackground = bBlack; }
void SetAllowInterrupt( bool bAllowInterrupt ) { m_bAllowInterruption = bAllowInterrupt; }
void SetStopAllSounds( bool bStopAllSounds ) { m_bStopAllSounds = bStopAllSounds; }
#ifdef MAPBASE
void SetLooping( bool bLooping ) { m_bLooping = bLooping; }
void SetMuted( bool bMuted ) { m_bMuted = bMuted; }
void SetFade( float flStartFade, float flEndFade ) { m_flFadeIn = flStartFade; m_flFadeOut = flEndFade; }
#endif
protected:
virtual void OnTick( void ) { BaseClass::OnTick(); }
virtual void OnTick( void );
virtual void OnCommand( const char *pcCommand ) { BaseClass::OnCommand( pcCommand ); }
virtual void OnVideoOver(){}
virtual void OnVideoOver();
protected:
IVideoMaterial *m_VideoMaterial;
@ -65,8 +73,19 @@ protected:
float m_flU; // U,V ranges for video on its sheet
float m_flV;
bool m_bLooping;
#ifdef MAPBASE
float m_flFadeIn;
float m_flFadeOut;
bool m_bMuted;
#endif
bool m_bStopAllSounds;
bool m_bAllowInterruption;
bool m_bBlackBackground;
bool m_bAllowAlternateMedia;
int m_nShutdownCount;
bool m_bStarted;
};

View File

@ -107,10 +107,11 @@ extern ConVar cl_forwardspeed;
static ConVar v_centermove( "v_centermove", "0.15");
static ConVar v_centerspeed( "v_centerspeed","500" );
#ifdef TF_CLIENT_DLL
#if defined(TF_CLIENT_DLL) || defined(MAPBASE)
// 54 degrees approximates a 35mm camera - we determined that this makes the viewmodels
// and motions look the most natural.
ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_ARCHIVE, "Sets the field-of-view for the viewmodel.", true, 0.1, true, 179.9 );
ConVar v_viewmodel_fov_script_override( "viewmodel_fov_script_override", "0", FCVAR_NONE, "If nonzero, overrides the viewmodel FOV of weapon scripts which override the viewmodel FOV." );
#else
ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_CHEAT, "Sets the field-of-view for the viewmodel.", true, 0.1, true, 179.9 );
#endif
@ -675,6 +676,10 @@ void CViewRender::SetUpViews()
Vector ViewModelOrigin;
QAngle ViewModelAngles;
#ifdef MAPBASE
view.fovViewmodel = g_pClientMode->GetViewModelFOV();
#endif
if ( engine->IsHLTV() )
{
HLTVCamera()->CalcView( view.origin, view.angles, view.fov );
@ -710,6 +715,18 @@ void CViewRender::SetUpViews()
bCalcViewModelView = true;
ViewModelOrigin = view.origin;
ViewModelAngles = view.angles;
#ifdef MAPBASE
// Allow weapons to override viewmodel FOV
C_BaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon();
if (pWeapon && pWeapon->GetViewmodelFOVOverride() != 0.0f)
{
if (v_viewmodel_fov_script_override.GetFloat() > 0.0f)
view.fovViewmodel = v_viewmodel_fov_script_override.GetFloat();
else
view.fovViewmodel = pWeapon->GetViewmodelFOVOverride();
}
#endif
}
else
{
@ -745,7 +762,7 @@ void CViewRender::SetUpViews()
//Adjust the viewmodel's FOV to move with any FOV offsets on the viewer's end
#ifdef MAPBASE
view.fovViewmodel = fabs(g_pClientMode->GetViewModelFOV()) - flFOVOffset;
view.fovViewmodel = max(0.001f, view.fovViewmodel - flFOVOffset);
#else
view.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset;
#endif

View File

@ -29,6 +29,9 @@ static ConVar mat_wateroverlaysize( "mat_wateroverlaysize", "256" );
static ConVar mat_showframebuffertexture( "mat_showframebuffertexture", "0", FCVAR_CHEAT );
static ConVar mat_framebuffercopyoverlaysize( "mat_framebuffercopyoverlaysize", "256" );
static ConVar mat_showcamerarendertarget( "mat_showcamerarendertarget", "0", FCVAR_CHEAT );
#ifdef MAPBASE
static ConVar mat_showcamerarendertarget_all( "mat_showcamerarendertarget_all", "0", FCVAR_CHEAT );
#endif
static ConVar mat_camerarendertargetoverlaysize( "mat_camerarendertargetoverlaysize", "256", FCVAR_CHEAT );
static ConVar mat_hsv( "mat_hsv", "0", FCVAR_CHEAT );
static ConVar mat_yuv( "mat_yuv", "0", FCVAR_CHEAT );
@ -178,6 +181,11 @@ void OverlayCameraRenderTarget( const char *pszMaterialName, float flX, float fl
pMaterial = materials->FindMaterial( pszMaterialName, TEXTURE_GROUP_OTHER, true );
if( !IsErrorMaterial( pMaterial ) )
{
#ifdef MAPBASE
// HACKHACK
pMaterial->IncrementReferenceCount();
#endif
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->Bind( pMaterial );
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
@ -203,6 +211,11 @@ void OverlayCameraRenderTarget( const char *pszMaterialName, float flX, float fl
meshBuilder.End();
pMesh->Draw();
#ifdef MAPBASE
// HACKHACK
pMaterial->DecrementReferenceCount();
#endif
}
}
@ -214,7 +227,11 @@ static void OverlayFrameBufferTexture( int nFrameBufferIndex )
IMaterial *pMaterial;
char buf[MAX_PATH];
Q_snprintf( buf, MAX_PATH, "debug/debugfbtexture%d", nFrameBufferIndex );
#ifdef MAPBASE
pMaterial = materials->FindMaterial( buf, NULL, true );
#else
pMaterial = materials->FindMaterial( buf, TEXTURE_GROUP_OTHER, true );
#endif
if( !IsErrorMaterial( pMaterial ) )
{
CMatRenderContextPtr pRenderContext( materials );
@ -586,12 +603,52 @@ void CDebugViewRender::Draw2DDebuggingInfo( const CViewSetup &view )
if ( mat_showcamerarendertarget.GetBool() )
{
#ifdef MAPBASE
float w = mat_camerarendertargetoverlaysize.GetFloat();
float h = mat_camerarendertargetoverlaysize.GetFloat();
#else
float w = mat_wateroverlaysize.GetFloat();
float h = mat_wateroverlaysize.GetFloat();
#endif
#ifdef PORTAL
g_pPortalRender->OverlayPortalRenderTargets( w, h );
#else
#ifdef MAPBASE
int iCameraNum = mat_showcamerarendertarget.GetInt();
if (iCameraNum == 1) // Display the default camera
{
OverlayCameraRenderTarget( "debug/debugcamerarendertarget", 0, 0, w, h );
}
else if (mat_showcamerarendertarget_all.GetBool()) // Display all cameras
{
OverlayCameraRenderTarget( "debug/debugcamerarendertarget", 0, 0, w, h );
// Already showed one camera
iCameraNum--;
// Show Mapbase's cameras
char szTextureName[48];
for (int i = 0; i < iCameraNum; i++)
{
V_snprintf( szTextureName, sizeof( szTextureName ), "debug/debugcamerarendertarget_camera%i", i );
// Show them vertically if the cvar is set to 2
if (mat_showcamerarendertarget_all.GetInt() == 2)
OverlayCameraRenderTarget( szTextureName, 0, h * (i + 1), w, h );
else
OverlayCameraRenderTarget( szTextureName, w * (i + 1), 0, w, h );
}
}
else // Display one of the new cameras
{
OverlayCameraRenderTarget( VarArgs( "debug/debugcamerarendertarget_camera%i", iCameraNum-2 ), 0, 0, w, h );
}
#else
OverlayCameraRenderTarget( "debug/debugcamerarendertarget", 0, 0, w, h );
#endif
#endif
}
@ -655,6 +712,57 @@ CON_COMMAND_F( r_screenoverlay, "Draw specified material as an overlay", FCVAR_C
}
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// The same as above, but using the new indexed overlays
//-----------------------------------------------------------------------------
CON_COMMAND_F( r_screenoverlay_indexed, "Draw specified material as an overlay in the specified index", FCVAR_CHEAT|FCVAR_SERVER_CAN_EXECUTE )
{
if( args.ArgC() == 3 )
{
int index = atoi( args[1] );
if (index < 0 || index >= MAX_SCREEN_OVERLAYS)
{
Warning( "r_screenoverlay_indexed: '%i' is out of range (should be 0-9)\n", index );
return;
}
if ( !Q_stricmp( "off", args[2] ) )
{
view->SetIndexedScreenOverlayMaterial( index, NULL );
}
else
{
IMaterial *pMaterial = materials->FindMaterial( args[2], TEXTURE_GROUP_OTHER, false );
if ( !IsErrorMaterial( pMaterial ) )
{
view->SetIndexedScreenOverlayMaterial( index, pMaterial );
}
else
{
view->SetIndexedScreenOverlayMaterial( index, NULL );
}
}
}
else if ( args.ArgC() == 2 )
{
int index = atoi( args[1] );
if (index < 0 || index >= MAX_SCREEN_OVERLAYS)
{
Warning( "r_screenoverlay_indexed: '%i' is out of range (should be 0-9)\n", index );
return;
}
IMaterial *pMaterial = view->GetIndexedScreenOverlayMaterial( index );
Warning( "r_screenoverlay_indexed %i: %s\n", index, pMaterial ? pMaterial->GetName() : "off" );
}
else
{
Warning( "Format: r_screenoverlay_indexed <index> [<material>]\n" );
}
}
#endif
// Used to verify frame syncing.
void CDebugViewRender::GenerateOverdrawForTesting()
{

View File

@ -76,6 +76,7 @@
#ifdef MAPBASE
#include "mapbase/c_func_fake_worldportal.h"
#include "colorcorrectionmgr.h"
#endif
// Projective textures
@ -408,10 +409,6 @@ protected:
void Enable3dSkyboxFog( void );
void DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostRender, ITexture *pRenderTarget, ITexture *pDepthTarget );
#ifdef MAPBASE
void CalculateSkyAngles( const QAngle &angAngles );
#endif
sky3dparams_t * PreRender3dSkyboxWorld( SkyboxVisibility_t nSkyboxVisible );
sky3dparams_t *m_pSky3dParams;
@ -1218,6 +1215,73 @@ IMaterial *CViewRender::GetScreenOverlayMaterial( )
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Sets the screen space effect material (can't be done during rendering)
//-----------------------------------------------------------------------------
void CViewRender::SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial )
{
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
return;
m_IndexedScreenOverlayMaterials[i].Init( pMaterial );
if (pMaterial == NULL)
{
// Check if we should set to false
int i;
for (i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
if (m_IndexedScreenOverlayMaterials[i] != NULL)
break;
}
if (i == MAX_SCREEN_OVERLAYS)
m_bUsingIndexedScreenOverlays = false;
}
else
{
m_bUsingIndexedScreenOverlays = true;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
IMaterial *CViewRender::GetIndexedScreenOverlayMaterial( int i )
{
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
return NULL;
return m_IndexedScreenOverlayMaterials[i];
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CViewRender::ResetIndexedScreenOverlays()
{
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
m_IndexedScreenOverlayMaterials[i].Init( NULL );
}
m_bUsingIndexedScreenOverlays = false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CViewRender::GetMaxIndexedScreenOverlays( ) const
{
return MAX_SCREEN_OVERLAYS;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Performs screen space effects, if any
//-----------------------------------------------------------------------------
@ -1254,6 +1318,44 @@ void CViewRender::PerformScreenOverlay( int x, int y, int w, int h )
render->ViewDrawFade( color, m_ScreenOverlayMaterial );
}
}
#ifdef MAPBASE
if (m_bUsingIndexedScreenOverlays)
{
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
if (!m_IndexedScreenOverlayMaterials[i])
continue;
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
if ( m_IndexedScreenOverlayMaterials[i]->NeedsFullFrameBufferTexture() )
{
// FIXME: check with multi/sub-rect renders. Should this be 0,0,w,h instead?
DrawScreenEffectMaterial( m_IndexedScreenOverlayMaterials[i], x, y, w, h );
}
else if ( m_IndexedScreenOverlayMaterials[i]->NeedsPowerOfTwoFrameBufferTexture() )
{
// First copy the FB off to the offscreen texture
UpdateRefractTexture( x, y, w, h, true );
// Now draw the entire screen using the material...
CMatRenderContextPtr pRenderContext( materials );
ITexture *pTexture = GetPowerOfTwoFrameBufferTexture( );
int sw = pTexture->GetActualWidth();
int sh = pTexture->GetActualHeight();
// Note - don't offset by x,y - already done by the viewport.
pRenderContext->DrawScreenSpaceRectangle( m_IndexedScreenOverlayMaterials[i], 0, 0, w, h,
0, 0, sw-1, sh-1, sw, sh );
}
else
{
byte color[4] = { 255, 255, 255, 255 };
render->ViewDrawFade( color, m_IndexedScreenOverlayMaterials[i] );
}
}
}
#endif
}
void CViewRender::DrawUnderwaterOverlay( void )
@ -2004,19 +2106,18 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
Frustum_t frustum;
GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum );
cplane_t portalPlane;
//C_FuncFakeWorldPortal *pPortalEnt = IsFakeWorldPortalInView( view, portalPlane );
//if ( pPortalEnt )
C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, portalPlane, frustum );
Vector vecAbsPlaneNormal;
float flLocalPlaneDist;
C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, vecAbsPlaneNormal, flLocalPlaneDist, frustum );
while ( pPortalEnt != NULL )
{
ITexture *pCameraTarget = pPortalEnt->RenderTarget();
int width = pCameraTarget->GetActualWidth();
int height = pCameraTarget->GetActualHeight();
DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, portalPlane );
DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, vecAbsPlaneNormal, flLocalPlaneDist );
pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, portalPlane, frustum );
pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, vecAbsPlaneNormal, flLocalPlaneDist, frustum );
}
#endif
}
@ -2027,6 +2128,10 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
// Must be first
render->SceneBegin();
#ifdef MAPBASE // From Alien Swarm SDK
g_pColorCorrectionMgr->UpdateColorCorrection();
#endif
pRenderContext.GetFrom( materials );
pRenderContext->TurnOnToneMapping();
pRenderContext.SafeRelease();
@ -3430,12 +3535,9 @@ bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_Poin
}
#ifdef MAPBASE
ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
//-----------------------------------------------------------------------------
// Purpose: Sets up scene and renders WIP fake world portal view.
// Based on code from monitors, mirrors, and 3D skyboxes.
// It's also terrible right now.
// Based on code from monitors, mirrors, and logic_measure_movement.
//
// Input : cameraNum -
// &cameraView
@ -3449,7 +3551,7 @@ ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
//-----------------------------------------------------------------------------
bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer,
int x, int y, int width, int height,
const CViewSetup &mainView, cplane_t &ourPlane )
const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, float flLocalPlaneDist )
{
#ifdef USE_MONITORS
VPROF_INCREMENT_COUNTER( "cameras rendered", 1 );
@ -3480,105 +3582,64 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
}
}
monitorView.width = width;
monitorView.height = height;
monitorView.x = x;
monitorView.y = y;
monitorView.origin = mainView.origin;
monitorView.angles = mainView.angles;
// Temporary debug stuff
static float flLastDebugTime = 0.0f;
bool bDebug = r_fakeworldportal_debug.GetBool() && gpGlobals->curtime > flLastDebugTime;
QAngle angTargetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() + pCameraEnt->m_PlaneAngles;
// RED - First origin
if (bDebug)
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 0, 0, 128, 10.0f );
// Make sure the origin and angles are relative to the target plane
monitorView.origin -= pCameraEnt->GetAbsOrigin();
// scale origin by sky scale
if ( pCameraEnt->m_flScale > 0 )
{
float scale = 1.0f / pCameraEnt->m_flScale;
VectorScale( monitorView.origin, scale, monitorView.origin );
}
// YELLOW - Main origin
if (bDebug)
debugoverlay->AddBoxOverlay( pCameraEnt->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 224, 0, 128, 10.0f );
// Make sure our angles are relative to the main plane, just like the origin
QAngle angOurAngles;
VectorAngles( ourPlane.normal * -1, angOurAngles );
//angles -= angOurAngles;
// First, create a matrix for the sky's angles.
matrix3x4_t matSkyAngles;
AngleMatrix( angTargetAngles - angOurAngles, matSkyAngles );
Vector vecSkyForward, vecSkyRight, vecSkyUp;
// Get vectors from our original angles.
Vector vPlayerForward, vPlayerRight, vPlayerUp;
AngleVectors( monitorView.angles, &vPlayerForward, &vPlayerRight, &vPlayerUp );
VectorTransform( vPlayerForward, matSkyAngles, vecSkyForward );
VectorTransform( vPlayerRight, matSkyAngles, vecSkyRight );
VectorTransform( vPlayerUp, matSkyAngles, vecSkyUp );
// Normalize them.
VectorNormalize( vecSkyForward );
VectorNormalize( vecSkyRight );
VectorNormalize( vecSkyUp );
Quaternion quat;
BasisToQuaternion( vecSkyForward, vecSkyRight, vecSkyUp, quat );
QuaternionAngles( quat, monitorView.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(monitorView.origin), matSkyAngles, monitorView.origin);
// BLUE - Target origin
if (bDebug)
debugoverlay->AddBoxOverlay( pCameraEnt->m_hTargetPlane->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 0, 255, 128, 10.0f );
monitorView.origin += pCameraEnt->m_hTargetPlane->GetAbsOrigin();
// GREEN - Final origin
if (bDebug)
{
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 255, 0, 128, 10.0f );
flLastDebugTime = gpGlobals->curtime + 5.0f;
}
monitorView.width = width;
monitorView.height = height;
monitorView.m_bOrtho = mainView.m_bOrtho;
monitorView.fov = mainView.fov;
monitorView.m_bOrtho = false;
monitorView.m_flAspectRatio = 0.0f;
monitorView.m_flAspectRatio = mainView.m_flAspectRatio;
monitorView.m_bViewToProjectionOverride = false;
matrix3x4_t worldToView;
AngleIMatrix( mainView.angles, mainView.origin, worldToView );
matrix3x4_t targetToWorld;
{
// NOTE: m_PlaneAngles is angle offset
QAngle targetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() - pCameraEnt->m_PlaneAngles;
AngleMatrix( targetAngles, pCameraEnt->m_hTargetPlane->GetAbsOrigin(), targetToWorld );
}
matrix3x4_t portalToWorld;
{
Vector left, up;
VectorVectors( vecAbsPlaneNormal, left, up );
VectorNegate( left );
portalToWorld.Init( vecAbsPlaneNormal, left, up, pCameraEnt->GetAbsOrigin() );
}
matrix3x4_t portalToView;
ConcatTransforms( worldToView, portalToWorld, portalToView );
if ( pCameraEnt->m_flScale > 0.0f )
{
portalToView[0][3] /= pCameraEnt->m_flScale;
portalToView[1][3] /= pCameraEnt->m_flScale;
portalToView[2][3] /= pCameraEnt->m_flScale;
}
matrix3x4_t viewToPortal;
MatrixInvert( portalToView, viewToPortal );
matrix3x4_t newViewToWorld;
ConcatTransforms( targetToWorld, viewToPortal, newViewToWorld );
MatrixAngles( newViewToWorld, monitorView.angles, monitorView.origin );
// @MULTICORE (toml 8/11/2006): this should be a renderer....
int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL);
bool bDrew3dSkybox = false;
SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode();
Frustum frustum;
render->Push3DView( monitorView, nClearFlags, pRenderTarget, (VPlane *)frustum );
//
// Monitor sky handling
// Sky handling
//
if ( pCameraEnt->SkyMode() == SKYBOX_3DSKYBOX_VISIBLE )
SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode();
if ( nSkyMode == SKYBOX_3DSKYBOX_VISIBLE )
{
// if the 3d skybox world is drawn, then don't draw the normal skybox
CSkyboxView *pSkyView = new CSkyboxView( this );
@ -3591,14 +3652,15 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
Vector4D plane;
// Combine the target angles and the plane angles
Vector vecAnglesNormal( angTargetAngles.x, angTargetAngles.y, angTargetAngles.z );
VectorNormalize( vecAnglesNormal );
VectorCopy( vecAnglesNormal, plane.AsVector3D() );
// target direction
MatrixGetColumn( targetToWorld, 0, plane.AsVector3D() );
VectorNormalize( plane.AsVector3D() );
VectorNegate( plane.AsVector3D() );
// TODO: How do we get a good value for this!?!?
//plane.w = m_OurPlane.dist + 0.1f;
plane.w = -32.0f + 0.1f;
plane.w =
MatrixColumnDotProduct( targetToWorld, 3, plane.AsVector3D() ) // target clip plane distance
- flLocalPlaneDist // portal plane distance on the brush. This distance needs to be accounted for while placing the exit target
- 0.1;
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->PushCustomClipPlane( plane.Base() );
@ -5293,10 +5355,16 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR
// Re-use the x coordinate to determine if we shuld do this with angles
if (m_pSky3dParams->angles.GetX() != 0)
{
CalculateSkyAngles( m_pSky3dParams->skycamera->GetAbsAngles() );
const matrix3x4_t &matSky = m_pSky3dParams->skycamera->EntityToWorldTransform();
matrix3x4_t matView;
AngleMatrix( angles, origin, matView );
ConcatTransforms( matSky, matView, matView );
MatrixAngles( matView, angles, origin );
}
else
{
VectorAdd( origin, m_pSky3dParams->skycamera->GetAbsOrigin(), origin );
}
VectorAdd( origin, m_pSky3dParams->skycamera->GetAbsOrigin(), origin );
}
else
{
@ -5304,10 +5372,16 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR
m_pSky3dParams->angles.GetY() != 0 ||
m_pSky3dParams->angles.GetZ() != 0)
{
CalculateSkyAngles( m_pSky3dParams->angles.Get() );
matrix3x4_t matSky, matView;
AngleMatrix( m_pSky3dParams->angles, m_pSky3dParams->origin, matSky );
AngleMatrix( angles, origin, matView );
ConcatTransforms( matSky, matView, matView );
MatrixAngles( matView, angles, origin );
}
else
{
VectorAdd( origin, m_pSky3dParams->origin, origin );
}
VectorAdd( origin, m_pSky3dParams->origin, origin );
}
#else
VectorAdd( origin, m_pSky3dParams->origin, origin );
@ -5424,55 +5498,6 @@ void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostR
#endif
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CSkyboxView::CalculateSkyAngles( const QAngle &angAngles )
{
// 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( angAngles, 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
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------

View File

@ -454,7 +454,7 @@ private:
#ifdef MAPBASE
bool DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer,
int x, int y, int width, int height,
const CViewSetup &mainView, cplane_t &ourPlane );
const CViewSetup &mainView, const Vector &vecAbsPlaneNormal, float flLocalPlaneDist );
#endif
// Drawing primitives
@ -468,6 +468,13 @@ private:
IMaterial *GetScreenOverlayMaterial( );
void PerformScreenOverlay( int x, int y, int w, int h );
#ifdef MAPBASE
void SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial );
IMaterial *GetIndexedScreenOverlayMaterial( int i );
void ResetIndexedScreenOverlays();
int GetMaxIndexedScreenOverlays() const;
#endif
void DrawUnderwaterOverlay( void );
// Water-related methods
@ -511,6 +518,10 @@ private:
CMaterialReference m_TranslucentSingleColor;
CMaterialReference m_ModulateSingleColor;
CMaterialReference m_ScreenOverlayMaterial;
#ifdef MAPBASE
CMaterialReference m_IndexedScreenOverlayMaterials[MAX_SCREEN_OVERLAYS];
bool m_bUsingIndexedScreenOverlays;
#endif
CMaterialReference m_UnderWaterOverlayMaterial;
Vector m_vecLastFacing;

View File

@ -15,11 +15,14 @@
#include "gamerules.h"
#include "vscript_client.nut"
#ifdef MAPBASE_VSCRIPT
#include "mapbase/matchers.h"
#include "view.h"
#include "c_world.h"
#include "proxyentity.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "mapbase/matchers.h"
#include "mapbase/vscript_singletons.h"
#include "mapbase/vscript_vgui.h"
#endif
extern IScriptManager *scriptmanager;
@ -40,12 +43,20 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
#endif // VMPROFILE
#ifdef MAPBASE_VSCRIPT
static ScriptHook_t g_Hook_OnEntityCreated;
static ScriptHook_t g_Hook_OnEntityDeleted;
//-----------------------------------------------------------------------------
// Purpose: A clientside variant of CScriptEntityIterator.
//-----------------------------------------------------------------------------
class CScriptClientEntityIterator
class CScriptClientEntityIterator : public IClientEntityListener
{
public:
HSCRIPT GetLocalPlayer()
{
return ToHScript( C_BasePlayer::GetLocalPlayer() );
}
HSCRIPT First() { return Next(NULL); }
HSCRIPT Next( HSCRIPT hStartEntity )
@ -90,15 +101,59 @@ public:
return NULL;
}
void EnableEntityListening()
{
// Start getting entity updates!
ClientEntityList().AddListenerEntity( this );
}
void DisableEntityListening()
{
// Stop getting entity updates!
ClientEntityList().RemoveListenerEntity( this );
}
void OnEntityCreated( CBaseEntity *pEntity )
{
if ( g_pScriptVM && GetScriptHookManager().IsEventHooked( "OnEntityCreated" ) )
{
// entity
ScriptVariant_t args[] = { ScriptVariant_t( pEntity->GetScriptInstance() ) };
g_Hook_OnEntityCreated.Call( NULL, NULL, args );
}
};
void OnEntityDeleted( CBaseEntity *pEntity )
{
if ( g_pScriptVM && GetScriptHookManager().IsEventHooked( "OnEntityDeleted" ) )
{
// entity
ScriptVariant_t args[] = { ScriptVariant_t( pEntity->GetScriptInstance() ) };
g_Hook_OnEntityDeleted.Call( NULL, NULL, args );
}
};
private:
} g_ScriptEntityIterator;
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptClientEntityIterator, "CEntities", SCRIPT_SINGLETON "The global list of entities" )
DEFINE_SCRIPTFUNC( GetLocalPlayer, "Get local player" )
DEFINE_SCRIPTFUNC( First, "Begin an iteration over the list of entities" )
DEFINE_SCRIPTFUNC( Next, "Continue an iteration over the list of entities, providing reference to a previously found entity" )
DEFINE_SCRIPTFUNC( CreateByClassname, "Creates an entity by classname" )
DEFINE_SCRIPTFUNC( FindByClassname, "Find entities by class name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
DEFINE_SCRIPTFUNC( FindByName, "Find entities by name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
DEFINE_SCRIPTFUNC( EnableEntityListening, "Enables the 'OnEntity' hooks. This function must be called before using them." )
DEFINE_SCRIPTFUNC( DisableEntityListening, "Disables the 'OnEntity' hooks." )
BEGIN_SCRIPTHOOK( g_Hook_OnEntityCreated, "OnEntityCreated", FIELD_VOID, "Called when an entity is created. Requires EnableEntityListening() to be fired beforehand." )
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( g_Hook_OnEntityDeleted, "OnEntityDeleted", FIELD_VOID, "Called when an entity is deleted. Requires EnableEntityListening() to be fired beforehand." )
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
END_SCRIPTHOOK()
END_SCRIPTDESC();
//-----------------------------------------------------------------------------
@ -158,6 +213,8 @@ public:
void SetVarFloat( int i, float value );
void SetVarVector( int i, const Vector &value );
const char *GetVarName( int i );
private:
IMaterialVar *m_MaterialVars[SCRIPT_MAT_PROXY_MAX_VARS];
@ -169,7 +226,16 @@ private:
HSCRIPT m_hFuncOnBind;
};
class CMaterialProxyScriptInstanceHelper : public IScriptInstanceHelper
{
bool ToString( void *p, char *pBuf, int bufSize );
void *BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId );
};
CMaterialProxyScriptInstanceHelper g_MaterialProxyScriptInstanceHelper;
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptMaterialProxy, "CScriptMaterialProxy", "Material proxy for VScript" )
DEFINE_SCRIPT_INSTANCE_HELPER( &g_MaterialProxyScriptInstanceHelper )
DEFINE_SCRIPTFUNC( GetVarString, "Gets a material var's string value" )
DEFINE_SCRIPTFUNC( GetVarInt, "Gets a material var's int value" )
DEFINE_SCRIPTFUNC( GetVarFloat, "Gets a material var's float value" )
@ -178,12 +244,16 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptMaterialProxy, "CScriptMaterialProxy", "Mate
DEFINE_SCRIPTFUNC( SetVarInt, "Sets a material var's int value" )
DEFINE_SCRIPTFUNC( SetVarFloat, "Sets a material var's float value" )
DEFINE_SCRIPTFUNC( SetVarVector, "Sets a material var's vector value" )
DEFINE_SCRIPTFUNC( GetVarName, "Gets a material var's name" )
END_SCRIPTDESC();
CScriptMaterialProxy::CScriptMaterialProxy()
{
m_hScriptInstance = NULL;
m_hFuncOnBind = NULL;
V_memset( m_MaterialVars, 0, sizeof(m_MaterialVars) );
}
CScriptMaterialProxy::~CScriptMaterialProxy()
@ -300,26 +370,25 @@ void CScriptMaterialProxy::TermScript()
void CScriptMaterialProxy::OnBind( void *pRenderable )
{
if( !pRenderable )
return;
if (m_hFuncOnBind != NULL)
{
IClientRenderable *pRend = ( IClientRenderable* )pRenderable;
C_BaseEntity *pEnt = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pEnt )
C_BaseEntity *pEnt = NULL;
if (pRenderable)
{
g_pScriptVM->SetValue( m_ScriptScope, "entity", pEnt->GetScriptInstance() );
IClientRenderable *pRend = (IClientRenderable*)pRenderable;
pEnt = pRend->GetIClientUnknown()->GetBaseEntity();
if ( pEnt )
{
g_pScriptVM->SetValue( m_ScriptScope, "entity", pEnt->GetScriptInstance() );
}
}
else
if (!pEnt)
{
// Needs to register as a null value so the script doesn't break if it looks for an entity
g_pScriptVM->SetValue( m_ScriptScope, "entity", SCRIPT_VARIANT_NULL );
}
m_ScriptScope.Call( m_hFuncOnBind, NULL );
g_pScriptVM->ClearValue( m_ScriptScope, "entity" );
}
else
{
@ -398,8 +467,29 @@ void CScriptMaterialProxy::SetVarVector( int i, const Vector &value )
return m_MaterialVars[i]->SetVecValue( value.Base(), 3 );
}
const char *CScriptMaterialProxy::GetVarName( int i )
{
if (!ValidateIndex( i ) || !m_MaterialVars[i])
return NULL;
return m_MaterialVars[i]->GetName();
}
EXPOSE_INTERFACE( CScriptMaterialProxy, IMaterialProxy, "VScriptProxy" IMATERIAL_PROXY_INTERFACE_VERSION );
#endif
bool CMaterialProxyScriptInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
{
CScriptMaterialProxy *pProxy = (CScriptMaterialProxy *)p;
V_snprintf( pBuf, bufSize, "(proxy: %s)", pProxy->GetMaterial() != NULL ? pProxy->GetMaterial()->GetName() : "<no material>" );
return true;
}
void *CMaterialProxyScriptInstanceHelper::BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId )
{
// TODO: Material proxy save/restore?
return NULL;
}
#endif // MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
//
@ -431,6 +521,53 @@ bool DoIncludeScript( const char *pszScript, HSCRIPT hScope )
return true;
}
#ifdef MAPBASE_VSCRIPT
int ScriptScreenWidth();
int ScriptScreenHeight();
static float FrameTime()
{
return gpGlobals->frametime;
}
static bool Con_IsVisible()
{
return engine->Con_IsVisible();
}
static bool IsWindowedMode()
{
return engine->IsWindowedMode();
}
// Creates a client-side prop
HSCRIPT CreateProp( const char *pszEntityName, const Vector &vOrigin, const char *pszModelName, int iAnim )
{
C_BaseAnimating *pBaseEntity = (C_BaseAnimating *)CreateEntityByName( pszEntityName );
if (!pBaseEntity)
return NULL;
pBaseEntity->SetAbsOrigin( vOrigin );
pBaseEntity->SetModelName( pszModelName );
if (!pBaseEntity->InitializeAsClientEntity( pszModelName, RENDER_GROUP_OPAQUE_ENTITY ))
{
Warning("Can't initialize %s as client entity\n", pszEntityName);
return NULL;
}
pBaseEntity->SetPlaybackRate( 1.0f );
int iSequence = pBaseEntity->SelectWeightedSequence( (Activity)iAnim );
if ( iSequence != -1 )
{
pBaseEntity->SetSequence( iSequence );
}
return ToHScript( pBaseEntity );
}
#endif
bool VScriptClientInit()
{
VMPROF_START
@ -491,10 +628,40 @@ bool VScriptClientInit()
#else
Log( "VSCRIPT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() );
#endif
#ifdef MAPBASE_VSCRIPT
GetScriptHookManager().OnInit();
#endif
ScriptRegisterFunction( g_pScriptVM, GetMapName, "Get the name of the map.");
ScriptRegisterFunction( g_pScriptVM, Time, "Get the current server time" );
ScriptRegisterFunction( g_pScriptVM, DoUniqueString, SCRIPT_ALIAS( "UniqueString", "Generate a string guaranteed to be unique across the life of the script VM, with an optional root string." ) );
ScriptRegisterFunction( g_pScriptVM, DoIncludeScript, "Execute a script (internal)" );
#ifdef MAPBASE_VSCRIPT
ScriptRegisterFunction( g_pScriptVM, FrameTime, "Get the time spent on the client in the last frame" );
ScriptRegisterFunction( g_pScriptVM, Con_IsVisible, "Returns true if the console is visible" );
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenWidth, "ScreenWidth", "Width of the screen in pixels" );
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenHeight, "ScreenHeight", "Height of the screen in pixels" );
ScriptRegisterFunction( g_pScriptVM, IsWindowedMode, "" );
ScriptRegisterFunction( g_pScriptVM, MainViewOrigin, "" );
ScriptRegisterFunction( g_pScriptVM, MainViewAngles, "" );
ScriptRegisterFunction( g_pScriptVM, PrevMainViewOrigin, "" );
ScriptRegisterFunction( g_pScriptVM, PrevMainViewAngles, "" );
ScriptRegisterFunction( g_pScriptVM, MainViewForward, "" );
ScriptRegisterFunction( g_pScriptVM, MainViewRight, "" );
ScriptRegisterFunction( g_pScriptVM, MainViewUp, "" );
ScriptRegisterFunction( g_pScriptVM, CurrentViewOrigin, "" );
ScriptRegisterFunction( g_pScriptVM, CurrentViewAngles, "" );
ScriptRegisterFunction( g_pScriptVM, CurrentViewForward, "" );
ScriptRegisterFunction( g_pScriptVM, CurrentViewRight, "" );
ScriptRegisterFunction( g_pScriptVM, CurrentViewUp, "" );
ScriptRegisterFunction( g_pScriptVM, CreateProp, "Create an animating prop" );
#endif
if ( GameRules() )
{
GameRules()->RegisterScriptFunctions();
@ -510,6 +677,7 @@ bool VScriptClientInit()
RegisterSharedScriptConstants();
RegisterSharedScriptFunctions();
RegisterScriptVGUI();
#else
//g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
#endif
@ -519,8 +687,13 @@ bool VScriptClientInit()
g_pScriptVM->Run( g_Script_vscript_client );
}
VScriptRunScript( "vscript_client", true );
VScriptRunScript( "mapspawn", false );
#ifdef MAPBASE_VSCRIPT
RunAddonScripts();
#endif
VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );
return true;
@ -530,6 +703,12 @@ bool VScriptClientInit()
CGWarning( 1, CON_GROUP_VSCRIPT, "VM Did not start!\n" );
}
}
#ifdef MAPBASE_VSCRIPT
else
{
CGMsg( 0, CON_GROUP_VSCRIPT, "VSCRIPT CLIENT: Not starting because language is set to 'none'\n" );
}
#endif
}
else
{
@ -571,28 +750,21 @@ public:
virtual void LevelInitPreEntity( void )
{
m_bAllowEntityCreationInScripts = true;
#ifndef MAPBASE_VSCRIPT // Now initted in C_World
VScriptClientInit();
#endif
}
virtual void LevelInitPostEntity( void )
{
m_bAllowEntityCreationInScripts = false;
#ifdef MAPBASE_VSCRIPT
if (g_pScriptVM)
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if (pPlayer)
{
g_pScriptVM->SetValue( "player", pPlayer->GetScriptInstance() );
}
}
#endif
}
virtual void LevelShutdownPostEntity( void )
{
#ifdef MAPBASE_VSCRIPT
g_ScriptNetMsg->LevelShutdownPreVM();
GetScriptHookManager().OnShutdown();
#endif
VScriptClientTerm();
}

View File

@ -5,18 +5,32 @@ static char g_Script_vscript_client[] = R"vscript(
//
//=============================================================================
local DoUniqueString = DoUniqueString
local DoDispatchParticleEffect = DoDispatchParticleEffect
function UniqueString( string = "" )
{
return DoUniqueString( string.tostring() );
return DoUniqueString( "" + string );
}
function IncludeScript( name, scope = null )
{
if ( scope == null )
if ( !scope )
{
scope = this;
}
return ::DoIncludeScript( name, scope );
}
function DispatchParticleEffect( particleName, origin, angles, entity = null )
{
return DoDispatchParticleEffect( particleName, origin, angles, entity );
}
function ImpulseScale( flTargetMass, flDesiredSpeed )
{
return flTargetMass * flDesiredSpeed;
}
__Documentation.RegisterHelp( "ImpulseScale", "float ImpulseScale(float, float)", "Returns an impulse scale required to push an object." );
)vscript";

View File

@ -27,6 +27,10 @@
static IVEngineServer *g_pEngineServer = NULL;
#ifdef MAPBASE
ConVar cl_worldlight_use_new_method("cl_worldlight_use_new_method", "1", FCVAR_NONE, "Uses the new world light iteration method which splits lights into multiple lists for each cluster.");
#endif
//-----------------------------------------------------------------------------
// Singleton exposure
//-----------------------------------------------------------------------------
@ -192,6 +196,83 @@ void CWorldLights::LevelInitPreEntity()
g_pFullFileSystem->Close(hFile);
DevMsg("CWorldLights: load successful (%d lights at 0x%p)\n", m_nWorldLights, m_pWorldLights);
#ifdef MAPBASE
// Now that the lights have been gathered, begin separating them into lists for each PVS cluster.
// This code is adapted from the soundscape cluster list code (see soundscape_system.cpp) and is intended to
// reduce frame drops in large maps which use dynamic RTT shadow angles.
CUtlVector<bbox_t> clusterbounds;
int clusterCount = g_pEngineServer->GetClusterCount();
clusterbounds.SetCount( clusterCount );
g_pEngineServer->GetAllClusterBounds( clusterbounds.Base(), clusterCount );
m_WorldLightsInCluster.SetCount(clusterCount);
for ( int i = 0; i < clusterCount; i++ )
{
m_WorldLightsInCluster[i].lightCount = 0;
m_WorldLightsInCluster[i].firstLight = 0;
}
unsigned char myPVS[16 * 1024];
CUtlVector<short> clusterIndexList;
CUtlVector<short> lightIndexList;
// Find the clusters visible from each light, then add it to those clusters' light lists
// (Also try to clip for radius if possible)
for (int i = 0; i < m_nWorldLights; ++i)
{
dworldlight_t *light = &m_pWorldLights[i];
// Assign the sun to its own pointer
if (light->type == emit_skylight)
{
m_iSunIndex = i;
continue;
}
float radiusSq = light->radius * light->radius;
if (radiusSq == 0.0f)
{
// TODO: Use intensity instead?
radiusSq = FLT_MAX;
}
g_pEngineServer->GetPVSForCluster( light->cluster, sizeof( myPVS ), myPVS );
for ( int j = 0; j < clusterCount; j++ )
{
if ( myPVS[ j >> 3 ] & (1<<(j&7)) )
{
float distSq = CalcSqrDistanceToAABB( clusterbounds[j].mins, clusterbounds[j].maxs, light->origin );
if ( distSq < radiusSq )
{
m_WorldLightsInCluster[j].lightCount++;
clusterIndexList.AddToTail(j);
lightIndexList.AddToTail(i);
}
}
}
}
m_WorldLightsIndexList.SetCount(lightIndexList.Count());
// Compute the starting index of each cluster
int firstLight = 0;
for ( int i = 0; i < clusterCount; i++ )
{
m_WorldLightsInCluster[i].firstLight = firstLight;
firstLight += m_WorldLightsInCluster[i].lightCount;
m_WorldLightsInCluster[i].lightCount = 0;
}
// Now add each light index to the appropriate cluster's list
for ( int i = 0; i < lightIndexList.Count(); i++ )
{
int cluster = clusterIndexList[i];
int outIndex = m_WorldLightsInCluster[cluster].lightCount + m_WorldLightsInCluster[cluster].firstLight;
m_WorldLightsInCluster[cluster].lightCount++;
m_WorldLightsIndexList[outIndex] = lightIndexList[i];
}
//DevMsg( "CWorldLights: Light clusters list has %i elements; Light index list has %i\n", m_WorldLightsInCluster.Count(), m_WorldLightsIndexList.Count() );
#endif
}
//-----------------------------------------------------------------------------
@ -208,6 +289,25 @@ bool CWorldLights::GetBrightestLightSource(const Vector &vecPosition, Vector &ve
// Find the size of the PVS for our current position
int nCluster = g_pEngineServer->GetClusterForOrigin(vecPosition);
#ifdef MAPBASE
if (cl_worldlight_use_new_method.GetBool())
{
FindBrightestLightSourceNew( vecPosition, vecLightPos, vecLightBrightness, nCluster );
}
else
#endif
{
FindBrightestLightSourceOld( vecPosition, vecLightPos, vecLightBrightness, nCluster );
}
//engine->Con_NPrintf(m_nWorldLights, "result: %d", !vecLightBrightness.IsZero());
return !vecLightBrightness.IsZero();
}
void CWorldLights::FindBrightestLightSourceOld( const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness, int nCluster )
{
// Find the size of the PVS for our current position
int nPVSSize = g_pEngineServer->GetPVSForCluster(nCluster, 0, NULL);
// Get the PVS at our position
@ -257,7 +357,7 @@ bool CWorldLights::GetBrightestLightSource(const Vector &vecPosition, Vector &ve
delete[] pvs;
return false;
return;
}
// Calculate square distance to this worldlight
@ -308,7 +408,87 @@ bool CWorldLights::GetBrightestLightSource(const Vector &vecPosition, Vector &ve
}
delete[] pvs;
}
//engine->Con_NPrintf(m_nWorldLights, "result: %d", !vecLightBrightness.IsZero());
return !vecLightBrightness.IsZero();
}
#ifdef MAPBASE
void CWorldLights::FindBrightestLightSourceNew( const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness, int nCluster )
{
// Handle sun
if (m_iSunIndex != -1)
{
dworldlight_t *light = &m_pWorldLights[m_iSunIndex];
// 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())
{
// 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))
{
// Act like we didn't find any valid worldlights, so the shadow
// manager uses the default shadow direction instead (should be the
// sun direction)
return;
}
}
}
// Iterate through all the worldlights
if ( nCluster >= 0 && nCluster < m_WorldLightsInCluster.Count() )
{
// find all soundscapes that could possibly attach to this player and update them
for ( int j = 0; j < m_WorldLightsInCluster[nCluster].lightCount; j++ )
{
int ssIndex = m_WorldLightsIndexList[m_WorldLightsInCluster[nCluster].firstLight + j];
dworldlight_t *light = &m_pWorldLights[ssIndex];
// 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;
}
// 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());
}
}
}
#endif

View File

@ -27,7 +27,9 @@ public:
// Find the brightest light source at a point
//-------------------------------------------------------------------------
bool GetBrightestLightSource(const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness);
void FindBrightestLightSourceOld( const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness, int nCluster );
#ifdef MAPBASE
void FindBrightestLightSourceNew(const Vector &vecPosition, Vector &vecLightPos, Vector &vecLightBrightness, int nCluster);
bool GetCumulativeLightSource(const Vector &vecPosition, Vector &vecLightPos, float flMinBrightnessSqr);
#endif
@ -42,6 +44,19 @@ private:
int m_nWorldLights;
dworldlight_t *m_pWorldLights;
#ifdef MAPBASE
int m_iSunIndex = -1; // The sun's personal index
struct clusterLightList_t
{
unsigned short lightCount;
unsigned short firstLight;
};
CUtlVector<clusterLightList_t> m_WorldLightsInCluster;
CUtlVector<unsigned short> m_WorldLightsIndexList;
#endif
};
//-----------------------------------------------------------------------------

View File

@ -4,6 +4,9 @@
//
//=============================================================================//
#ifdef NEW_RESPONSE_SYSTEM
#include "ai_criteria_new.h"
#else
#ifndef AI_CRITERIA_H
#define AI_CRITERIA_H
#ifdef _WIN32
@ -278,3 +281,4 @@ private:
};
#endif // AI_CRITERIA_H
#endif

View File

@ -2025,7 +2025,8 @@ void CResponseSystem::ParseInclude( CStringPool &includedFiles )
if (len+1 != strlen(scriptfile))
{
Q_snprintf(includefile, sizeof(includefile), "%s/%s", includefile, token);
Q_strncat( includefile, "/", sizeof( includefile ) );
Q_strncat( includefile, token, sizeof( includefile ) );
}
else
includefile[0] = '\0';

View File

@ -4,6 +4,9 @@
//
//=============================================================================//
#ifdef NEW_RESPONSE_SYSTEM
#include "ai_responsesystem_new.h"
#else
#ifndef AI_RESPONSESYSTEM_H
#define AI_RESPONSESYSTEM_H
@ -40,3 +43,4 @@ class ISaveRestoreBlockHandler *GetDefaultResponseSystemSaveRestoreBlockHandler(
class ISaveRestoreOps *GetResponseSystemSaveRestoreOps();
#endif // AI_RESPONSESYSTEM_H
#endif

View File

@ -57,6 +57,45 @@ BEGIN_DATADESC( CBaseAnimatingOverlay )
END_DATADESC()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( CBaseAnimatingOverlay, CBaseAnimating, "Animating models which support dynamic animation layers/overlays." )
DEFINE_SCRIPTFUNC( GetNumAnimOverlays, "Gets the current number of animation layers." )
DEFINE_SCRIPTFUNC( RemoveAllGestures, "Removes all animation layers." )
DEFINE_SCRIPTFUNC( IsValidLayer, "Returns true if the specified layer index is valid." )
DEFINE_SCRIPTFUNC( HasActiveLayer, "Returns true if there is currently an active layer." )
DEFINE_SCRIPTFUNC( RemoveLayer, "Removes the specified layer index with the specified kill rate and delay." )
DEFINE_SCRIPTFUNC( FastRemoveLayer, "Removes the specified layer index immediately." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGesture, "AddGesture", "Adds a new animation layer using the specified activity name." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGestureID, "AddGestureID", "Adds a new animation layer using the specified activity index." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGestureSequence, "AddGestureSequence", "Adds a new animation layer using the specified activity name." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddGestureSequenceID, "AddGestureSequenceID", "Adds a new animation layer using the specified sequence index." )
DEFINE_SCRIPTFUNC_NAMED( ScriptFindGestureLayer, "FindGestureLayer", "Finds and returns the first active animation layer which uses the specified activity name." )
DEFINE_SCRIPTFUNC_NAMED( ScriptFindGestureLayerByID, "FindGestureLayerByID", "Finds and returns the first active animation layer which uses the specified activity index." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLayerActivity, "GetLayerActivity", "Gets the activity name of the specified layer index." )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLayerActivityID, "GetLayerActivityID", "Gets the activity index of the specified layer index." )
DEFINE_SCRIPTFUNC( GetLayerSequence, "Gets the sequence index of the specified layer index." )
DEFINE_SCRIPTFUNC( SetLayerDuration, "Sets the duration of the specified layer index." )
DEFINE_SCRIPTFUNC( GetLayerDuration, "Gets the duration of the specified layer index." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetLayerCycle, "SetLayerCycle", "Sets the cycle of the specified layer index." )
DEFINE_SCRIPTFUNC( GetLayerCycle, "Gets the cycle of the specified layer index." )
DEFINE_SCRIPTFUNC( SetLayerPlaybackRate, "Sets the playback rate of the specified layer index." )
DEFINE_SCRIPTFUNC( SetLayerWeight, "Sets the weight of the specified layer index." )
DEFINE_SCRIPTFUNC( GetLayerWeight, "Gets the weight of the specified layer index." )
DEFINE_SCRIPTFUNC( SetLayerBlendIn, "Sets the fade-in of the specified layer index, with the fade being a 0-1 fraction of the cycle." )
DEFINE_SCRIPTFUNC( SetLayerBlendOut, "Sets the fade-out of the specified layer index, with the fade being a 0-1 fraction of the cycle." )
DEFINE_SCRIPTFUNC( SetLayerAutokill, "Sets whether or not the specified layer index should remove itself when it's finished playing." )
DEFINE_SCRIPTFUNC( SetLayerLooping, "Sets whether or not the specified layer index should loop." )
DEFINE_SCRIPTFUNC( SetLayerNoRestore, "Sets whether or not the specified layer index should restore after a save is loaded." )
DEFINE_SCRIPTFUNC( SetLayerNoEvents, "Sets whether or not the specified layer index should fire animation events." )
END_SCRIPTDESC();
#endif
#define ORDER_BITS 4
#define WEIGHT_BITS 8
@ -354,7 +393,11 @@ void CBaseAnimatingOverlay::DispatchAnimEvents ( CBaseAnimating *eventHandler )
for ( int i = 0; i < m_AnimOverlay.Count(); i++ )
{
#ifdef MAPBASE // From Alien Swarm SDK
if (m_AnimOverlay[ i ].IsActive() && !m_AnimOverlay[ i ].NoEvents())
#else
if (m_AnimOverlay[ i ].IsActive())
#endif
{
m_AnimOverlay[ i ].DispatchAnimEvents( eventHandler, this );
}
@ -427,6 +470,11 @@ void CAnimationLayer::DispatchAnimEvents( CBaseAnimating *eventHandler, CBaseAni
event.eventtime = pOwner->m_flAnimTime + (flCycle - m_flCycle) / flCycleRate + pOwner->GetAnimTimeInterval();
}
#ifdef MAPBASE_VSCRIPT
if (eventHandler->m_ScriptScope.IsInitialized() && eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
continue;
#endif
// Msg( "dispatch %d (%d : %.2f)\n", index - 1, event.event, event.eventtime );
eventHandler->HandleAnimEvent( &event );
}
@ -1066,6 +1114,38 @@ void CBaseAnimatingOverlay::SetLayerNoRestore( int iLayer, bool bNoRestore )
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// From Alien Swarm SDK
//-----------------------------------------------------------------------------
void CBaseAnimatingOverlay::SetLayerNoEvents( int iLayer, bool bNoEvents )
{
if (!IsValidLayer( iLayer ))
return;
if (bNoEvents)
{
m_AnimOverlay[iLayer].m_fFlags |= ANIM_LAYER_NOEVENTS;
}
else
{
m_AnimOverlay[iLayer].m_fFlags &= ~ANIM_LAYER_NOEVENTS;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseAnimatingOverlay::IsLayerFinished( int iLayer )
{
if (!IsValidLayer( iLayer ))
return true;
return m_AnimOverlay[iLayer].m_bSequenceFinished;
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -1163,4 +1243,36 @@ bool CBaseAnimatingOverlay::HasActiveLayer( void )
return false;
}
#ifdef MAPBASE_VSCRIPT
int CBaseAnimatingOverlay::ScriptAddGesture( const char *pszActivity, bool autokill )
{
return AddGesture( (Activity)CAI_BaseNPC::GetActivityID( pszActivity ), autokill );
}
int CBaseAnimatingOverlay::ScriptAddGestureID( int iActivity, bool autokill )
{
return AddGesture( (Activity)iActivity, autokill );
}
int CBaseAnimatingOverlay::ScriptFindGestureLayer( const char *pszActivity )
{
return FindGestureLayer( (Activity)CAI_BaseNPC::GetActivityID( pszActivity ) );
}
int CBaseAnimatingOverlay::ScriptFindGestureLayerByID( int iActivity )
{
return FindGestureLayer( (Activity)iActivity );
}
const char *CBaseAnimatingOverlay::ScriptGetLayerActivity( int iLayer )
{
return CAI_BaseNPC::GetActivityName( GetLayerActivity( iLayer ) );
}
int CBaseAnimatingOverlay::ScriptGetLayerActivityID( int iLayer )
{
return GetLayerActivity( iLayer );
}
#endif
//-----------------------------------------------------------------------------

View File

@ -43,6 +43,9 @@ public:
#define ANIM_LAYER_DONTRESTORE 0x0008
#define ANIM_LAYER_CHECKACCESS 0x0010
#define ANIM_LAYER_DYING 0x0020
#ifdef MAPBASE // From Alien Swarm SDK
#define ANIM_LAYER_NOEVENTS 0x0040
#endif
int m_fFlags;
@ -80,6 +83,9 @@ public:
void Dying( void ) { m_fFlags |= ANIM_LAYER_DYING; }
bool IsDying( void ) { return ((m_fFlags & ANIM_LAYER_DYING) != 0); }
void Dead( void ) { m_fFlags &= ~ANIM_LAYER_DYING; }
#ifdef MAPBASE // From Alien Swarm SDK
bool NoEvents( void ) { return ((m_fFlags & ANIM_LAYER_NOEVENTS) != 0); }
#endif
bool IsAbandoned( void );
void MarkActive( void );
@ -176,6 +182,11 @@ public:
void SetLayerAutokill( int iLayer, bool bAutokill );
void SetLayerLooping( int iLayer, bool bLooping );
void SetLayerNoRestore( int iLayer, bool bNoRestore );
#ifdef MAPBASE
void SetLayerNoEvents( int iLayer, bool bNoEvents ); // From Alien Swarm SDK
bool IsLayerFinished( int iLayer );
#endif
Activity GetLayerActivity( int iLayer );
int GetLayerSequence( int iLayer );
@ -196,9 +207,26 @@ public:
private:
int AllocateLayer( int iPriority = 0 ); // lower priorities are processed first
#ifdef MAPBASE_VSCRIPT
int ScriptAddGesture( const char *pszActivity, bool autokill );
int ScriptAddGestureID( int iActivity, bool autokill );
int ScriptAddGestureSequence( const char *pszSequence, bool autokill ) { return AddGestureSequence( LookupSequence( pszSequence ), autokill ); }
int ScriptAddGestureSequenceID( int iSequence, bool autokill ) { return AddGestureSequence( iSequence, autokill ); }
int ScriptFindGestureLayer( const char *pszActivity );
int ScriptFindGestureLayerByID( int iActivity );
const char *ScriptGetLayerActivity( int iLayer );
int ScriptGetLayerActivityID( int iLayer );
void ScriptSetLayerCycle( int iLayer, float flCycle ) { SetLayerCycle( iLayer, flCycle ); }
#endif
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
DECLARE_PREDICTABLE();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
};
EXTERN_SEND_TABLE(DT_BaseAnimatingOverlay);

View File

@ -77,6 +77,8 @@ public:
#ifdef MAPBASE
virtual bool PassesDoorFilter(CBaseEntity *pEntity) { return true; }
virtual bool KeyValue( const char *szKeyName, const char *szValue );
#endif
protected:
@ -103,6 +105,12 @@ protected:
inline CBaseEntity *GetActivator();
#ifdef MAPBASE
inline float GetNPCOpenDistance() { return m_flNPCOpenDistance; }
inline Activity GetNPCOpenFrontActivity() { return m_eNPCOpenFrontActivity; }
inline Activity GetNPCOpenBackActivity() { return m_eNPCOpenBackActivity; }
#endif
private:
// Implement these in your leaf class.
@ -196,6 +204,12 @@ private:
string_t m_SoundOpen;
string_t m_SoundClose;
#ifdef MAPBASE
float m_flNPCOpenDistance;
Activity m_eNPCOpenFrontActivity;
Activity m_eNPCOpenBackActivity;
#endif
// dvs: FIXME: can we remove m_flSpeed from CBaseEntity?
//float m_flSpeed; // Rotation speed when opening or closing in degrees per second.

View File

@ -24,6 +24,8 @@
#include "Sprite.h"
#ifdef MAPBASE
#include "mapbase/SystemConvarMod.h"
#include <vgui_controls/Controls.h>
#include <vgui/ILocalize.h>
#endif
// memdbgon must be the last include file in a .cpp file!!!
@ -72,8 +74,23 @@ class CPointCommentaryNode : public CBaseAnimating
DECLARE_CLASS( CPointCommentaryNode, CBaseAnimating );
public:
DECLARE_DATADESC();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
DECLARE_SERVERCLASS();
CPointCommentaryNode()
{
#ifdef MAPBASE
m_flViewTargetSpeedScale = 1.0f;
m_flViewPositionSpeedScale = 1.0f;
m_flReturnSpeedScale = 0.0f;
m_flPanelScale = 1.0f;
m_flPanelX = -1.0f;
m_flPanelY = -1.0f;
#endif
}
void Spawn( void );
void Precache( void );
void Activate( void );
@ -102,11 +119,39 @@ public:
void TeleportTo( CBasePlayer *pPlayer );
bool CanTeleportTo( void );
#ifdef MAPBASE
bool IsActive() { return m_bActive; }
bool IsDisabled() { return m_bDisabled; }
int GetCommentaryType() { return m_iCommentaryType; }
void SetCommentaryType( int iType ) { m_iCommentaryType = iType; }
const char *GetCommentaryFile() { return STRING( m_iszCommentaryFile.Get() ); }
void SetCommentaryFile( const char *pszNewFile ) { m_iszCommentaryFile.Set( AllocPooledString( pszNewFile ) ); }
const char *GetSpeakers() { return STRING( m_iszSpeakers.Get() ); }
void SetSpeakers( const char *pszSpeakers ) { m_iszSpeakers.Set( AllocPooledString( pszSpeakers ) ); }
const char *GetPrintName() { return STRING( m_iszPrintName.Get() ); }
void SetPrintName( const char *pszPrintName ) { m_iszPrintName.Set( AllocPooledString( pszPrintName ) ); }
const char *GetFootnote() { return STRING( m_iszFootnote.Get() ); }
void SetFootnote( const char *pszFootnote ) { m_iszFootnote.Set( AllocPooledString( pszFootnote ) ); }
#endif
// Inputs
void InputStartCommentary( inputdata_t &inputdata );
void InputStartUnstoppableCommentary( inputdata_t &inputdata );
void InputEnable( inputdata_t &inputdata );
void InputDisable( inputdata_t &inputdata );
#ifdef MAPBASE
void InputSetViewTarget( inputdata_t &inputdata );
void InputSetViewPosition( inputdata_t &inputdata );
void InputSetViewTargetSpeed( inputdata_t &inputdata );
void InputSetViewPositionSpeed( inputdata_t &inputdata );
void InputSetReturnSpeed( inputdata_t &inputdata );
#endif
#ifdef MAPBASE_VSCRIPT
static ScriptHook_t g_Hook_PreStartCommentary;
#endif
private:
string_t m_iszPreCommands;
@ -119,6 +164,14 @@ private:
string_t m_iszViewPosition;
CNetworkVar( EHANDLE, m_hViewPosition );
EHANDLE m_hViewPositionMover; // Entity used to blend the view to the viewposition entity
#ifdef MAPBASE
float m_flViewTargetSpeedScale;
float m_flViewPositionSpeedScale;
float m_flReturnSpeedScale;
CNetworkVar( string_t, m_iszPrintName );
CNetworkVar( string_t, m_iszFootnote );
float m_flViewPositionChangedTime; // View position now blends relative to this value. Mainly needed for when SetViewPosition is used
#endif
bool m_bPreventMovement;
bool m_bUnderCrosshair;
bool m_bUnstoppable;
@ -138,6 +191,13 @@ private:
CNetworkVar( string_t, m_iszSpeakers );
CNetworkVar( int, m_iNodeNumber );
CNetworkVar( int, m_iNodeNumberMax );
#ifdef MAPBASE
CNetworkVar( int, m_iCommentaryType );
CNetworkVar( float, m_flPanelScale );
CNetworkVar( float, m_flPanelX );
CNetworkVar( float, m_flPanelY );
#endif
};
BEGIN_DATADESC( CPointCommentaryNode )
@ -166,6 +226,18 @@ BEGIN_DATADESC( CPointCommentaryNode )
DEFINE_FIELD( m_bPreventChangesWhileMoving, FIELD_BOOLEAN ),
DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "start_disabled" ),
DEFINE_KEYFIELD( m_vecTeleportOrigin, FIELD_VECTOR, "teleport_origin" ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_flViewTargetSpeedScale, FIELD_FLOAT, "viewtarget_speed" ),
DEFINE_KEYFIELD( m_flViewPositionSpeedScale, FIELD_FLOAT, "viewposition_speed" ),
DEFINE_KEYFIELD( m_flReturnSpeedScale, FIELD_FLOAT, "return_speed" ),
DEFINE_KEYFIELD( m_iszPrintName, FIELD_STRING, "printname" ),
DEFINE_KEYFIELD( m_iszFootnote, FIELD_STRING, "footnote" ),
DEFINE_FIELD( m_flViewPositionChangedTime, FIELD_TIME ),
DEFINE_KEYFIELD( m_iCommentaryType, FIELD_INTEGER, "type" ),
DEFINE_KEYFIELD( m_flPanelScale, FIELD_FLOAT, "panelscale" ),
DEFINE_KEYFIELD( m_flPanelX, FIELD_FLOAT, "x" ),
DEFINE_KEYFIELD( m_flPanelY, FIELD_FLOAT, "y" ),
#endif
// Outputs
DEFINE_OUTPUT( m_pOnCommentaryStarted, "OnCommentaryStarted" ),
@ -176,6 +248,13 @@ BEGIN_DATADESC( CPointCommentaryNode )
DEFINE_INPUTFUNC( FIELD_VOID, "StartUnstoppableCommentary", InputStartUnstoppableCommentary ),
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
#ifdef MAPBASE
DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetViewTarget", InputSetViewTarget ),
DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetViewPosition", InputSetViewPosition ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetViewTargetSpeed", InputSetViewTargetSpeed ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetViewPositionSpeed", InputSetViewPositionSpeed ),
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetReturnSpeed", InputSetReturnSpeed ),
#endif
// Functions
DEFINE_THINKFUNC( SpinThink ),
@ -183,6 +262,37 @@ BEGIN_DATADESC( CPointCommentaryNode )
DEFINE_THINKFUNC( UpdateViewPostThink ),
END_DATADESC()
#ifdef MAPBASE_VSCRIPT
ScriptHook_t CPointCommentaryNode::g_Hook_PreStartCommentary;
BEGIN_ENT_SCRIPTDESC( CPointCommentaryNode, CBaseAnimating, "Commentary nodes which play commentary in commentary mode." )
DEFINE_SCRIPTFUNC( IsDisabled, "" )
DEFINE_SCRIPTFUNC( SetDisabled, "" )
DEFINE_SCRIPTFUNC( IsActive, "" )
DEFINE_SCRIPTFUNC( GetCommentaryFile, "" )
DEFINE_SCRIPTFUNC( SetCommentaryFile, "" )
DEFINE_SCRIPTFUNC( GetSpeakers, "" )
DEFINE_SCRIPTFUNC( SetSpeakers, "" )
DEFINE_SCRIPTFUNC( GetPrintName, "" )
DEFINE_SCRIPTFUNC( SetPrintName, "" )
DEFINE_SCRIPTFUNC( GetFootnote, "" )
DEFINE_SCRIPTFUNC( SetFootnote, "" )
DEFINE_SCRIPTFUNC( GetCommentaryType, "" )
DEFINE_SCRIPTFUNC( SetCommentaryType, "" )
DEFINE_SCRIPTFUNC( HasViewTarget, "" )
DEFINE_SCRIPTFUNC( PreventsMovement, "" )
DEFINE_SCRIPTFUNC( CannotBeStopped, "" )
DEFINE_SCRIPTFUNC( AbortPlaying, "Stops playing the node and snaps out of its camera control immediately. The game uses this function to shut down commentary while in the middle of playing a node, as it can't smoothly blend out (since the commentary entities need to be removed)." )
DEFINE_SIMPLE_SCRIPTHOOK( CPointCommentaryNode::g_Hook_PreStartCommentary, "PreStartCommentary", FIELD_BOOLEAN, "Called just before commentary begins. Use this to modify variables or commentary behavior before it begins. Returning false will prevent the commentary from starting." )
END_SCRIPTDESC();
#endif // MAPBASE_VSCRIPT
IMPLEMENT_SERVERCLASS_ST( CPointCommentaryNode, DT_PointCommentaryNode )
SendPropBool( SENDINFO(m_bActive) ),
SendPropStringT( SENDINFO(m_iszCommentaryFile) ),
@ -192,6 +302,14 @@ IMPLEMENT_SERVERCLASS_ST( CPointCommentaryNode, DT_PointCommentaryNode )
SendPropInt( SENDINFO(m_iNodeNumber), 8, SPROP_UNSIGNED ),
SendPropInt( SENDINFO(m_iNodeNumberMax), 8, SPROP_UNSIGNED ),
SendPropEHandle( SENDINFO(m_hViewPosition) ),
#ifdef MAPBASE
SendPropStringT( SENDINFO( m_iszPrintName ) ),
SendPropStringT( SENDINFO( m_iszFootnote ) ),
SendPropInt( SENDINFO( m_iCommentaryType ), 2, SPROP_UNSIGNED ),
SendPropFloat( SENDINFO( m_flPanelScale ) ),
SendPropFloat( SENDINFO( m_flPanelX ) ),
SendPropFloat( SENDINFO( m_flPanelY ) ),
#endif
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS( point_commentary_node, CPointCommentaryNode );
@ -673,6 +791,11 @@ public:
#endif
engine->LockNetworkStringTables( oldLock );
#ifdef MAPBASE
// Special commentary localization file (useful for things like text nodes or print names)
g_pVGuiLocalize->AddFile( "resource/commentary_%language%.txt", "MOD" );
#endif
}
void ShutDownCommentary( void )
@ -892,10 +1015,32 @@ bool IsListeningToCommentary( void )
void CPointCommentaryNode::Spawn( void )
{
// No model specified?
char *szModel = (char *)STRING( GetModelName() );
const char *szModel = STRING( GetModelName() );
if (!szModel || !*szModel)
{
#ifdef MAPBASE
switch (m_iCommentaryType)
{
case COMMENTARY_TYPE_TEXT:
szModel = "models/extras/info_text.mdl";
break;
case COMMENTARY_TYPE_IMAGE:
szModel = "models/extras/info_image.mdl";
break;
case COMMENTARY_TYPE_SCENE:
szModel = "models/extras/info_scene.mdl";
break;
default:
case COMMENTARY_TYPE_AUDIO:
szModel = "models/extras/info_speech.mdl";
break;
}
#else
szModel = "models/extras/info_speech.mdl";
#endif
SetModelName( AllocPooledString(szModel) );
}
@ -906,6 +1051,12 @@ void CPointCommentaryNode::Spawn( void )
AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST );
AddEffects( EF_NOSHADOW );
#ifdef MAPBASE
// Default to view position speed scale (which in turn defaults to 1.0)
if (m_flReturnSpeedScale == 0.0f)
m_flReturnSpeedScale = m_flViewPositionSpeedScale;
#endif
// Setup for animation
ResetSequence( LookupSequence("idle") );
SetThink( &CPointCommentaryNode::SpinThink );
@ -1119,6 +1270,19 @@ void CPointCommentaryNode::StartCommentary( void )
if ( !pPlayer )
return;
#ifdef MAPBASE_VSCRIPT
if (m_ScriptScope.IsInitialized() && g_Hook_PreStartCommentary.CanRunInScope( m_ScriptScope ))
{
ScriptVariant_t functionReturn;
if ( g_Hook_PreStartCommentary.Call( m_ScriptScope, &functionReturn, NULL ) && functionReturn.m_type == FIELD_BOOLEAN )
{
// Don't play the commentary if it returned false
if (functionReturn.m_bool == false)
return;
}
}
#endif
m_bActive = true;
m_flAnimTime = gpGlobals->curtime;
@ -1140,6 +1304,21 @@ void CPointCommentaryNode::StartCommentary( void )
// Start the commentary
m_flStartTime = gpGlobals->curtime;
#ifdef MAPBASE
if (m_hViewPosition.Get())
{
m_flViewPositionChangedTime = gpGlobals->curtime;
}
else
{
m_flViewPositionChangedTime = -1.0f;
}
// This is now used in certain places to denote the "last blend to" origin
m_vecFinishOrigin = pPlayer->EyePosition();
m_vecFinishAngles = pPlayer->EyeAngles();
#endif
// If we have a view target, start blending towards it
if ( m_hViewTarget || m_hViewPosition.Get() )
{
@ -1214,6 +1393,10 @@ void CPointCommentaryNode::UpdateViewThink( void )
float dx = AngleDiff( angGoal.x, angCurrent.x );
float dy = AngleDiff( angGoal.y, angCurrent.y );
float mod = 1.0 - ExponentialDecay( 0.5, 0.3, gpGlobals->frametime );
#ifdef MAPBASE
if (m_flViewTargetSpeedScale != 1.0f)
mod *= m_flViewTargetSpeedScale;
#endif
float dxmod = dx * mod;
float dymod = dy * mod;
@ -1254,16 +1437,85 @@ void CPointCommentaryNode::UpdateViewThink( void )
}
// Blend to the target position over time.
float flCurTime = (gpGlobals->curtime - m_flStartTime);
#ifdef MAPBASE
float flCurTime = (gpGlobals->curtime - m_flViewPositionChangedTime);
if (m_flViewPositionSpeedScale != 1.0f)
flCurTime *= m_flViewPositionSpeedScale;
#else
float flCurTime = (gpGlobals->curtime - m_flStartTime);
#endif
float flBlendPerc = clamp( flCurTime * 0.5f, 0.f, 1.f );
// Figure out the current view position
Vector vecCurEye;
#ifdef MAPBASE
VectorLerp( m_vecFinishOrigin, m_hViewPosition.Get()->GetAbsOrigin(), flBlendPerc, vecCurEye );
#else
VectorLerp( pPlayer->EyePosition(), m_hViewPosition.Get()->GetAbsOrigin(), flBlendPerc, vecCurEye );
#endif
m_hViewPositionMover->SetAbsOrigin( vecCurEye );
SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink );
}
#ifdef MAPBASE
else if ( m_flViewPositionChangedTime != -1.0f && m_hViewPositionMover )
{
// Blend back to the player's position over time.
float flCurTime = (gpGlobals->curtime - m_flViewPositionChangedTime);
if (m_flViewPositionSpeedScale != 1.0f)
flCurTime *= m_flViewPositionSpeedScale;
//float flTimeToBlend = MIN( 2.0, m_flViewPositionChangedTime - m_flStartTime );
//float flBlendPerc = 1.0f - clamp( flCurTime / flTimeToBlend, 0.f, 1.f );
float flBlendPerc = 1.0f - clamp( flCurTime * 0.5f, 0.f, 1.f );
//Msg("OUT: CurTime %.2f, BlendTime: %.2f, Blend: %.3f\n", flCurTime, flTimeToBlend, flBlendPerc );
// Only do this while we're still moving
if ( flBlendPerc > 0 )
{
// Figure out the current view position
Vector vecPlayerPos = pPlayer->EyePosition();
Vector vecToPosition = (m_vecFinishOrigin - vecPlayerPos);
Vector vecCurEye = pPlayer->EyePosition() + (vecToPosition * flBlendPerc);
m_hViewPositionMover->SetAbsOrigin( vecCurEye );
if ( m_hViewTarget )
{
Quaternion quatFinish;
Quaternion quatOriginal;
Quaternion quatCurrent;
AngleQuaternion( m_vecOriginalAngles, quatOriginal );
AngleQuaternion( m_vecFinishAngles, quatFinish );
QuaternionSlerp( quatFinish, quatOriginal, 1.0 - flBlendPerc, quatCurrent );
QAngle angCurrent;
QuaternionAngles( quatCurrent, angCurrent );
m_hViewPositionMover->SetAbsAngles( angCurrent );
}
SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink );
return;
}
else
{
pPlayer->SnapEyeAngles( m_hViewPositionMover->GetAbsAngles() );
// Try to clean up the view position stuff without ending the commentary
if ( !m_hViewTargetAngles && pPlayer->GetActiveWeapon() )
{
pPlayer->GetActiveWeapon()->Deploy();
}
if (pPlayer->GetViewEntity() == m_hViewPositionMover)
{
pPlayer->SetViewEntity( NULL );
}
UTIL_Remove( m_hViewPositionMover );
m_flViewPositionChangedTime = -1.0f;
}
}
#endif
}
//-----------------------------------------------------------------------------
@ -1279,6 +1531,10 @@ void CPointCommentaryNode::UpdateViewPostThink( void )
{
// Blend back to the player's position over time.
float flCurTime = (gpGlobals->curtime - m_flFinishedTime);
#ifdef MAPBASE
if (m_flReturnSpeedScale != 1.0f)
flCurTime *= m_flReturnSpeedScale;
#endif
float flTimeToBlend = MIN( 2.0, m_flFinishedTime - m_flStartTime );
float flBlendPerc = 1.0f - clamp( flCurTime / flTimeToBlend, 0.f, 1.f );
@ -1440,6 +1696,79 @@ void CPointCommentaryNode::InputDisable( inputdata_t &inputdata )
SetDisabled( true );
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointCommentaryNode::InputSetViewTarget( inputdata_t &inputdata )
{
m_hViewTarget = inputdata.value.Entity();
// Do not let Activate() reassign this
m_iszViewTarget = NULL_STRING;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointCommentaryNode::InputSetViewPosition( inputdata_t &inputdata )
{
if (m_hViewPosition.Get() && m_hViewPositionMover)
{
// In case the view position is being cleared, assign the "finish" vectors
m_vecFinishOrigin = m_hViewPositionMover->GetAbsOrigin();
m_vecFinishAngles = m_hViewPositionMover->GetAbsAngles();
}
else
{
CBasePlayer *pPlayer = GetCommentaryPlayer();
if (pPlayer)
{
// And in case it's a new view position coming from the player, assign the "finish" vectors to the player
m_vecFinishOrigin = pPlayer->EyePosition();
m_vecFinishAngles = m_vecOriginalAngles = pPlayer->EyeAngles();
}
}
m_hViewPosition = inputdata.value.Entity();
// Do not let Activate() reassign this
m_iszViewPosition = NULL_STRING;
m_flViewPositionChangedTime = gpGlobals->curtime;
// If we have a view target, start blending towards it
if ( m_hViewPosition.Get() )
{
SetContextThink( &CPointCommentaryNode::UpdateViewThink, gpGlobals->curtime, s_pCommentaryUpdateViewThink );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointCommentaryNode::InputSetViewTargetSpeed( inputdata_t &inputdata )
{
m_flViewTargetSpeedScale = inputdata.value.Float();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointCommentaryNode::InputSetViewPositionSpeed( inputdata_t &inputdata )
{
m_flViewPositionSpeedScale = inputdata.value.Float();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPointCommentaryNode::InputSetReturnSpeed( inputdata_t &inputdata )
{
m_flReturnSpeedScale = inputdata.value.Float();
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -1501,7 +1830,11 @@ void CPointCommentaryNode::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways
bool CPointCommentaryNode::PreventsMovement( void )
{
// If we're moving the player's view at all, prevent movement
#ifdef MAPBASE
if ( m_hViewPosition.Get() || m_flViewPositionChangedTime != -1.0f )
#else
if ( m_hViewPosition.Get() )
#endif
return true;
return m_bPreventMovement;

View File

@ -242,7 +242,12 @@ void CEntityFlame::FlameThink( void )
}
CAI_BaseNPC *pNPC = m_hEntAttached->MyNPCPointer();
#ifdef MAPBASE
// Don't extingish if the NPC is still dying
if ( pNPC && !pNPC->IsAlive() && pNPC->m_lifeState != LIFE_DYING )
#else
if ( pNPC && !pNPC->IsAlive() )
#endif
{
UTIL_Remove( this );
// Notify the NPC that it's no longer burning!

View File

@ -154,6 +154,9 @@ public:
DECLARE_DATADESC();
void Spawn( void );
#ifdef MAPBASE
void PrecacheCreditsThink();
#endif
void InputRollCredits( inputdata_t &inputdata );
void InputRollOutroCredits( inputdata_t &inputdata );
void InputShowLogo( inputdata_t &inputdata );
@ -186,6 +189,8 @@ BEGIN_DATADESC( CCredits )
#ifdef MAPBASE
DEFINE_KEYFIELD( m_iszCreditsFile, FIELD_STRING, "CreditsFile" ),
DEFINE_THINKFUNC( PrecacheCreditsThink ),
#endif
DEFINE_FIELD( m_bRolledOutroCredits, FIELD_BOOLEAN ),
@ -196,8 +201,35 @@ void CCredits::Spawn( void )
{
SetSolid( SOLID_NONE );
SetMoveType( MOVETYPE_NONE );
#ifdef MAPBASE
// Ensures the player has time to spawn
SetContextThink( &CCredits::PrecacheCreditsThink, gpGlobals->curtime + 0.5f, "PrecacheCreditsContext" );
#endif
}
#ifdef MAPBASE
void CCredits::PrecacheCreditsThink()
{
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
if (!pPlayer)
{
Warning( "%s: No player\n", GetDebugName() );
return;
}
CSingleUserRecipientFilter user( pPlayer );
user.MakeReliable();
UserMessageBegin( user, "CreditsMsg" );
WRITE_BYTE( 4 );
WRITE_STRING( STRING(m_iszCreditsFile) );
MessageEnd();
SetContextThink( NULL, TICK_NEVER_THINK, "PrecacheCreditsContext" );
}
#endif
static void CreditsDone_f( void )
{
CCredits *pCredits = (CCredits*)gEntList.FindEntityByClassname( NULL, "env_credits" );
@ -212,6 +244,10 @@ static ConCommand creditsdone("creditsdone", CreditsDone_f );
extern ConVar sv_unlockedchapters;
#ifdef MAPBASE
extern int Mapbase_GetChapterCount();
#endif
void CCredits::OnRestore()
{
BaseClass::OnRestore();
@ -226,6 +262,10 @@ void CCredits::OnRestore()
void CCredits::RollOutroCredits()
{
#ifdef MAPBASE
// Don't set this if we're using Mapbase chapters or if sv_unlockedchapters is already greater than 15
if (Mapbase_GetChapterCount() <= 0 && sv_unlockedchapters.GetInt() < 15)
#endif
sv_unlockedchapters.SetValue( "15" );
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();

Some files were not shown because too many files have changed in this diff Show More