Merge pull request #113 from mapbase-source/develop

Mapbase v7.0
This commit is contained in:
Blixibon 2022-10-05 20:37:37 -05:00 committed by GitHub
commit 4aeaaa46c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
429 changed files with 33341 additions and 3566 deletions

View File

@ -23,7 +23,12 @@ All contributions must follow the following rules:
is usually not fit for Mapbase.
* All content in a contribution must be either already legally open-source or done with the
full permission of the content's original creator(s).
full permission of the content's original creator(s). If licensing is involved, the contribution
must ensure Mapbase follows said licensing.
* **NOTE:** Due to concerns with mods which do not wish to be open-source, content using GPL licenses (or any
license with similar open-source requirements) are currently not allowed to be distributed with Mapbase.
Contributions which can draw from them without actually distributing the licensed content may theoretically
be excepted from this rule.
* Contributions must not break existing maps/content or interfere with them in a negative or non-objective way.
@ -34,6 +39,15 @@ All contributions must follow the following rules:
use the custom "Mapbase - Source 2013" header used in other Mapbase files as of Mapbase v5.0.
You are encouraged to append an "Author(s)" part to that header in your file in order to clarify who wrote it.
* Do not modify the README to add attribution for your contribution. That is handled by Mapbase's maintainers.
Contributions which do not follow these guidelines cannot be accepted into Mapbase.
Attempting to contribute content which seriously violates the rules above can lead to being blocked from contributing,
especially if done repeatedly.
---
If your contribution is accepted, you may be listed in Mapbase's credits and the README's external content list:
https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Credits#Contributors
https://github.com/mapbase-source/source-sdk-2013/blob/master/README

77
README
View File

@ -1,6 +1,6 @@
//===================================================================================================================================================
Mapbase - Source 2013
Mapbase v7.0 - Source 2013
https://github.com/mapbase-source/source-sdk-2013
https://www.moddb.com/mods/mapbase
@ -20,10 +20,14 @@ Mapbase's main content in this repository may include:
- View rendering changes for drawing 3D skyboxes and RT-based entities
- Countless other fixes and improvements
For more information, view this page:
https://github.com/mapbase-source/source-sdk-2013/wiki/Introduction-to-Mapbase
//===================================================================================================================================================
Mapbase is an open-source project and its contents can be distributed and used at the discretion of its users. However, this project represents many parts of
the Source modding community packaged into a whole, so credit is taken very seriously.
Mapbase is an open-source project and its contents can be distributed and used at the discretion of its users. However, this project contains content from
a vast number of different sources which have their own licensing or attribution requirements. We try to handle most of that ourselves, but users who plan on
distributing Mapbase content are expected to comply with certain rules.
Up-to-date information about Mapbase content usage and credit are addressed in this article on Mapbase's wiki:
https://github.com/mapbase-source/source-sdk-2013/wiki/Using-Mapbase-Content
@ -37,25 +41,33 @@ and repositories (especially ones which are specifically published as free sourc
or complicated code changes accessible and easy to use for level designers and other kinds of Source modders who would otherwise have no idea how to implement them.
*** DISCLAIMER: Mapbase has a strict no-leak-content policy and only allows content created directly by contributors or content originating from open-source repositories.
If you believe any content in Mapbase originates from any leak or unauthorized source (from Valve or otherwise), please contact Blixibon immediately.
If you believe any content in Mapbase originates from any leak or unauthorized source (Valve or otherwise), please contact Blixibon immediately.
Mapbase is intended to be usable by everyone, including licensed Source projects and Steam mods. ***
-- The Alien Swarm SDK was used to backport features and code from newer branches of Source into a Source 2013/Half-Life 2 environment.
-- Mapbase also implements some of Tony Sergi's code changes from the Source 2007 SDK codebase. Both SDKs are publicly distributed by Valve and are available on Steam.
Mapbase uses content from the following non-Source SDK 2013 Valve games or SDKs:
Some of the features backported from the Alien Swarm SDK (e.g. game instructor, particle rain) require assets from later versions of Source in order to work properly.
The required assets have been backported from Alien Swarm and Left 4 Dead for the release build. They are not available in the code repository.
-- Alien Swarm SDK (Used to backport features and code from newer branches of Source into a Source 2013/Half-Life 2 environment)
-- Source SDK 2007 Code (Used to implement some of Tony Sergi's code changes)
Here's a list of Mapbase's other known external code sources:
-- Alien Swarm (Used to port assets from the aforementioned SDK code features, e.g. game instructor icons)
-- Left 4 Dead (Used to port certain animations as well as assets from the aforementioned SDK code features, e.g. particle rain)
-- Half-Life: Source (Used to port friction tool textures)
Valve allows assets from these titles to be distributed for modding purposes. Note that ported assets are only used in the release build, not the code repository.
Mapbase may also contain new third-party software distributed under specific licensing. Please see the bottom of thirdpartylegalnotices.txt for more information.
Here's a list of Mapbase's other external code sources:
- https://github.com/95Navigator/insolence-2013 (Initial custom shader code and projected texture improvements; also used to implement ASW SDK particle precipitation code)
- https://github.com/Biohazard90/g-string_2013 (Custom shadow filters, included indirectly via Insolence repo)
- https://github.com/KyleGospo/City-17-Episode-One-Source (Brush phong and projected texture changes, included indirectly via Insolence repo)
-- https://github.com/Biohazard90/g-string_2013 (Custom shadow filters, included indirectly via Insolence repo)
-- https://github.com/KyleGospo/City-17-Episode-One-Source (Brush phong and projected texture changes, included indirectly via Insolence repo)
- https://github.com/DownFall-Team/DownFall (Multiple skybox code and fix for ent_fire delay not using floats; Also used as a guide to port certain Alien Swarm SDK changes to Source 2013,
including radial fog, rope code, and treesway)
- https://github.com/momentum-mod/game (Used as a guide to port postprocess_controller and env_dof_controller to Source 2013)
- https://github.com/momentum-mod/game (Used as a guide to port postprocess_controller and env_dof_controller to Source 2013 from the Alien Swarm SDK)
- https://github.com/DeathByNukes/source-sdk-2013 (VBSP manifest fixes)
- https://github.com/entropy-zero/source-sdk-2013 (skill_changed game event)
- https://github.com/Nbc66/source-sdk-2013-ce/tree/v142 (Base for VS2019 toolset support)
//---------------------------------------------------------------------------------------------------------------------------------------------------
@ -89,11 +101,13 @@ interchangeable arms; this may change in the future)
Direct contributions:
- https://github.com/mapbase-source/source-sdk-2013/pull/3 ("playvideo" command playback fix from Avanate)
- https://github.com/mapbase-source/source-sdk-2013/pull/5 (Custom VScript implementation by ReDucTor; was placed into feature branch before being merged in a subsequent PR)
- https://github.com/mapbase-source/source-sdk-2013/pull/3 ("playvideo" command playback fix from Avantate)
- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux fixes from z33ky)
- https://github.com/mapbase-source/source-sdk-2013/pull/60 (Adjustment by RoyaleNoir to one of Saul's VDC changes)
- https://github.com/mapbase-source/source-sdk-2013/pull/84 (CS:S viewmodel chirality from 1upD)
- https://github.com/mapbase-source/source-sdk-2013/pull/116 (vgui_movie_display mute keyvalue from Alivebyte/rzkid)
- https://github.com/mapbase-source/source-sdk-2013/pull/140 (logic_substring entity and icon created by moofemp)
- https://github.com/mapbase-source/source-sdk-2013/pull/143 (Propper features for VBSP from Matty-64)
- Demo autorecord code provided by Klems
- cc_emit crash fix provided by 1upD
- Custom HL2 ammo crate models created by Rara (Textures created by Blixibon; This is asset-based and, aside from the SLAM crate, not reflected in the code)
@ -107,6 +121,33 @@ Direct contributions:
=-- https://github.com/mapbase-source/source-sdk-2013/pull/59 (New VScript functions and singletons based on API documentation in later Source/Source 2 games)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/80 (More VScript changes, including support for extremely flexible client/server messaging)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/105 (VScript fixes and optimizations, Vector class extensions, custom convars/commands)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/114 (VScript fixes and extensions)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/122 (Minor VScript-related adjustments)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/148 (Minor fixup)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/167 (Security fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/168 (Squirrel update)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/171 (VScript documentation sorting)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/173 (VScript fixes and optimizations)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/192 (VScript hook manager and fixes)
== Contributions from z33ky:
=-- https://github.com/mapbase-source/source-sdk-2013/pull/21 (Various GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/95 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/117 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/124 (Memory error fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/130 (Memory error fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/131 (env_projectedtexture target shadows fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/132 (Console error fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/152 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/159 (Additional GCC/Linux compilation fixes)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/162 (VS2019 exception specification fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/170 (HL2 non-Episodic build fix)
== Contributions from Petercov:
=-- https://github.com/mapbase-source/source-sdk-2013/pull/182 (NPCs load dynamic interactions from all animation MDLs)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/184 (Projected texture horizontal FOV shadow fix)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/185 (Fix enemyfinders becoming visible when they wake)
=-- https://github.com/mapbase-source/source-sdk-2013/pull/186 (Fix for brightly glowing teeth)
//---------------------------------------------------------------------------------------------------------------------------------------------------
@ -135,6 +176,14 @@ If there is anything missing from this list, please contact Blixibon.
Aside from the content list above, Mapbase has more descriptive and up-to-date credits on this wiki article:
https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Credits
Other relevant articles:
* https://github.com/mapbase-source/source-sdk-2013/wiki/Mapbase-Disclaimers
* https://github.com/mapbase-source/source-sdk-2013/wiki/Frequently-Asked-Questions-(FAQ)
//---------------------------------------------------------------------------------------------------------------------------------------------------
In memory of Holly Liberatore (moofemp)
//===================================================================================================================================================
Please see the Source SDK 2013 license below:

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) -o $(SRCROOT)/devtools/gcc9+support.o $(SRCROOT)/devtools/gcc9+support.cpp &&\
ln -sf $(MAKEFILE_BASE).gcc8 $@ ;\
fi

View File

@ -259,6 +259,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 ),
@ -294,6 +297,7 @@ 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" )
@ -310,6 +314,14 @@ BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-si
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" )
@ -320,7 +332,7 @@ 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" )
@ -354,6 +366,9 @@ BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-si
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();
@ -365,6 +380,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");
@ -445,7 +463,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 );
@ -772,6 +794,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;
@ -1538,10 +1564,43 @@ HSCRIPT C_BaseAnimating::ScriptGetAttachmentMatrix( int iAttachment )
void C_BaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform )
{
if (hTransform == NULL)
matrix3x4_t *matTransform = HScriptToClass<matrix3x4_t>( hTransform );
if (matTransform == NULL)
return;
GetBoneTransform( iBone, *HScriptToClass<matrix3x4_t>( hTransform ) );
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()
@ -1719,7 +1778,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
}
//-----------------------------------------------------------------------------
@ -1925,6 +2000,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
//-----------------------------------------------------------------------------
@ -1941,6 +2020,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(),
@ -2720,14 +2807,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 );
}
@ -4808,12 +4910,18 @@ void C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matri
}
}
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;
@ -4881,26 +4989,26 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient()
{
MoveToLastReceivedPosition( true );
GetAbsOrigin();
C_BaseAnimating *pRagdoll = CreateRagdollCopy();
m_pClientsideRagdoll = CreateRagdollCopy();
matrix3x4_t boneDelta0[MAXSTUDIOBONES];
matrix3x4_t boneDelta1[MAXSTUDIOBONES];
matrix3x4_t currentBones[MAXSTUDIOBONES];
const float boneDt = 0.1f;
GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt );
pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
m_pClientsideRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt );
#ifdef MAPBASE_VSCRIPT
// Hook for ragdolling
if (m_ScriptScope.IsInitialized() && g_Hook_OnClientRagdoll.CanRunInScope( m_ScriptScope ))
{
// ragdoll
ScriptVariant_t args[] = { ScriptVariant_t( pRagdoll->GetScriptInstance() ) };
ScriptVariant_t args[] = { ScriptVariant_t( m_pClientsideRagdoll->GetScriptInstance() ) };
g_Hook_OnClientRagdoll.Call( m_ScriptScope, NULL, args );
}
#endif
return pRagdoll;
return m_pClientsideRagdoll;
}
bool C_BaseAnimating::InitAsClientRagdoll( const matrix3x4_t *pDeltaBones0, const matrix3x4_t *pDeltaBones1, const matrix3x4_t *pCurrentBonePosition, float boneDt, bool bFixedConstraints )
@ -5366,6 +5474,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;
};
@ -301,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 );
@ -354,6 +356,8 @@ public:
void ClientSideAnimationChanged();
virtual unsigned int ComputeClientSideAnimationFlags();
virtual void ReachedEndOfSequence() { return; }
virtual void ResetClientsideFrame( void ) { SetCycle( 0 ); }
void SetCycle( float flCycle );
@ -464,6 +468,11 @@ public:
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 ); }
@ -482,6 +491,7 @@ public:
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
@ -521,6 +531,10 @@ private:
public:
CRagdoll *m_pRagdoll;
C_BaseAnimating *m_pClientsideRagdoll; // From Alien Swarm SDK
#ifdef MAPBASE
C_BaseAnimating *m_pServerRagdoll; // Not from Alien Swarm SDK (note that this can exist without the entity having died)
#endif
// Texture group to use
int m_nSkin;
@ -723,6 +737,10 @@ public:
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

@ -178,3 +178,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 );
@ -99,6 +102,12 @@ public:
virtual void GetGlowEffectColor( float *r, float *g, float *b );
#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;
}
//-----------------------------------------------------------------------------
@ -502,25 +508,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,6 +428,11 @@ 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", "" )
@ -550,7 +555,14 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
#endif
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();
@ -1340,6 +1352,12 @@ 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;
@ -4914,9 +4932,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
//-----------------------------------------------------------------------------

View File

@ -164,10 +164,9 @@ struct thinkfunc_t
#ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t
{
int m_nNextThinkTick;
HSCRIPT m_hfnThink;
unsigned short m_iContextHash;
bool m_bNoParam;
float m_flNextThink;
HSCRIPT m_hfnThink;
unsigned m_iContextHash;
};
#endif
@ -295,6 +294,9 @@ public:
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.
@ -400,7 +402,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,
@ -1262,7 +1264,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;

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

@ -281,6 +281,7 @@ END_RECV_TABLE()
RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ),
RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ),
RecvPropBool ( RECVINFO( m_bInTriggerFall ) ),
#endif
END_RECV_TABLE()
@ -331,7 +332,10 @@ END_RECV_TABLE()
RecvPropString( RECVINFO(m_szLastPlaceName) ),
RecvPropEHandle(RECVINFO(m_hPostProcessCtrl)), // Send to everybody - for spectating
#ifdef MAPBASE // From Alien Swarm SDK
RecvPropEHandle( RECVINFO( m_hPostProcessCtrl ) ), // Send to everybody - for spectating
RecvPropEHandle( RECVINFO( m_hColorCorrectionCtrl ) ), // Send to everybody - for spectating
#endif
#if defined USES_ECON_ITEMS
RecvPropUtlVector( RECVINFO_UTLVECTOR( m_hMyWearables ), MAX_WEARABLES_SENT_FROM_SERVER, RecvPropEHandle(NULL, 0, 0) ),
@ -1363,6 +1367,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 );
@ -1485,8 +1493,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())
@ -1509,6 +1518,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:
//-----------------------------------------------------------------------------
@ -2917,6 +2958,7 @@ void C_BasePlayer::UpdateFogBlend( void )
}
}
#ifdef MAPBASE // From Alien Swarm SDK
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
@ -2925,6 +2967,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:
@ -645,7 +659,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

@ -192,7 +192,7 @@ bool C_BaseViewModel::Interpolate( float currentTime )
}
inline bool C_BaseViewModel::ShouldFlipViewModel()
bool C_BaseViewModel::ShouldFlipViewModel()
{
#if defined(CSTRIKE_DLL) || defined (MAPBASE)
// If cl_righthand is set, then we want them all right-handed.

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;
@ -283,6 +283,8 @@ void C_EnvProjectedTexture::UpdateLight( void )
// VectorNormalize( vRight );
// VectorNormalize( vUp );
VectorVectors( vForward, vRight, vUp );
}
}
else

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

@ -13,6 +13,7 @@
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()

View File

@ -20,6 +20,7 @@ public:
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; }
@ -27,6 +28,7 @@ public:
private:
bool m_bEnabled;
bool m_bLooping;
bool m_bMuted;
char m_szMovieFilename[128];
char m_szGroupName[128];
};

File diff suppressed because it is too large Load Diff

View File

@ -73,6 +73,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
@ -2022,6 +2043,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

@ -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

@ -71,6 +71,7 @@ $Configuration
$SystemFrameworks "Carbon" [$OSXALL]
$SystemLibraries "rt" [$LINUXALL]
$IgnoreImportLibrary "TRUE"
$AdditionalOptions "$BASE /force:multiple" [($VS2015||$VS2017||$VS2019||$VS2022)] // Required to fix _hypot in particles.lib (this may be a temporary solution)
$AdditionalDependencies "$BASE winmm.lib" [$WIN32]
$AdditionalDependencies "$BASE wsock32.lib Ws2_32.lib" [$BUILD_REPLAY]
}
@ -536,7 +537,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" \
@ -1107,6 +1107,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]
@ -1163,7 +1164,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"

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]
}
}
@ -34,6 +35,7 @@ $Project
$File "c_movie_display.cpp"
$File "c_movie_display.h"
$File "vgui_movie_display.cpp"
$File "convarproxy.cpp"
$Folder "Mapbase"
{
@ -45,6 +47,8 @@ $Project
$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]
@ -61,6 +65,7 @@ $Project
$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

@ -292,8 +292,11 @@ ClientModeShared::ClientModeShared()
m_pWeaponSelection = NULL;
m_nRootSize[ 0 ] = m_nRootSize[ 1 ] = -1;
#ifdef MAPBASE // From Alien Swarm SDK
m_pCurrentPostProcessController = NULL;
m_PostProcessLerpTimer.Invalidate();
m_pCurrentColorCorrection = NULL;
#endif
#if defined( REPLAY_ENABLED )
m_pReplayReminderPanel = NULL;
@ -635,6 +638,43 @@ void ClientModeShared::Update()
}
}
#ifdef MAPBASE // From Alien Swarm SDK
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ClientModeShared::OnColorCorrectionWeightsReset( void )
{
C_ColorCorrection *pNewColorCorrection = NULL;
C_ColorCorrection *pOldColorCorrection = m_pCurrentColorCorrection;
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer )
{
pNewColorCorrection = pPlayer->GetActiveColorCorrection();
}
if ( pNewColorCorrection != pOldColorCorrection )
{
if ( pOldColorCorrection )
{
pOldColorCorrection->EnableOnClient( false );
}
if ( pNewColorCorrection )
{
pNewColorCorrection->EnableOnClient( true, pOldColorCorrection == NULL );
}
m_pCurrentColorCorrection = pNewColorCorrection;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float ClientModeShared::GetColorCorrectionScale( void ) const
{
return 1.0f;
}
#endif
//-----------------------------------------------------------------------------
// This processes all input before SV Move messages are sent
//-----------------------------------------------------------------------------
@ -1259,7 +1299,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;
}
@ -4470,13 +4484,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
@ -4484,6 +4503,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
{
@ -4492,6 +4515,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

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

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

@ -1302,7 +1302,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;
@ -1317,8 +1317,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';
@ -1333,6 +1336,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';
@ -1360,7 +1366,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 ) )
{
@ -1384,7 +1390,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 ) )
{
@ -1423,7 +1429,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 ) )
{
@ -1515,7 +1521,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" ) )
{
@ -1612,6 +1618,9 @@ struct WorkUnitParams
clr = Color( 255, 255, 255, 255 );
newline = false;
font = 0;
#ifdef MAPBASE
customFont = false;
#endif
}
~WorkUnitParams()
@ -1657,6 +1666,9 @@ struct WorkUnitParams
Color clr;
bool newline;
vgui::HFont font;
#ifdef MAPBASE
bool customFont;
#endif
};
void CHudCloseCaption::AddWorkUnit( CCloseCaptionItem *item,
@ -1716,7 +1728,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" ) )
{
@ -1771,27 +1783,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;
@ -1939,7 +1982,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" ) )
{
@ -2630,6 +2673,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

@ -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: $
@ -120,8 +120,8 @@ C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t
//-----------------------------------------------------------------------------
// Iterates through fake world portals instead of just picking one
//-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, cplane_t &plane,
const Frustum_t &frustum )
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum )
{
// Early out if no cameras
C_FuncFakeWorldPortal *pReflectiveGlass = NULL;
@ -167,6 +167,7 @@ C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const
if ( !pReflectiveGlass->m_hTargetPlane )
continue;
vecPlaneOrigin = vecOrigin;
return pReflectiveGlass;
}
}

View File

@ -55,8 +55,8 @@ public:
//-----------------------------------------------------------------------------
C_FuncFakeWorldPortal *IsFakeWorldPortalInView( const CViewSetup& view, cplane_t &plane );
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view, cplane_t &plane,
const Frustum_t &frustum );
C_FuncFakeWorldPortal *NextFakeWorldPortal( C_FuncFakeWorldPortal *pStart, const CViewSetup& view,
cplane_t &plane, Vector &vecPlaneOrigin, const Frustum_t &frustum );
#endif // C_FUNC_FAKE_WORLDPORTAL

View File

@ -157,11 +157,34 @@ void C_TextDisplayPanel::UpdateText()
m_pDisplayTextLabel->SetText( m_hScreenEntity->GetDisplayText() );
//SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
//m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetTextSize(), m_hScreenEntity->GetTextSize() );
Label::Alignment iAlignment = m_hScreenEntity->GetContentAlignment();
switch (iAlignment)
{
// Use a special scaling method when using a south alignment
case Label::Alignment::a_southwest:
case Label::Alignment::a_south:
case Label::Alignment::a_southeast:
int lW, lT;
m_pDisplayTextLabel->GetContentSize( lW, lT );
SetSize( m_hScreenEntity->GetResolution(), lT );
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), lT );
float sW, sT;
m_hVGUIScreen->GetSize( sW, sT );
//Msg( "Screen width: %f, new height: %f\n", sW, sW * (lT / m_hScreenEntity->GetResolution()) );
m_hVGUIScreen->SetHeight( sW * ((float)lT / (float)m_hScreenEntity->GetResolution()) );
m_hVGUIScreen->SetPixelHeight( lT );
break;
default:
SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
m_pDisplayTextLabel->SetSize( m_hScreenEntity->GetResolution(), m_hScreenEntity->GetResolution() );
break;
}
m_pDisplayTextLabel->SetContentAlignment( iAlignment );
bool bWrap = true;

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();
}

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

@ -7,16 +7,16 @@
#include "cbase.h"
#include "c_vguiscreen.h"
#include "vgui_controls/Label.h"
#include "vgui_BitmapPanel.h"
#include <vgui/IVGUI.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 "engine/IEngineSound.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "c_movie_display.h"
// NOTE: This has to be the last file included!
@ -81,7 +81,6 @@ private:
bool m_bBlackBackground;
bool m_bSlaved;
bool m_bInitialized;
bool m_bLastActiveState; // HACK: I'd rather get a real callback...
// VGUI specifics
@ -110,10 +109,9 @@ CMovieDisplayScreen::CMovieDisplayScreen( vgui::Panel *parent, const char *panel
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();
}
@ -295,6 +293,11 @@ void CMovieDisplayScreen::UpdateMovie( void )
// OnVideoOver();
// StopPlayback();
}
if (!m_hScreenEntity->IsMuted())
{
m_VideoMaterial->SetMuted(false);
}
}
}
@ -365,25 +368,27 @@ bool CMovieDisplayScreen::BeginPlayback( const char *pFilename )
}
else
{
Q_strncpy( szMaterialName, pFilename, sizeof(szMaterialName) );
Q_snprintf( szMaterialName, sizeof(szMaterialName), "%s_%s", pFilename, m_hScreenEntity->GetEntityName() );
}
const char *pszMaterialName = CFmtStrN<128>( "VideoMaterial_", m_hScreenEntity->GetEntityName() );
m_VideoMaterial = g_pVideo->CreateVideoMaterial( pszMaterialName, pFilename, "GAME",
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?
m_VideoMaterial->SetMuted(true); // FIXME: Allow?
if ( m_hScreenEntity->IsLooping() )
{
m_VideoMaterial->SetLooping( true );
}
if ( m_VideoMaterial->HasAudio() )
if ( m_VideoMaterial->HasAudio())
{
// We want to be the sole audio source
enginesound->NotifyBeginMoviePlayback();

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 );
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 );
#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
@ -1218,6 +1219,73 @@ IMaterial *CViewRender::GetScreenOverlayMaterial( )
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: Sets the screen space effect material (can't be done during rendering)
//-----------------------------------------------------------------------------
void CViewRender::SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial )
{
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
return;
m_IndexedScreenOverlayMaterials[i].Init( pMaterial );
if (pMaterial == NULL)
{
// Check if we should set to false
int i;
for (i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
if (m_IndexedScreenOverlayMaterials[i] != NULL)
break;
}
if (i == MAX_SCREEN_OVERLAYS)
m_bUsingIndexedScreenOverlays = false;
}
else
{
m_bUsingIndexedScreenOverlays = true;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
IMaterial *CViewRender::GetIndexedScreenOverlayMaterial( int i )
{
if (i < 0 || i >= MAX_SCREEN_OVERLAYS)
return NULL;
return m_IndexedScreenOverlayMaterials[i];
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CViewRender::ResetIndexedScreenOverlays()
{
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
m_IndexedScreenOverlayMaterials[i].Init( NULL );
}
m_bUsingIndexedScreenOverlays = false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CViewRender::GetMaxIndexedScreenOverlays( ) const
{
return MAX_SCREEN_OVERLAYS;
}
#endif
//-----------------------------------------------------------------------------
// Purpose: Performs screen space effects, if any
//-----------------------------------------------------------------------------
@ -1254,6 +1322,44 @@ void CViewRender::PerformScreenOverlay( int x, int y, int w, int h )
render->ViewDrawFade( color, m_ScreenOverlayMaterial );
}
}
#ifdef MAPBASE
if (m_bUsingIndexedScreenOverlays)
{
for (int i = 0; i < MAX_SCREEN_OVERLAYS; i++)
{
if (!m_IndexedScreenOverlayMaterials[i])
continue;
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
if ( m_IndexedScreenOverlayMaterials[i]->NeedsFullFrameBufferTexture() )
{
// FIXME: check with multi/sub-rect renders. Should this be 0,0,w,h instead?
DrawScreenEffectMaterial( m_IndexedScreenOverlayMaterials[i], x, y, w, h );
}
else if ( m_IndexedScreenOverlayMaterials[i]->NeedsPowerOfTwoFrameBufferTexture() )
{
// First copy the FB off to the offscreen texture
UpdateRefractTexture( x, y, w, h, true );
// Now draw the entire screen using the material...
CMatRenderContextPtr pRenderContext( materials );
ITexture *pTexture = GetPowerOfTwoFrameBufferTexture( );
int sw = pTexture->GetActualWidth();
int sh = pTexture->GetActualHeight();
// Note - don't offset by x,y - already done by the viewport.
pRenderContext->DrawScreenSpaceRectangle( m_IndexedScreenOverlayMaterials[i], 0, 0, w, h,
0, 0, sw-1, sh-1, sw, sh );
}
else
{
byte color[4] = { 255, 255, 255, 255 };
render->ViewDrawFade( color, m_IndexedScreenOverlayMaterials[i] );
}
}
}
#endif
}
void CViewRender::DrawUnderwaterOverlay( void )
@ -2005,18 +2111,19 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
GeneratePerspectiveFrustum( view.origin, view.angles, view.zNear, view.zFar, view.fov, view.m_flAspectRatio, frustum );
cplane_t portalPlane;
Vector vecPlaneOrigin;
//C_FuncFakeWorldPortal *pPortalEnt = IsFakeWorldPortalInView( view, portalPlane );
//if ( pPortalEnt )
C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, portalPlane, frustum );
C_FuncFakeWorldPortal *pPortalEnt = NextFakeWorldPortal( NULL, view, portalPlane, vecPlaneOrigin, frustum );
while ( pPortalEnt != NULL )
{
ITexture *pCameraTarget = pPortalEnt->RenderTarget();
int width = pCameraTarget->GetActualWidth();
int height = pCameraTarget->GetActualHeight();
DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, portalPlane );
DrawFakeWorldPortal( pCameraTarget, pPortalEnt, viewMiddle, C_BasePlayer::GetLocalPlayer(), 0, 0, width, height, view, portalPlane, vecPlaneOrigin );
pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, portalPlane, frustum );
pPortalEnt = NextFakeWorldPortal( pPortalEnt, view, portalPlane, vecPlaneOrigin, frustum );
}
#endif
}
@ -2027,6 +2134,10 @@ void CViewRender::RenderView( const CViewSetup &view, int nClearFlags, int whatT
// Must be first
render->SceneBegin();
#ifdef MAPBASE // From Alien Swarm SDK
g_pColorCorrectionMgr->UpdateColorCorrection();
#endif
pRenderContext.GetFrom( materials );
pRenderContext->TurnOnToneMapping();
pRenderContext.SafeRelease();
@ -3434,8 +3545,7 @@ ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
//-----------------------------------------------------------------------------
// Purpose: Sets up scene and renders WIP fake world portal view.
// Based on code from monitors, mirrors, and 3D skyboxes.
// It's also terrible right now.
// Based on code from monitors, mirrors, and logic_measure_movement.
//
// Input : cameraNum -
// &cameraView
@ -3449,7 +3559,7 @@ ConVar r_fakeworldportal_debug("r_fakeworldportal_debug", "0");
//-----------------------------------------------------------------------------
bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldPortal *pCameraEnt, const CViewSetup &cameraView, C_BasePlayer *localPlayer,
int x, int y, int width, int height,
const CViewSetup &mainView, cplane_t &ourPlane )
const CViewSetup &mainView, cplane_t &ourPlane, const Vector &vecPlaneOrigin )
{
#ifdef USE_MONITORS
VPROF_INCREMENT_COUNTER( "cameras rendered", 1 );
@ -3488,97 +3598,89 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
monitorView.origin = mainView.origin;
monitorView.angles = mainView.angles;
// Temporary debug stuff
// Debug stuff
static float flLastDebugTime = 0.0f;
bool bDebug = r_fakeworldportal_debug.GetBool() && gpGlobals->curtime > flLastDebugTime;
QAngle angTargetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() + pCameraEnt->m_PlaneAngles;
// RED - First origin
if (bDebug)
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 0, 0, 128, 10.0f );
// Make sure the origin and angles are relative to the target plane
monitorView.origin -= pCameraEnt->GetAbsOrigin();
// scale origin by sky scale
if ( pCameraEnt->m_flScale > 0 )
{
float scale = 1.0f / pCameraEnt->m_flScale;
VectorScale( monitorView.origin, scale, monitorView.origin );
}
// YELLOW - Main origin
if (bDebug)
debugoverlay->AddBoxOverlay( pCameraEnt->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 224, 0, 128, 10.0f );
// Make sure our angles are relative to the main plane, just like the origin
QAngle angOurAngles;
VectorAngles( ourPlane.normal * -1, angOurAngles );
//angles -= angOurAngles;
// First, create a matrix for the sky's angles.
matrix3x4_t matSkyAngles;
AngleMatrix( angTargetAngles - angOurAngles, matSkyAngles );
Vector vecSkyForward, vecSkyRight, vecSkyUp;
//
// Calculate the angles for the fake portal plane
//
QAngle angTargetAngles = pCameraEnt->m_hTargetPlane->GetAbsAngles() - pCameraEnt->m_PlaneAngles;
QAngle angFakePortalAngles;
// Get vectors from our original angles.
Vector vPlayerForward, vPlayerRight, vPlayerUp;
AngleVectors( monitorView.angles, &vPlayerForward, &vPlayerRight, &vPlayerUp );
VectorTransform( vPlayerForward, matSkyAngles, vecSkyForward );
VectorTransform( vPlayerRight, matSkyAngles, vecSkyRight );
VectorTransform( vPlayerUp, matSkyAngles, vecSkyUp );
// Normalize them.
VectorNormalize( vecSkyForward );
VectorNormalize( vecSkyRight );
VectorNormalize( vecSkyUp );
Vector vOurForward, vOurRight, vOurUp;
AngleVectors( pCameraEnt->GetAbsAngles(), &vOurForward, &vOurRight, &vOurUp );
Quaternion quat;
BasisToQuaternion( vecSkyForward, vecSkyRight, vecSkyUp, quat );
QuaternionAngles( quat, monitorView.angles );
BasisToQuaternion( ourPlane.normal, vOurRight, vOurUp, quat );
QuaternionAngles( quat, angFakePortalAngles );
// End of code mostly lifted from projected texture screenspace stuff
// ----------------------------------------------------------------------
// Now just rotate our origin with that matrix.
// We create a copy of the origin since VectorRotate doesn't want in1 to be the same variable as the destination.
VectorRotate(Vector(monitorView.origin), matSkyAngles, monitorView.origin);
// BLUE - Target origin
if (bDebug)
debugoverlay->AddBoxOverlay( pCameraEnt->m_hTargetPlane->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 0, 255, 128, 10.0f );
monitorView.origin += pCameraEnt->m_hTargetPlane->GetAbsOrigin();
// GREEN - Final origin
if (bDebug)
{
// RED - Initial player origin
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 255, 0, 0, 128, 10.0f );
// YELLOW - Portal origin
debugoverlay->AddBoxOverlay( pCameraEnt->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angFakePortalAngles, 255, 224, 0, 128, 10.0f );
}
//
// Translate the actual portal view position to be relative to the target
//
matrix3x4_t matPlayer, matPortal, matPlayerToPortal;
AngleIMatrix( monitorView.angles, monitorView.origin, matPlayer );
AngleMatrix( angFakePortalAngles, pCameraEnt->GetAbsOrigin(), matPortal );
ConcatTransforms( matPlayer, matPortal, matPlayerToPortal );
// Apply the scale factor
if ( pCameraEnt->m_flScale > 0 )
{
Vector vecTranslation;
MatrixGetColumn( matPlayerToPortal, 3, vecTranslation );
vecTranslation /= pCameraEnt->m_flScale;
MatrixSetColumn( vecTranslation, 3, matPlayerToPortal );
}
matrix3x4_t matTarget;
AngleMatrix( angTargetAngles, pCameraEnt->m_hTargetPlane->GetAbsOrigin(), matTarget );
// Now apply the new matrix to the new reference point
matrix3x4_t matPortalToPlayer, matNewPlayerPosition;
MatrixInvert( matPlayerToPortal, matPortalToPlayer );
ConcatTransforms( matTarget, matPortalToPlayer, matNewPlayerPosition );
MatrixAngles( matNewPlayerPosition, monitorView.angles, monitorView.origin );
if (bDebug)
{
// BLUE - Target origin
debugoverlay->AddBoxOverlay( pCameraEnt->m_hTargetPlane->GetAbsOrigin(), Vector(-32,-32,-32), Vector(32,32,32), angTargetAngles, 0, 0, 255, 128, 10.0f );
// GREEN - Final origin
debugoverlay->AddBoxOverlay( monitorView.origin, Vector(-32,-32,-32), Vector(32,32,32), monitorView.angles, 0, 255, 0, 128, 10.0f );
flLastDebugTime = gpGlobals->curtime + 5.0f;
}
monitorView.fov = mainView.fov;
monitorView.m_bOrtho = false;
monitorView.m_flAspectRatio = 0.0f;
monitorView.m_bOrtho = mainView.m_bOrtho;
monitorView.m_flAspectRatio = mainView.m_flAspectRatio;
monitorView.m_bViewToProjectionOverride = false;
// @MULTICORE (toml 8/11/2006): this should be a renderer....
int nClearFlags = (VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL);
bool bDrew3dSkybox = false;
SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode();
Frustum frustum;
render->Push3DView( monitorView, nClearFlags, pRenderTarget, (VPlane *)frustum );
//
// Monitor sky handling
// Sky handling
//
if ( pCameraEnt->SkyMode() == SKYBOX_3DSKYBOX_VISIBLE )
SkyboxVisibility_t nSkyMode = pCameraEnt->SkyMode();
if ( nSkyMode == SKYBOX_3DSKYBOX_VISIBLE )
{
// if the 3d skybox world is drawn, then don't draw the normal skybox
CSkyboxView *pSkyView = new CSkyboxView( this );
@ -3589,16 +3691,21 @@ bool CViewRender::DrawFakeWorldPortal( ITexture *pRenderTarget, C_FuncFakeWorldP
SafeRelease( pSkyView );
}
//
// Make a clipping plane for the target view
//
Vector4D plane;
// Combine the target angles and the plane angles
Vector vecAnglesNormal( angTargetAngles.x, angTargetAngles.y, angTargetAngles.z );
Vector vecAnglesNormal;
AngleVectors( angTargetAngles, &vecAnglesNormal );
VectorNormalize( vecAnglesNormal );
VectorCopy( vecAnglesNormal, plane.AsVector3D() );
VectorCopy( -vecAnglesNormal, plane.AsVector3D() );
// TODO: How do we get a good value for this!?!?
//plane.w = m_OurPlane.dist + 0.1f;
plane.w = -32.0f + 0.1f;
// The portal plane's distance from the actual brush's origin
float flPlaneDist = vecPlaneOrigin.Length();
// The target's distance from world origin
plane.w = -((pCameraEnt->m_hTargetPlane->GetAbsOrigin() * vecAnglesNormal).Length() + flPlaneDist) + 0.1f;
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->PushCustomClipPlane( plane.Base() );

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, cplane_t &ourPlane, const Vector &vecPlaneOrigin );
#endif
// Drawing primitives
@ -468,6 +468,13 @@ private:
IMaterial *GetScreenOverlayMaterial( );
void PerformScreenOverlay( int x, int y, int w, int h );
#ifdef MAPBASE
void SetIndexedScreenOverlayMaterial( int i, IMaterial *pMaterial );
IMaterial *GetIndexedScreenOverlayMaterial( int i );
void ResetIndexedScreenOverlays();
int GetMaxIndexedScreenOverlays() const;
#endif
void DrawUnderwaterOverlay( void );
// Water-related methods
@ -511,6 +518,10 @@ private:
CMaterialReference m_TranslucentSingleColor;
CMaterialReference m_ModulateSingleColor;
CMaterialReference m_ScreenOverlayMaterial;
#ifdef MAPBASE
CMaterialReference m_IndexedScreenOverlayMaterials[MAX_SCREEN_OVERLAYS];
bool m_bUsingIndexedScreenOverlays;
#endif
CMaterialReference m_UnderWaterOverlayMaterial;
Vector m_vecLastFacing;

View File

@ -15,11 +15,12 @@
#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"
#endif
@ -41,10 +42,13 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
#endif // VMPROFILE
#ifdef MAPBASE_VSCRIPT
static ScriptHook_t g_Hook_OnEntityCreated;
static ScriptHook_t g_Hook_OnEntityDeleted;
//-----------------------------------------------------------------------------
// Purpose: A clientside variant of CScriptEntityIterator.
//-----------------------------------------------------------------------------
class CScriptClientEntityIterator
class CScriptClientEntityIterator : public IClientEntityListener
{
public:
HSCRIPT GetLocalPlayer()
@ -96,6 +100,38 @@ public:
return NULL;
}
void EnableEntityListening()
{
// Start getting entity updates!
ClientEntityList().AddListenerEntity( this );
}
void DisableEntityListening()
{
// Stop getting entity updates!
ClientEntityList().RemoveListenerEntity( this );
}
void OnEntityCreated( CBaseEntity *pEntity )
{
if ( g_pScriptVM && 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;
@ -106,6 +142,17 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptClientEntityIterator, "CEntities", SCRIPT_SI
DEFINE_SCRIPTFUNC( CreateByClassname, "Creates an entity by classname" )
DEFINE_SCRIPTFUNC( FindByClassname, "Find entities by class name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
DEFINE_SCRIPTFUNC( FindByName, "Find entities by name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
DEFINE_SCRIPTFUNC( EnableEntityListening, "Enables the 'OnEntity' hooks. This function must be called before using them." )
DEFINE_SCRIPTFUNC( DisableEntityListening, "Disables the 'OnEntity' hooks." )
BEGIN_SCRIPTHOOK( g_Hook_OnEntityCreated, "OnEntityCreated", FIELD_VOID, "Called when an entity is created. Requires EnableEntityListening() to be fired beforehand." )
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
END_SCRIPTHOOK()
BEGIN_SCRIPTHOOK( g_Hook_OnEntityDeleted, "OnEntityDeleted", FIELD_VOID, "Called when an entity is deleted. Requires EnableEntityListening() to be fired beforehand." )
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
END_SCRIPTHOOK()
END_SCRIPTDESC();
//-----------------------------------------------------------------------------
@ -165,6 +212,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];
@ -194,12 +243,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()
@ -316,26 +369,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
{
@ -414,6 +466,14 @@ 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 );
bool CMaterialProxyScriptInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
@ -585,6 +645,11 @@ 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." ) );
@ -597,6 +662,20 @@ bool VScriptClientInit()
ScriptRegisterFunction( g_pScriptVM, IsWindowedMode, "" );
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get the x & y positions of a world position in screen space. Returns true if it's onscreen" );
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
@ -628,6 +707,10 @@ bool VScriptClientInit()
VScriptRunScript( "vscript_client", true );
VScriptRunScript( "mapspawn", false );
#ifdef MAPBASE_VSCRIPT
RunAddonScripts();
#endif
VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );
return true;
@ -696,6 +779,8 @@ public:
{
#ifdef MAPBASE_VSCRIPT
g_ScriptNetMsg->LevelShutdownPreVM();
GetScriptHookManager().OnShutdown();
#endif
VScriptClientTerm();
}

View File

@ -24,7 +24,13 @@ function IncludeScript( name, scope = null )
function DispatchParticleEffect( particleName, origin, angles, entity = null )
{
DoDispatchParticleEffect( particleName, origin, angles, entity );
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
@ -276,3 +279,4 @@ private:
};
#endif // AI_CRITERIA_H
#endif

View File

@ -4,6 +4,9 @@
//
//=============================================================================//
#ifdef NEW_RESPONSE_SYSTEM
#include "ai_responsesystem_new.h"
#else
#ifndef AI_RESPONSESYSTEM_H
#define AI_RESPONSESYSTEM_H
@ -39,3 +42,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 );
}
@ -1052,6 +1095,38 @@ void CBaseAnimatingOverlay::SetLayerNoRestore( int iLayer, bool bNoRestore )
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// From Alien Swarm SDK
//-----------------------------------------------------------------------------
void CBaseAnimatingOverlay::SetLayerNoEvents( int iLayer, bool bNoEvents )
{
if (!IsValidLayer( iLayer ))
return;
if (bNoEvents)
{
m_AnimOverlay[iLayer].m_fFlags |= ANIM_LAYER_NOEVENTS;
}
else
{
m_AnimOverlay[iLayer].m_fFlags &= ~ANIM_LAYER_NOEVENTS;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseAnimatingOverlay::IsLayerFinished( int iLayer )
{
if (!IsValidLayer( iLayer ))
return true;
return m_AnimOverlay[iLayer].m_bSequenceFinished;
}
#endif
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
@ -1149,4 +1224,36 @@ bool CBaseAnimatingOverlay::HasActiveLayer( void )
return false;
}
#ifdef MAPBASE_VSCRIPT
int CBaseAnimatingOverlay::ScriptAddGesture( const char *pszActivity, bool autokill )
{
return AddGesture( (Activity)CAI_BaseNPC::GetActivityID( pszActivity ), autokill );
}
int CBaseAnimatingOverlay::ScriptAddGestureID( int iActivity, bool autokill )
{
return AddGesture( (Activity)iActivity, autokill );
}
int CBaseAnimatingOverlay::ScriptFindGestureLayer( const char *pszActivity )
{
return FindGestureLayer( (Activity)CAI_BaseNPC::GetActivityID( pszActivity ) );
}
int CBaseAnimatingOverlay::ScriptFindGestureLayerByID( int iActivity )
{
return FindGestureLayer( (Activity)iActivity );
}
const char *CBaseAnimatingOverlay::ScriptGetLayerActivity( int iLayer )
{
return CAI_BaseNPC::GetActivityName( GetLayerActivity( iLayer ) );
}
int CBaseAnimatingOverlay::ScriptGetLayerActivityID( int iLayer )
{
return GetLayerActivity( iLayer );
}
#endif
//-----------------------------------------------------------------------------

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 );
@ -175,6 +181,11 @@ public:
void SetLayerAutokill( int iLayer, bool bAutokill );
void SetLayerLooping( int iLayer, bool bLooping );
void SetLayerNoRestore( int iLayer, bool bNoRestore );
#ifdef MAPBASE
void SetLayerNoEvents( int iLayer, bool bNoEvents ); // From Alien Swarm SDK
bool IsLayerFinished( int iLayer );
#endif
Activity GetLayerActivity( int iLayer );
int GetLayerSequence( int iLayer );
@ -195,9 +206,26 @@ public:
private:
int AllocateLayer( int iPriority = 0 ); // lower priorities are processed first
#ifdef MAPBASE_VSCRIPT
int ScriptAddGesture( const char *pszActivity, bool autokill );
int ScriptAddGestureID( int iActivity, bool autokill );
int ScriptAddGestureSequence( const char *pszSequence, bool autokill ) { return AddGestureSequence( LookupSequence( pszSequence ), autokill ); }
int ScriptAddGestureSequenceID( int iSequence, bool autokill ) { return AddGestureSequence( iSequence, autokill ); }
int ScriptFindGestureLayer( const char *pszActivity );
int ScriptFindGestureLayerByID( int iActivity );
const char *ScriptGetLayerActivity( int iLayer );
int ScriptGetLayerActivityID( int iLayer );
void ScriptSetLayerCycle( int iLayer, float flCycle ) { SetLayerCycle( iLayer, flCycle ); }
#endif
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
DECLARE_PREDICTABLE();
#ifdef MAPBASE_VSCRIPT
DECLARE_ENT_SCRIPTDESC();
#endif
};
EXTERN_SEND_TABLE(DT_BaseAnimatingOverlay);

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" );

View File

@ -2180,15 +2180,22 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR2 );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2 );
//ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR2_LOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_AR2 );
ADD_ACTIVITY_TO_SR( ACT_COVER_AR2_LOW );
#endif
#ifdef SHARED_COMBINE_ACTIVITIES
#if SHARED_COMBINE_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_COMBINE_THROW_GRENADE );
ADD_ACTIVITY_TO_SR( ACT_COMBINE_AR2_ALTFIRE );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_COMBINE_THROW_GRENADE );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_COMBINE_AR2_ALTFIRE );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SPECIAL_ATTACK1 );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SPECIAL_ATTACK2 );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_ADVANCE );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_FORWARD );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_GROUP );
@ -2198,8 +2205,612 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
ADD_ACTIVITY_TO_SR( ACT_GESTURE_SIGNAL_TAKECOVER );
#endif
#ifdef COMPANION_HOLSTER_WORKAROUND
#if EXPANDED_HL2_WEAPON_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_IDLE_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_WALK_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_RUN_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_REVOLVER_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_REVOLVER_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_REVOLVER_LOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_IDLE_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_WALK_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_RUN_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_CROSSBOW_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_CROSSBOW_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_CROSSBOW_LOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_IDLE_CROSSBOW_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_CROSSBOW_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_CROSSBOW_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_CROSSBOW_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_CROSSBOW_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_CROSSBOW_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_CROSSBOW_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_CROSSBOW_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_CROSSBOW_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_PISTOL_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_PISTOL_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_PISTOL_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_PISTOL_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_PISTOL_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_PISTOL_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_PISTOL_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_AIM_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_AIM_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_COVER_SHOTGUN_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SHOTGUN_LOW );
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_SHOTGUN_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SHOTGUN_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_SHOTGUN_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SHOTGUN_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SHOTGUN_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_RPG_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_RPG_LOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_RPG );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_ANNABELLE );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_ANNABELLE_LOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_ANNABELLE );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_ANNABELLE );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_ANNABELLE_LOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_ANNABELLE );
ADD_ACTIVITY_TO_SR( ACT_WALK_MELEE );
ADD_ACTIVITY_TO_SR( ACT_RUN_MELEE );
ADD_ACTIVITY_TO_SR( ACT_RUN_PACKAGE );
ADD_ACTIVITY_TO_SR( ACT_RUN_SUITCASE );
ADD_ACTIVITY_TO_SR( ACT_ARM_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_ARM_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_ARM_RPG );
ADD_ACTIVITY_TO_SR( ACT_ARM_MELEE );
ADD_ACTIVITY_TO_SR( ACT_DISARM_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_DISARM_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_DISARM_RPG );
ADD_ACTIVITY_TO_SR( ACT_DISARM_MELEE );
#endif
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR1 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_AR1 );
ADD_ACTIVITY_TO_SR( ACT_WALK_AR1 );
ADD_ACTIVITY_TO_SR( ACT_RUN_AR1 );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR1 );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR1 );
//ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR1 );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR1 );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR1_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR1_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_AR1_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR1_LOW );
//ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_AR1 );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_AR1 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR1_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AR1_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AR1_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AR1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AR1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_AR1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR3 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_AR3 );
ADD_ACTIVITY_TO_SR( ACT_WALK_AR3 );
ADD_ACTIVITY_TO_SR( ACT_RUN_AR3 );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR3 );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR3 );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR3 );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR3 );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR3_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_AR3_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_AR3_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR3_LOW );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_AR3 );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_AR3 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR3_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AR3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AR3_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AR3_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AR3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AR3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_AR3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AR3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AR3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_WALK_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_RUN_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SMG2 );
//ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG2_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG2_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_SMG2_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG2_LOW );
//ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG2_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG2_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_SMG2_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SMG2_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_SMG2_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SMG2_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_SMG2_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SMG2_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SMG2_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_WALK_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_RUN_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SMG3 );
//ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG3_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG3_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_SMG3_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG3_LOW );
//ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG3_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_SMG3_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SMG3_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_SMG3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SMG3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_SMG3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SMG3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SMG3_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_WALK_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_RUN_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_HMG1 );
//ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_HMG1_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_HMG1_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_HMG1_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_HMG1_LOW );
//ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_IDLE_HMG1_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_HMG1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_HMG1_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_HMG1_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_HMG1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_HMG1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_HMG1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_HMG1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_HMG1_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_WALK_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_RUN_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SNIPER_RIFLE );
//ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SNIPER_RIFLE_LOW );
ADD_ACTIVITY_TO_SR( ACT_RELOAD_SNIPER_RIFLE_LOW );
ADD_ACTIVITY_TO_SR( ACT_COVER_SNIPER_RIFLE_LOW );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SNIPER_RIFLE_LOW );
//ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SNIPER_RIFLE_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_SNIPER_RIFLE_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_SNIPER_RIFLE_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SNIPER_RIFLE_RELAXED );
ADD_ACTIVITY_TO_SR( ACT_WALK_SNIPER_RIFLE_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_SNIPER_RIFLE_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_SNIPER_RIFLE_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SNIPER_RIFLE_STIMULATED );
ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SNIPER_RIFLE_STIMULATED );
#endif
#if EXPANDED_NAVIGATION_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_CLIMB_ALL );
ADD_ACTIVITY_TO_SR( ACT_CLIMB_IDLE );
ADD_ACTIVITY_TO_SR( ACT_CLIMB_MOUNT_TOP );
ADD_ACTIVITY_TO_SR( ACT_CLIMB_MOUNT_BOTTOM );
ADD_ACTIVITY_TO_SR( ACT_CLIMB_DISMOUNT_BOTTOM );
#endif
#if EXPANDED_HL2_COVER_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK1_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK2_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR2_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG1_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SHOTGUN_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_PISTOL_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_RPG_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_REVOLVER_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_CROSSBOW_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR2_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG1_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SHOTGUN_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_PISTOL_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_RPG_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_REVOLVER_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_CROSSBOW_MED );
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR1_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR1_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR3_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR3_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG2_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG2_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG3_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG3_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_HMG1_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_HMG1_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SNIPER_RIFLE_MED );
ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SNIPER_RIFLE_MED );
#endif
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_R_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_L_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_R_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_COVER_WALL_LOW_L_PISTOL );
#endif
#if EXPANDED_HL2DM_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_AR2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_PHYSGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_GRENADE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_RPG );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_MELEE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SLAM );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_PISTOL );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SHOTGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_PHYSGUN );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_GRENADE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_RPG );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_CROSSBOW );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_REVOLVER );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_REVOLVER );
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG2 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG3 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_HMG1 );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SNIPER_RIFLE );
#endif
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_USE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_USE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_USE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_USE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_USE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_USE );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_USE_HEAVY );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_USE_HEAVY );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_USE_HEAVY );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_USE_HEAVY );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_USE_HEAVY );
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_USE_HEAVY );
#endif
}
#ifdef MAPBASE
//-----------------------------------------------------------------------------
// Purpose: This is a multi-purpose table which links NPC activities to their gesture variants.
//-----------------------------------------------------------------------------
CAI_BaseNPC::actlink_t CAI_BaseNPC::gm_ActivityGestureLinks[] =
{
{ ACT_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK1 },
{ ACT_RANGE_ATTACK2, ACT_GESTURE_RANGE_ATTACK2 },
{ ACT_MELEE_ATTACK1, ACT_GESTURE_MELEE_ATTACK1 },
{ ACT_MELEE_ATTACK2, ACT_GESTURE_MELEE_ATTACK2 },
{ ACT_RELOAD, ACT_GESTURE_RELOAD },
{ ACT_RANGE_ATTACK1_LOW, ACT_GESTURE_RANGE_ATTACK1 }, // NOTE: ACT_GESTURE_RANGE_ATTACK1_LOW exists, but isn't used
{ ACT_RANGE_ATTACK2_LOW, ACT_GESTURE_RANGE_ATTACK2 }, // NOTE: ACT_GESTURE_RANGE_ATTACK2_LOW exists, but isn't used
{ ACT_RELOAD_LOW, ACT_GESTURE_RELOAD },
{ ACT_MELEE_ATTACK_SWING, ACT_GESTURE_MELEE_ATTACK_SWING },
// -----------------------------------------------------------
{ ACT_RANGE_ATTACK_AR2, ACT_GESTURE_RANGE_ATTACK_AR2 },
{ ACT_RANGE_ATTACK_AR2_LOW, ACT_GESTURE_RANGE_ATTACK_AR2 },
{ ACT_RANGE_ATTACK_SMG1, ACT_GESTURE_RANGE_ATTACK_SMG1 },
{ ACT_RANGE_ATTACK_SMG1_LOW, ACT_GESTURE_RANGE_ATTACK_SMG1 },
{ ACT_RANGE_ATTACK_SHOTGUN, ACT_GESTURE_RANGE_ATTACK_SHOTGUN },
{ ACT_RANGE_ATTACK_SHOTGUN_LOW, ACT_GESTURE_RANGE_ATTACK_SHOTGUN },
{ ACT_RANGE_ATTACK_PISTOL, ACT_GESTURE_RANGE_ATTACK_PISTOL },
{ ACT_RANGE_ATTACK_PISTOL_LOW, ACT_GESTURE_RANGE_ATTACK_PISTOL },
// -----------------------------------------------------------
{ ACT_SMALL_FLINCH, ACT_GESTURE_SMALL_FLINCH },
{ ACT_BIG_FLINCH, ACT_GESTURE_BIG_FLINCH },
{ ACT_FLINCH_HEAD, ACT_GESTURE_FLINCH_HEAD },
{ ACT_FLINCH_CHEST, ACT_GESTURE_FLINCH_CHEST },
{ ACT_FLINCH_STOMACH, ACT_GESTURE_FLINCH_STOMACH },
{ ACT_FLINCH_LEFTARM, ACT_GESTURE_FLINCH_LEFTARM },
{ ACT_FLINCH_RIGHTARM, ACT_GESTURE_FLINCH_RIGHTARM },
{ ACT_FLINCH_LEFTLEG, ACT_GESTURE_FLINCH_LEFTLEG },
{ ACT_FLINCH_RIGHTLEG, ACT_GESTURE_FLINCH_RIGHTLEG },
// -----------------------------------------------------------
#if AR2_ACTIVITY_FIX == 1
{ ACT_RELOAD_AR2, ACT_GESTURE_RELOAD_AR2 },
{ ACT_RELOAD_AR2_LOW, ACT_GESTURE_RELOAD_AR2 },
#endif
{ ACT_RELOAD_SMG1, ACT_GESTURE_RELOAD_SMG1 },
{ ACT_RELOAD_SMG1_LOW, ACT_GESTURE_RELOAD_SMG1 },
{ ACT_RELOAD_SHOTGUN, ACT_GESTURE_RELOAD_SHOTGUN },
{ ACT_RELOAD_SHOTGUN_LOW, ACT_GESTURE_RELOAD_SHOTGUN },
{ ACT_RELOAD_PISTOL, ACT_GESTURE_RELOAD_PISTOL },
{ ACT_RELOAD_PISTOL_LOW, ACT_GESTURE_RELOAD_PISTOL },
#if SHARED_COMBINE_ACTIVITIES
{ ACT_SPECIAL_ATTACK1, ACT_GESTURE_SPECIAL_ATTACK1 },
{ ACT_SPECIAL_ATTACK2, ACT_GESTURE_SPECIAL_ATTACK2 },
{ ACT_COMBINE_THROW_GRENADE, ACT_GESTURE_COMBINE_THROW_GRENADE },
{ ACT_COMBINE_AR2_ALTFIRE, ACT_GESTURE_COMBINE_AR2_ALTFIRE },
{ ACT_SIGNAL_ADVANCE, ACT_GESTURE_SIGNAL_ADVANCE },
{ ACT_SIGNAL_FORWARD, ACT_GESTURE_SIGNAL_FORWARD },
{ ACT_SIGNAL_GROUP, ACT_GESTURE_SIGNAL_GROUP },
{ ACT_SIGNAL_HALT, ACT_GESTURE_SIGNAL_HALT },
{ ACT_SIGNAL_LEFT, ACT_GESTURE_SIGNAL_LEFT },
{ ACT_SIGNAL_RIGHT, ACT_GESTURE_SIGNAL_RIGHT },
{ ACT_SIGNAL_TAKECOVER, ACT_GESTURE_SIGNAL_TAKECOVER },
#endif
#if EXPANDED_HL2_WEAPON_ACTIVITIES
{ ACT_RANGE_ATTACK_REVOLVER, ACT_GESTURE_RANGE_ATTACK_REVOLVER },
{ ACT_RANGE_ATTACK_REVOLVER_LOW, ACT_GESTURE_RANGE_ATTACK_REVOLVER },
{ ACT_RANGE_ATTACK_CROSSBOW, ACT_GESTURE_RANGE_ATTACK_CROSSBOW },
{ ACT_RANGE_ATTACK_CROSSBOW_LOW, ACT_GESTURE_RANGE_ATTACK_CROSSBOW },
{ ACT_RANGE_ATTACK_RPG, ACT_GESTURE_RANGE_ATTACK_RPG },
{ ACT_RANGE_ATTACK_RPG_LOW, ACT_GESTURE_RANGE_ATTACK_RPG },
{ ACT_RANGE_ATTACK_ANNABELLE, ACT_GESTURE_RANGE_ATTACK_ANNABELLE },
{ ACT_RANGE_ATTACK_ANNABELLE_LOW, ACT_GESTURE_RANGE_ATTACK_ANNABELLE },
{ ACT_RELOAD_REVOLVER, ACT_GESTURE_RELOAD_REVOLVER },
{ ACT_RELOAD_REVOLVER_LOW, ACT_GESTURE_RELOAD_REVOLVER },
{ ACT_RELOAD_CROSSBOW, ACT_GESTURE_RELOAD_CROSSBOW },
{ ACT_RELOAD_CROSSBOW_LOW, ACT_GESTURE_RELOAD_CROSSBOW },
{ ACT_RELOAD_ANNABELLE, ACT_GESTURE_RELOAD_ANNABELLE },
{ ACT_RELOAD_ANNABELLE_LOW, ACT_GESTURE_RELOAD_ANNABELLE },
#endif
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
{ ACT_RANGE_ATTACK_AR1, ACT_GESTURE_RANGE_ATTACK_AR1 },
{ ACT_RANGE_ATTACK_AR1_LOW, ACT_GESTURE_RANGE_ATTACK_AR1 },
{ ACT_RANGE_ATTACK_AR3, ACT_GESTURE_RANGE_ATTACK_AR3 },
{ ACT_RANGE_ATTACK_AR3_LOW, ACT_GESTURE_RANGE_ATTACK_AR3 },
{ ACT_RANGE_ATTACK_AR2_GRENADE, ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE },
{ ACT_RANGE_ATTACK_HMG1, ACT_GESTURE_RANGE_ATTACK_HMG1 },
{ ACT_RANGE_ATTACK_HMG1_LOW, ACT_GESTURE_RANGE_ATTACK_HMG1 },
{ ACT_RANGE_ATTACK_ML, ACT_GESTURE_RANGE_ATTACK_ML },
{ ACT_RANGE_ATTACK_SMG2, ACT_GESTURE_RANGE_ATTACK_SMG2 },
{ ACT_RANGE_ATTACK_SMG2_LOW, ACT_GESTURE_RANGE_ATTACK_SMG2 },
{ ACT_RANGE_ATTACK_SMG3, ACT_GESTURE_RANGE_ATTACK_SMG3 },
{ ACT_RANGE_ATTACK_SMG3_LOW, ACT_GESTURE_RANGE_ATTACK_SMG3 },
{ ACT_RANGE_ATTACK_SLAM, ACT_GESTURE_RANGE_ATTACK_SLAM },
{ ACT_RANGE_ATTACK_TRIPWIRE, ACT_GESTURE_RANGE_ATTACK_TRIPWIRE },
{ ACT_RANGE_ATTACK_THROW, ACT_GESTURE_RANGE_ATTACK_THROW },
{ ACT_RANGE_ATTACK_SNIPER_RIFLE, ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE },
{ ACT_RANGE_ATTACK_SNIPER_RIFLE_LOW, ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE },
{ ACT_RELOAD_AR1, ACT_GESTURE_RELOAD_AR1 },
{ ACT_RELOAD_AR1_LOW, ACT_GESTURE_RELOAD_AR1 },
{ ACT_RELOAD_AR3, ACT_GESTURE_RELOAD_AR3 },
{ ACT_RELOAD_AR3_LOW, ACT_GESTURE_RELOAD_AR3 },
{ ACT_RELOAD_SMG2, ACT_GESTURE_RELOAD_SMG2 },
{ ACT_RELOAD_SMG2_LOW, ACT_GESTURE_RELOAD_SMG2 },
{ ACT_RELOAD_SMG3, ACT_GESTURE_RELOAD_SMG3 },
{ ACT_RELOAD_SMG3_LOW, ACT_GESTURE_RELOAD_SMG3 },
{ ACT_RELOAD_HMG1, ACT_GESTURE_RELOAD_HMG1 },
{ ACT_RELOAD_HMG1_LOW, ACT_GESTURE_RELOAD_HMG1 },
{ ACT_RELOAD_SNIPER_RIFLE, ACT_GESTURE_RELOAD_SNIPER_RIFLE },
{ ACT_RELOAD_SNIPER_RIFLE_LOW, ACT_GESTURE_RELOAD_SNIPER_RIFLE },
#endif
#if EXPANDED_HL2_COVER_ACTIVITIES
{ ACT_RANGE_ATTACK1_MED, ACT_GESTURE_RANGE_ATTACK1 },
{ ACT_RANGE_ATTACK2_MED, ACT_GESTURE_RANGE_ATTACK2 },
{ ACT_RANGE_ATTACK_AR2_MED, ACT_GESTURE_RANGE_ATTACK_AR2 },
{ ACT_RANGE_ATTACK_SMG1_MED, ACT_GESTURE_RANGE_ATTACK_SMG1 },
{ ACT_RANGE_ATTACK_SHOTGUN_MED, ACT_GESTURE_RANGE_ATTACK_SHOTGUN },
{ ACT_RANGE_ATTACK_PISTOL_MED, ACT_GESTURE_RANGE_ATTACK_PISTOL },
#if EXPANDED_HL2_WEAPON_ACTIVITIES
{ ACT_RANGE_ATTACK_RPG_MED, ACT_GESTURE_RANGE_ATTACK_RPG },
{ ACT_RANGE_ATTACK_REVOLVER_MED, ACT_GESTURE_RANGE_ATTACK_REVOLVER },
{ ACT_RANGE_ATTACK_CROSSBOW_MED, ACT_GESTURE_RANGE_ATTACK_CROSSBOW },
#endif
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
{ ACT_RANGE_ATTACK_AR1_MED, ACT_GESTURE_RANGE_ATTACK_AR1 },
{ ACT_RANGE_ATTACK_AR3_MED, ACT_GESTURE_RANGE_ATTACK_AR3 },
{ ACT_RANGE_ATTACK_SMG2_MED, ACT_GESTURE_RANGE_ATTACK_SMG2 },
{ ACT_RANGE_ATTACK_SMG3_MED, ACT_GESTURE_RANGE_ATTACK_SMG3 },
{ ACT_RANGE_ATTACK_HMG1_MED, ACT_GESTURE_RANGE_ATTACK_HMG1 },
{ ACT_RANGE_ATTACK_SNIPER_RIFLE_MED, ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE },
#endif
#endif
};
Activity CAI_BaseNPC::GetGestureVersionOfActivity( Activity inActivity )
{
actlink_t *pTable = gm_ActivityGestureLinks;
int actCount = ARRAYSIZE( gm_ActivityGestureLinks );
for ( int i = 0; i < actCount; i++, pTable++ )
{
if ( inActivity == pTable->sequence )
{
return pTable->gesture;
}
}
return ACT_INVALID;
}
Activity CAI_BaseNPC::GetSequenceVersionOfGesture( Activity inActivity )
{
actlink_t *pTable = gm_ActivityGestureLinks;
int actCount = ARRAYSIZE( gm_ActivityGestureLinks );
for (int i = 0; i < actCount; i++, pTable++)
{
if (inActivity == pTable->gesture)
{
return pTable->sequence;
}
}
return ACT_INVALID;
}
#endif

View File

@ -101,8 +101,8 @@ END_DATADESC()
#ifdef MAPBASE_VSCRIPT
BEGIN_ENT_SCRIPTDESC( CAI_BaseActor, CAI_BaseNPC, "The base class for NPCs which act in complex choreo scenes." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTarget, "AddLookTarget", "Add a potential look target for this actor." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTargetPos, "AddLookTargetPos", "Add a potential look target position for this actor." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTarget, "AddLookTarget", "Add a potential look target for this actor with the specified importance, duration, and ramp." )
DEFINE_SCRIPTFUNC_NAMED( ScriptAddLookTargetPos, "AddLookTargetPos", "Add a potential look target position for this actor with the specified importance, duration, and ramp." )
END_SCRIPTDESC();
#endif
@ -835,7 +835,11 @@ void CAI_BaseActor::UpdateLatchedValues( )
// set head latch
m_fLatchedPositions |= HUMANOID_LATCHED_HEAD;
#ifdef MAPBASE // From Alien Swarm SDK
if ( CanSkipAnimation() || !GetAttachment( "eyes", m_latchedEyeOrigin, &m_latchedHeadDirection ))
#else
if (!HasCondition( COND_IN_PVS ) || !GetAttachment( "eyes", m_latchedEyeOrigin, &m_latchedHeadDirection ))
#endif
{
m_latchedEyeOrigin = BaseClass::EyePosition( );
AngleVectors( GetLocalAngles(), &m_latchedHeadDirection );
@ -1138,6 +1142,24 @@ void CAI_BaseActor::UpdateHeadControl( const Vector &vHeadTarget, float flHeadIn
ConcatTransforms( worldToForward, targetXform, headXform );
MatrixAngles( headXform, vTargetAngles );
#ifdef MAPBASE
// This is here to cover an edge case where pose parameters set to NaN invalidate the model.
if (!vTargetAngles.IsValid())
{
Warning( "================================================================================\n"
"!!!!! %s tried to set a NaN head angle (can happen when look targets have >1 importance) !!!!!\n"
"================================================================================\n", GetDebugName() );
m_goalHeadCorrection.Init();
Set( m_FlexweightHeadRightLeft, 0.0f );
Set( m_FlexweightHeadUpDown, 0.0f );
Set( m_FlexweightHeadTilt, 0.0f );
Set( m_ParameterHeadYaw, 0.0f );
Set( m_ParameterHeadPitch, 0.0f );
Set( m_ParameterHeadRoll, 0.0f );
return;
}
#endif
// partially debounce head goal
float s0 = 1.0 - flHeadInfluence + GetHeadDebounce() * flHeadInfluence;
float s1 = (1.0 - s0);
@ -1626,7 +1648,11 @@ void CAI_BaseActor::MaintainLookTargets( float flInterval )
}
// don't bother with any of the rest if the player can't see you
#ifdef MAPBASE // From Alien Swarm SDK
if ( CanSkipAnimation() )
#else
if (!HasCondition( COND_IN_PVS ))
#endif
{
return;
}
@ -2033,7 +2059,11 @@ bool CAI_BaseActor::UseSemaphore( void )
CAI_Expresser *CAI_BaseActor::CreateExpresser()
{
#ifdef NEW_RESPONSE_SYSTEM
m_pExpresser = new CAI_ExpresserWithFollowup(this);
#else
m_pExpresser = new CAI_Expresser(this);
#endif
return m_pExpresser;
}

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,9 @@ class CBaseGrenade;
class CBaseDoor;
class CBasePropDoor;
struct AI_Waypoint_t;
#ifndef NEW_RESPONSE_SYSTEM
class AI_Response;
#endif
class CBaseFilter;
typedef CBitVec<MAX_CONDITIONS> CAI_ScheduleBits;
@ -98,11 +100,6 @@ extern bool AIStrongOpt( void );
#ifdef MAPBASE
// Defines Mapbase's extended NPC response system usage.
#define EXPANDED_RESPONSE_SYSTEM_USAGE
// Use the model keyvalue if it is defined
#define DefaultOrCustomModel(defaultModel) GetModelName() != NULL_STRING ? STRING(GetModelName()) : defaultModel
#else
#define DefaultOrCustomModel() defaultModel
#endif
#ifdef EXPANDED_RESPONSE_SYSTEM_USAGE
@ -670,6 +667,7 @@ public:
virtual bool ShouldAlwaysThink();
void ForceGatherConditions() { m_bForceConditionsGather = true; SetEfficiency( AIE_NORMAL ); } // Force an NPC out of PVS to call GatherConditions on next think
bool IsForceGatherConditionsSet() { return m_bForceConditionsGather; }
virtual float LineOfSightDist( const Vector &vecDir = vec3_invalid, float zEye = FLT_MAX );
@ -963,7 +961,7 @@ public:
void RemoveSleepFlags( int flags ) { m_SleepFlags &= ~flags; }
bool HasSleepFlags( int flags ) { return (m_SleepFlags & flags) == flags; }
void UpdateSleepState( bool bInPVS );
virtual void UpdateSleepState( bool bInPVS );
virtual void Wake( bool bFireOutput = true );
#ifdef MAPBASE
// A version of Wake() that takes an activator
@ -1000,12 +998,17 @@ public:
Activity NPC_TranslateActivity( Activity eNewActivity );
#ifdef MAPBASE
Activity TranslateCrouchActivity( Activity baseAct );
virtual bool CanTranslateCrouchActivity( void ) { return true; }
virtual Activity NPC_BackupActivity( Activity eNewActivity );
#endif
Activity GetActivity( void ) { return m_Activity; }
virtual void SetActivity( Activity NewActivity );
Activity GetIdealActivity( void ) { return m_IdealActivity; }
void SetIdealActivity( Activity NewActivity );
#ifdef MAPBASE
Activity GetTranslatedActivity( void ) { return m_translatedActivity; }
Activity GetIdealTranslatedActivity( void ) { return m_IdealTranslatedActivity; }
#endif
void ResetIdealActivity( Activity newIdealActivity );
void SetSequenceByName( const char *szSequence );
void SetSequenceById( int iSequence );
@ -1022,6 +1025,25 @@ public:
void SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity);
#ifdef MAPBASE
//-----------------------------------------------------
// Returns the gesture variant of an activity (i.e. "ACT_GESTURE_RANGE_ATTACK1")
static Activity GetGestureVersionOfActivity( Activity inActivity );
// Returns the sequence variant of a gesture activity
static Activity GetSequenceVersionOfGesture( Activity inActivity );
//-----------------------------------------------------
virtual bool ShouldPlayFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity );
virtual Activity SelectFakeSequenceGesture( Activity nActivity, Activity nTranslatedActivity );
void PlayFakeSequenceGesture( Activity nActivity, Activity nSequence, Activity nTranslatedSequence );
int GetFakeSequenceGesture();
void ResetFakeSequenceGesture();
#endif
private:
void AdvanceToIdealActivity(void);
@ -1035,6 +1057,10 @@ private:
Activity m_IdealTranslatedActivity; // Desired actual translated animation state
Activity m_IdealWeaponActivity; // Desired weapon animation state
#ifdef MAPBASE
int m_FakeSequenceGestureLayer; // The gesture layer impersonating a sequence (-1 if invalid)
#endif
CNetworkVar(int, m_iDeathPose );
CNetworkVar(int, m_iDeathFrame );
@ -1219,6 +1245,8 @@ public:
#endif
#ifdef MAPBASE_VSCRIPT
private:
// VScript stuff uses "VScript" instead of just "Script" to avoid
// confusion with NPC_STATE_SCRIPT or StartScripting
HSCRIPT VScriptGetEnemy();
@ -1245,6 +1273,11 @@ public:
int ScriptTranslateActivity( const char *szActivity ) { return TranslateActivity( (Activity)GetActivityID( szActivity ) ); }
int ScriptTranslateActivityID( int iActivity ) { return TranslateActivity( (Activity)iActivity ); }
const char* VScriptGetGestureVersionOfActivity( const char *pszActivity ) { return GetActivityName( GetGestureVersionOfActivity( (Activity)GetActivityID( pszActivity ) ) ); }
int VScriptGetGestureVersionOfActivityID( int iActivity ) { return GetGestureVersionOfActivity( (Activity)iActivity ); }
const char* VScriptGetSequenceVersionOfGesture( const char *pszActivity ) { return GetActivityName( GetSequenceVersionOfGesture( (Activity)GetActivityID( pszActivity ) ) ); }
int VScriptGetSequenceVersionOfGestureID( int iActivity ) { return GetSequenceVersionOfGesture( (Activity)iActivity ); }
const char* VScriptGetSchedule();
int VScriptGetScheduleID();
void VScriptSetSchedule( const char *szSchedule );
@ -1733,8 +1766,8 @@ public:
virtual bool DoHolster(void);
virtual bool DoUnholster(void);
virtual bool ShouldUnholsterWeapon() { return GetState() == NPC_STATE_COMBAT; }
virtual bool CanUnholsterWeapon() { return IsWeaponHolstered(); }
virtual bool ShouldUnholsterWeapon();
virtual bool CanUnholsterWeapon();
void InputGiveWeaponHolstered( inputdata_t &inputdata );
void InputChangeWeapon( inputdata_t &inputdata );
@ -2121,6 +2154,7 @@ public:
COutputEHANDLE m_OnUnholsterWeapon;
COutputEHANDLE m_OnItemPickup;
COutputEHANDLE m_OnItemDrop;
COutputInt m_OnStateChange;
#endif
@ -2208,6 +2242,10 @@ public:
inline void ForceCrouch( void );
inline void ClearForceCrouch( void );
#ifdef MAPBASE
bool CouldShootIfCrouchingAt( const Vector &vecPosition, const Vector &vecForward, const Vector &vecRight, float flDist = 48.0f );
#endif
protected:
virtual bool Crouch( void );
virtual bool Stand( void );
@ -2267,6 +2305,16 @@ private:
static CAI_GlobalScheduleNamespace gm_SchedulingSymbols;
static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace;
#ifdef MAPBASE
typedef struct
{
Activity sequence;
Activity gesture;
} actlink_t;
static actlink_t gm_ActivityGestureLinks[];
#endif
public:
//----------------------------------------------------
// Debugging tools
@ -2318,6 +2366,7 @@ public:
static ScriptHook_t g_Hook_TranslateSchedule;
static ScriptHook_t g_Hook_GetActualShootPosition;
static ScriptHook_t g_Hook_OverrideMove;
static ScriptHook_t g_Hook_ShouldPlayFakeSequenceGesture;
#endif
private:

View File

@ -980,11 +980,12 @@ bool CAI_BaseNPC::FindCoverFromEnemy( bool bNodesOnly, float flMinDistance, floa
// FIXME: add to goal
if (GetHintNode())
{
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
#ifdef MAPBASE
if (GetHintNode()->GetIgnoreFacing() != HIF_NO)
#endif
GetHintNode()->NPCHandleStartNav( this, true );
#else
GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) );
GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() );
#endif
}
return true;
@ -1363,6 +1364,14 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
break;
case TASK_STOP_MOVING:
#ifdef MAPBASE
if ( GetNavType() == NAV_CLIMB )
{
// Don't clear the goal so that the climb can finish
DbgNavMsg( this, "Start TASK_STOP_MOVING with climb workaround\n" );
}
else
#endif
if ( ( GetNavigator()->IsGoalSet() && GetNavigator()->IsGoalActive() ) || GetNavType() == NAV_JUMP )
{
DbgNavMsg( this, "Start TASK_STOP_MOVING\n" );
@ -3015,7 +3024,16 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
case TASK_ITEM_PICKUP:
{
SetIdealActivity( ACT_PICKUP_GROUND );
#ifdef MAPBASE
if (GetTarget() && fabs( GetTarget()->WorldSpaceCenter().z - GetAbsOrigin().z ) >= 12.0f)
{
SetIdealActivity( ACT_PICKUP_RACK );
}
else
#endif
{
SetIdealActivity( ACT_PICKUP_GROUND );
}
}
break;
@ -3339,8 +3357,40 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
// a navigation while in the middle of a climb
if (GetNavType() == NAV_CLIMB)
{
#ifdef MAPBASE
if (GetActivity() != ACT_CLIMB_DISMOUNT)
{
// Try to just pause the climb, but dismount if we're in SCHED_FAIL
if (IsCurSchedule( SCHED_FAIL, false ))
{
GetMotor()->MoveClimbStop();
}
else
{
GetMotor()->MoveClimbPause();
}
TaskComplete();
}
else if (IsActivityFinished())
{
// Dismount complete.
GetMotor()->MoveClimbStop();
// Fix up our position if we have to
Vector vecTeleportOrigin;
if (GetMotor()->MoveClimbShouldTeleportToSequenceEnd( vecTeleportOrigin ))
{
SetLocalOrigin( vecTeleportOrigin );
}
TaskComplete();
}
break;
#else
// wait until you reach the end
break;
#endif
}
DbgNavMsg( this, "TASK_STOP_MOVING Complete\n" );
@ -3385,6 +3435,17 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
// If the yaw is locked, this function will not act correctly
Assert( GetMotor()->IsYawLocked() == false );
#ifdef MAPBASE
if ( GetHintNode() && GetHintNode()->OverridesNPCYaw( this ) )
{
// If the yaw is supposed to use that of a hint node, chain to TASK_FACE_HINTNODE
GetMotor()->SetIdealYaw( GetHintNode()->Yaw() );
GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw
ChainRunTask( TASK_FACE_HINTNODE, pTask->flTaskData );
break;
}
#endif
Vector vecEnemyLKP = GetEnemyLKP();
if (!FInAimCone( vecEnemyLKP ))
{
@ -3979,10 +4040,16 @@ void CAI_BaseNPC::RunTask( const Task_t *pTask )
// If we have an entry, we have to play it first
if ( m_hCine->m_iszEntry != NULL_STRING )
{
#ifdef MAPBASE
m_hCine->OnEntrySequence( this );
#endif
m_hCine->StartSequence( (CAI_BaseNPC *)this, m_hCine->m_iszEntry, true );
}
else
{
#ifdef MAPBASE
m_hCine->OnActionSequence( this );
#endif
m_hCine->StartSequence( (CAI_BaseNPC *)this, m_hCine->m_iszPlay, true );
}
@ -4265,6 +4332,15 @@ void CAI_BaseNPC::SetTurnActivity ( void )
float flYD;
flYD = GetMotor()->DeltaIdealYaw();
#ifdef MAPBASE
// Allow AddTurnGesture() to decide this
if (GetMotor()->AddTurnGesture( flYD ))
{
SetIdealActivity( ACT_IDLE );
Remember( bits_MEMORY_TURNING );
return;
}
#else
// FIXME: unknown case, update yaw should catch these
/*
if (GetMotor()->AddTurnGesture( flYD ))
@ -4274,6 +4350,7 @@ void CAI_BaseNPC::SetTurnActivity ( void )
return;
}
*/
#endif
if( flYD <= -80 && flYD >= -100 && SelectWeightedSequence( ACT_90_RIGHT ) != ACTIVITY_NOT_AVAILABLE )
{

View File

@ -420,6 +420,24 @@ bool CAI_BehaviorBase::CanUnholsterWeapon( void )
return m_pBackBridge->BackBridge_CanUnholsterWeapon();
}
//-------------------------------------
bool CAI_BehaviorBase::ShouldPickADeathPose( void )
{
Assert( m_pBackBridge != NULL );
return m_pBackBridge->BackBridge_ShouldPickADeathPose();
}
//-------------------------------------
bool CAI_BehaviorBase::CanTranslateCrouchActivity( void )
{
Assert( m_pBackBridge != NULL );
return m_pBackBridge->BackBridge_CanTranslateCrouchActivity();
}
#endif
//-------------------------------------

View File

@ -132,6 +132,8 @@ public:
void BridgeHandleAnimEvent( animevent_t *pEvent );
#ifdef MAPBASE
bool BridgeCanUnholsterWeapon( void );
bool BridgeShouldPickADeathPose( void );
bool BridgeCanTranslateCrouchActivity( void );
#endif
virtual void GatherConditions();
@ -220,6 +222,8 @@ protected:
virtual void HandleAnimEvent( animevent_t *pEvent );
#ifdef MAPBASE
virtual bool CanUnholsterWeapon( void );
virtual bool ShouldPickADeathPose( void );
virtual bool CanTranslateCrouchActivity( void );
#endif
virtual bool ShouldAlwaysThink();
@ -370,6 +374,9 @@ public:
#ifdef MAPBASE
// For func_tank behavior
virtual bool BackBridge_CanUnholsterWeapon( void ) = 0;
virtual bool BackBridge_ShouldPickADeathPose( void ) = 0;
virtual bool BackBridge_CanTranslateCrouchActivity( void ) = 0;
#endif
//-------------------------------------
@ -470,6 +477,8 @@ public:
void HandleAnimEvent( animevent_t *pEvent );
#ifdef MAPBASE
bool CanUnholsterWeapon( void );
bool ShouldPickADeathPose( void );
bool CanTranslateCrouchActivity( void );
#endif
bool ShouldAlwaysThink();
@ -534,6 +543,9 @@ private:
#ifdef MAPBASE
// For func_tank behavior
bool BackBridge_CanUnholsterWeapon( void );
bool BackBridge_ShouldPickADeathPose( void );
bool BackBridge_CanTranslateCrouchActivity( void );
#endif
CAI_BehaviorBase **AccessBehaviors();
@ -913,6 +925,20 @@ inline bool CAI_BehaviorBase::BridgeCanUnholsterWeapon( void )
{
return CanUnholsterWeapon();
}
//-----------------------------------------------------------------------------
inline bool CAI_BehaviorBase::BridgeShouldPickADeathPose( void )
{
return ShouldPickADeathPose();
}
//-----------------------------------------------------------------------------
inline bool CAI_BehaviorBase::BridgeCanTranslateCrouchActivity( void )
{
return CanTranslateCrouchActivity();
}
#endif
//-----------------------------------------------------------------------------
@ -1498,6 +1524,22 @@ inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanUnholsterWeapon( void )
{
return BaseClass::CanUnholsterWeapon();
}
//-------------------------------------
template <class BASE_NPC>
inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_ShouldPickADeathPose( void )
{
return BaseClass::ShouldPickADeathPose();
}
//-------------------------------------
template <class BASE_NPC>
inline bool CAI_BehaviorHost<BASE_NPC>::BackBridge_CanTranslateCrouchActivity( void )
{
return BaseClass::CanTranslateCrouchActivity();
}
#endif
//-------------------------------------
@ -1914,6 +1956,28 @@ inline bool CAI_BehaviorHost<BASE_NPC>::CanUnholsterWeapon( void )
return BaseClass::CanUnholsterWeapon();
}
//-------------------------------------
template <class BASE_NPC>
inline bool CAI_BehaviorHost<BASE_NPC>::ShouldPickADeathPose( void )
{
if (m_pCurBehavior)
return m_pCurBehavior->BridgeShouldPickADeathPose();
return BaseClass::ShouldPickADeathPose();
}
//-------------------------------------
template <class BASE_NPC>
inline bool CAI_BehaviorHost<BASE_NPC>::CanTranslateCrouchActivity( void )
{
if (m_pCurBehavior)
return m_pCurBehavior->BridgeCanTranslateCrouchActivity();
return BaseClass::CanTranslateCrouchActivity();
}
#endif
//-------------------------------------

View File

@ -408,10 +408,11 @@ bool CAI_FollowBehavior::SetFollowGoal( CAI_FollowGoal *pGoal, bool fFinishCurSc
SetFollowTarget( pGoal->GetGoalEntity() );
#ifdef MAPBASE
Assert( pGoal->m_iFormation < AIF_NUM_FORMATIONS );
SetParameters( AI_FollowParams_t( (AI_Formations_t)pGoal->m_iFormation, pGoal->m_bNormalMemoryDiscard ) );
#else
Assert( pGoal->m_iFormation == AIF_SIMPLE || pGoal->m_iFormation == AIF_WIDE || pGoal->m_iFormation == AIF_MEDIUM || pGoal->m_iFormation == AIF_SIDEKICK || pGoal->m_iFormation == AIF_VORTIGAUNT );
#endif
SetParameters( AI_FollowParams_t( (AI_Formations_t)pGoal->m_iFormation ) );
#endif
m_hFollowGoalEnt = pGoal;
m_flTimeUpdatedFollowPosition = 0;
return true;
@ -2138,6 +2139,9 @@ bool CAI_FollowBehavior::ShouldAlwaysThink()
BEGIN_DATADESC( CAI_FollowGoal )
DEFINE_KEYFIELD( m_iFormation, FIELD_INTEGER, "Formation" ),
#ifdef MAPBASE
DEFINE_KEYFIELD( m_bNormalMemoryDiscard, FIELD_BOOLEAN, "NormalMemoryDiscard" ),
#endif
#ifdef HL2_EPISODIC
DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ),

View File

@ -71,6 +71,10 @@ public:
int m_iFormation;
#ifdef MAPBASE
bool m_bNormalMemoryDiscard = false;
#endif
DECLARE_DATADESC();
};

View File

@ -9,12 +9,19 @@
#include "simtimer.h"
#include "ai_behavior.h"
#ifdef NEW_RESPONSE_SYSTEM
#include "ai_speechconcept.h"
#endif
#if defined( _WIN32 )
#pragma once
#endif
#ifdef NEW_RESPONSE_SYSTEM
typedef CAI_Concept AIConcept_t;
#else
typedef const char *AIConcept_t;
#endif
// Speak concepts
#define TLK_LEAD_START "TLK_LEAD_START"

View File

@ -240,6 +240,23 @@ void CAI_StandoffBehavior::SetActive( bool fActive )
{
if ( fActive != m_fActive )
{
#ifdef MAPBASE
// These sentences are only spoken if the standoff behavior is active, so they have to be arranged separately
if ( fActive )
{
m_fActive = fActive;
NotifyChangeBehaviorStatus();
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_BEGIN_STANDOFF );
}
else
{
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_END_STANDOFF );
m_fActive = fActive;
NotifyChangeBehaviorStatus();
}
#else
if ( fActive )
{
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_BEGIN_STANDOFF );
@ -251,6 +268,7 @@ void CAI_StandoffBehavior::SetActive( bool fActive )
m_fActive = fActive;
NotifyChangeBehaviorStatus();
#endif
}
}
@ -278,7 +296,12 @@ bool CAI_StandoffBehavior::CanSelectSchedule()
if ( !m_fActive )
return false;
#ifdef MAPBASE
// Allow NPCs with innate range attacks to use standoffs
return ( GetNpcState() == NPC_STATE_COMBAT && (GetOuter()->GetActiveWeapon() != NULL || GetOuter()->CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK1) );
#else
return ( GetNpcState() == NPC_STATE_COMBAT && GetOuter()->GetActiveWeapon() != NULL );
#endif
}
//-------------------------------------
@ -517,10 +540,11 @@ int CAI_StandoffBehavior::SelectScheduleCheckCover( void )
{
StandoffMsg( "Regulated to not shoot\n" );
#ifdef MAPBASE
if ( GetHintType() == HINT_TACTICAL_COVER_LOW || GetHintType() == HINT_TACTICAL_COVER_MED )
#else
if ( GetHintType() == HINT_TACTICAL_COVER_LOW )
if ( GetHintType() == HINT_TACTICAL_COVER_MED || GetCoverActivity() == ACT_COVER_MED )
SetPosture( AIP_CROUCHING_MED );
else
#endif
if ( GetHintType() == HINT_TACTICAL_COVER_LOW )
SetPosture( AIP_CROUCHING );
else
SetPosture( AIP_STANDING );
@ -539,7 +563,11 @@ int CAI_StandoffBehavior::SelectScheduleEstablishAim( void )
{
if ( HasCondition( COND_ENEMY_OCCLUDED ) )
{
#if EXPANDED_HL2_COVER_ACTIVITIES
if ( GetPosture() == AIP_CROUCHING || GetPosture() == AIP_CROUCHING_MED )
#else
if ( GetPosture() == AIP_CROUCHING )
#endif
{
// force a stand up, just in case
GetOuter()->SpeakSentence( STANDOFF_SENTENCE_STAND_CHECK_TARGET );
@ -577,7 +605,11 @@ int CAI_StandoffBehavior::SelectScheduleAttack( void )
!HasCondition( COND_CAN_MELEE_ATTACK1 ) &&
HasCondition( COND_TOO_FAR_TO_ATTACK ) )
{
#ifdef MAPBASE
if ( (GetOuter()->GetActiveWeapon() && ( GetOuter()->GetActiveWeapon()->CapabilitiesGet() & bits_CAP_WEAPON_RANGE_ATTACK1 )) || GetOuter()->CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK1 )
#else
if ( GetOuter()->GetActiveWeapon() && ( GetOuter()->GetActiveWeapon()->CapabilitiesGet() & bits_CAP_WEAPON_RANGE_ATTACK1 ) )
#endif
{
if ( !HasCondition( COND_ENEMY_OCCLUDED ) || random->RandomInt(0,99) < 50 )
// Don't advance, just fire anyway
@ -650,6 +682,15 @@ Activity CAI_MappedActivityBehavior_Temporary::GetMappedActivity( AI_Posture_t p
{
if ( posture != AIP_STANDING )
{
#if EXPANDED_HL2_COVER_ACTIVITIES
// See UpdateTranslateActivityMap() for more information on what this is for
if ( posture == AIP_CROUCHING_MED )
{
if (activity != ACT_RANGE_ATTACK1)
posture = AIP_CROUCHING;
}
#endif
unsigned short iActivityTranslation = m_ActivityMap.Find( MAKE_ACTMAP_KEY( posture, activity ) );
if ( iActivityTranslation != m_ActivityMap.InvalidIndex() )
{
@ -667,10 +708,28 @@ Activity CAI_StandoffBehavior::NPC_TranslateActivity( Activity activity )
Activity coverActivity = GetCoverActivity();
if ( coverActivity != ACT_INVALID )
{
#ifdef MAPBASE
if ( GetPosture() == AIP_STANDING )
{
if ( coverActivity == ACT_COVER_LOW )
SetPosture( AIP_CROUCHING );
else if ( coverActivity == ACT_COVER_MED )
{
SetPosture( AIP_CROUCHING_MED );
coverActivity = ACT_COVER_LOW;
}
}
else if (coverActivity == ACT_COVER_MED)
coverActivity = ACT_COVER_LOW;
if ( activity == ACT_IDLE )
activity = coverActivity;
#else
if (activity == ACT_IDLE)
activity = coverActivity;
if ( GetPosture() == AIP_STANDING && coverActivity == ACT_COVER_LOW )
SetPosture( AIP_CROUCHING );
#endif
}
Activity result = GetMappedActivity( GetPosture(), activity );
@ -1071,12 +1130,25 @@ void CAI_StandoffBehavior::UnlockHintNode()
Activity CAI_StandoffBehavior::GetCoverActivity()
{
#ifdef MAPBASE
// This does two things:
// A. Allows medium cover nodes to be used, kind of.
// B. GetCoverActivity() already checks everything we checked here.
Activity coveract = GetOuter()->GetCoverActivity( GetHintNode() );
return coveract == ACT_IDLE ? ACT_INVALID : coveract;
#if EXPANDED_HL2_COVER_ACTIVITIES
// GetCoverActivity() already checks everything we checked here.
Activity coverActivity = GetOuter()->GetCoverActivity( GetHintNode() );
if (coverActivity == ACT_COVER_LOW)
{
// Check if this node will block our line of sight if aiming low.
Vector vHintPos, vHintForward, vHintRight;
GetHintNode()->GetPosition( GetHullType(), &vHintPos );
vHintForward = GetHintNode()->GetDirection();
GetHintNode()->GetVectors( NULL, &vHintRight, NULL );
if (GetOuter()->CouldShootIfCrouchingAt( vHintPos, vHintForward, vHintRight ))
{
coverActivity = ACT_COVER_MED;
}
}
return coverActivity == ACT_IDLE ? ACT_INVALID : coverActivity;
#else
CAI_Hint *pHintNode = GetHintNode();
if ( pHintNode && pHintNode->HintType() == HINT_TACTICAL_COVER_LOW )
@ -1094,6 +1166,14 @@ struct AI_ActivityMapping_t
Activity activity;
const char * pszWeapon;
Activity translation;
#ifdef MAPBASE
Activity backup;
AI_ActivityMapping_t( AI_Posture_t _p, Activity _a, const char *_w, Activity _t, Activity _b = ACT_INVALID )
{
posture = _p; activity = _a; pszWeapon = _w; translation = _t; backup = _b;
}
#endif
};
void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
@ -1107,15 +1187,60 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
{ AIP_CROUCHING, ACT_WALK_AIM, NULL, ACT_WALK_CROUCH_AIM, },
{ AIP_CROUCHING, ACT_RUN_AIM, NULL, ACT_RUN_CROUCH_AIM, },
{ AIP_CROUCHING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
#ifdef MAPBASE
{ AIP_CROUCHING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_LOW, },
{ AIP_CROUCHING, ACT_COVER_MED, NULL, ACT_COVER_LOW, },
#else
{ AIP_CROUCHING, ACT_RANGE_ATTACK_SMG1, NULL, ACT_RANGE_ATTACK_SMG1_LOW, },
{ AIP_CROUCHING, ACT_RANGE_ATTACK_AR2, NULL, ACT_RANGE_ATTACK_AR2_LOW, },
#endif
#if EXPANDED_HL2_COVER_ACTIVITIES
//
// ============ Really long explanation that should be in a wiki/documentation article somewhere ~ Blixibon, 10/27/2021 ============
//
// Standoff behavior assumes low attack animations allow NPCs to see over barricades, with ACT_COVER_LOW being their "safely in cover" animation.
// This is why AIP_CROUCHING translates ACT_RANGE_ATTACK1 to its low animation, but translates ACT_IDLE_ANGRY to ACT_COVER_LOW instead of ACT_RANGE_AIM_LOW,
// as this would ideally allow NPCs to pop in and out of cover to shoot.
// This is also why AIP_PEEKING translates ACT_COVER_LOW to ACT_RANGE_AIM_LOW, as it's supposed to force the NPC to peek over their cover.
//
// However, this assumption mainly just applies to metrocops. Citizens' low attacking animations crouch low to the ground (which isn't effective for
// shooting over most barricades) and, while they do have a distinct ACT_COVER_LOW animation with transitions, they are close enough together that popping
// in and out of cover is redundant in most cases. Meanwhile, Combine soldiers have identical ACT_COVER_LOW and ACT_RANGE_AIM_LOW animations, which means
// they do not pop in and out of cover and AIP_PEEKING does nothing. This may be the reason why Combine soldiers occasionally get stuck in cover after a fight.
//
// -------------------------------------------------------------
//
// As part of Mapbase v7.0's NPC activity overhaul, a new "medium cover" activity set has been added. Metrocops' previous "low cover" animation set (which, as
// mentioned before, is different from that of other NPCs) has been retroactively changed to use "medium cover". This was done for a few reasons unrelated to
// standoff behavior, but the important point is that these activities indicate a new cover height. This means we can use them to give standoff behavior more leeway
// for judging which animations to use in various levels of cover.
//
// Standoff behavior can use "medium cover" animations in cover which is too high for the "low" animations, and when the medium cover animations are not available,
// it simply falls back to the "standing" animations, thus resolving the issue with other NPCs not peeking in and out of cover without requiring new medium cover
// animations.
//
// In Mapbase, this is done by changing AIP_PEEKING to use the medium cover animations and adding a new alternate crouching posture posture called "AIP_CROUCHING_MED",
// which only uses the medium cover attack activity and otherwise automatically falls back to AIP_CROUCHING. AIP_CROUCHING_MED is automatically set if the NPC cannot
// get LOS from a regular crouching position.
//
{ AIP_CROUCHING_MED, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_MED, },
//----
{ AIP_PEEKING, ACT_IDLE, NULL, ACT_RANGE_AIM_MED, },
{ AIP_PEEKING, ACT_IDLE_ANGRY, NULL, ACT_RANGE_AIM_MED, },
{ AIP_PEEKING, ACT_COVER_LOW, NULL, ACT_RANGE_AIM_MED, ACT_IDLE_ANGRY },
{ AIP_PEEKING, ACT_COVER_MED, NULL, ACT_RANGE_AIM_MED, ACT_IDLE_ANGRY },
{ AIP_PEEKING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_MED, },
{ AIP_PEEKING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
#else
//----
{ AIP_PEEKING, ACT_IDLE, NULL, ACT_RANGE_AIM_LOW, },
{ AIP_PEEKING, ACT_IDLE_ANGRY, NULL, ACT_RANGE_AIM_LOW, },
{ AIP_PEEKING, ACT_COVER_LOW, NULL, ACT_RANGE_AIM_LOW, },
{ AIP_PEEKING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_LOW, },
{ AIP_PEEKING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, },
#endif
};
m_ActivityMap.RemoveAll();
@ -1127,7 +1252,7 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
if ( !mappings[i].pszWeapon || stricmp( mappings[i].pszWeapon, pszWeaponClass ) == 0 )
{
#ifdef MAPBASE
// Check backup activity
// Check NPC backup activity
if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) || HaveSequenceForActivity( GetOuter()->Weapon_BackupActivity( mappings[i].translation ) ) )
#else
if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) )
@ -1136,6 +1261,14 @@ void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap()
Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() );
m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].translation );
}
#ifdef MAPBASE
// Check activity map backup activity
else if ( mappings[i].backup != ACT_INVALID && HaveSequenceForActivity( mappings[i].backup ) )
{
Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() );
m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].backup );
}
#endif
}
}
}

View File

@ -51,6 +51,9 @@ enum AI_Posture_t
AIP_INDIFFERENT,
AIP_STANDING,
AIP_CROUCHING,
#if EXPANDED_HL2_COVER_ACTIVITIES
AIP_CROUCHING_MED, // See UpdateTranslateActivityMap() for more information on what this is for
#endif
AIP_PEEKING,
};
@ -149,6 +152,14 @@ protected:
// Standoff overrides base AI crouch handling
bool IsCrouching( void ) { return false; }
#ifdef MAPBASE
// Standoff overrides base cover activity translation
bool CanTranslateCrouchActivity( void ) { return false; }
// Don't do death poses while crouching
bool ShouldPickADeathPose( void ) { return (GetPosture() != AIP_CROUCHING && GetPosture() != AIP_PEEKING) && BaseClass::ShouldPickADeathPose(); }
#endif
private:

View File

@ -1640,10 +1640,17 @@ void CAI_BlendedMotor::MaintainTurnActivity( void )
ConVar scene_flatturn( "scene_flatturn", "1" );
#ifdef MAPBASE
ConVar ai_turning_enabled( "ai_turning_enabled", "1", FCVAR_NONE, "Enables NPC turning, which was previously disabled by Valve at some point after 2004 due to a now-unknown major issue." );
#endif
bool CAI_BlendedMotor::AddTurnGesture( float flYD )
{
// some funky bug with human turn gestures, disable for now
#ifdef MAPBASE
if (!ai_turning_enabled.GetBool())
#endif
return false;
// try using a turn gesture

View File

@ -0,0 +1,509 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "ai_speech.h"
#include "game.h"
#include "eventqueue.h"
#include "ai_basenpc.h"
#include "basemultiplayerplayer.h"
#include "ai_baseactor.h"
#include "sceneentity.h"
//#include "flex_expresser.h"
/*
#include "engine/ienginesound.h"
#include "keyvalues.h"
#include "ai_criteria.h"
#include "isaverestore.h"
#include "sceneentity.h"
*/
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
static const char *GetResponseName( CBaseEntity *pEnt )
{
Assert( pEnt );
if ( pEnt == NULL )
return "";
return STRING( pEnt->GetEntityName() );
}
// This is a tiny helper function for below -- what I'd use a lambda for, usually
static void DispatchComeback( CAI_ExpresserWithFollowup *pExpress, CBaseEntity *pSpeaker, CBaseEntity *pRespondent, AI_ResponseFollowup &followup )
{
AssertMsg(pSpeaker != NULL, "Response expressor somehow got called with a NULL Outer.\n");
if ( !pRespondent )
{
return;
}
float delay = followup.followup_delay;
if (pSpeaker == pRespondent && delay < 0)
{
Warning("Response rule with a 'self' target specified negative delay, which isn't legal because that would make someone talk over himself.");
delay = 0;
}
// Msg( "%s: Dispatch comeback about %s to %s\n", pSpeaker->GetBotString(), g_pConceptManager->GetTopicName( handle ), pRespondent->GetBotString() );
// build an input event that we will use to force the bot to talk through the IO system
variant_t value;
// Don't send along null contexts
if (followup.followup_contexts && followup.followup_contexts[0] != '\0')
{
value.SetString( MAKE_STRING( followup.followup_contexts ) );
g_EventQueue.AddEvent( pRespondent, "AddContext", value, delay - 0.01, pSpeaker, pSpeaker );
}
/*
value.SetString(MAKE_STRING(followup.followup_concept));
g_EventQueue.AddEvent( pRespondent, "SpeakResponseConcept", value, delay , pSpeaker, pSpeaker );
*/
AI_CriteriaSet criteria;
// add in the FROM context so dispatchee knows was from me
const char * RESTRICT pszSpeakerName = GetResponseName( pSpeaker );
criteria.AppendCriteria( "From", pszSpeakerName );
#ifdef MAPBASE
// See DispatchFollowupThroughQueue()
criteria.AppendCriteria( "From_idx", CNumStr( pSpeaker->entindex() ) );
criteria.AppendCriteria( "From_class", pSpeaker->GetClassname() );
#endif
// if a SUBJECT criteria is missing, put it back in.
if ( criteria.FindCriterionIndex( "Subject" ) == -1 )
{
criteria.AppendCriteria( "Subject", pszSpeakerName );
}
// add in any provided contexts from the parameters onto the ones stored in the followup
criteria.Merge( followup.followup_contexts );
// This is kludgy and needs to be fixed in class hierarchy, but for now, try to guess at the most likely
// kinds of targets and dispatch to them.
if (CBaseMultiplayerPlayer *pPlayer = dynamic_cast<CBaseMultiplayerPlayer *>(pRespondent))
{
pPlayer->Speak( followup.followup_concept, &criteria );
}
else if (CAI_BaseActor *pActor = dynamic_cast<CAI_BaseActor *>(pRespondent))
{
pActor->Speak( followup.followup_concept, &criteria );
}
}
#if 0
//-----------------------------------------------------------------------------
// Purpose: Placeholder for rules based response system
// Input : concept -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CAI_ExpresserWithFollowup::Speak( AIConcept_t &concept, const char *modifiers /*= NULL*/, char *pszOutResponseChosen /* = NULL*/, size_t bufsize /* = 0 */, IRecipientFilter *filter /* = NULL */ )
{
AI_Response *result = SpeakFindResponse( concept, modifiers );
if ( !result )
{
return false;
}
CNPC_CompanionBot *pBot = dynamic_cast<CNPC_CompanionBot *>(GetOuter());
if ( pBot )
{
pBot->SetConversationTopic( g_pConceptManager->GetTopic( handle ) );
pBot->SetLastSpeaker( g_pConceptManager->GetSpeaker( handle ) );
// Msg( "%s: Conversing about %s\n", pBot->GetBotString(), g_pConceptManager->GetTopicName( handle ) );
}
SpeechMsg( GetOuter(), "%s (%x) spoke %s (%f)\n", STRING(GetOuter()->GetEntityName()), GetOuter(), g_pConceptManager->GetConcept( handle ), gpGlobals->curtime );
bool spoke = SpeakDispatchResponse( handle, result, filter );
if ( pszOutResponseChosen )
{
result->GetResponse( pszOutResponseChosen, bufsize );
}
return spoke;
}
#endif
// Work out the character from the "subject" context.
// Right now, this is a simple find by entity name search.
// But you can define arbitrary subject names, like L4D does
// for "biker", "manager", etc.
static CBaseEntity *AscertainSpeechSubjectFromContext( AI_Response *response, AI_CriteriaSet &criteria, const char *pContextName )
{
const char *subject = criteria.GetValue( criteria.FindCriterionIndex( pContextName ) );
if (subject)
{
CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, subject );
#ifdef MAPBASE
// Allow entity indices to be used (see DispatchFollowupThroughQueue() for one particular use case)
if (!pEnt && atoi(subject))
{
pEnt = CBaseEntity::Instance( atoi( subject ) );
}
#endif
return pEnt;
}
else
{
return NULL;
}
}
// TODO: Currently uses awful stricmp. Use symbols! Once I know which ones we want, that is.
static CResponseQueue::CFollowupTargetSpec_t ResolveFollowupTargetToEntity( AIConcept_t &concept, AI_CriteriaSet &criteria, const char * RESTRICT szTarget, AI_Response * RESTRICT response = NULL )
{
if ( Q_stricmp(szTarget, "self") == 0 )
{
return CResponseQueue::CFollowupTargetSpec_t( kDRT_SPECIFIC, concept.GetSpeaker() );
}
else if ( Q_stricmp(szTarget, "subject") == 0 )
{
return CResponseQueue::CFollowupTargetSpec_t( AscertainSpeechSubjectFromContext( response, criteria, "Subject" ) );
}
else if ( Q_stricmp(szTarget, "from") == 0 )
{
#ifdef MAPBASE
// See DispatchFollowupThroughQueue()
return CResponseQueue::CFollowupTargetSpec_t( AscertainSpeechSubjectFromContext( response, criteria, "From_idx" ) );
#else
return CResponseQueue::CFollowupTargetSpec_t( AscertainSpeechSubjectFromContext( response, criteria, "From" ) );
#endif
}
else if ( Q_stricmp(szTarget, "any") == 0 )
{
return CResponseQueue::CFollowupTargetSpec_t( kDRT_ANY, concept.GetSpeaker() );
}
else if ( Q_stricmp(szTarget, "all") == 0 )
{
return CResponseQueue::CFollowupTargetSpec_t( kDRT_ALL );
}
// last resort, try a named lookup
#ifdef MAPBASE
else if ( CBaseEntity *pSpecific = gEntList.FindEntityByName(NULL, szTarget, concept.GetSpeaker()) ) // it could be anything
#else
else if ( CBaseEntity *pSpecific = gEntList.FindEntityByName(NULL, szTarget) ) // it could be anything
#endif
{
return CResponseQueue::CFollowupTargetSpec_t( pSpecific );
}
Warning("Couldn't resolve response target %s\n", szTarget );
return CResponseQueue::CFollowupTargetSpec_t(); // couldn't resolve.
}
// TODO: Currently uses awful stricmp. Use symbols! Once I know which ones we want, that is.
static CResponseQueue::CFollowupTargetSpec_t ResolveFollowupTargetToEntity( AIConcept_t &concept, AI_CriteriaSet &criteria, AI_Response * RESTRICT response, AI_ResponseFollowup * RESTRICT followup )
{
const char * RESTRICT szTarget = followup->followup_target;
const CResponseQueue::CFollowupTargetSpec_t INVALID; // default: invalid result
if ( szTarget == NULL )
return INVALID;
else
return ResolveFollowupTargetToEntity( concept, criteria, szTarget, response );
}
ConVar chet_debug_idle( "chet_debug_idle", "0", FCVAR_ARCHIVE, "If set one, many debug prints to help track down the TLK_IDLE issue. Set two for super verbose info" );
// extern ConVar chet_debug_idle;
bool CAI_ExpresserWithFollowup::Speak( AIConcept_t concept, const char *modifiers /*= NULL*/, char *pszOutResponseChosen /* = NULL*/, size_t bufsize /* = 0 */, IRecipientFilter *filter /* = NULL */ )
{
VPROF("CAI_Expresser::Speak");
if ( IsSpeechGloballySuppressed() )
{
return false;
}
concept.SetSpeaker(GetOuter());
AI_CriteriaSet criteria;
GatherCriteria(&criteria, concept, modifiers);
GetOuter()->ModifyOrAppendDerivedCriteria(criteria);
AI_Response result;
if ( !FindResponse( result, concept, &criteria ) )
{
if (chet_debug_idle.GetBool())
{
const char *name = GetOuter()->GetDebugName();
Msg( "TLK_IDLE: %s did not FindResponse\n", name );
}
return false;
}
else
{
if (chet_debug_idle.GetBool())
{
const char *name = GetOuter()->GetDebugName();
Msg( "TLK_IDLE: %s SUCCESSFUL FindResponse\n", name );
}
}
SpeechMsg( GetOuter(), "%s (%p) spoke %s (%f)", STRING(GetOuter()->GetEntityName()), GetOuter(), (const char*)concept, gpGlobals->curtime );
// Msg( "%s:%s to %s:%s\n", GetOuter()->GetDebugName(), concept.GetStringConcept(), criteria.GetValue(criteria.FindCriterionIndex("Subject")), pTarget ? pTarget->GetDebugName() : "none" );
bool spoke = SpeakDispatchResponse( concept, &result, &criteria, filter );
if ( pszOutResponseChosen )
{
result.GetResponse( pszOutResponseChosen, bufsize );
}
return spoke;
}
extern ISoundEmitterSystemBase* soundemitterbase;
static float GetSpeechDurationForResponse( const AI_Response * RESTRICT response, const char *szActorModel)
{
switch (response->GetType())
{
case ResponseRules::RESPONSE_SCENE:
{
char szScene[MAX_PATH];
soundemitterbase->GenderExpandString(szActorModel, response->GetResponsePtr(), szScene, MAX_PATH);
return GetSceneSpeechDuration(szScene);
}
break;
default:
break;
}
return 0.f;
}
//-----------------------------------------------------------------------------
// Purpose: Dispatches the result
// Input : *response -
//-----------------------------------------------------------------------------
bool CAI_ExpresserWithFollowup::SpeakDispatchResponse( AIConcept_t concept, AI_Response *response, AI_CriteriaSet *criteria, IRecipientFilter *filter )
{
// This gives the chance for the other bot to respond.
if ( !concept.GetSpeaker().IsValid() )
{
concept.SetSpeaker(GetOuter());
}
bool bInterrupted = IsSpeaking();
bool bSuc = CAI_Expresser::SpeakDispatchResponse( concept, response, criteria, filter );
if (!bSuc)
{
return false;
}
if ( bInterrupted )
{
g_ResponseQueueManager.GetQueue()->RemoveSpeechQueuedFor( GetOuter() );
}
// Record my followup details so that I may defer its use til end of the speech
AI_ResponseFollowup * RESTRICT followup = response->GetParams()->m_pFollowup;
if ( followup )
{
if ( followup->followup_entityiotarget && followup->followup_entityioinput )
{
#ifdef MAPBASE
CBaseEntity * RESTRICT pTarget = ResolveFollowupTargetToEntity( concept, *criteria, followup->followup_entityiotarget, response ).m_hHandle;
#else
CBaseEntity * RESTRICT pTarget = gEntList.FindEntityByName( NULL, followup->followup_entityiotarget );
#endif
if ( pTarget )
{
g_EventQueue.AddEvent( pTarget, followup->followup_entityioinput, variant_t(), followup->followup_entityiodelay, GetOuter(), GetOuter() );
}
}
if ( followup->IsValid() )
{
// 11th hour change: rather than trigger followups from the end of a VCD,
// instead fire it from the end of the last speech event in the VCD, because
// there's a multisecond facial relax delay built into the scene.
// The speech length is stored in the cache, so we can post the followup now.
if ( response->GetType() == ResponseRules::RESPONSE_SCENE &&
followup->followup_delay >= 0 )
{
float fTimeToLastSpeech = GetSpeechDurationForResponse( response, STRING(GetOuter()->GetModelName()) );
// failsafe
if ( fTimeToLastSpeech > 0 )
{
DispatchFollowupThroughQueue( followup->followup_concept, followup->followup_contexts,
ResolveFollowupTargetToEntity( concept, *criteria, response, followup ),
fTimeToLastSpeech + followup->followup_delay, GetOuter() );
}
else // error
{
// old way, copied from "else" below
m_pPostponedFollowup = followup;
if ( criteria )
m_followupTarget = ResolveFollowupTargetToEntity( concept, *criteria, response, m_pPostponedFollowup );
else
{
AI_CriteriaSet tmpCriteria;
m_followupTarget = ResolveFollowupTargetToEntity( concept, tmpCriteria, response, m_pPostponedFollowup );
}
}
}
else if ( followup->followup_delay < 0 )
{
// a negative delay has a special meaning. Usually the comeback dispatches after
// the currently said line is finished; the delay is added to that, to provide a
// pause between when character A finishes speaking and B begins.
// A negative delay (-n) actually means "dispatch the comeback n seconds
// after I start talking".
// In this case we do not need to postpone the followup; we just throw it directly
// into the queue.
DispatchFollowupThroughQueue( followup->followup_concept, followup->followup_contexts,
ResolveFollowupTargetToEntity( concept, *criteria, response, followup ),
-followup->followup_delay, GetOuter() );
}
#ifndef MAPBASE // RESPONSE_PRINT now notes speaking time
else if ( response->GetType() == ResponseRules::RESPONSE_PRINT )
{ // zero-duration responses dispatch immediately via the queue (must be the queue bec.
// the m_pPostponedFollowup will never trigger)
DispatchFollowupThroughQueue( followup->followup_concept, followup->followup_contexts,
ResolveFollowupTargetToEntity( concept, *criteria, response, followup ),
followup->followup_delay, GetOuter() );
}
#endif
else
{
// this is kind of a quick patch to immediately deal with the issue of null criteria
// (arose while branching to main) without replumbing a bunch of stuff -- to be fixed
// 5.13.08 egr
m_pPostponedFollowup = followup;
if ( criteria )
m_followupTarget = ResolveFollowupTargetToEntity( concept, *criteria, response, m_pPostponedFollowup );
else
{
AI_CriteriaSet tmpCriteria;
m_followupTarget = ResolveFollowupTargetToEntity( concept, tmpCriteria, response, m_pPostponedFollowup );
}
}
}
}
return bSuc;
}
// This is a gimmick used when a negative delay is specified in a followup, which is a shorthand
// for "this many seconds after the beginning of the line" rather than "this may seconds after the end
// of the line", eg to create a THEN rule when two characters talk over each other.
// It's static to avoid accidental use of the postponed followup/target members.
void CAI_ExpresserWithFollowup::DispatchFollowupThroughQueue( const AIConcept_t &concept,
const char * RESTRICT criteriaStr,
const CResponseQueue::CFollowupTargetSpec_t &target,
float delay,
CBaseEntity * RESTRICT pOuter
)
{
AI_CriteriaSet criteria;
// Don't add my own criteria! GatherCriteria( &criteria, followup.followup_concept, followup.followup_contexts );
criteria.AppendCriteria( "From", STRING( pOuter->GetEntityName() ) );
#ifdef MAPBASE
// The index of the "From" entity.
// In HL2 mods, many followup users would be generic NPCs (e.g. citizens) who might not have any particular significance.
// Those generic NPCs are quite likely to have no name or have a name in common with other entities. As a result, Mapbase
// changes internal operations of the "From" context to search for an entity index. This won't be 100% reliable if the source
// talker dies and another entity is created immediately afterwards, but it's a lot more reliable than a simple entity name search.
criteria.AppendCriteria( "From_idx", CNumStr( pOuter->entindex() ) );
// Generic NPCs should also be attributable by classname
criteria.AppendCriteria( "From_class", pOuter->GetClassname() );
#endif
criteria.Merge( criteriaStr );
g_ResponseQueueManager.GetQueue()->Add( concept, &criteria, gpGlobals->curtime + delay, target, pOuter );
}
//-----------------------------------------------------------------------------
// Purpose: Handles the new concept objects
//-----------------------------------------------------------------------------
void CAI_ExpresserWithFollowup::SpeakDispatchFollowup( AI_ResponseFollowup &followup )
{
if ( !m_followupTarget.IsValid() )
return;
// If a specific entity target is given, use the old pathway for now
if ( m_followupTarget.m_iTargetType == kDRT_SPECIFIC && followup.followup_delay == 0 )
{
CBaseEntity *pTarget = m_followupTarget.m_hHandle.Get();
if (!pTarget)
{
return;
}
DispatchComeback( this, GetOuter(), pTarget, followup );
}
else
{
DispatchFollowupThroughQueue( followup.followup_concept, followup.followup_contexts, m_followupTarget, followup.followup_delay, GetOuter() );
}
// clear out the followup member just in case.
m_pPostponedFollowup = NULL;
m_followupTarget.m_iTargetType = kDRT_MAX;
}
void CAI_ExpresserWithFollowup::OnSpeechFinished()
{
if (m_pPostponedFollowup && m_pPostponedFollowup->IsValid())
{
#ifdef MAPBASE
// HACKHACK: Non-scene speech (e.g. noscene speak/sentence) fire OnSpeechFinished() immediately,
// so add the actual speech time to the followup delay
if (GetTimeSpeechCompleteWithoutDelay() > gpGlobals->curtime)
m_pPostponedFollowup->followup_delay += GetTimeSpeechCompleteWithoutDelay() - gpGlobals->curtime;
#endif
return SpeakDispatchFollowup(*m_pPostponedFollowup);
}
}
void CC_RR_ForceConcept_f( const CCommand &args )
{
if ( args.ArgC() < 3 )
{
Msg("USAGE: rr_forceconcept <target> <concept> \"criteria1:value1,criteria2:value2,...\"\n");
return;
}
AI_CriteriaSet criteria;
if ( args.ArgC() >= 3 )
{
const char *criteriastring = args[3];
criteria.Merge( criteriastring );
}
AIConcept_t concept( args[2] );
QueueSpeak( concept, ResolveFollowupTargetToEntity( concept, criteria, args[1] ), criteria );
}
static ConCommand rr_forceconcept( "rr_forceconcept", CC_RR_ForceConcept_f,
"fire a response concept directly at a given character.\n"
"USAGE: rr_forceconcept <target> <concept> \"criteria1:value1,criteria2:value2,...\"\n"
"criteria values are optional.\n"
, FCVAR_CHEAT );

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