mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-03-03 17:25:27 +03:00
Merge branch 'develop' into mapbase/feature/protagonist-system
This commit is contained in:
commit
940745c7fd
7
.gitignore
vendored
7
.gitignore
vendored
@ -19,6 +19,8 @@ ipch
|
||||
*.idb
|
||||
*.vcxproj
|
||||
*.sln
|
||||
*.vcxproj.FileListAbsolute.txt
|
||||
*.pdb
|
||||
|
||||
# OSX/Linux build products
|
||||
*.mak
|
||||
@ -49,6 +51,8 @@ client.dylib.dSYM/
|
||||
server.dylib
|
||||
server.dylib.dSYM/
|
||||
|
||||
sp/game/bin
|
||||
|
||||
# files generated by running a mod
|
||||
config.cfg
|
||||
|
||||
@ -61,6 +65,7 @@ config.cfg
|
||||
*.filters
|
||||
*.vpc_crc
|
||||
*.sentinel
|
||||
*.recipe
|
||||
|
||||
# Backup files
|
||||
*.bak
|
||||
@ -90,4 +95,4 @@ sp/src/vgui2/*.dll
|
||||
sp/src/vgui2/*.pdb
|
||||
|
||||
# Build support files
|
||||
sp/src/devtools/gcc9+support.o
|
||||
sp/src/devtools/gcc9+support.o
|
@ -1531,35 +1531,32 @@ float C_BaseAnimating::ClampCycle( float flCycle, bool isLooping )
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vector& C_BaseAnimating::ScriptGetAttachmentOrigin( int iAttachment )
|
||||
{
|
||||
|
||||
static Vector absOrigin;
|
||||
static QAngle qa;
|
||||
QAngle qa;
|
||||
|
||||
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
|
||||
|
||||
return absOrigin;
|
||||
}
|
||||
|
||||
const Vector& C_BaseAnimating::ScriptGetAttachmentAngles( int iAttachment )
|
||||
const QAngle& C_BaseAnimating::ScriptGetAttachmentAngles( int iAttachment )
|
||||
{
|
||||
|
||||
static Vector absOrigin;
|
||||
static Vector absAngles;
|
||||
static QAngle qa;
|
||||
Vector absOrigin;
|
||||
|
||||
C_BaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
|
||||
absAngles.x = qa.x;
|
||||
absAngles.y = qa.y;
|
||||
absAngles.z = qa.z;
|
||||
return absAngles;
|
||||
return qa;
|
||||
}
|
||||
|
||||
HSCRIPT C_BaseAnimating::ScriptGetAttachmentMatrix( int iAttachment )
|
||||
HSCRIPT_RC C_BaseAnimating::ScriptGetAttachmentMatrix( int iAttachment )
|
||||
{
|
||||
static matrix3x4_t matrix;
|
||||
matrix3x4_t *matrix = new matrix3x4_t;
|
||||
|
||||
C_BaseAnimating::GetAttachment( iAttachment, matrix );
|
||||
return g_pScriptVM->RegisterInstance( &matrix );
|
||||
if ( C_BaseAnimating::GetAttachment( iAttachment, *matrix ) )
|
||||
return g_pScriptVM->RegisterInstance( matrix, true );
|
||||
|
||||
delete matrix;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void C_BaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform )
|
||||
|
@ -464,8 +464,8 @@ public:
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
int ScriptLookupAttachment( const char *pAttachmentName ) { return LookupAttachment( pAttachmentName ); }
|
||||
const Vector& ScriptGetAttachmentOrigin(int iAttachment);
|
||||
const Vector& ScriptGetAttachmentAngles(int iAttachment);
|
||||
HSCRIPT ScriptGetAttachmentMatrix(int iAttachment);
|
||||
const QAngle& ScriptGetAttachmentAngles(int iAttachment);
|
||||
HSCRIPT_RC ScriptGetAttachmentMatrix(int iAttachment);
|
||||
|
||||
void ScriptGetBoneTransform( int iBone, HSCRIPT hTransform );
|
||||
void ScriptSetBoneTransform( int iBone, HSCRIPT hTransform );
|
||||
|
@ -90,11 +90,10 @@ static inline bool ShouldDrawLocalPlayerViewModel( void )
|
||||
C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer();
|
||||
if (localplayer)
|
||||
{
|
||||
if (localplayer->m_bDrawPlayerModelExternally)
|
||||
if (localplayer->DrawingPlayerModelExternally() && localplayer->InFirstPersonView())
|
||||
{
|
||||
// If this isn't the main view, draw the weapon.
|
||||
view_id_t viewID = CurrentViewID();
|
||||
if (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)
|
||||
if (!localplayer->InPerspectiveView())
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -224,8 +223,16 @@ ShadowType_t C_BaseCombatWeapon::ShadowCastType()
|
||||
if (!IsBeingCarried())
|
||||
return SHADOWS_RENDER_TO_TEXTURE;
|
||||
|
||||
if (IsCarriedByLocalPlayer() && !C_BasePlayer::ShouldDrawLocalPlayer())
|
||||
return SHADOWS_NONE;
|
||||
if (IsCarriedByLocalPlayer())
|
||||
{
|
||||
if (!C_BasePlayer::ShouldDrawLocalPlayer())
|
||||
return SHADOWS_NONE;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (C_BasePlayer::GetLocalPlayer() && C_BasePlayer::GetLocalPlayer()->ShadowCastType() == SHADOWS_NONE)
|
||||
return SHADOWS_NONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
return SHADOWS_RENDER_TO_TEXTURE;
|
||||
}
|
||||
@ -458,7 +465,7 @@ bool C_BaseCombatWeapon::ShouldDraw( void )
|
||||
|
||||
#ifdef MAPBASE
|
||||
// We're drawing this in non-main views, handle it in DrawModel()
|
||||
if ( pLocalPlayer->m_bDrawPlayerModelExternally )
|
||||
if ( pLocalPlayer->DrawingPlayerModelExternally() )
|
||||
return true;
|
||||
#endif
|
||||
|
||||
@ -511,11 +518,10 @@ int C_BaseCombatWeapon::DrawModel( int flags )
|
||||
if ( localplayer )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (localplayer->m_bDrawPlayerModelExternally)
|
||||
if (GetOwner() == localplayer && localplayer->DrawingPlayerModelExternally())
|
||||
{
|
||||
// If this isn't the main view, draw the weapon.
|
||||
view_id_t viewID = CurrentViewID();
|
||||
if ( (!localplayer->InFirstPersonView() || (viewID != VIEW_MAIN && viewID != VIEW_INTRO_CAMERA)) && (viewID != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)) )
|
||||
if ( (!localplayer->InPerspectiveView() || !localplayer->InFirstPersonView()) && (CurrentViewID() != VIEW_SHADOW_DEPTH_TEXTURE || !localplayer->IsEffectActive(EF_DIMLIGHT)))
|
||||
{
|
||||
// TODO: Is this inefficient?
|
||||
int nModelIndex = GetModelIndex();
|
||||
@ -534,6 +540,10 @@ int C_BaseCombatWeapon::DrawModel( int flags )
|
||||
|
||||
return iDraw;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ( localplayer->IsObserver() && GetOwner() )
|
||||
@ -551,6 +561,24 @@ int C_BaseCombatWeapon::DrawModel( int flags )
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool C_BaseCombatWeapon::DispatchMuzzleEffect( const char *options, bool isFirstPerson )
|
||||
{
|
||||
// Don't show muzzle flashes in first-person
|
||||
C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||||
if (pPlayer)
|
||||
{
|
||||
if (pPlayer->DrawingPlayerModelExternally() && pPlayer->InFirstPersonView())
|
||||
return false;
|
||||
}
|
||||
|
||||
return BaseClass::DispatchMuzzleEffect( options, isFirstPerson );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allows the client-side entity to override what the network tells it to use for
|
||||
|
@ -433,8 +433,7 @@ 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 )
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( C_BaseEntity, "Root class of all client-side entities", &g_BaseEntityScriptInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetForward, "GetForwardVector", "Get the forward vector of the entity" )
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
|
@ -125,6 +125,16 @@ ConVar demo_fov_override( "demo_fov_override", "0", FCVAR_CLIENTDLL | FCVAR_DONT
|
||||
// This value is found by hand, and a good value depends more on the in-game models than on actual human shapes.
|
||||
ConVar cl_meathook_neck_pivot_ingame_up( "cl_meathook_neck_pivot_ingame_up", "7.0" );
|
||||
ConVar cl_meathook_neck_pivot_ingame_fwd( "cl_meathook_neck_pivot_ingame_fwd", "3.0" );
|
||||
#ifdef MAPBASE
|
||||
ConVar cl_meathook_neck_pivot_override( "cl_meathook_neck_pivot_override", "0", FCVAR_NONE, "Overrides playermodel values for meathook and uses cvars only" );
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
||||
ConVar cl_playermodel_draw_externally_override( "cl_playermodel_draw_externally_override", "-1", FCVAR_ARCHIVE, "Overrides developer-placed options to draw the player's model externally." );
|
||||
|
||||
ConVar cl_playermodel_legs_override( "cl_playermodel_legs_override", "-1", FCVAR_ARCHIVE, "Overrides developer-placed options to draw the player's model below the camera." );
|
||||
ConVar cl_playermodel_legs_scale_bones( "cl_playermodel_legs_scale_bones", "1" );
|
||||
#endif
|
||||
|
||||
void RecvProxy_LocalVelocityX( const CRecvProxyData *pData, void *pStruct, void *pOut );
|
||||
void RecvProxy_LocalVelocityY( const CRecvProxyData *pData, void *pStruct, void *pOut );
|
||||
@ -280,6 +290,7 @@ END_RECV_TABLE()
|
||||
// See baseplayer_shared.h for more details.
|
||||
RecvPropInt ( RECVINFO( m_spawnflags ), 0, RecvProxy_ShiftPlayerSpawnflags ),
|
||||
|
||||
RecvPropBool ( RECVINFO( m_bDrawPlayerLegs ) ),
|
||||
RecvPropBool ( RECVINFO( m_bDrawPlayerModelExternally ) ),
|
||||
RecvPropBool ( RECVINFO( m_bInTriggerFall ) ),
|
||||
#endif
|
||||
@ -1486,13 +1497,186 @@ bool C_BasePlayer::ShouldInterpolate()
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool C_BasePlayer::InPerspectiveView() const
|
||||
{
|
||||
// VIEW_NONE is used by the water intersection view, see CAboveWaterView::CIntersectionView::Draw()
|
||||
// (TODO: Consider changing the view ID at the source to VIEW_REFRACTION? VIEW_NONE could be an oversight)
|
||||
view_id_t viewID = CurrentViewID();
|
||||
return (viewID == VIEW_MAIN || viewID == VIEW_INTRO_CAMERA || viewID == VIEW_REFRACTION || viewID == VIEW_NONE);
|
||||
}
|
||||
|
||||
bool C_BasePlayer::DrawingPlayerModelExternally() const
|
||||
{
|
||||
if (cl_playermodel_draw_externally_override.GetInt() > -1)
|
||||
return cl_playermodel_draw_externally_override.GetBool();
|
||||
|
||||
return m_bDrawPlayerModelExternally;
|
||||
}
|
||||
|
||||
bool C_BasePlayer::DrawingLegs() const
|
||||
{
|
||||
if (cl_playermodel_legs_override.GetInt() > -1)
|
||||
return cl_playermodel_legs_override.GetBool();
|
||||
|
||||
// For now, don't draw legs if looking up in any way
|
||||
// (fixes issues with some animations causing clipping with chest)
|
||||
if (GetAbsAngles().x < 0.0f)
|
||||
return false;
|
||||
|
||||
return m_bDrawPlayerLegs;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CStudioHdr *C_BasePlayer::OnNewModel( void )
|
||||
{
|
||||
CStudioHdr *hdr = BaseClass::OnNewModel();
|
||||
if (!hdr)
|
||||
return NULL;
|
||||
|
||||
KeyValues *modelKeyValues = new KeyValues( "" );
|
||||
CUtlBuffer buf( 1024, 0, CUtlBuffer::TEXT_BUFFER );
|
||||
|
||||
// Init values
|
||||
m_FirstPersonModelData.Reset();
|
||||
|
||||
if (!modelinfo->GetModelKeyValue( GetModel(), buf ))
|
||||
{
|
||||
modelKeyValues->deleteThis();
|
||||
return hdr;
|
||||
}
|
||||
|
||||
if (modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), buf ))
|
||||
{
|
||||
CUtlVector<string_t> iszUsedNames;
|
||||
for (KeyValues *pkvModelBlock = modelKeyValues; pkvModelBlock != nullptr; pkvModelBlock = pkvModelBlock->GetNextKey())
|
||||
{
|
||||
KeyValues *pkvPlayerModelData = pkvModelBlock->FindKey( "playermodel_data" );
|
||||
if (pkvPlayerModelData)
|
||||
{
|
||||
m_FirstPersonModelData.ParseModelData( this, pkvPlayerModelData );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modelKeyValues->deleteThis();
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BasePlayer::FirstPersonModelData_t::ParseModelData( C_BasePlayer *pPlayer, KeyValues *pkvPlayerModelData )
|
||||
{
|
||||
m_flFirstPersonNeckPivotUp = pkvPlayerModelData->GetFloat( "neck_pivot_up", FLT_MAX );
|
||||
m_flFirstPersonNeckPivotFwd = pkvPlayerModelData->GetFloat( "neck_pivot_fwd", FLT_MAX );
|
||||
|
||||
m_flFirstPersonNeckPivotDuckUp = pkvPlayerModelData->GetFloat( "neck_pivot_duck_up", FLT_MAX );
|
||||
m_flFirstPersonNeckPivotDuckFwd = pkvPlayerModelData->GetFloat( "neck_pivot_duck_fwd", FLT_MAX );
|
||||
|
||||
KeyValues *pkvBoneScales = pkvPlayerModelData->FindKey( "bone_transforms" );
|
||||
if (pkvBoneScales)
|
||||
{
|
||||
KeyValues *pkvSpineTransforms = pkvBoneScales->FindKey( "spine" );
|
||||
if (pkvSpineTransforms)
|
||||
{
|
||||
for (KeyValues *pkvBone = pkvSpineTransforms->GetFirstSubKey(); pkvBone != nullptr; pkvBone = pkvBone->GetNextKey())
|
||||
{
|
||||
int nBone = pPlayer->LookupBone( pkvBone->GetName() );
|
||||
if (nBone == -1)
|
||||
continue;
|
||||
|
||||
m_FirstPersonBoneScales[BoneScales_Spine].Insert(nBone, pkvBone->GetFloat());
|
||||
}
|
||||
}
|
||||
|
||||
KeyValues *pkvArmsTransforms = pkvBoneScales->FindKey( "arms" );
|
||||
if (pkvArmsTransforms)
|
||||
{
|
||||
for (KeyValues *pkvBone = pkvArmsTransforms->GetFirstSubKey(); pkvBone != nullptr; pkvBone = pkvBone->GetNextKey())
|
||||
{
|
||||
int nBone = pPlayer->LookupBone( pkvBone->GetName() );
|
||||
if (nBone == -1)
|
||||
continue;
|
||||
|
||||
m_FirstPersonBoneScales[BoneScales_Arms].Insert( nBone, pkvBone->GetFloat() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: move position and rotation transforms into global matrices
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BasePlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion *q, const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed )
|
||||
{
|
||||
BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed );
|
||||
|
||||
if (DrawingLegs() && InPerspectiveView() && InFirstPersonView())
|
||||
{
|
||||
//BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" );
|
||||
|
||||
if (cl_playermodel_legs_scale_bones.GetBool())
|
||||
{
|
||||
// For now, only do transforms when we have an active weapon
|
||||
// (since we typically just cull stuff influenced by viewmodels and upper-body weapon posture, like arms)
|
||||
if ((GetActiveWeapon() && !GetActiveWeapon()->IsEffectActive( EF_NODRAW )) || GetUseEntity())
|
||||
{
|
||||
matrix3x4_t *pFirstZero = NULL;
|
||||
|
||||
for (int nMap = 0; nMap < FirstPersonModelData_t::BoneScales_Max; nMap++)
|
||||
{
|
||||
const CUtlMap<int, float> &scaleMap = m_FirstPersonModelData.m_FirstPersonBoneScales[nMap];
|
||||
FOR_EACH_MAP( scaleMap, i )
|
||||
{
|
||||
int nBone = scaleMap.Key(i);
|
||||
if (nBone == -1)
|
||||
continue;
|
||||
|
||||
if (!(hdr->boneFlags( nBone ) & boneMask))
|
||||
continue;
|
||||
|
||||
float flScale = scaleMap.Element(i);
|
||||
|
||||
matrix3x4_t &mTransform = GetBoneForWrite( nBone );
|
||||
|
||||
if (flScale == 0.0f)
|
||||
{
|
||||
if (!pFirstZero)
|
||||
{
|
||||
MatrixScaleByZero( mTransform );
|
||||
pFirstZero = &mTransform;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep zeroes in one place
|
||||
MatrixCopy( *pFirstZero, mTransform );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MatrixScaleBy( flScale, mTransform );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool C_BasePlayer::ShouldDraw()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
// We have to "always draw" a player with m_bDrawPlayerModelExternally in order to show up in whatever rendering list all of the views use,
|
||||
// but we can't put this in ShouldDrawThisPlayer() because we would have no way of knowing if it stomps the other checks that draw the player model anyway.
|
||||
// As a result, we have to put it here in the central ShouldDraw() function. DrawModel() makes sure we only draw in non-main views and nothing's drawing the model anyway.
|
||||
return (ShouldDrawThisPlayer() || m_bDrawPlayerModelExternally) && BaseClass::ShouldDraw();
|
||||
return (ShouldDrawThisPlayer() || DrawingPlayerModelExternally() || DrawingLegs()) && BaseClass::ShouldDraw();
|
||||
#else
|
||||
return ShouldDrawThisPlayer() && BaseClass::ShouldDraw();
|
||||
#endif
|
||||
@ -1501,12 +1685,16 @@ bool C_BasePlayer::ShouldDraw()
|
||||
int C_BasePlayer::DrawModel( int flags )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (m_bDrawPlayerModelExternally)
|
||||
if (DrawingLegs() && InFirstPersonView() && InPerspectiveView())
|
||||
{
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
if (DrawingPlayerModelExternally())
|
||||
{
|
||||
// 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 || (viewID == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT)))
|
||||
if (InPerspectiveView() || (CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE && IsEffectActive(EF_DIMLIGHT)))
|
||||
{
|
||||
// Make sure the player model wouldn't draw anyway...
|
||||
if (!ShouldDrawThisPlayer())
|
||||
@ -3057,13 +3245,21 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !InPerspectiveView() )
|
||||
#else
|
||||
if ( !DrawingMainView() )
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If we aren't drawing the player anyway, don't mess with the bones. This can happen in Portal.
|
||||
#ifdef MAPBASE
|
||||
if ( !ShouldDrawThisPlayer() && !DrawingPlayerModelExternally() && !DrawingLegs() )
|
||||
#else
|
||||
if( !ShouldDrawThisPlayer() )
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -3084,6 +3280,63 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
Vector vHeadTransformTranslation ( mHeadTransform[0][3], mHeadTransform[1][3], mHeadTransform[2][3] );
|
||||
|
||||
|
||||
float flNeckPivotUp = cl_meathook_neck_pivot_ingame_up.GetFloat();
|
||||
float flNeckPivotFwd = cl_meathook_neck_pivot_ingame_fwd.GetFloat();
|
||||
#ifdef MAPBASE
|
||||
if (DrawingLegs() && !cl_meathook_neck_pivot_override.GetBool())
|
||||
{
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotUp != FLT_MAX || m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd != FLT_MAX)
|
||||
{
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotUp != FLT_MAX)
|
||||
flNeckPivotUp = m_FirstPersonModelData.m_flFirstPersonNeckPivotUp;
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd != FLT_MAX)
|
||||
flNeckPivotFwd = m_FirstPersonModelData.m_flFirstPersonNeckPivotFwd;
|
||||
|
||||
if (GetFlags() & FL_DUCKING || m_Local.m_flDucktime > 0.0f)
|
||||
{
|
||||
if (!IsLocalPlayer() || m_Local.m_flDucktime <= 0.0f)
|
||||
{
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX)
|
||||
flNeckPivotUp = m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp;
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX)
|
||||
flNeckPivotFwd = m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bDucking;
|
||||
if (IsLocalPlayer())
|
||||
bDucking = input->GetButtonBits(0) & IN_DUCK;
|
||||
else
|
||||
bDucking = GetCurrentUserCommand()->buttons & IN_DUCK;
|
||||
|
||||
// HACKHACK using constants from game movement
|
||||
float flPerc = SimpleSpline( RemapValClamped( m_Local.m_flDucktime, bDucking ? 600.0f : 800.0f, 1000.0f, 0.0f, 1.0f ) );
|
||||
|
||||
if (bDucking)
|
||||
{
|
||||
// Ducking
|
||||
//Msg( "Ducking with perc %f (%f)\n", flPerc, m_Local.m_flDucktime );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX)
|
||||
flNeckPivotUp = FLerp( m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp, flNeckPivotUp, flPerc );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX)
|
||||
flNeckPivotFwd = FLerp( m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd, flNeckPivotFwd, flPerc );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unducking
|
||||
//Msg( "Unducking with perc %f (%f)\n", flPerc, m_Local.m_flDucktime );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp != FLT_MAX)
|
||||
flNeckPivotUp = FLerp( flNeckPivotUp, m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckUp, flPerc );
|
||||
if (m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd != FLT_MAX)
|
||||
flNeckPivotFwd = FLerp( flNeckPivotFwd, m_FirstPersonModelData.m_flFirstPersonNeckPivotDuckFwd, flPerc );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Find out where the player's head (driven by the HMD) is in the world.
|
||||
// We can't move this with animations or effects without causing nausea, so we need to move
|
||||
// the whole body so that the animated head is in the right place to match the player-controlled head.
|
||||
@ -3100,7 +3353,7 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
// The head bone is the neck pivot point of the in-game character.
|
||||
|
||||
Vector vRealMidEyePos = mWorldFromMideye.GetTranslation();
|
||||
vRealPivotPoint = vRealMidEyePos - ( mWorldFromMideye.GetUp() * cl_meathook_neck_pivot_ingame_up.GetFloat() ) - ( mWorldFromMideye.GetForward() * cl_meathook_neck_pivot_ingame_fwd.GetFloat() );
|
||||
vRealPivotPoint = vRealMidEyePos - ( mWorldFromMideye.GetUp() * flNeckPivotUp ) - ( mWorldFromMideye.GetForward() * flNeckPivotFwd );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3108,7 +3361,7 @@ void C_BasePlayer::BuildFirstPersonMeathookTransformations( CStudioHdr *hdr, Vec
|
||||
Vector vForward, vRight, vUp;
|
||||
AngleVectors( MainViewAngles(), &vForward, &vRight, &vUp );
|
||||
|
||||
vRealPivotPoint = MainViewOrigin() - ( vUp * cl_meathook_neck_pivot_ingame_up.GetFloat() ) - ( vForward * cl_meathook_neck_pivot_ingame_fwd.GetFloat() );
|
||||
vRealPivotPoint = MainViewOrigin() - ( vUp * flNeckPivotUp ) - ( vForward * flNeckPivotFwd );
|
||||
}
|
||||
|
||||
Vector vDeltaToAdd = vRealPivotPoint - vHeadTransformTranslation;
|
||||
|
@ -293,6 +293,15 @@ public:
|
||||
|
||||
virtual bool ShouldInterpolate();
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool InPerspectiveView() const; // In a view that renders directly from the player's perspective (and may, for example, render the playermodel)
|
||||
bool DrawingPlayerModelExternally() const;
|
||||
bool DrawingLegs() const;
|
||||
|
||||
virtual CStudioHdr *OnNewModel( void );
|
||||
virtual void BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed );
|
||||
#endif
|
||||
|
||||
virtual bool ShouldDraw();
|
||||
virtual int DrawModel( int flags );
|
||||
|
||||
@ -468,6 +477,9 @@ public:
|
||||
inline void RemoveSpawnFlags( int flags ) { m_spawnflags &= ~flags; }
|
||||
inline void AddSpawnFlags( int flags ) { m_spawnflags |= flags; }
|
||||
|
||||
// Draws the player's model below the camera, visible when the player looks down.
|
||||
bool m_bDrawPlayerLegs;
|
||||
|
||||
// Allows the player's model to draw on non-main views, like monitors or mirrors.
|
||||
bool m_bDrawPlayerModelExternally;
|
||||
|
||||
@ -502,6 +514,10 @@ protected:
|
||||
|
||||
virtual void FireGameEvent( IGameEvent *event );
|
||||
|
||||
#ifdef MAPBASE
|
||||
inline CUtlMap<int, float> &GetFirstPersonArmScales() { return m_FirstPersonModelData.m_FirstPersonBoneScales[FirstPersonModelData_t::BoneScales_Arms]; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Did we just enter a vehicle this frame?
|
||||
bool JustEnteredVehicle();
|
||||
@ -556,6 +572,41 @@ private:
|
||||
|
||||
bool m_bFiredWeapon;
|
||||
|
||||
#ifdef MAPBASE
|
||||
struct FirstPersonModelData_t
|
||||
{
|
||||
void Reset()
|
||||
{
|
||||
m_flFirstPersonNeckPivotUp = m_flFirstPersonNeckPivotFwd = FLT_MAX;
|
||||
m_flFirstPersonNeckPivotDuckUp = m_flFirstPersonNeckPivotDuckFwd = FLT_MAX;
|
||||
|
||||
for (int i = 0; i < BoneScales_Max; i++)
|
||||
{
|
||||
m_FirstPersonBoneScales[i].RemoveAll();
|
||||
m_FirstPersonBoneScales[i].SetLessFunc( DefLessFunc( int ) );
|
||||
}
|
||||
}
|
||||
|
||||
void ParseModelData( C_BasePlayer *pPlayer, KeyValues *pkvPlayerModelData );
|
||||
|
||||
enum
|
||||
{
|
||||
BoneScales_Spine,
|
||||
BoneScales_Arms,
|
||||
|
||||
BoneScales_Max
|
||||
};
|
||||
|
||||
// Values to scale bones by when drawing playermodel in first person
|
||||
CUtlMap<int, float> m_FirstPersonBoneScales[BoneScales_Max];
|
||||
|
||||
float m_flFirstPersonNeckPivotUp, m_flFirstPersonNeckPivotFwd = FLT_MAX;
|
||||
float m_flFirstPersonNeckPivotDuckUp, m_flFirstPersonNeckPivotDuckFwd = FLT_MAX;
|
||||
};
|
||||
|
||||
FirstPersonModelData_t m_FirstPersonModelData;
|
||||
#endif
|
||||
|
||||
|
||||
// Player flashlight dynamic light pointers
|
||||
CFlashlightEffect *m_pFlashlight;
|
||||
|
@ -399,10 +399,38 @@ int C_SpriteRenderer::DrawSprite(
|
||||
if ( group == RENDER_GROUP_VIEW_MODEL_TRANSLUCENT || group == RENDER_GROUP_VIEW_MODEL_OPAQUE )
|
||||
return 0;
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
if (ent->m_iViewHideFlags > 0)
|
||||
{
|
||||
// Hide this entity if it's not supposed to be drawn in this view.
|
||||
if (ent->m_iViewHideFlags & (1 << CurrentViewID()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
QAngle temp;
|
||||
ent->GetAttachment( attachmentindex, effect_origin, temp );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( entity )
|
||||
{
|
||||
C_BaseEntity *ent = entity->GetBaseEntity();
|
||||
if ( ent )
|
||||
{
|
||||
if (ent->m_iViewHideFlags > 0)
|
||||
{
|
||||
// Hide this entity if it's not supposed to be drawn in this view.
|
||||
if (ent->m_iViewHideFlags & (1 << CurrentViewID()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( rendermode != kRenderNormal )
|
||||
{
|
||||
|
@ -47,8 +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\mapbase_playeranimstate.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\mapbase_playeranimstate.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
|
||||
|
@ -157,6 +157,22 @@ void CColorCorrectionMgr::CommitColorCorrectionWeights()
|
||||
}
|
||||
m_colorCorrectionWeights.RemoveAll();
|
||||
}
|
||||
|
||||
void CColorCorrectionMgr::LevelShutdownPreEntity()
|
||||
{
|
||||
//Clean up the vectors when shuting down a level
|
||||
//will keep dangling pointers inside of the vector causing a nullptr crash
|
||||
if (g_ColorCorrectionVolumeList.Base())
|
||||
{
|
||||
g_ColorCorrectionVolumeList.Purge();
|
||||
}
|
||||
|
||||
if (g_ColorCorrectionList.Base())
|
||||
{
|
||||
g_ColorCorrectionList.Purge();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void CColorCorrectionMgr::SetColorCorrectionWeight( ClientCCHandle_t h, float flWeight )
|
||||
{
|
||||
|
@ -76,6 +76,8 @@ private:
|
||||
CUtlVector< SetWeightParams_t > m_colorCorrectionWeights;
|
||||
|
||||
void CommitColorCorrectionWeights();
|
||||
|
||||
void LevelShutdownPreEntity();
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -36,6 +36,7 @@ IMPLEMENT_CLIENTCLASS_DT(C_BaseHLPlayer, DT_HL2_Player, CHL2_Player)
|
||||
#endif
|
||||
#ifdef SP_ANIM_STATE
|
||||
RecvPropFloat( RECVINFO( m_flAnimRenderYaw ) ),
|
||||
RecvPropFloat( RECVINFO( m_flAnimRenderZ ) ),
|
||||
#endif
|
||||
END_RECV_TABLE()
|
||||
|
||||
@ -108,6 +109,22 @@ void C_BaseHLPlayer::OnDataChanged( DataUpdateType_t updateType )
|
||||
BaseClass::OnDataChanged( updateType );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseHLPlayer::AddEntity( void )
|
||||
{
|
||||
BaseClass::AddEntity();
|
||||
|
||||
#ifdef MAPBASE_MP
|
||||
if (m_pPlayerAnimState)
|
||||
{
|
||||
QAngle angEyeAngles = EyeAngles();
|
||||
m_pPlayerAnimState->Update( angEyeAngles.y, angEyeAngles.x );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -669,24 +686,76 @@ bool C_BaseHLPlayer::CreateMove( float flInputSampleTime, CUserCmd *pCmd )
|
||||
void C_BaseHLPlayer::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed )
|
||||
{
|
||||
BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed );
|
||||
/*#ifdef MAPBASE
|
||||
// BuildFirstPersonMeathookTransformations is used prior to this when drawing legs
|
||||
if (!DrawingLegs() || !InPerspectiveView() || !InFirstPersonView())
|
||||
#endif*/
|
||||
BuildFirstPersonMeathookTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed, "ValveBiped.Bip01_Head1" );
|
||||
}
|
||||
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vector &C_BaseHLPlayer::GetRenderOrigin()
|
||||
{
|
||||
if (m_flAnimRenderZ != 0.0f)
|
||||
{
|
||||
static Vector vecRender;
|
||||
vecRender = BaseClass::GetRenderOrigin();
|
||||
vecRender.z += m_flAnimRenderZ;
|
||||
return vecRender;
|
||||
}
|
||||
|
||||
return BaseClass::GetRenderOrigin();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const QAngle& C_BaseHLPlayer::GetRenderAngles( void )
|
||||
{
|
||||
#ifdef MAPBASE_MP
|
||||
if ( m_pPlayerAnimState )
|
||||
{
|
||||
return m_pPlayerAnimState->GetRenderAngles();
|
||||
}
|
||||
#else
|
||||
if ( m_flAnimRenderYaw != FLT_MAX )
|
||||
{
|
||||
return m_angAnimRender;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return BaseClass::GetRenderAngles();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: model-change notification. Fires on dynamic load completion as well
|
||||
//-----------------------------------------------------------------------------
|
||||
CStudioHdr *C_BaseHLPlayer::OnNewModel()
|
||||
{
|
||||
CStudioHdr *hdr = BaseClass::OnNewModel();
|
||||
|
||||
#ifdef MAPBASE_MP
|
||||
// Clears the animation state if we already have one.
|
||||
if ( m_pPlayerAnimState != NULL )
|
||||
{
|
||||
m_pPlayerAnimState->Release();
|
||||
m_pPlayerAnimState = NULL;
|
||||
}
|
||||
|
||||
if ( hdr && hdr->HaveSequenceForActivity(ACT_HL2MP_IDLE) /*&& hl2_use_sp_animstate.GetBool()*/ )
|
||||
{
|
||||
// Here we create and init the player animation state.
|
||||
m_pPlayerAnimState = CreatePlayerAnimationState(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
return hdr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "c_hl2_playerlocaldata.h"
|
||||
|
||||
#if !defined( HL2MP ) && defined ( MAPBASE )
|
||||
#include "mapbase/singleplayer_animstate.h"
|
||||
#include "mapbase/mapbase_playeranimstate.h"
|
||||
#endif
|
||||
|
||||
class C_BaseHLPlayer : public C_BasePlayer
|
||||
@ -29,6 +29,7 @@ public:
|
||||
C_BaseHLPlayer();
|
||||
|
||||
virtual void OnDataChanged( DataUpdateType_t updateType );
|
||||
virtual void AddEntity( void );
|
||||
|
||||
void Weapon_DropPrimary( void );
|
||||
|
||||
@ -67,7 +68,9 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
virtual const Vector& GetRenderOrigin();
|
||||
virtual const QAngle& GetRenderAngles( void );
|
||||
virtual CStudioHdr *OnNewModel();
|
||||
#endif
|
||||
|
||||
public:
|
||||
@ -95,10 +98,13 @@ private:
|
||||
int m_nProtagonistIndex;
|
||||
#endif
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
#ifdef MAPBASE_MP
|
||||
CSinglePlayerAnimState *m_pPlayerAnimState;
|
||||
#elif MAPBASE
|
||||
// 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;
|
||||
float m_flAnimRenderZ;
|
||||
QAngle m_angAnimRender;
|
||||
#endif
|
||||
|
||||
|
@ -100,7 +100,11 @@ void CHudSuitPower::OnThink( void )
|
||||
}
|
||||
|
||||
bool flashlightActive = pPlayer->IsFlashlightActive();
|
||||
#ifdef MAPBASE
|
||||
bool sprintActive = pPlayer->IsSprintActive();
|
||||
#else
|
||||
bool sprintActive = pPlayer->IsSprinting();
|
||||
#endif
|
||||
bool breatherActive = pPlayer->IsBreatherActive();
|
||||
int activeDevices = (int)flashlightActive + (int)sprintActive + (int)breatherActive;
|
||||
|
||||
@ -250,7 +254,11 @@ void CHudSuitPower::Paint()
|
||||
ypos += text2_gap;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (pPlayer->IsSprintActive())
|
||||
#else
|
||||
if (pPlayer->IsSprinting())
|
||||
#endif
|
||||
{
|
||||
tempString = g_pVGuiLocalize->Find("#Valve_Hud_SPRINT");
|
||||
|
||||
|
@ -1031,7 +1031,7 @@ void CScriptSurface::DrawColoredTextRect( int font, int x, int y, int w, int h,
|
||||
#define __base() this->_base
|
||||
|
||||
#define BEGIN_SCRIPTDESC_VGUI( panelClass )\
|
||||
BEGIN_SCRIPTDESC_NAMED( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "" )\
|
||||
BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( CScript_##panelClass##_Helper, IScriptVGUIObject, #panelClass, "", VGUI_SCRIPT_INSTANCE_HELPER )\
|
||||
DEFINE_VGUI_SCRIPTFUNC_##panelClass()
|
||||
|
||||
//
|
||||
@ -1235,9 +1235,9 @@ class CScriptVGUIScriptInstanceHelper : public IScriptInstanceHelper
|
||||
|
||||
static CScriptVGUIScriptInstanceHelper g_ScriptVGUIScriptInstanceHelper;
|
||||
|
||||
#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER() DEFINE_SCRIPT_INSTANCE_HELPER( &g_ScriptVGUIScriptInstanceHelper )
|
||||
#define VGUI_SCRIPT_INSTANCE_HELPER &g_ScriptVGUIScriptInstanceHelper
|
||||
#else
|
||||
#define DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()
|
||||
#define VGUI_SCRIPT_INSTANCE_HELPER NULL
|
||||
#endif
|
||||
|
||||
|
||||
@ -1866,8 +1866,6 @@ public:
|
||||
};
|
||||
|
||||
#define DEFINE_VGUI_SCRIPTFUNC_Panel()\
|
||||
DEFINE_VGUI_SCRIPT_INSTANCE_HELPER()\
|
||||
\
|
||||
DEFINE_SCRIPTFUNC( Destroy, "" )\
|
||||
DEFINE_SCRIPTFUNC( MakeReadyForUse, "" )\
|
||||
DEFINE_SCRIPTFUNC( GetName, "" )\
|
||||
@ -2612,9 +2610,17 @@ public:
|
||||
|
||||
static inline void SetHScript( HSCRIPT &var, HSCRIPT val )
|
||||
{
|
||||
if ( var && g_pScriptVM )
|
||||
g_pScriptVM->ReleaseScript( var );
|
||||
var = val;
|
||||
if ( g_pScriptVM )
|
||||
{
|
||||
if ( var )
|
||||
g_pScriptVM->ReleaseScript( var );
|
||||
|
||||
var = g_pScriptVM->CopyObject( val );
|
||||
}
|
||||
else
|
||||
{
|
||||
var = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define CheckCallback(s)\
|
||||
|
@ -855,7 +855,7 @@ void CPrediction::RunCommand( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
||||
C_BaseCombatWeapon *weapon = dynamic_cast< C_BaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) );
|
||||
if ( weapon )
|
||||
{
|
||||
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
|
||||
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,7 @@ ConVar gl_clear_randomcolor( "gl_clear_randomcolor", "0", FCVAR_CHEAT, "Clear th
|
||||
static ConVar r_farz( "r_farz", "-1", FCVAR_CHEAT, "Override the far clipping plane. -1 means to use the value in env_fog_controller." );
|
||||
#ifdef MAPBASE
|
||||
static ConVar r_nearz( "r_nearz", "-1", FCVAR_CHEAT, "Override the near clipping plane. -1 means to use the default value (usually 7)." );
|
||||
static ConVar cl_camera_anim_intensity("cl_camera_anim_intensity", "1.0", FCVAR_ARCHIVE, "Intensity of cambone animations");
|
||||
#endif
|
||||
static ConVar cl_demoviewoverride( "cl_demoviewoverride", "0", 0, "Override view during demo playback" );
|
||||
|
||||
@ -1306,6 +1307,37 @@ void CViewRender::Render( vrect_t *rect )
|
||||
g_ClientVirtualReality.OverlayHUDQuadWithUndistort( view, bDoUndistort, g_pClientMode->ShouldBlackoutAroundHUD(), bTranslucent );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//--------------------------------
|
||||
// Handle camera anims
|
||||
//--------------------------------
|
||||
if (!UseVR() && pPlayer && cl_camera_anim_intensity.GetFloat() > 0)
|
||||
{
|
||||
if (pPlayer->GetViewModel(0))
|
||||
{
|
||||
int attachment = pPlayer->GetViewModel(0)->LookupAttachment("camera");
|
||||
if (attachment != -1)
|
||||
{
|
||||
int rootBone = pPlayer->GetViewModel(0)->LookupAttachment("camera_root");
|
||||
Vector cameraOrigin = Vector(0, 0, 0);
|
||||
QAngle cameraAngles = QAngle(0, 0, 0);
|
||||
Vector rootOrigin = Vector(0, 0, 0);
|
||||
QAngle rootAngles = QAngle(0, 0, 0);
|
||||
|
||||
pPlayer->GetViewModel(0)->GetAttachmentLocal(attachment, cameraOrigin, cameraAngles);
|
||||
if (rootBone != -1)
|
||||
{
|
||||
pPlayer->GetViewModel(0)->GetAttachmentLocal(rootBone, rootOrigin, rootAngles);
|
||||
cameraOrigin -= rootOrigin;
|
||||
cameraAngles -= rootAngles;
|
||||
}
|
||||
view.angles += cameraAngles * cl_camera_anim_intensity.GetFloat();
|
||||
view.origin += cameraOrigin * cl_camera_anim_intensity.GetFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // MAPBASE
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,10 @@
|
||||
extern IScriptManager *scriptmanager;
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
extern int vscript_debugger_port;
|
||||
#endif
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
@ -234,8 +238,7 @@ class CMaterialProxyScriptInstanceHelper : public IScriptInstanceHelper
|
||||
|
||||
CMaterialProxyScriptInstanceHelper g_MaterialProxyScriptInstanceHelper;
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptMaterialProxy, "CScriptMaterialProxy", "Material proxy for VScript" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_MaterialProxyScriptInstanceHelper )
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( CScriptMaterialProxy, "CScriptMaterialProxy", "Material proxy for VScript", &g_MaterialProxyScriptInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC( GetVarString, "Gets a material var's string value" )
|
||||
DEFINE_SCRIPTFUNC( GetVarInt, "Gets a material var's int value" )
|
||||
DEFINE_SCRIPTFUNC( GetVarFloat, "Gets a material var's float value" )
|
||||
@ -683,6 +686,14 @@ bool VScriptClientInit()
|
||||
//g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if ( vscript_debugger_port )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||
vscript_debugger_port = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scriptLanguage == SL_SQUIRREL)
|
||||
{
|
||||
g_pScriptVM->Run( g_Script_vscript_client );
|
||||
@ -771,11 +782,19 @@ public:
|
||||
VScriptClientTerm();
|
||||
}
|
||||
|
||||
virtual void FrameUpdatePostEntityThink()
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual void Update( float frametime )
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
g_pScriptVM->Frame( frametime );
|
||||
}
|
||||
#else
|
||||
virtual void FrameUpdatePostEntityThink()
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
g_pScriptVM->Frame( gpGlobals->frametime );
|
||||
}
|
||||
#endif
|
||||
|
||||
bool m_bAllowEntityCreationInScripts;
|
||||
};
|
||||
|
@ -16,6 +16,10 @@
|
||||
#include "saverestore_utlvector.h"
|
||||
#include "dt_utlvector_send.h"
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#include "mapbase/vscript_funcs_shared.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
@ -471,7 +475,8 @@ void CAnimationLayer::DispatchAnimEvents( CBaseAnimating *eventHandler, CBaseAni
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (eventHandler->m_ScriptScope.IsInitialized() && eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
|
||||
scriptanimevent_t wrapper( event );
|
||||
if (eventHandler->m_ScriptScope.IsInitialized() && !eventHandler->ScriptHookHandleAnimEvent( wrapper ))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
|
@ -2594,6 +2594,18 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_PISTOL );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SHOTGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SMG1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_AR2 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_PHYSGUN );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_GRENADE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_RPG );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_CROSSBOW );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_MELEE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_SLAM );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_REVOLVER );
|
||||
@ -2603,6 +2615,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX_REVOLVER );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_REVOLVER );
|
||||
|
||||
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
|
||||
@ -2614,6 +2627,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX_AR1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR1 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_AR3 );
|
||||
@ -2624,6 +2638,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX_AR3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_AR3 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG2 );
|
||||
@ -2634,6 +2649,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX_SMG2 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG2 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SMG3 );
|
||||
@ -2644,6 +2660,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX_SMG3 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SMG3 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_HMG1 );
|
||||
@ -2654,6 +2671,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX_HMG1 );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_HMG1 );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SNIPER_RIFLE );
|
||||
@ -2664,6 +2682,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
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_GESTURE_RELAX_SNIPER_RIFLE );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SNIPER_RIFLE );
|
||||
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_DUAL_PISTOLS );
|
||||
@ -2674,6 +2693,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void)
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS );
|
||||
ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_DUAL_PISTOLS );
|
||||
#endif
|
||||
|
||||
|
@ -318,6 +318,14 @@ ScriptHook_t CAI_BaseNPC::g_Hook_TranslateSchedule;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_GetActualShootPosition;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OverrideMove;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_IsValidEnemy;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_CanBeAnEnemyOf;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_UpdateEnemyMemory;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OnSeeEntity;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_OnListened;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_BuildScheduleTestBits;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_StartTask;
|
||||
ScriptHook_t CAI_BaseNPC::g_Hook_RunTask;
|
||||
#endif
|
||||
|
||||
//
|
||||
@ -746,10 +754,19 @@ Vector CAI_BaseNPC::VScriptGetEnemyLKP()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptFindEnemyMemory( HSCRIPT pEnemy )
|
||||
int CAI_BaseNPC::VScriptNumEnemies()
|
||||
{
|
||||
return GetEnemies()->NumEnemies();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetFirstEnemyMemory()
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
AI_EnemyInfo_t *info = GetEnemies()->Find( ToEnt(pEnemy) );
|
||||
|
||||
AIEnemiesIter_t iter;
|
||||
AI_EnemyInfo_t *info = GetEnemies()->GetFirst( &iter );
|
||||
if (info)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( reinterpret_cast<Script_AI_EnemyInfo_t*>(info) );
|
||||
@ -758,6 +775,70 @@ HSCRIPT CAI_BaseNPC::VScriptFindEnemyMemory( HSCRIPT pEnemy )
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetNextEnemyMemory( HSCRIPT hMemory )
|
||||
{
|
||||
Script_AI_EnemyInfo_t *pCurEMemory = HScriptToClass<Script_AI_EnemyInfo_t>( hMemory );
|
||||
if (!pCurEMemory)
|
||||
return NULL;
|
||||
|
||||
HSCRIPT hScript = NULL;
|
||||
|
||||
AIEnemiesIter_t iter = (AIEnemiesIter_t)GetEnemies()->FindIndex( pCurEMemory->hEnemy );
|
||||
AI_EnemyInfo_t *pEMemory = GetEnemies()->GetNext( &iter );
|
||||
if (pEMemory)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( reinterpret_cast<Script_AI_EnemyInfo_t*>(pEMemory) );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptFindEnemyMemory( HSCRIPT hEnemy )
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
AI_EnemyInfo_t *info = GetEnemies()->Find( ToEnt(hEnemy) );
|
||||
if (info)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( reinterpret_cast<Script_AI_EnemyInfo_t*>(info) );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CAI_BaseNPC::VScriptUpdateEnemyMemory( HSCRIPT hEnemy, const Vector &position, HSCRIPT hInformer )
|
||||
{
|
||||
return UpdateEnemyMemory( ToEnt( hEnemy ), position, ToEnt( hInformer ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptClearEnemyMemory( HSCRIPT hEnemy )
|
||||
{
|
||||
CBaseEntity *pEnemy = ToEnt( hEnemy );
|
||||
if (!pEnemy)
|
||||
return;
|
||||
|
||||
GetEnemies()->ClearMemory( pEnemy );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptSetFreeKnowledgeDuration( float flDuration )
|
||||
{
|
||||
GetEnemies()->SetFreeKnowledgeDuration( flDuration );
|
||||
}
|
||||
|
||||
void CAI_BaseNPC::VScriptSetEnemyDiscardTime( float flDuration )
|
||||
{
|
||||
GetEnemies()->SetEnemyDiscardTime( flDuration );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_BaseNPC::VScriptGetState()
|
||||
@ -765,6 +846,34 @@ int CAI_BaseNPC::VScriptGetState()
|
||||
return (int)GetState();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_BaseNPC::VScriptGetIdealState()
|
||||
{
|
||||
return (int)GetIdealState();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptSetIdealState( int nNPCState )
|
||||
{
|
||||
SetIdealState( (NPC_STATE)nNPCState );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetTarget()
|
||||
{
|
||||
return ToHScript( GetTarget() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CAI_BaseNPC::VScriptSetTarget( HSCRIPT hTarget )
|
||||
{
|
||||
SetTarget( ToEnt( hTarget ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetHintNode()
|
||||
@ -832,7 +941,7 @@ int CAI_BaseNPC::VScriptGetTaskID()
|
||||
const Task_t *pTask = GetTask();
|
||||
int iID = -1;
|
||||
if (pTask)
|
||||
iID = GetTaskID( TaskName( pTask->iTask ) );
|
||||
iID = AI_RemapFromGlobal( GetTaskID( TaskName( pTask->iTask ) ) );
|
||||
|
||||
return iID;
|
||||
}
|
||||
@ -867,6 +976,70 @@ HSCRIPT CAI_BaseNPC::VScriptGetSquad()
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetBestSound( int validTypes )
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
CSound *pSound = GetBestSound( validTypes );
|
||||
if (pSound)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( pSound );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetFirstHeardSound()
|
||||
{
|
||||
HSCRIPT hScript = NULL;
|
||||
|
||||
AISoundIter_t iter;
|
||||
CSound *pSound = GetSenses()->GetFirstHeardSound( &iter );
|
||||
if (pSound)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( pSound );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetNextHeardSound( HSCRIPT hSound )
|
||||
{
|
||||
CSound *pCurSound = HScriptToClass<CSound>( hSound );
|
||||
if (!pCurSound)
|
||||
return NULL;
|
||||
|
||||
int iCurrent = pCurSound->m_iNextAudible;
|
||||
if ( iCurrent == SOUNDLIST_EMPTY )
|
||||
return NULL;
|
||||
|
||||
HSCRIPT hScript = NULL;
|
||||
|
||||
CSound *pNextSound = CSoundEnt::SoundPointerForIndex( iCurrent );
|
||||
if (pNextSound)
|
||||
{
|
||||
hScript = g_pScriptVM->RegisterInstance( pNextSound );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetFirstSeenEntity( int nSeenType )
|
||||
{
|
||||
AISightIter_t iter;
|
||||
return ToHScript( GetSenses()->GetFirstSeenEntity( &iter, (seentype_t)nSeenType ) );
|
||||
}
|
||||
|
||||
HSCRIPT CAI_BaseNPC::VScriptGetNextSeenEntity( HSCRIPT hEnt, int nSeenType )
|
||||
{
|
||||
CBaseEntity *pEnt = ToEnt( hEnt );
|
||||
|
||||
AISightIter_t iter;
|
||||
GetSenses()->GetSeenEntityIndex( &iter, pEnt, (seentype_t)nSeenType );
|
||||
|
||||
return ToHScript( GetSenses()->GetNextSeenEntity( &iter ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CAI_BaseNPC::PassesDamageFilter( const CTakeDamageInfo &info )
|
||||
@ -2595,6 +2768,29 @@ void CAI_BaseNPC::OnListened()
|
||||
{
|
||||
m_OnHearCombat.FireOutput(this, this);
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnListened.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
g_Hook_OnListened.Call( m_ScriptScope, &functionReturn, NULL );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CAI_BaseNPC::OnSeeEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnSeeEntity.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// entity
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEntity ) };
|
||||
g_Hook_OnSeeEntity.Call( m_ScriptScope, &functionReturn, args );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
@ -6107,6 +6303,22 @@ bool CAI_BaseNPC::UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position
|
||||
|
||||
if ( GetEnemies() )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_UpdateEnemyMemory.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// enemy, position, informer
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEnemy ), position, ToHScript( pInformer ) };
|
||||
if (g_Hook_UpdateEnemyMemory.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
// Returning false normally indicates this is a known enemy
|
||||
// Most uses of that functionality involve checking for new enemies, so this is acceptable
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// If the was eluding me and allow the NPC to play a sound
|
||||
if (GetEnemies()->HasEludedMe(pEnemy))
|
||||
{
|
||||
@ -8979,6 +9191,20 @@ bool CAI_BaseNPC::IsValidEnemy( CBaseEntity *pEnemy )
|
||||
if ( m_hEnemyFilter.Get()!= NULL && m_hEnemyFilter->PassesFilter( this, pEnemy ) == false )
|
||||
return false;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_IsValidEnemy.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// enemy
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEnemy ) };
|
||||
if (g_Hook_IsValidEnemy.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8988,6 +9214,20 @@ bool CAI_BaseNPC::CanBeAnEnemyOf( CBaseEntity *pEnemy )
|
||||
if ( GetSleepState() > AISS_WAITING_FOR_THREAT )
|
||||
return false;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_CanBeAnEnemyOf.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// enemy
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pEnemy ) };
|
||||
if (g_Hook_CanBeAnEnemyOf.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -11529,6 +11769,13 @@ float CAI_BaseNPC::GetEnemyLastTimeSeen() const
|
||||
void CAI_BaseNPC::MarkEnemyAsEluded()
|
||||
{
|
||||
GetEnemies()->MarkAsEluded( GetEnemy() );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_pSquad)
|
||||
{
|
||||
m_pSquad->MarkEnemyAsEluded( this, GetEnemy() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CAI_BaseNPC::ClearEnemyMemory()
|
||||
@ -12307,7 +12554,17 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetEnemy, "SetEnemy", "Set the NPC's current enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetEnemyLKP, "GetEnemyLKP", "Get the last known position of the NPC's current enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptNumEnemies, "NumEnemies", "Get the number of enemies this NPC knows about." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetFirstEnemyMemory, "GetFirstEnemyMemory", "Get information about the NPC's first enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetNextEnemyMemory, "GetNextEnemyMemory", "Get information about the NPC's next enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptFindEnemyMemory, "FindEnemyMemory", "Get information about the NPC's current enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptUpdateEnemyMemory, "UpdateEnemyMemory", "Update information on this enemy. First parameter is the enemy, second is the position we now know the enemy is at, third parameter is the informer (e.g. squadmate who sees enemy, null if I see it myself). Returns true if this is a new enemy." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptClearEnemyMemory, "ClearEnemyMemory", "Makes the NPC forget about the specified enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetFreeKnowledgeDuration, "SetFreeKnowledgeDuration", "Sets the amount of time the NPC can always know an enemy's location after losing sight." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetEnemyDiscardTime, "SetEnemyDiscardTime", "Sets the amount of time needed before the NPC discards an unseen enemy's memory." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetLastAttackTime, "Get the last time the NPC has used an attack (e.g. fired a bullet from a gun)." )
|
||||
DEFINE_SCRIPTFUNC( GetLastDamageTime, "Get the last time the NPC has been damaged." )
|
||||
@ -12315,6 +12572,11 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC( GetLastEnemyTime, "Get the last time the NPC has seen an enemy." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetState, "GetNPCState", "Get the NPC's current state." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetIdealState, "GetIdealNPCState", "Get the NPC's ideal state." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetIdealState, "SetIdealNPCState", "Set the NPC's ideal state." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetTarget, "GetNPCTarget", "Get the NPC's AI target." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetTarget, "SetNPCTarget", "Set the NPC's AI target." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptWake, "Wake", "Awakens the NPC if it is currently asleep." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSleep, "Sleep", "Puts the NPC into a sleeping state." )
|
||||
@ -12362,6 +12624,16 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptClearCondition, "ClearCondition", "Clear a condition on the NPC." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ClearCondition, "ClearConditionID", "Clear a condition on the NPC by ID." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptSetCustomInterruptCondition, "SetCustomInterruptCondition", "Use with BuildScheduleTestBits to define conditions which should interrupt the schedule." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptIsCustomInterruptConditionSet, "IsCustomInterruptConditionSet", "Use with BuildScheduleTestBits to define conditions which should interrupt the schedule." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptClearCustomInterruptCondition, "ClearCustomInterruptCondition", "Use with BuildScheduleTestBits to define conditions which should interrupt the schedule." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptChainStartTask, "ChainStartTask", "Use with StartTask to redirect to the specified task." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptChainRunTask, "ChainRunTask", "Use with RunTask to redirect to the specified task." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptFailTask, "FailTask", "Fails the currently running task with the specified error message." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptCompleteTask, "CompleteTask", "Completes the currently running task." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetTaskStatus, "GetTaskStatus", "Gets the current task's status." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( IsMoving, "Check if the NPC is moving." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetExpresser, "GetExpresser", "Get a handle for this NPC's expresser." )
|
||||
@ -12380,6 +12652,13 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTFUNC( IsCrouching, "Returns true if the NPC is crouching." )
|
||||
DEFINE_SCRIPTFUNC( Crouch, "Tells the NPC to crouch." )
|
||||
DEFINE_SCRIPTFUNC( Stand, "Tells the NPC to stand if it is crouching." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetBestSound, "GetBestSound", "Get the NPC's best sound of the specified type(s). Use 'ALL_SOUNDS' to get any sound." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetFirstHeardSound, "GetFirstHeardSound", "Get the NPC's first heard sound." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetNextHeardSound, "GetNextHeardSound", "Get the NPC's next heard sound." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetFirstSeenEntity, "GetFirstSeenEntity", "Get the NPC's first seen entity in the specified 'SEEN_' list." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( VScriptGetNextSeenEntity, "GetNextSeenEntity", "Get the NPC's next seen entity in the specified 'SEEN_' list." )
|
||||
|
||||
//
|
||||
// Hooks
|
||||
@ -12409,6 +12688,32 @@ BEGIN_ENT_SCRIPTDESC( CAI_BaseNPC, CBaseCombatCharacter, "The base class all NPC
|
||||
DEFINE_SCRIPTHOOK_PARAM( "activity", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "translatedActivity", FIELD_CSTRING )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_IsValidEnemy, "IsValidEnemy", FIELD_BOOLEAN, "Whether or not the specified enemy should be considered valid." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "enemy", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_CanBeAnEnemyOf, "CanBeAnEnemyOf", FIELD_BOOLEAN, "Whether or not this NPC can be an enemy of another NPC." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "enemy", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_UpdateEnemyMemory, "UpdateEnemyMemory", FIELD_BOOLEAN, "Whether or not this NPC can be an enemy of another NPC." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "enemy", FIELD_HSCRIPT )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "position", FIELD_VECTOR )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "informer", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_OnSeeEntity, "OnSeeEntity", FIELD_VOID, "Called when the NPC sees an entity." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CAI_BaseNPC::g_Hook_OnListened, "OnListened", FIELD_VOID, "Called when the NPC assigns sound conditions after checking for sounds it hears." )
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CAI_BaseNPC::g_Hook_BuildScheduleTestBits, "BuildScheduleTestBits", FIELD_VOID, "Called when the NPC is determining which conditions can interrupt the current schedule." )
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_StartTask, "StartTask", FIELD_VOID, "Called when a task is starting. The task is provided in both string and ID form. Return false to override actual task functionality." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_id", FIELD_INTEGER )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_data", FIELD_FLOAT )
|
||||
END_SCRIPTHOOK()
|
||||
BEGIN_SCRIPTHOOK( CAI_BaseNPC::g_Hook_RunTask, "RunTask", FIELD_VOID, "Called every think while the task is running. The task is provided in both string and ID form. Return false to override actual task functionality." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task", FIELD_CSTRING )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_id", FIELD_INTEGER )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "task_data", FIELD_FLOAT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
@ -1104,7 +1104,7 @@ public:
|
||||
virtual void OnLooked( int iDistance );
|
||||
virtual void OnListened();
|
||||
|
||||
virtual void OnSeeEntity( CBaseEntity *pEntity ) {}
|
||||
virtual void OnSeeEntity( CBaseEntity *pEntity );
|
||||
|
||||
// If true, AI will try to see this entity regardless of distance.
|
||||
virtual bool ShouldNotDistanceCull() { return false; }
|
||||
@ -1271,9 +1271,24 @@ private:
|
||||
void VScriptSetEnemy( HSCRIPT pEnemy );
|
||||
Vector VScriptGetEnemyLKP();
|
||||
|
||||
HSCRIPT VScriptFindEnemyMemory( HSCRIPT pEnemy );
|
||||
int VScriptNumEnemies();
|
||||
|
||||
HSCRIPT VScriptGetFirstEnemyMemory();
|
||||
HSCRIPT VScriptGetNextEnemyMemory( HSCRIPT hMemory );
|
||||
|
||||
HSCRIPT VScriptFindEnemyMemory( HSCRIPT hEnemy );
|
||||
bool VScriptUpdateEnemyMemory( HSCRIPT hEnemy, const Vector &position, HSCRIPT hInformer );
|
||||
void VScriptClearEnemyMemory( HSCRIPT hEnemy );
|
||||
|
||||
void VScriptSetFreeKnowledgeDuration( float flDuration );
|
||||
void VScriptSetEnemyDiscardTime( float flDuration );
|
||||
|
||||
int VScriptGetState();
|
||||
int VScriptGetIdealState();
|
||||
void VScriptSetIdealState( int nNPCState );
|
||||
|
||||
HSCRIPT VScriptGetTarget();
|
||||
void VScriptSetTarget( HSCRIPT hTarget );
|
||||
|
||||
void VScriptWake( HSCRIPT hActivator ) { Wake( ToEnt(hActivator) ); }
|
||||
void VScriptSleep() { Sleep(); }
|
||||
@ -1308,12 +1323,29 @@ private:
|
||||
void VScriptSetCondition( const char *szCondition ) { SetCondition( GetConditionID( szCondition ) ); }
|
||||
void VScriptClearCondition( const char *szCondition ) { ClearCondition( GetConditionID( szCondition ) ); }
|
||||
|
||||
void VScriptSetCustomInterruptCondition( const char *szCondition ) { SetCustomInterruptCondition( GetConditionID( szCondition ) ); }
|
||||
bool VScriptIsCustomInterruptConditionSet( const char *szCondition ) { return IsCustomInterruptConditionSet( GetConditionID( szCondition ) ); }
|
||||
void VScriptClearCustomInterruptCondition( const char *szCondition ) { ClearCustomInterruptCondition( GetConditionID( szCondition ) ); }
|
||||
|
||||
void VScriptChainStartTask( const char *szTask, float flTaskData ) { ChainStartTask( AI_RemapFromGlobal( GetTaskID( szTask ) ), flTaskData ); }
|
||||
void VScriptChainRunTask( const char *szTask, float flTaskData ) { ChainRunTask( AI_RemapFromGlobal( GetTaskID( szTask ) ), flTaskData ); }
|
||||
void VScriptFailTask( const char *szFailReason ) { TaskFail( szFailReason ); }
|
||||
void VScriptCompleteTask() { TaskComplete(); }
|
||||
int VScriptGetTaskStatus() { return (int)GetTaskStatus(); }
|
||||
|
||||
HSCRIPT VScriptGetExpresser();
|
||||
|
||||
HSCRIPT VScriptGetCine();
|
||||
int GetScriptState() { return m_scriptState; }
|
||||
|
||||
HSCRIPT VScriptGetSquad();
|
||||
|
||||
HSCRIPT VScriptGetBestSound( int validTypes );
|
||||
HSCRIPT VScriptGetFirstHeardSound();
|
||||
HSCRIPT VScriptGetNextHeardSound( HSCRIPT hSound );
|
||||
|
||||
HSCRIPT VScriptGetFirstSeenEntity( int nSeenType );
|
||||
HSCRIPT VScriptGetNextSeenEntity( HSCRIPT hEnt, int nSeenType );
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------
|
||||
@ -2399,6 +2431,14 @@ public:
|
||||
static ScriptHook_t g_Hook_GetActualShootPosition;
|
||||
static ScriptHook_t g_Hook_OverrideMove;
|
||||
static ScriptHook_t g_Hook_ShouldPlayFakeSequenceGesture;
|
||||
static ScriptHook_t g_Hook_IsValidEnemy;
|
||||
static ScriptHook_t g_Hook_CanBeAnEnemyOf;
|
||||
static ScriptHook_t g_Hook_UpdateEnemyMemory;
|
||||
static ScriptHook_t g_Hook_OnSeeEntity;
|
||||
static ScriptHook_t g_Hook_OnListened;
|
||||
static ScriptHook_t g_Hook_BuildScheduleTestBits;
|
||||
static ScriptHook_t g_Hook_StartTask;
|
||||
static ScriptHook_t g_Hook_RunTask;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -45,6 +45,10 @@ extern ConVar ai_use_think_optimizations;
|
||||
|
||||
ConVar ai_simulate_task_overtime( "ai_simulate_task_overtime", "0" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_enemy_memory_fixes( "ai_enemy_memory_fixes", "0", FCVAR_NONE, "Toggles Mapbase fixes for certain NPC AI not using enemy memory when it should." );
|
||||
#endif
|
||||
|
||||
#define MAX_TASKS_RUN 10
|
||||
|
||||
struct TaskTimings
|
||||
@ -276,6 +280,14 @@ void CAI_BaseNPC::NextScheduledTask ( void )
|
||||
void CAI_BaseNPC::BuildScheduleTestBits( void )
|
||||
{
|
||||
//NOTENOTE: Always defined in the leaf classes
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_BuildScheduleTestBits.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
g_Hook_BuildScheduleTestBits.Call( m_ScriptScope, &functionReturn, NULL );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -730,6 +742,23 @@ void CAI_BaseNPC::MaintainSchedule ( void )
|
||||
AI_PROFILE_SCOPE_BEGIN_( pszTaskName );
|
||||
AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_StartTask);
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_StartTask.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// task, task_id, task_data
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { (bDebugTaskNames) ? pszTaskName : TaskName( pTask->iTask ), pTask->iTask, pTask->flTaskData };
|
||||
if (g_Hook_StartTask.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
// Returning false overrides original functionality
|
||||
if (functionReturn.m_bool != false)
|
||||
StartTask( pTask );
|
||||
}
|
||||
else
|
||||
StartTask( pTask );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
StartTask( pTask );
|
||||
|
||||
AI_PROFILE_SCOPE_END();
|
||||
@ -766,6 +795,23 @@ void CAI_BaseNPC::MaintainSchedule ( void )
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_RunTask.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
// task, task_id, task_data
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { (bDebugTaskNames) ? pszTaskName : TaskName( pTask->iTask ), pTask->iTask, pTask->flTaskData };
|
||||
if (g_Hook_RunTask.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
// Returning false overrides original functionality
|
||||
if (functionReturn.m_bool != false)
|
||||
RunTask( pTask );
|
||||
}
|
||||
else
|
||||
RunTask( pTask );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
RunTask( pTask );
|
||||
|
||||
if ( GetTaskInterrupt() == 0 || TaskIsComplete() || HasCondition(COND_TASK_FAILED) )
|
||||
@ -1971,7 +2017,17 @@ void CAI_BaseNPC::StartTask( const Task_t *pTask )
|
||||
flMaxRange = m_flDistTooFar;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
// By default, TASK_GET_PATH_TO_ENEMY_LKP_LOS acts identical to TASK_GET_PATH_TO_ENEMY_LOS.
|
||||
// Considering the fact TASK_GET_PATH_TO_ENEMY_LKP doesn't use this code, this appears to be a mistake.
|
||||
// In HL2, this task is used by Combine soldiers, metrocops, striders, and hunters.
|
||||
// With this change, these NPCs will establish LOS according to enemy memory instead of where the enemy
|
||||
// actually is. This may make the NPCs more consistent and fair, but their AI and levels built around it
|
||||
// may have been designed around this bug, so this is currently being tied to a cvar.
|
||||
Vector vecEnemy = ( task != TASK_GET_PATH_TO_ENEMY_LKP_LOS || !ai_enemy_memory_fixes.GetBool() ) ? GetEnemy()->GetAbsOrigin() : GetEnemyLKP();
|
||||
#else
|
||||
Vector vecEnemy = ( task != TASK_GET_PATH_TO_ENEMY_LKP ) ? GetEnemy()->GetAbsOrigin() : GetEnemyLKP();
|
||||
#endif
|
||||
Vector vecEnemyEye = vecEnemy + GetEnemy()->GetViewOffset();
|
||||
|
||||
Vector posLos;
|
||||
|
@ -500,6 +500,13 @@ public:
|
||||
g_AI_SensedObjectsManager.Init();
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual void RegisterVScript()
|
||||
{
|
||||
g_pScriptVM->RegisterInstance( &g_AI_SensedObjectsManager, "SensedObjectsManager" );
|
||||
}
|
||||
#endif
|
||||
|
||||
void LevelShutdownPreEntity()
|
||||
{
|
||||
CBaseCombatCharacter::ResetVisibilityCache();
|
||||
|
@ -78,6 +78,7 @@ static void DispatchComeback( CAI_ExpresserWithFollowup *pExpress, CBaseEntity *
|
||||
// See DispatchFollowupThroughQueue()
|
||||
criteria.AppendCriteria( "From_idx", CNumStr( pSpeaker->entindex() ) );
|
||||
criteria.AppendCriteria( "From_class", pSpeaker->GetClassname() );
|
||||
pSpeaker->AppendContextToCriteria( criteria, "From_" );
|
||||
#endif
|
||||
// if a SUBJECT criteria is missing, put it back in.
|
||||
if ( criteria.FindCriterionIndex( "Subject" ) == -1 )
|
||||
|
@ -225,6 +225,18 @@ AI_EnemyInfo_t *CAI_Enemies::Find( CBaseEntity *pEntity, bool bTryDangerMemory )
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE
|
||||
unsigned char CAI_Enemies::FindIndex( CBaseEntity *pEntity )
|
||||
{
|
||||
if ( pEntity == AI_UNKNOWN_ENEMY )
|
||||
pEntity = NULL;
|
||||
|
||||
return m_Map.Find( pEntity );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
AI_EnemyInfo_t *CAI_Enemies::GetDangerMemory()
|
||||
|
@ -63,6 +63,9 @@ public:
|
||||
AI_EnemyInfo_t *GetFirst( AIEnemiesIter_t *pIter );
|
||||
AI_EnemyInfo_t *GetNext( AIEnemiesIter_t *pIter );
|
||||
AI_EnemyInfo_t *Find( CBaseEntity *pEntity, bool bTryDangerMemory = false );
|
||||
#ifdef MAPBASE
|
||||
unsigned char FindIndex( CBaseEntity *pEntity );
|
||||
#endif
|
||||
AI_EnemyInfo_t *GetDangerMemory();
|
||||
|
||||
int NumEnemies() const { return m_Map.Count(); }
|
||||
|
@ -298,6 +298,43 @@ CBaseEntity *CAI_Senses::GetNextSeenEntity( AISightIter_t *pIter ) const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool CAI_Senses::GetSeenEntityIndex( AISightIter_t *pIter, CBaseEntity *pSightEnt, seentype_t iSeenType ) const
|
||||
{
|
||||
COMPILE_TIME_ASSERT( sizeof( AISightIter_t ) == sizeof( AISightIterVal_t ) );
|
||||
|
||||
AISightIterVal_t *pIterVal = (AISightIterVal_t *)pIter;
|
||||
|
||||
// If we're searching for a specific type, start in that array
|
||||
pIterVal->SeenArray = (char)iSeenType;
|
||||
int iFirstArray = ( iSeenType == SEEN_ALL ) ? 0 : iSeenType;
|
||||
|
||||
for ( int i = iFirstArray; i < ARRAYSIZE( m_SeenArrays ); i++ )
|
||||
{
|
||||
for ( int j = pIterVal->iNext; j < m_SeenArrays[i]->Count(); j++ )
|
||||
{
|
||||
if ( (*m_SeenArrays[i])[j].Get() == pSightEnt )
|
||||
{
|
||||
pIterVal->array = i;
|
||||
pIterVal->iNext = j+1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pIterVal->iNext = 0;
|
||||
|
||||
// If we're searching for a specific type, don't move to the next array
|
||||
if ( pIterVal->SeenArray != SEEN_ALL )
|
||||
break;
|
||||
}
|
||||
|
||||
(*pIter) = (AISightIter_t)(-1);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CAI_Senses::BeginGather()
|
||||
@ -749,4 +786,27 @@ void CAI_SensedObjectsManager::AddEntity( CBaseEntity *pEntity )
|
||||
m_SensedObjects.AddToTail( pEntity );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CAI_SensedObjectsManager::RemoveEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
int i = m_SensedObjects.Find( pEntity );
|
||||
if (i == m_SensedObjects.InvalidIndex())
|
||||
return;
|
||||
|
||||
pEntity->RemoveFlag( FL_OBJECT );
|
||||
m_SensedObjects.FastRemove( i );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
BEGIN_SCRIPTDESC_ROOT( CAI_SensedObjectsManager, SCRIPT_SINGLETON "Manager which handles sensed objects." )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddEntity, "AddEntity", "Adds an entity to the sensed object list." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptRemoveEntity, "RemoveEntity", "Removes an entity from the sensed object list." )
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
|
@ -82,6 +82,9 @@ public:
|
||||
|
||||
CBaseEntity * GetFirstSeenEntity( AISightIter_t *pIter, seentype_t iSeenType = SEEN_ALL ) const;
|
||||
CBaseEntity * GetNextSeenEntity( AISightIter_t *pIter ) const;
|
||||
#ifdef MAPBASE
|
||||
bool GetSeenEntityIndex( AISightIter_t *pIter, CBaseEntity *pSightEnt, seentype_t iSeenType ) const;
|
||||
#endif
|
||||
|
||||
CSound * GetFirstHeardSound( AISoundIter_t *pIter );
|
||||
CSound * GetNextHeardSound( AISoundIter_t *pIter );
|
||||
@ -152,6 +155,14 @@ public:
|
||||
CBaseEntity * GetNext( int *pIter );
|
||||
|
||||
virtual void AddEntity( CBaseEntity *pEntity );
|
||||
#ifdef MAPBASE
|
||||
virtual void RemoveEntity( CBaseEntity *pEntity );
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
void ScriptAddEntity( HSCRIPT hEnt ) { AddEntity( ToEnt( hEnt ) ); }
|
||||
void ScriptRemoveEntity( HSCRIPT hEnt ) { RemoveEntity( ToEnt( hEnt ) ); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual void OnEntitySpawned( CBaseEntity *pEntity );
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "sceneentity.h"
|
||||
#include "ai_speechqueue.h"
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/choreosentence.h"
|
||||
#include "ai_squad.h"
|
||||
#endif
|
||||
|
||||
@ -846,6 +847,9 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res
|
||||
case ResponseRules::RESPONSE_NONE:
|
||||
break;
|
||||
|
||||
#ifdef MAPBASE
|
||||
case ResponseRules::RESPONSE_CHOREOSENTENCE:
|
||||
#endif
|
||||
case ResponseRules::RESPONSE_SPEAK:
|
||||
{
|
||||
if ( !result->ShouldntUseScene() )
|
||||
@ -918,7 +922,7 @@ bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *res
|
||||
textParams.g1 = 255;
|
||||
textParams.b1 = 255;
|
||||
|
||||
if (ai_speech_print_mode.GetBool() && GetOuter()->GetGameTextSpeechParams( textParams ))
|
||||
if (ai_speech_print_mode.GetBool() && GetOuter()->DispatchGetGameTextSpeechParams( textParams ))
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddAllPlayers();
|
||||
@ -1194,6 +1198,15 @@ float CAI_Expresser::GetResponseDuration( AI_Response *result )
|
||||
case ResponseRules::RESPONSE_NONE:
|
||||
case ResponseRules::RESPONSE_ENTITYIO:
|
||||
return 0.0f;
|
||||
#ifdef MAPBASE
|
||||
case ResponseRules::RESPONSE_CHOREOSENTENCE:
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( GetOuter(), response );
|
||||
if (pSentence)
|
||||
return GetChoreoSentenceDuration( GetOuter(), *pSentence );
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
|
@ -18,6 +18,10 @@
|
||||
|
||||
CAI_SquadManager g_AI_SquadManager;
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar ai_squad_broadcast_elusion("ai_squad_broadcast_elusion", "0", FCVAR_NONE, "Tells the entire squad when an enemy is eluded");
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAI_SquadManager
|
||||
//
|
||||
@ -740,6 +744,25 @@ void CAI_Squad::UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, c
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CAI_Squad::MarkEnemyAsEluded( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy )
|
||||
{
|
||||
if (!ai_squad_broadcast_elusion.GetBool())
|
||||
return;
|
||||
|
||||
//Broadcast to all members of the squad
|
||||
for ( int i = 0; i < m_SquadMembers.Count(); i++ )
|
||||
{
|
||||
if ( m_SquadMembers[i] != pUpdater )
|
||||
{
|
||||
m_SquadMembers[i]->GetEnemies()->MarkAsEluded( pEnemy );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifdef PER_ENEMY_SQUADSLOTS
|
||||
|
||||
AISquadEnemyInfo_t *CAI_Squad::FindEnemyInfo( CBaseEntity *pEnemy )
|
||||
@ -883,14 +906,14 @@ void CAI_Squad::ScriptRemoveFromSquad( HSCRIPT hNPC ) { RemoveFromSquad( HScrip
|
||||
|
||||
bool CAI_Squad::ScriptIsSilentMember( HSCRIPT hNPC ) { return IsSilentMember( HScriptToClass<CAI_BaseNPC>( hNPC ) ); }
|
||||
|
||||
void CAI_Squad::ScriptSetSquadData( int iSlot, const char *data )
|
||||
void CAI_Squad::ScriptSetSquadData( int iSlot, int data )
|
||||
{
|
||||
SetSquadData( iSlot, data );
|
||||
}
|
||||
|
||||
const char *CAI_Squad::ScriptGetSquadData( int iSlot )
|
||||
int CAI_Squad::ScriptGetSquadData( int iSlot )
|
||||
{
|
||||
const char *data;
|
||||
int data;
|
||||
GetSquadData( iSlot, &data );
|
||||
return data;
|
||||
}
|
||||
|
@ -107,6 +107,12 @@ public:
|
||||
|
||||
void SquadNewEnemy ( CBaseEntity *pEnemy );
|
||||
void UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, const Vector &position );
|
||||
#ifdef MAPBASE
|
||||
// The idea behind this is that, if one squad member fails to locate the enemy, nobody in the squad knows where the enemy is
|
||||
// Makes combat utilizing elusion a bit smoother
|
||||
// (gated by ai_squad_broadcast_elusion cvar)
|
||||
void MarkEnemyAsEluded( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy );
|
||||
#endif
|
||||
|
||||
bool OccupyStrategySlotRange( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd, int *pSlot );
|
||||
void VacateStrategySlot( CBaseEntity *pEnemy, int slot);
|
||||
@ -186,8 +192,8 @@ private:
|
||||
|
||||
bool ScriptIsSilentMember( HSCRIPT hNPC );
|
||||
|
||||
void ScriptSetSquadData( int iSlot, const char *data );
|
||||
const char *ScriptGetSquadData( int iSlot );
|
||||
void ScriptSetSquadData( int iSlot, int data );
|
||||
int ScriptGetSquadData( int iSlot );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
@ -317,7 +317,7 @@ BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceActivity, "GetSequenceActivity", "Gets the activity ID of the specified sequence index" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectWeightedSequence, "SelectWeightedSequence", "Selects a sequence for the specified activity ID" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectHeaviestSequence, "SelectHeaviestSequence", "Selects the sequence with the heaviest weight for the specified activity ID" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceKeyValues, "GetSequenceKeyValues", "Get a KeyValue class instance on the specified sequence. WARNING: This uses the same KeyValue pointer as GetModelKeyValues!" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceKeyValues, "GetSequenceKeyValues", "Get a KeyValue class instance on the specified sequence" )
|
||||
DEFINE_SCRIPTFUNC( ResetSequenceInfo, "" )
|
||||
DEFINE_SCRIPTFUNC( StudioFrameAdvance, "" )
|
||||
DEFINE_SCRIPTFUNC( GetPlaybackRate, "" )
|
||||
@ -1261,7 +1261,8 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (eventHandler->ScriptHookHandleAnimEvent( &event ) == false)
|
||||
scriptanimevent_t wrapper( event );
|
||||
if (!eventHandler->ScriptHookHandleAnimEvent( wrapper ))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
@ -1299,11 +1300,11 @@ void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseAnimating::ScriptHookHandleAnimEvent( animevent_t *pEvent )
|
||||
bool CBaseAnimating::ScriptHookHandleAnimEvent( scriptanimevent_t &event )
|
||||
{
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_HandleAnimEvent.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( reinterpret_cast<scriptanimevent_t*>(pEvent) );
|
||||
HSCRIPT hEvent = g_pScriptVM->RegisterInstance( &event );
|
||||
|
||||
// event
|
||||
ScriptVariant_t args[] = { hEvent };
|
||||
@ -2305,21 +2306,14 @@ void CBaseAnimating::ScriptGetBoneTransform( int iBone, HSCRIPT hTransform )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// VScript access to sequence's key values
|
||||
// for iteration and value access, use:
|
||||
// ScriptFindKey, ScriptGetFirstSubKey, ScriptGetString,
|
||||
// ScriptGetInt, ScriptGetFloat, ScriptGetNextKey
|
||||
// NOTE: This is recycled from ScriptGetModelKeyValues() and uses its pointer!!!
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseAnimating::ScriptGetSequenceKeyValues( int iSequence )
|
||||
HSCRIPT_RC CBaseAnimating::ScriptGetSequenceKeyValues( int iSequence )
|
||||
{
|
||||
KeyValues *pSeqKeyValues = GetSequenceKeyValues( iSequence );
|
||||
HSCRIPT hScript = NULL;
|
||||
if ( pSeqKeyValues )
|
||||
{
|
||||
// UNDONE: how does destructor get called on this
|
||||
m_pScriptModelKeyValues = hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pSeqKeyValues, true );
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??? Does name need to be unique???
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pSeqKeyValues );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include "datacache/idatacache.h"
|
||||
#include "tier0/threadtools.h"
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
struct scriptanimevent_t;
|
||||
#endif
|
||||
|
||||
struct animevent_t;
|
||||
struct matrix3x4_t;
|
||||
@ -146,7 +149,7 @@ public:
|
||||
virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); // Handle events that have happend since last time called up until X seconds into the future
|
||||
virtual void HandleAnimEvent( animevent_t *pEvent );
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
bool ScriptHookHandleAnimEvent( animevent_t *pEvent );
|
||||
bool ScriptHookHandleAnimEvent( scriptanimevent_t &event );
|
||||
#endif
|
||||
|
||||
int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName );
|
||||
@ -208,7 +211,7 @@ public:
|
||||
int ScriptSelectHeaviestSequence( int activity ) { return SelectHeaviestSequence( (Activity)activity ); }
|
||||
int ScriptSelectWeightedSequence( int activity, int curSequence ) { return SelectWeightedSequence( (Activity)activity, curSequence ); }
|
||||
|
||||
HSCRIPT ScriptGetSequenceKeyValues( int iSequence );
|
||||
HSCRIPT_RC ScriptGetSequenceKeyValues( int iSequence );
|
||||
|
||||
// For VScript
|
||||
int GetSkin() { return m_nSkin; }
|
||||
|
@ -3482,13 +3482,13 @@ void CBaseCombatCharacter::AddRelationship( const char *pszRelationship, CBaseEn
|
||||
bool bFoundEntity = false;
|
||||
|
||||
// Try to get pointer to an entity of this name
|
||||
CBaseEntity *entity = gEntList.FindEntityByName( NULL, entityString );
|
||||
CBaseEntity *entity = gEntList.FindEntityByName( NULL, entityString, this, pActivator );
|
||||
while( entity )
|
||||
{
|
||||
// make sure you catch all entities of this name.
|
||||
bFoundEntity = true;
|
||||
AddEntityRelationship(entity, disposition, priority );
|
||||
entity = gEntList.FindEntityByName( entity, entityString );
|
||||
entity = gEntList.FindEntityByName( entity, entityString, this, pActivator );
|
||||
}
|
||||
|
||||
if( !bFoundEntity )
|
||||
|
@ -1628,10 +1628,53 @@ void CBaseEntity::TakeDamage( const CTakeDamageInfo &inputInfo )
|
||||
DamageFilterDamageMod(info);
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_OnTakeDamage.CanRunInScope( m_ScriptScope ))
|
||||
{
|
||||
HSCRIPT hInfo = g_pScriptVM->RegisterInstance( &info );
|
||||
|
||||
// info
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ScriptVariant_t( hInfo ) };
|
||||
if ( g_Hook_OnTakeDamage.Call( m_ScriptScope, &functionReturn, args ) )
|
||||
{
|
||||
if (functionReturn.m_type == FIELD_BOOLEAN && functionReturn.m_bool == false)
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( hInfo );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_pScriptVM->RemoveInstance( hInfo );
|
||||
}
|
||||
#endif
|
||||
|
||||
OnTakeDamage( info );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Allows entities to be 'invisible' to NPC senses.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseEntity::CanBeSeenBy( CAI_BaseNPC *pNPC )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_CanBeSeenBy.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
// npc
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { ToHScript( pNPC ) };
|
||||
if (g_Hook_CanBeSeenBy.Call( m_ScriptScope, &functionReturn, args ))
|
||||
{
|
||||
if (functionReturn.m_bool == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns a value that scales all damage done by this entity.
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2251,14 +2294,16 @@ ScriptHook_t CBaseEntity::g_Hook_OnEntText;
|
||||
ScriptHook_t CBaseEntity::g_Hook_VPhysicsCollision;
|
||||
ScriptHook_t CBaseEntity::g_Hook_FireBullets;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnDeath;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnTakeDamage;
|
||||
ScriptHook_t CBaseEntity::g_Hook_OnKilledOther;
|
||||
ScriptHook_t CBaseEntity::g_Hook_HandleInteraction;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifyEmitSoundParams;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifySentenceParams;
|
||||
ScriptHook_t CBaseEntity::g_Hook_ModifyOrAppendCriteria;
|
||||
ScriptHook_t CBaseEntity::g_Hook_CanBeSeenBy;
|
||||
#endif
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( CBaseEntity, "Root class of all server-side entities", &g_BaseEntityScriptInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ConnectOutputToScript, "ConnectOutput", "Adds an I/O connection that will call the named function when the specified output fires" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( DisconnectOutputFromScript, "DisconnectOutput", "Removes a connected script function from an I/O event." )
|
||||
|
||||
@ -2377,6 +2422,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetContext, "GetContext", "Get a response context value" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptAddContext, "AddContext", "Add a response context value" )
|
||||
DEFINE_SCRIPTFUNC( RemoveContext, "Remove a response context" )
|
||||
DEFINE_SCRIPTFUNC( GetContextExpireTime, "Get a response context's expiration time" )
|
||||
DEFINE_SCRIPTFUNC( GetContextCount, "Get the number of response contexts" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetContextIndex, "GetContextIndex", "Get a response context at a specific index in the form of a table" )
|
||||
@ -2515,14 +2561,15 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
DEFINE_SCRIPTHOOK_PARAM( "normal", FIELD_VECTOR )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_FireBullets, "FireBullets", FIELD_VOID, "Called for every single VPhysics-related collision experienced by this entity." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "entity", FIELD_HSCRIPT )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "speed", FIELD_FLOAT )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "point", FIELD_VECTOR )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "normal", FIELD_VECTOR )
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_FireBullets, "FireBullets", FIELD_VOID, "Called when the entity fires bullets from itself or from a weapon. The parameter is the associated FireBulletsInfo_t handle. Return false to cancel bullet firing." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_OnDeath, "OnDeath", FIELD_BOOLEAN, "Called when the entity dies (Event_Killed). Returning false makes the entity cancel death, although this could have unforeseen consequences. For hooking any damage instead of just death, see filter_script and PassesFinalDamageFilter." )
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_OnDeath, "OnDeath", FIELD_BOOLEAN, "Called when the entity dies (Event_Killed). Returning false makes the entity cancel death, although this could have unforeseen consequences. For hooking any damage instead of just death, use OnTakeDamage." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_OnTakeDamage, "OnTakeDamage", FIELD_BOOLEAN, "Called when the entity takes damage (OnTakeDamage). Returning false makes the entity cancel the damage, similar to a damage filter. This is called after any damage filter operations." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "info", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
@ -2544,6 +2591,12 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_ModifySentenceParams, "ModifySentenceParams", FIELD_VOID, "Called every time a sentence is emitted on this entity, allowing for its parameters to be modified." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "params", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
|
||||
DEFINE_SIMPLE_SCRIPTHOOK( CBaseEntity::g_Hook_ModifyOrAppendCriteria, "ModifyOrAppendCriteria", FIELD_HSCRIPT, "Called when the criteria set is collected for a response. Return a table of keyvalues to add to the criteria set." )
|
||||
|
||||
BEGIN_SCRIPTHOOK( CBaseEntity::g_Hook_CanBeSeenBy, "CanBeSeenBy", FIELD_BOOLEAN, "Whether or not this entity can be seen by the specified NPC." )
|
||||
DEFINE_SCRIPTHOOK_PARAM( "npc", FIELD_HSCRIPT )
|
||||
END_SCRIPTHOOK()
|
||||
#endif
|
||||
END_SCRIPTDESC();
|
||||
|
||||
@ -7544,6 +7597,61 @@ void CBaseEntity::ModifyOrAppendCriteria( AI_CriteriaSet& set )
|
||||
set.AppendCriteria("spawnflags", UTIL_VarArgs("%i", GetSpawnFlags()));
|
||||
set.AppendCriteria("flags", UTIL_VarArgs("%i", GetFlags()));
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_ModifyOrAppendCriteria.CanRunInScope(m_ScriptScope))
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
if (g_Hook_ModifyOrAppendCriteria.Call( m_ScriptScope, &functionReturn, NULL ))
|
||||
{
|
||||
if (functionReturn.m_hScript != NULL)
|
||||
{
|
||||
int nIterator = -1;
|
||||
ScriptVariant_t varKey, varValue;
|
||||
while ((nIterator = g_pScriptVM->GetKeyValue( functionReturn.m_hScript, nIterator, &varKey, &varValue )) != -1)
|
||||
{
|
||||
float flWeight = 1.0f;
|
||||
char szValue[128];
|
||||
switch (varValue.m_type)
|
||||
{
|
||||
case FIELD_CSTRING:
|
||||
{
|
||||
char *colon = V_strstr( varValue.m_pszString, ":" );
|
||||
if (colon)
|
||||
{
|
||||
// Use as weight
|
||||
flWeight = atof(colon+1);
|
||||
*colon = NULL;
|
||||
}
|
||||
V_strncpy( szValue, varValue.m_pszString, sizeof( szValue ) );
|
||||
}
|
||||
break;
|
||||
case FIELD_BOOLEAN:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%d", varValue.m_bool );
|
||||
break;
|
||||
case FIELD_INTEGER:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%i", varValue.m_int );
|
||||
break;
|
||||
case FIELD_FLOAT:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%f", varValue.m_float );
|
||||
break;
|
||||
case FIELD_VECTOR:
|
||||
V_snprintf( szValue, sizeof( szValue ), "%f %f %f", varValue.m_pVector->x, varValue.m_pVector->y, varValue.m_pVector->z );
|
||||
break;
|
||||
default:
|
||||
Warning( "ModifyOrAppendCriteria doesn't know how to handle field %i for %s\n", varValue.m_type, varKey.m_pszString );
|
||||
break;
|
||||
}
|
||||
|
||||
set.AppendCriteria( varKey.m_pszString, szValue, flWeight );
|
||||
|
||||
g_pScriptVM->ReleaseValue( varKey );
|
||||
g_pScriptVM->ReleaseValue( varValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -10154,7 +10262,7 @@ void CBaseEntity::SetScriptOwnerEntity(HSCRIPT pOwner)
|
||||
// ScriptFindKey, ScriptGetFirstSubKey, ScriptGetString,
|
||||
// ScriptGetInt, ScriptGetFloat, ScriptGetNextKey
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::ScriptGetModelKeyValues( void )
|
||||
HSCRIPT_RC CBaseEntity::ScriptGetModelKeyValues( void )
|
||||
{
|
||||
KeyValues *pModelKeyValues = new KeyValues("");
|
||||
HSCRIPT hScript = NULL;
|
||||
@ -10163,16 +10271,12 @@ HSCRIPT CBaseEntity::ScriptGetModelKeyValues( void )
|
||||
|
||||
if ( pModelKeyValues->LoadFromBuffer( pszModelName, pBuffer ) )
|
||||
{
|
||||
// UNDONE: how does destructor get called on this
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
m_pScriptModelKeyValues = hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pModelKeyValues, true ); // Allow VScript to delete this when the instance is removed.
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pModelKeyValues );
|
||||
#else
|
||||
// UNDONE: how does destructor get called on this
|
||||
m_pScriptModelKeyValues = new CScriptKeyValues( pModelKeyValues );
|
||||
#endif
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??? Does name need to be unique???
|
||||
|
||||
#ifndef MAPBASE_VSCRIPT
|
||||
hScript = g_pScriptVM->RegisterInstance( m_pScriptModelKeyValues );
|
||||
#endif
|
||||
|
||||
|
@ -1440,7 +1440,7 @@ public:
|
||||
virtual bool FVisible ( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
virtual bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
|
||||
virtual bool CanBeSeenBy( CAI_BaseNPC *pNPC ) { return true; } // allows entities to be 'invisible' to NPC senses.
|
||||
virtual bool CanBeSeenBy( CAI_BaseNPC *pNPC ); // allows entities to be 'invisible' to NPC senses.
|
||||
|
||||
// This function returns a value that scales all damage done by this entity.
|
||||
// Use CDamageModifier to hook in damage modifiers on a guy.
|
||||
@ -2114,7 +2114,7 @@ public:
|
||||
#endif
|
||||
|
||||
const char* ScriptGetModelName(void) const;
|
||||
HSCRIPT ScriptGetModelKeyValues(void);
|
||||
HSCRIPT_RC ScriptGetModelKeyValues(void);
|
||||
|
||||
void ScriptStopSound(const char* soundname);
|
||||
void ScriptEmitSound(const char* soundname);
|
||||
@ -2177,10 +2177,13 @@ public:
|
||||
static ScriptHook_t g_Hook_VPhysicsCollision;
|
||||
static ScriptHook_t g_Hook_FireBullets;
|
||||
static ScriptHook_t g_Hook_OnDeath;
|
||||
static ScriptHook_t g_Hook_OnTakeDamage;
|
||||
static ScriptHook_t g_Hook_OnKilledOther;
|
||||
static ScriptHook_t g_Hook_HandleInteraction;
|
||||
static ScriptHook_t g_Hook_ModifyEmitSoundParams;
|
||||
static ScriptHook_t g_Hook_ModifySentenceParams;
|
||||
static ScriptHook_t g_Hook_ModifyOrAppendCriteria;
|
||||
static ScriptHook_t g_Hook_CanBeSeenBy;
|
||||
#endif
|
||||
|
||||
string_t m_iszVScripts;
|
||||
@ -2188,9 +2191,7 @@ public:
|
||||
CScriptScope m_ScriptScope;
|
||||
HSCRIPT m_hScriptInstance;
|
||||
string_t m_iszScriptId;
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
HSCRIPT m_pScriptModelKeyValues;
|
||||
#else
|
||||
#ifndef MAPBASE_VSCRIPT
|
||||
CScriptKeyValues* m_pScriptModelKeyValues;
|
||||
#endif
|
||||
};
|
||||
|
@ -816,7 +816,7 @@ bool CBaseFlex::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CCh
|
||||
textParams.g1 = 255;
|
||||
textParams.b1 = 255;
|
||||
|
||||
if ( GetGameTextSpeechParams( textParams ) )
|
||||
if ( DispatchGetGameTextSpeechParams( textParams ) )
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
filter.AddAllPlayers();
|
||||
@ -1654,6 +1654,12 @@ bool CBaseFlex::ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, C
|
||||
case CChoreoEvent::SPEAK:
|
||||
return true;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Prevents "unknown type" console spam on players
|
||||
case CChoreoEvent::GENERIC:
|
||||
return true;
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
Msg( "unknown type %d in ProcessSceneEvent()\n", event->GetType() );
|
||||
@ -2093,8 +2099,16 @@ float CBaseFlex::PlayScene( const char *pszScene, float flDelay, AI_Response *re
|
||||
#ifdef MAPBASE
|
||||
float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname, float flDelay, AI_Response *response, IRecipientFilter *filter )
|
||||
{
|
||||
if (response && response->GetType() == ResponseRules::RESPONSE_CHOREOSENTENCE)
|
||||
return InstancedChoreoSentenceScene( this, soundname, NULL, flDelay, false, response, false, filter );
|
||||
|
||||
return InstancedAutoGeneratedSoundScene( this, soundname, NULL, flDelay, false, response, false, filter );
|
||||
}
|
||||
|
||||
float CBaseFlex::PlayChoreoSentenceScene( const char *pszSentence, float flDelay, AI_Response *response, IRecipientFilter *filter )
|
||||
{
|
||||
return InstancedChoreoSentenceScene( this, pszSentence, NULL, flDelay, false, response, false, filter );
|
||||
}
|
||||
#else
|
||||
float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname )
|
||||
{
|
||||
@ -2106,11 +2120,17 @@ float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Parameters for scene event AI_GameText
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseFlex::GetGameTextSpeechParams( hudtextparms_t ¶ms )
|
||||
bool CBaseFlex::DispatchGetGameTextSpeechParams( hudtextparms_t ¶ms )
|
||||
{
|
||||
// First, get any default values overridden by this class
|
||||
bool bReturn = GetGameTextSpeechParams( params );
|
||||
|
||||
// Allow VScript to override after
|
||||
ScriptVariant_t varTable;
|
||||
if (g_pScriptVM->GetValue(m_ScriptScope, "m_GameTextSpeechParams", &varTable) && varTable.m_type == FIELD_HSCRIPT)
|
||||
if (g_pScriptVM->GetValue( m_ScriptScope, "m_GameTextSpeechParams", &varTable ) && varTable.m_type == FIELD_HSCRIPT)
|
||||
{
|
||||
bReturn = true;
|
||||
|
||||
int nIterator = -1;
|
||||
ScriptVariant_t varKey, varValue;
|
||||
while ((nIterator = g_pScriptVM->GetKeyValue( varTable.m_hScript, nIterator, &varKey, &varValue )) != -1)
|
||||
@ -2147,13 +2167,18 @@ bool CBaseFlex::GetGameTextSpeechParams( hudtextparms_t ¶ms )
|
||||
{
|
||||
params.fxTime = varValue.m_float;
|
||||
}
|
||||
else if (FStrEq( varKey.m_pszString, "disabled" ))
|
||||
{
|
||||
// Allow the params to disable game_text choreo if needed
|
||||
bReturn = !(varValue.m_int > 0);
|
||||
}
|
||||
|
||||
g_pScriptVM->ReleaseValue( varKey );
|
||||
g_pScriptVM->ReleaseValue( varValue );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return bReturn;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -129,6 +129,7 @@ public:
|
||||
|
||||
virtual float PlayScene( const char *pszScene, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
#ifdef MAPBASE
|
||||
virtual float PlayChoreoSentenceScene( const char *pszSentenceName, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
virtual float PlayAutoGeneratedSoundScene( const char *soundname, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL );
|
||||
#else
|
||||
virtual float PlayAutoGeneratedSoundScene( const char *soundname );
|
||||
@ -141,7 +142,8 @@ public:
|
||||
virtual int GetSpecialDSP( void ) { return 0; }
|
||||
|
||||
#ifdef MAPBASE
|
||||
virtual bool GetGameTextSpeechParams( hudtextparms_t ¶ms );
|
||||
bool DispatchGetGameTextSpeechParams( hudtextparms_t ¶ms );
|
||||
virtual bool GetGameTextSpeechParams( hudtextparms_t ¶ms ) { return true; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
@ -42,6 +42,10 @@ virtual void NullThink( void );
|
||||
|
||||
ConVar g_debug_basehelicopter( "g_debug_basehelicopter", "0", FCVAR_CHEAT );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar g_helicopter_use_sight_condition( "g_helicopter_use_sight_condition", "0", 0, "If enabled, helicopters will use the AI sight condition instead of just checking if there's a clear path to the player. This prevents them from cheating." );
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------
|
||||
//---------------------------------------------------------
|
||||
// TODOs
|
||||
@ -702,7 +706,11 @@ void CBaseHelicopter::UpdateEnemy()
|
||||
{
|
||||
CBaseEntity *pEnemy = GetEnemy();
|
||||
GatherEnemyConditions( pEnemy );
|
||||
#ifdef MAPBASE
|
||||
if ( (g_helicopter_use_sight_condition.GetBool() && pEnemy->Classify() != CLASS_BULLSEYE) ? HasCondition( COND_SEE_ENEMY ) : FVisible( pEnemy ) )
|
||||
#else
|
||||
if ( FVisible( pEnemy ) )
|
||||
#endif
|
||||
{
|
||||
if (m_flLastSeen < gpGlobals->curtime - 2)
|
||||
{
|
||||
|
@ -297,6 +297,19 @@ void CSpeaker::DispatchResponse( const char *conceptName )
|
||||
CAI_Expresser::RunScriptResponse( pTarget, response, &set, true );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef MAPBASE
|
||||
case ResponseRules::RESPONSE_CHOREOSENTENCE:
|
||||
{
|
||||
CBaseFlex *pFlex = NULL;
|
||||
if (pTarget != this)
|
||||
{
|
||||
// Attempt to get flex on the target
|
||||
pFlex = dynamic_cast<CBaseFlex*>(pTarget);
|
||||
}
|
||||
InstancedAutoGeneratedSoundScene(pFlex, response);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
|
@ -122,6 +122,7 @@ ConVar player_autoswitch_enabled( "player_autoswitch_enabled", "1", FCVAR_NONE,
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
ConVar hl2_use_sp_animstate( "hl2_use_sp_animstate", "1", FCVAR_NONE, "Allows SP HL2 players to use HL2:DM animations for custom player models. (changes may not apply until model is reloaded)" );
|
||||
ConVar player_process_scene_events( "player_process_scene_events", "1", FCVAR_NONE, "Allows players to process scene events." );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -268,6 +269,7 @@ public:
|
||||
void InputSetHandModelBodyGroup( inputdata_t &inputdata );
|
||||
|
||||
void InputSetPlayerModel( inputdata_t &inputdata );
|
||||
void InputSetPlayerDrawLegs( inputdata_t &inputdata );
|
||||
void InputSetPlayerDrawExternally( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
@ -691,6 +693,7 @@ IMPLEMENT_SERVERCLASS_ST(CHL2_Player, DT_HL2_Player)
|
||||
#endif
|
||||
#ifdef SP_ANIM_STATE
|
||||
SendPropFloat( SENDINFO(m_flAnimRenderYaw), 0, SPROP_NOSCALE ),
|
||||
SendPropFloat( SENDINFO(m_flAnimRenderZ), 0, SPROP_NOSCALE ),
|
||||
#endif
|
||||
END_SEND_TABLE()
|
||||
|
||||
@ -1183,6 +1186,18 @@ void CHL2_Player::PostThink( void )
|
||||
m_pPlayerAnimState->Update( angEyeAngles.y, angEyeAngles.x );
|
||||
|
||||
m_flAnimRenderYaw.Set( m_pPlayerAnimState->GetRenderAngles().y );
|
||||
|
||||
if (m_pPlayerAnimState->IsJumping() && !m_pPlayerAnimState->IsDuckJumping())
|
||||
{
|
||||
m_flAnimRenderZ.Set( -(GetViewOffset().z) );
|
||||
}
|
||||
else
|
||||
m_flAnimRenderZ.Set( 0.0f );
|
||||
|
||||
if (player_process_scene_events.GetBool())
|
||||
{
|
||||
ProcessSceneEvents();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1505,6 +1520,7 @@ CStudioHdr *CHL2_Player::OnNewModel()
|
||||
}
|
||||
|
||||
extern char g_szDefaultPlayerModel[MAX_PATH];
|
||||
extern bool g_bDefaultPlayerLegs;
|
||||
extern bool g_bDefaultPlayerDrawExternally;
|
||||
|
||||
extern char g_szDefaultProtagonist[MAX_PROTAGONIST_NAME];
|
||||
@ -1539,6 +1555,7 @@ void CHL2_Player::Spawn(void)
|
||||
RemoveEffects( EF_NODRAW );
|
||||
}
|
||||
|
||||
SetDrawPlayerLegs( g_bDefaultPlayerLegs );
|
||||
SetDrawPlayerModelExternally( g_bDefaultPlayerDrawExternally );
|
||||
|
||||
if (m_iszProtagonistName == NULL_STRING && *g_szDefaultProtagonist)
|
||||
@ -3376,6 +3393,11 @@ void CHL2_Player::Weapon_Equip( CBaseCombatWeapon *pWeapon )
|
||||
if( GetActiveWeapon() == NULL )
|
||||
{
|
||||
m_HL2Local.m_bWeaponLowered = false;
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if (m_pPlayerAnimState)
|
||||
m_pPlayerAnimState->StopWeaponRelax();
|
||||
#endif
|
||||
}
|
||||
|
||||
BaseClass::Weapon_Equip( pWeapon );
|
||||
@ -3781,6 +3803,11 @@ bool CHL2_Player::Weapon_Lower( void )
|
||||
|
||||
m_HL2Local.m_bWeaponLowered = true;
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if (m_pPlayerAnimState)
|
||||
m_pPlayerAnimState->StartWeaponRelax();
|
||||
#endif
|
||||
|
||||
CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(GetActiveWeapon());
|
||||
|
||||
if ( pWeapon == NULL )
|
||||
@ -3803,6 +3830,11 @@ bool CHL2_Player::Weapon_Ready( void )
|
||||
|
||||
m_HL2Local.m_bWeaponLowered = false;
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if (m_pPlayerAnimState)
|
||||
m_pPlayerAnimState->StopWeaponRelax();
|
||||
#endif
|
||||
|
||||
CBaseCombatWeapon *pWeapon = dynamic_cast<CBaseCombatWeapon *>(GetActiveWeapon());
|
||||
|
||||
if ( pWeapon == NULL )
|
||||
@ -4016,6 +4048,21 @@ void CHL2_Player::OnRestore()
|
||||
{
|
||||
BaseClass::OnRestore();
|
||||
m_pPlayerAISquad = g_AI_SquadManager.FindCreateSquad(AllocPooledString(PLAYER_SQUADNAME));
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
if ( m_pPlayerAnimState == NULL )
|
||||
{
|
||||
if ( GetModelPtr() && GetModelPtr()->HaveSequenceForActivity(ACT_HL2MP_IDLE) && hl2_use_sp_animstate.GetBool() )
|
||||
{
|
||||
// Here we create and init the player animation state.
|
||||
m_pPlayerAnimState = CreatePlayerAnimationState(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_flAnimRenderYaw = FLT_MAX;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
@ -4763,6 +4810,7 @@ BEGIN_DATADESC( CLogicPlayerProxy )
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelSkin", InputSetHandModelSkin ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHandModelBodyGroup", InputSetHandModelBodyGroup ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetPlayerModel", InputSetPlayerModel ),
|
||||
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawLegs", InputSetPlayerDrawLegs ),
|
||||
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetPlayerDrawExternally", InputSetPlayerDrawExternally ),
|
||||
DEFINE_INPUT( m_MaxArmor, FIELD_INTEGER, "SetMaxInputArmor" ),
|
||||
DEFINE_INPUT( m_SuitZoomFOV, FIELD_INTEGER, "SetSuitZoomFOV" ),
|
||||
@ -5241,6 +5289,15 @@ void CLogicPlayerProxy::InputSetPlayerModel( inputdata_t &inputdata )
|
||||
m_hPlayer->SetModel( STRING(iszModel) );
|
||||
}
|
||||
|
||||
void CLogicPlayerProxy::InputSetPlayerDrawLegs( inputdata_t &inputdata )
|
||||
{
|
||||
if (!m_hPlayer)
|
||||
return;
|
||||
|
||||
CBasePlayer *pPlayer = static_cast<CBasePlayer*>(m_hPlayer.Get());
|
||||
pPlayer->SetDrawPlayerLegs( inputdata.value.Bool() );
|
||||
}
|
||||
|
||||
void CLogicPlayerProxy::InputSetPlayerDrawExternally( inputdata_t &inputdata )
|
||||
{
|
||||
if (!m_hPlayer)
|
||||
|
@ -19,7 +19,7 @@
|
||||
#if defined ( HL2MP )
|
||||
#include "basemultiplayerplayer.h"
|
||||
#elif defined ( MAPBASE )
|
||||
#include "mapbase/singleplayer_animstate.h"
|
||||
#include "mapbase/mapbase_playeranimstate.h"
|
||||
#endif
|
||||
|
||||
class CAI_Squad;
|
||||
@ -458,11 +458,12 @@ private:
|
||||
#endif
|
||||
|
||||
#ifdef SP_ANIM_STATE
|
||||
CSinglePlayerAnimState* m_pPlayerAnimState;
|
||||
CMapbasePlayerAnimState* m_pPlayerAnimState;
|
||||
|
||||
// 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.
|
||||
CNetworkVar( float, m_flAnimRenderYaw );
|
||||
CNetworkVar( float, m_flAnimRenderZ );
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -63,3 +63,88 @@ BEGIN_DATADESC( CItemBattery )
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern ConVar sk_battery;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Custom player battery. Heals the player when picked up.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CItemBatteryCustom : public CItem
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CItemBatteryCustom, CItem );
|
||||
CItemBatteryCustom();
|
||||
|
||||
void Spawn( void );
|
||||
void Precache( void );
|
||||
bool MyTouch( CBasePlayer *pPlayer );
|
||||
|
||||
float GetItemAmount() { return m_flPowerAmount; }
|
||||
|
||||
void InputSetPowerAmount( inputdata_t &inputdata ) { m_flPowerAmount = inputdata.value.Float(); }
|
||||
|
||||
float m_flPowerAmount;
|
||||
string_t m_iszTouchSound;
|
||||
|
||||
DECLARE_DATADESC();
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( item_battery_custom, CItemBatteryCustom );
|
||||
|
||||
#ifdef MAPBASE
|
||||
BEGIN_DATADESC( CItemBatteryCustom )
|
||||
|
||||
DEFINE_KEYFIELD( m_flPowerAmount, FIELD_FLOAT, "PowerAmount" ),
|
||||
DEFINE_KEYFIELD( m_iszTouchSound, FIELD_STRING, "TouchSound" ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPowerAmount", InputSetPowerAmount ),
|
||||
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
|
||||
CItemBatteryCustom::CItemBatteryCustom()
|
||||
{
|
||||
SetModelName( AllocPooledString( "models/items/battery.mdl" ) );
|
||||
m_flPowerAmount = sk_battery.GetFloat();
|
||||
m_iszTouchSound = AllocPooledString( "ItemBattery.Touch" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItemBatteryCustom::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
SetModel( STRING( GetModelName() ) );
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItemBatteryCustom::Precache( void )
|
||||
{
|
||||
PrecacheModel( STRING( GetModelName() ) );
|
||||
|
||||
PrecacheScriptSound( STRING( m_iszTouchSound ) );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pPlayer -
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CItemBatteryCustom::MyTouch( CBasePlayer *pPlayer )
|
||||
{
|
||||
CHL2_Player *pHL2Player = assert_cast<CHL2_Player *>(pPlayer);
|
||||
if (!pHL2Player || sk_battery.GetFloat() == 0.0f)
|
||||
return false;
|
||||
|
||||
float flPowerMult = m_flPowerAmount / sk_battery.GetFloat();
|
||||
return pHL2Player->ApplyBattery( flPowerMult );
|
||||
}
|
||||
#endif
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "filters.h"
|
||||
#include "ai_hint.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
@ -164,6 +165,15 @@ ConVar g_helicopter_bullrush_mega_bomb_health( "g_helicopter_bullrush_mega_bomb_
|
||||
|
||||
ConVar g_helicopter_bomb_danger_radius( "g_helicopter_bomb_danger_radius", "120" );
|
||||
|
||||
#ifdef MAPBASE
|
||||
ConVar g_helicopter_crashpoint_nearest( "g_helicopter_crashpoint_nearest", "1", 0, "Selects the nearest crash point instead of just the first in the entity list." );
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
ConVar g_helicopter_phys_follow_while_crashing( "g_helicopter_phys_follow_while_crashing", "0", 0, "Allows the phys_bone_followers to follow the helicopter while flying to crash point" );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Activity ACT_HELICOPTER_DROP_BOMB;
|
||||
Activity ACT_HELICOPTER_CRASHING;
|
||||
|
||||
@ -191,7 +201,60 @@ enum
|
||||
|
||||
#define GRENADE_HELICOPTER_MODEL "models/combine_helicopter/helicopter_bomb01.mdl"
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTargetHelicopterCrash : public CPointEntity
|
||||
{
|
||||
DECLARE_CLASS( CTargetHelicopterCrash, CPointEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void InputEnable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisabled = false;
|
||||
}
|
||||
void InputDisable( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisabled = true;
|
||||
}
|
||||
bool IsDisabled( void )
|
||||
{
|
||||
return m_bDisabled;
|
||||
}
|
||||
void HelicopterCrashedOnTarget( CBaseHelicopter *pChopper )
|
||||
{
|
||||
m_OnCrashed.FireOutput( pChopper, this );
|
||||
}
|
||||
void HelicopterAcquiredCrashTarget( CBaseHelicopter *pChopper )
|
||||
{
|
||||
m_OnBeginCrash.FireOutput( pChopper, this );
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_bDisabled;
|
||||
|
||||
COutputEvent m_OnCrashed;
|
||||
COutputEvent m_OnBeginCrash;
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( info_target_helicopter_crash, CTargetHelicopterCrash );
|
||||
|
||||
BEGIN_DATADESC( CTargetHelicopterCrash )
|
||||
DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ),
|
||||
|
||||
// Inputs
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ),
|
||||
DEFINE_OUTPUT( m_OnBeginCrash, "OnBeginCrash" ),
|
||||
END_DATADESC()
|
||||
#else
|
||||
LINK_ENTITY_TO_CLASS( info_target_helicopter_crash, CPointEntity );
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -499,6 +562,13 @@ private:
|
||||
// Death, etc.
|
||||
void InputSelfDestruct( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// This is identical to SelfDestruct, except the helicopter won't throw out chunks while flying to a crash point.
|
||||
// This input is meant to be used when the pilot is killed and there's nothing wrong with the helicopter itself.
|
||||
// If there are no crash points, the helicopter will explode in place as normal.
|
||||
void InputSelfDestructNoFX( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
// Enemy visibility check
|
||||
CBaseEntity *FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos );
|
||||
|
||||
@ -522,6 +592,7 @@ private:
|
||||
|
||||
// Various states of the helicopter firing...
|
||||
bool PoseGunTowardTargetDirection( const Vector &vTargetDir );
|
||||
float GetGunPoseSpeed() const;
|
||||
|
||||
// Compute the position to fire at (vehicle + non-vehicle case)
|
||||
void ComputeFireAtPosition( Vector *pVecActualTargetPosition );
|
||||
@ -533,6 +604,17 @@ private:
|
||||
bool DoGunFiring( const Vector &vBasePos, const Vector &vGunDir, const Vector &vecFireAtPosition );
|
||||
void FireElectricityGun( );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Idle aiming
|
||||
bool FindIdleAimTarget();
|
||||
bool ValidIdleAimTarget( CBaseEntity *pAimTarget );
|
||||
|
||||
bool FValidateHintType( CAI_Hint *pHint );
|
||||
|
||||
inline CBaseEntity *GetIdleAimTarget() const { return m_hIdleAimTarget; }
|
||||
inline void SetIdleAimTarget( CBaseEntity *pNewAimTarget ) { m_hIdleAimTarget = pNewAimTarget; }
|
||||
#endif
|
||||
|
||||
// Chooses a point within the circle of death to fire in
|
||||
void PickDirectionToCircleOfDeath( const Vector &vBasePos, const Vector &vecFireAtPosition, Vector *pResult );
|
||||
|
||||
@ -650,6 +732,7 @@ private:
|
||||
void SpotlightStartup();
|
||||
void SpotlightShutdown();
|
||||
|
||||
CBaseEntity *FindCrashPoint();
|
||||
CBaseEntity *GetCrashPoint() { return m_hCrashPoint.Get(); }
|
||||
|
||||
private:
|
||||
@ -721,6 +804,17 @@ private:
|
||||
bool m_bBombsExplodeOnContact;
|
||||
bool m_bNonCombat;
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool m_bIdleAimAround;
|
||||
EHANDLE m_hIdleAimTarget;
|
||||
Vector m_vecIdleAimDir;
|
||||
float m_flNextIdleAimTime;
|
||||
|
||||
bool m_bDisableSmokeTrails;
|
||||
bool m_bDisableCorpses;
|
||||
bool m_bDisableExplosions;
|
||||
#endif
|
||||
|
||||
int m_nNearShots;
|
||||
int m_nMaxNearShots;
|
||||
|
||||
@ -860,6 +954,15 @@ BEGIN_DATADESC( CNPC_AttackHelicopter )
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bIdleAimAround, FIELD_BOOLEAN, "IdleAimAround" ),
|
||||
DEFINE_FIELD( m_hIdleAimTarget, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_vecIdleAimDir, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_flNextIdleAimTime, FIELD_TIME ),
|
||||
|
||||
DEFINE_KEYFIELD( m_bDisableSmokeTrails, FIELD_BOOLEAN, "DisableSmokeTrails" ),
|
||||
DEFINE_KEYFIELD( m_bDisableCorpses, FIELD_BOOLEAN, "DisableCorpses" ),
|
||||
DEFINE_KEYFIELD( m_bDisableExplosions, FIELD_BOOLEAN, "DisableExplosions" ),
|
||||
#endif
|
||||
|
||||
DEFINE_FIELD( m_hCrashPoint, FIELD_EHANDLE ),
|
||||
@ -896,6 +999,9 @@ BEGIN_DATADESC( CNPC_AttackHelicopter )
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "EnablePathVisibilityTests", InputEnablePathVisibilityTests ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestruct", InputSelfDestruct ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestructNoFX", InputSelfDestructNoFX ),
|
||||
#endif
|
||||
|
||||
DEFINE_THINKFUNC( BlinkLightsThink ),
|
||||
DEFINE_THINKFUNC( SpotlightThink ),
|
||||
@ -1646,6 +1752,21 @@ void CNPC_AttackHelicopter::InputSelfDestruct( inputdata_t &inputdata )
|
||||
TakeDamage( info );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
void CNPC_AttackHelicopter::InputSelfDestructNoFX( inputdata_t &inputdata )
|
||||
{
|
||||
m_bDisableSmokeTrails = true;
|
||||
m_bDisableCorpses = true;
|
||||
m_bDisableExplosions = true;
|
||||
|
||||
m_lifeState = LIFE_ALIVE; // Force to die properly.
|
||||
CTakeDamageInfo info( this, this, Vector(0, 0, 1), WorldSpaceCenter(), GetMaxHealth(), CLASS_MISSILE );
|
||||
TakeDamage( info );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// For scripted times where it *has* to shoot
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2245,21 +2366,23 @@ bool CNPC_AttackHelicopter::PoseGunTowardTargetDirection( const Vector &vTargetD
|
||||
}
|
||||
}
|
||||
|
||||
float flPoseSpeed = GetGunPoseSpeed();
|
||||
|
||||
if (angles.x > m_angGun.x)
|
||||
{
|
||||
m_angGun.x = MIN( angles.x, m_angGun.x + 12 );
|
||||
m_angGun.x = MIN( angles.x, m_angGun.x + flPoseSpeed );
|
||||
}
|
||||
if (angles.x < m_angGun.x)
|
||||
{
|
||||
m_angGun.x = MAX( angles.x, m_angGun.x - 12 );
|
||||
m_angGun.x = MAX( angles.x, m_angGun.x - flPoseSpeed );
|
||||
}
|
||||
if (angles.y > m_angGun.y)
|
||||
{
|
||||
m_angGun.y = MIN( angles.y, m_angGun.y + 12 );
|
||||
m_angGun.y = MIN( angles.y, m_angGun.y + flPoseSpeed );
|
||||
}
|
||||
if (angles.y < m_angGun.y)
|
||||
{
|
||||
m_angGun.y = MAX( angles.y, m_angGun.y - 12 );
|
||||
m_angGun.y = MAX( angles.y, m_angGun.y - flPoseSpeed );
|
||||
}
|
||||
|
||||
SetPoseParameter( m_poseWeapon_Pitch, -m_angGun.x );
|
||||
@ -2269,6 +2392,20 @@ bool CNPC_AttackHelicopter::PoseGunTowardTargetDirection( const Vector &vTargetD
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Various states of the helicopter firing...
|
||||
//------------------------------------------------------------------------------
|
||||
float CNPC_AttackHelicopter::GetGunPoseSpeed() const
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (m_bIdleAimAround && !GetEnemy())
|
||||
return 4.0f;
|
||||
#endif
|
||||
|
||||
return 12.0f;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Compute the enemy position (non-vehicle case)
|
||||
//------------------------------------------------------------------------------
|
||||
@ -2363,6 +2500,87 @@ bool CNPC_AttackHelicopter::DoGunIdle( const Vector &vGunDir, const Vector &vTar
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds an idle aim target. Based on CNPC_PlayerCompanion code
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::FindIdleAimTarget()
|
||||
{
|
||||
CAI_Hint *pHint;
|
||||
CHintCriteria hintCriteria;
|
||||
CBaseEntity *pPriorAimTarget = GetIdleAimTarget();
|
||||
|
||||
hintCriteria.SetHintType( HINT_WORLD_VISUALLY_INTERESTING );
|
||||
hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV | bits_HINT_NODE_USE_GROUP | bits_HINT_NODE_NEAREST );
|
||||
hintCriteria.AddIncludePosition( GetAbsOrigin(), CHOPPER_MAX_GUN_DIST );
|
||||
pHint = CAI_HintManager::FindHint( this, hintCriteria );
|
||||
|
||||
if( pHint )
|
||||
{
|
||||
if ( !ValidIdleAimTarget( pHint ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( pHint != pPriorAimTarget )
|
||||
{
|
||||
// Notify of the change.
|
||||
SetIdleAimTarget( pHint );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find an aim target, or found the same one.
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finds an idle aim target. Based on CNPC_PlayerCompanion code
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::ValidIdleAimTarget( CBaseEntity *pAimTarget )
|
||||
{
|
||||
Vector vecTargetOrigin = pAimTarget->GetAbsOrigin();
|
||||
|
||||
Vector vBasePos;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos );
|
||||
|
||||
if ( vecTargetOrigin.z > vBasePos.z || (vecTargetOrigin - vBasePos).Length() < 128.0f )
|
||||
{
|
||||
// Too close!
|
||||
return false;
|
||||
}
|
||||
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( vBasePos, vecTargetOrigin, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 1.0f && tr.m_pEnt != pAimTarget )
|
||||
{
|
||||
// No LOS
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CNPC_AttackHelicopter::FValidateHintType( CAI_Hint *pHint )
|
||||
{
|
||||
switch( pHint->HintType() )
|
||||
{
|
||||
case HINT_WORLD_VISUALLY_INTERESTING:
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return BaseClass::FValidateHintType( pHint );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// How easy is the target to hit?
|
||||
//------------------------------------------------------------------------------
|
||||
@ -3653,12 +3871,20 @@ int CNPC_AttackHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) && !m_bDisableSmokeTrails )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) )
|
||||
#endif
|
||||
{
|
||||
AddSmokeTrail( info.GetDamagePosition() );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_CORPSES ) && !m_bDisableCorpses )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_CORPSES ) )
|
||||
#endif
|
||||
{
|
||||
if ( nPrevHealth != GetMaxHealth() )
|
||||
{
|
||||
@ -3666,7 +3892,11 @@ int CNPC_AttackHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) && !m_bDisableExplosions )
|
||||
#else
|
||||
if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) )
|
||||
#endif
|
||||
{
|
||||
ExplodeAndThrowChunk( info.GetDamagePosition() );
|
||||
}
|
||||
@ -3774,6 +4004,46 @@ void Chopper_BecomeChunks( CBaseEntity *pChopper )
|
||||
pBodyChunk->m_pCockpitConstraint = physenv->CreateFixedConstraint( pBodyObject, pCockpitObject, pGroup, fixed );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Find a valid crash point
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseEntity *CNPC_AttackHelicopter::FindCrashPoint()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
float flNearest = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH;
|
||||
CTargetHelicopterCrash *pNearest = NULL;
|
||||
CBaseEntity *pEnt = NULL;
|
||||
while( (pEnt = gEntList.FindEntityByClassname(pEnt, "info_target_helicopter_crash")) != NULL )
|
||||
{
|
||||
CTargetHelicopterCrash *pCrashTarget = assert_cast<CTargetHelicopterCrash*>(pEnt);
|
||||
if ( pCrashTarget->IsDisabled() )
|
||||
continue;
|
||||
|
||||
if (g_helicopter_crashpoint_nearest.GetBool())
|
||||
{
|
||||
float flDist = ( pEnt->WorldSpaceCenter() - WorldSpaceCenter() ).LengthSqr();
|
||||
if( flDist < flNearest )
|
||||
{
|
||||
pNearest = pCrashTarget;
|
||||
flNearest = flDist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pNearest = pCrashTarget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pNearest)
|
||||
pNearest->HelicopterAcquiredCrashTarget( this );
|
||||
|
||||
return pNearest;
|
||||
#else
|
||||
return gEntList.FindEntityByClassname( NULL, "info_target_helicopter_crash" );
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start us crashing
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -3791,7 +4061,7 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info )
|
||||
|
||||
if( GetCrashPoint() == NULL )
|
||||
{
|
||||
CBaseEntity *pCrashPoint = gEntList.FindEntityByClassname( NULL, "info_target_helicopter_crash" );
|
||||
CBaseEntity *pCrashPoint = FindCrashPoint();
|
||||
if( pCrashPoint != NULL )
|
||||
{
|
||||
m_hCrashPoint.Set( pCrashPoint );
|
||||
@ -3812,6 +4082,12 @@ void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info )
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else
|
||||
{
|
||||
assert_cast<CTargetHelicopterCrash*>( GetCrashPoint() )->HelicopterCrashedOnTarget( this );
|
||||
}
|
||||
#endif
|
||||
|
||||
Chopper_BecomeChunks( this );
|
||||
StopLoopingSounds();
|
||||
@ -3869,7 +4145,11 @@ void CNPC_AttackHelicopter::PrescheduleThink( void )
|
||||
SetDesiredPosition( GetCrashPoint()->WorldSpaceCenter() );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( !m_bDisableExplosions && random->RandomInt( 0, 4 ) == 0 )
|
||||
#else
|
||||
if ( random->RandomInt( 0, 4 ) == 0 )
|
||||
#endif
|
||||
{
|
||||
Vector explodePoint;
|
||||
CollisionProp()->RandomPointInBounds( Vector(0.25,0.25,0.25), Vector(0.75,0.75,0.75), &explodePoint );
|
||||
@ -4821,6 +5101,15 @@ void CNPC_AttackHelicopter::Hunt( void )
|
||||
{
|
||||
Flight();
|
||||
UpdatePlayerDopplerShift( );
|
||||
|
||||
#if defined(MAPBASE) && defined(HL2_EPISODIC)
|
||||
if (g_helicopter_phys_follow_while_crashing.GetBool())
|
||||
{
|
||||
// Update our bone followers
|
||||
m_BoneFollowerManager.UpdateBoneFollowers( this );
|
||||
}
|
||||
#endif // HL2_EPISODIC
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4885,6 +5174,55 @@ void CNPC_AttackHelicopter::Hunt( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_bIdleAimAround)
|
||||
{
|
||||
if (!GetEnemy())
|
||||
{
|
||||
if (GetIdleAimTarget())
|
||||
{
|
||||
if (!ValidIdleAimTarget( GetIdleAimTarget() ))
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
m_flNextIdleAimTime = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_flNextIdleAimTime < gpGlobals->curtime)
|
||||
{
|
||||
if (!FindIdleAimTarget())
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
|
||||
// Find a random direction in front of us instead
|
||||
Vector vBasePos, vecForward, vecRight, vecUp;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos, &vecForward, &vecRight, &vecUp );
|
||||
|
||||
m_vecIdleAimDir = vecForward + (vecRight * RandomFloat( -0.25f, 0.25f )) + (vecUp * RandomFloat( -0.8f, -0.25f ));
|
||||
}
|
||||
|
||||
m_flNextIdleAimTime = gpGlobals->curtime + RandomFloat( 4.0f, 6.0f );
|
||||
}
|
||||
|
||||
if (GetIdleAimTarget())
|
||||
{
|
||||
// Get gun attachment points
|
||||
Vector vBasePos;
|
||||
GetAttachment( m_nGunBaseAttachment, vBasePos );
|
||||
|
||||
m_vecIdleAimDir = GetIdleAimTarget()->GetAbsOrigin() - vBasePos;
|
||||
VectorNormalize( m_vecIdleAimDir );
|
||||
}
|
||||
|
||||
PoseGunTowardTargetDirection( m_vecIdleAimDir );
|
||||
}
|
||||
else if (GetIdleAimTarget())
|
||||
{
|
||||
SetIdleAimTarget( NULL );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
// Update our bone followers
|
||||
m_BoneFollowerManager.UpdateBoneFollowers(this);
|
||||
|
@ -2551,6 +2551,24 @@ int CNPC_Combine::TranslateSchedule( int scheduleType )
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern ConVar ai_enemy_memory_fixes;
|
||||
|
||||
// SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE uses TASK_GET_PATH_TO_ENEMY_LKP_LOS, a task with a mistake
|
||||
// detailed in CAI_BaseNPC::StartTask and fixed by ai_enemy_memory_fixes.
|
||||
//
|
||||
// However, SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE only stops being used once the NPC has LOS to its target.
|
||||
// Since the fixed task now uses the enemy's last known position instead of the enemy's actual position,
|
||||
// this schedule risks getting stuck in a loop.
|
||||
//
|
||||
// This code makes the soldier run up directly to the last known position if it's visible, allowing the AI
|
||||
// to mark the enemy as eluded.
|
||||
if ( ai_enemy_memory_fixes.GetBool() && FVisible( GetEnemyLKP() ) )
|
||||
{
|
||||
return SCHED_COMBINE_PRESS_ATTACK;
|
||||
}
|
||||
#endif
|
||||
|
||||
return SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE;
|
||||
}
|
||||
break;
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
int RangeAttack2Conditions( float flDot, float flDist ); // For innate grenade attack
|
||||
int MeleeAttack1Conditions( float flDot, float flDist ); // For kick/punch
|
||||
bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); }
|
||||
virtual bool IsCurTaskContinuousMove();
|
||||
|
||||
virtual float GetJumpGravity() const { return 1.8f; }
|
||||
|
@ -134,6 +134,11 @@ enum LandingState_t
|
||||
LANDING_HOVER_DESCEND,
|
||||
LANDING_HOVER_TOUCHDOWN,
|
||||
LANDING_END_HOVER,
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Strider dropoff
|
||||
LANDING_STRIDER,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -295,6 +300,9 @@ private:
|
||||
bool IsHovering();
|
||||
void UpdateGroundRotorWashSound( float flAltitude );
|
||||
void UpdateRotorWashVolume( CSoundPatch *pRotorSound, float flVolume, float flDeltaTime );
|
||||
#ifdef MAPBASE
|
||||
void DeathNotice(CBaseEntity* pVictim);
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Timers
|
||||
@ -353,6 +361,12 @@ private:
|
||||
string_t m_sRollermineTemplate;
|
||||
string_t m_sRollermineTemplateData;
|
||||
|
||||
#ifdef MAPBASE
|
||||
// Template for strider carried by this dropship
|
||||
string_t m_sStriderTemplate;
|
||||
string_t m_sStriderTemplateData;
|
||||
#endif
|
||||
|
||||
// Cached attachment points
|
||||
int m_iMuzzleAttachment;
|
||||
int m_iMachineGunBaseAttachment;
|
||||
@ -827,6 +841,11 @@ BEGIN_DATADESC( CNPC_CombineDropship )
|
||||
DEFINE_KEYFIELD( m_sRollermineTemplate, FIELD_STRING, "RollermineTemplate" ),
|
||||
DEFINE_FIELD( m_sRollermineTemplateData, FIELD_STRING ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_KEYFIELD(m_sStriderTemplate, FIELD_STRING, "StriderTemplate"),
|
||||
DEFINE_FIELD(m_sStriderTemplateData, FIELD_STRING),
|
||||
#endif
|
||||
|
||||
DEFINE_ARRAY( m_sNPCTemplateData, FIELD_STRING, DROPSHIP_MAX_SOLDIERS ),
|
||||
DEFINE_KEYFIELD( m_sNPCTemplate[0], FIELD_STRING, "NPCTemplate" ),
|
||||
DEFINE_KEYFIELD( m_sNPCTemplate[1], FIELD_STRING, "NPCTemplate2" ),
|
||||
@ -962,12 +981,60 @@ void CNPC_CombineDropship::Spawn( void )
|
||||
break;
|
||||
|
||||
case CRATE_STRIDER:
|
||||
#ifdef MAPBASE
|
||||
if ( m_sStriderTemplate != NULL_STRING )
|
||||
{
|
||||
m_sStriderTemplateData = Templates_FindByTargetName( STRING( m_sStriderTemplate ) );
|
||||
if (m_sStriderTemplateData == NULL_STRING)
|
||||
{
|
||||
Warning("npc_combinedropship %s: Strider Template %s not found!\n", STRING(GetEntityName()), STRING(m_sStriderTemplate));
|
||||
break;
|
||||
}
|
||||
|
||||
CAI_BaseNPC* pent = NULL;
|
||||
CBaseEntity* pEntity = NULL;
|
||||
MapEntity_ParseEntity( pEntity, STRING( m_sStriderTemplateData ), NULL);
|
||||
if ( pEntity != NULL )
|
||||
{
|
||||
pent = ( CAI_BaseNPC* )pEntity;
|
||||
}
|
||||
|
||||
if ( !FClassnameIs(pent, "npc_strider"))
|
||||
{
|
||||
Warning("npc_combinedropship %s: Strider Template %s is not a strider!\n", STRING(GetEntityName()), STRING(m_sStriderTemplate));
|
||||
break;
|
||||
}
|
||||
|
||||
m_OnSpawnNPC.Set( pEntity, pEntity, this );
|
||||
|
||||
pent->RemoveSpawnFlags( SF_NPC_TEMPLATE );
|
||||
|
||||
pent->SetOwnerEntity( this );
|
||||
|
||||
m_hContainer = pent;
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector(0, 0, 100) );
|
||||
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||
m_hContainer->SetParent( this, 0 );
|
||||
m_hContainer->SetOwnerEntity( this );
|
||||
DispatchSpawn(pent);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hContainer = ( CBaseAnimating* )CreateEntityByName("npc_strider");
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector(0, 0, 100) );
|
||||
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||
m_hContainer->SetParent( this, 0 );
|
||||
m_hContainer->SetOwnerEntity( this );
|
||||
m_hContainer->Spawn();
|
||||
}
|
||||
#else
|
||||
m_hContainer = (CBaseAnimating*)CreateEntityByName( "npc_strider" );
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
||||
m_hContainer->SetAbsAngles( GetAbsAngles() );
|
||||
m_hContainer->SetParent(this, 0);
|
||||
m_hContainer->SetOwnerEntity(this);
|
||||
m_hContainer->Spawn();
|
||||
#endif
|
||||
m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) );
|
||||
#ifdef MAPBASE
|
||||
m_OnSpawnNPC.Set( m_hContainer, m_hContainer, this );
|
||||
@ -1201,13 +1268,24 @@ void CNPC_CombineDropship::Precache( void )
|
||||
void CNPC_CombineDropship::Flight( void )
|
||||
{
|
||||
// Only run the flight model in some flight states
|
||||
#ifdef MAPBASE
|
||||
bool bRunFlight = ( GetLandingState() == LANDING_NO ||
|
||||
GetLandingState() == LANDING_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_LIFTOFF ||
|
||||
GetLandingState() == LANDING_SWOOPING ||
|
||||
GetLandingState() == LANDING_DESCEND ||
|
||||
GetLandingState() == LANDING_HOVER_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_HOVER_DESCEND );
|
||||
GetLandingState() == LANDING_HOVER_DESCEND ||
|
||||
GetLandingState() == LANDING_STRIDER );
|
||||
#else
|
||||
bool bRunFlight = (GetLandingState() == LANDING_NO ||
|
||||
GetLandingState() == LANDING_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_LIFTOFF ||
|
||||
GetLandingState() == LANDING_SWOOPING ||
|
||||
GetLandingState() == LANDING_DESCEND ||
|
||||
GetLandingState() == LANDING_HOVER_LEVEL_OUT ||
|
||||
GetLandingState() == LANDING_HOVER_DESCEND );
|
||||
#endif
|
||||
|
||||
Vector forward, right, up;
|
||||
GetVectors( &forward, &right, &up );
|
||||
@ -1429,8 +1507,14 @@ void CNPC_CombineDropship::Flight( void )
|
||||
}
|
||||
|
||||
// If we're landing, deliberately tuck in the back end
|
||||
#ifdef MAPBASE
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN ||
|
||||
GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED ||
|
||||
GetLandingState() == LANDING_STRIDER || IsHovering() )
|
||||
#else
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN ||
|
||||
GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED || IsHovering() )
|
||||
#endif
|
||||
{
|
||||
finspeed = -60;
|
||||
}
|
||||
@ -1779,6 +1863,16 @@ void CNPC_CombineDropship::InputDropStrider( inputdata_t &inputdata )
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (m_iszLandTarget != NULL_STRING)
|
||||
{
|
||||
LandCommon();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLandingState(LANDING_STRIDER);
|
||||
}
|
||||
#else
|
||||
QAngle angles = GetAbsAngles();
|
||||
|
||||
angles.x = 0.0;
|
||||
@ -1790,6 +1884,7 @@ void CNPC_CombineDropship::InputDropStrider( inputdata_t &inputdata )
|
||||
m_hContainer->SetAbsVelocity( vec3_origin );
|
||||
|
||||
m_hContainer = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2016,7 +2111,11 @@ void CNPC_CombineDropship::SetLandingState( LandingState_t landingState )
|
||||
if ( m_pDescendingWarningSound )
|
||||
{
|
||||
CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController();
|
||||
#ifdef MAPBASE
|
||||
if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) || ( landingState == LANDING_STRIDER ) )
|
||||
#else
|
||||
if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) )
|
||||
#endif
|
||||
{
|
||||
controller.SoundChangeVolume( m_pDescendingWarningSound, m_bSuppressSound ? 0.0f : 1.0f, 0.3f );
|
||||
}
|
||||
@ -2112,8 +2211,15 @@ void CNPC_CombineDropship::PrescheduleThink( void )
|
||||
if ( flDistance < 70 && flSpeed < 100 )
|
||||
{
|
||||
m_flLandingSpeed = flSpeed;
|
||||
|
||||
if( IsHovering() )
|
||||
#ifdef MAPBASE
|
||||
if ( m_iCrateType == CRATE_STRIDER )
|
||||
{
|
||||
SetLandingState( LANDING_STRIDER );
|
||||
}
|
||||
else if( IsHovering() )
|
||||
#else
|
||||
if ( IsHovering() )
|
||||
#endif
|
||||
{
|
||||
SetLandingState( LANDING_HOVER_DESCEND );
|
||||
}
|
||||
@ -2315,6 +2421,98 @@ void CNPC_CombineDropship::PrescheduleThink( void )
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef MAPBASE
|
||||
case LANDING_STRIDER:
|
||||
{
|
||||
if (!m_hContainer)
|
||||
{
|
||||
// Strider died, get out of here
|
||||
SetLandingState(LANDING_LIFTOFF);
|
||||
return;
|
||||
}
|
||||
|
||||
// Orient myself to the desired direction
|
||||
bool bStillOrienting = false;
|
||||
Vector targetDir;
|
||||
if (m_hLandTarget)
|
||||
{
|
||||
// We've got a land target, so match it's orientation
|
||||
AngleVectors(m_hLandTarget->GetAbsAngles(), &targetDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No land target.
|
||||
targetDir = GetDesiredPosition() - GetAbsOrigin();
|
||||
}
|
||||
|
||||
// Don't unload until we're facing the way the dropoff point specifies
|
||||
float flTargetYaw = UTIL_VecToYaw(targetDir);
|
||||
float flDeltaYaw = UTIL_AngleDiff(flTargetYaw, GetAbsAngles().y);
|
||||
if (fabs(flDeltaYaw) > 5)
|
||||
{
|
||||
bStillOrienting = true;
|
||||
}
|
||||
|
||||
// Ensure we land on the drop point. Stop dropping if we're still turning.
|
||||
Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin());
|
||||
float flDistance = vecToTarget.Length();
|
||||
float flRampedSpeed = m_flLandingSpeed * (flDistance / 70);
|
||||
Vector vecVelocity = (flRampedSpeed / flDistance) * vecToTarget;
|
||||
|
||||
#define STRIDER_LANDING_HEIGHT 540.0f
|
||||
|
||||
float flFactor = MIN(1.0, MAX(0.1f, (flAltitude - STRIDER_LANDING_HEIGHT) / flAltitude));
|
||||
float flDescendVelocity = MIN(-75, MAX_LAND_VEL * flFactor);
|
||||
|
||||
vecVelocity.z = flDescendVelocity;
|
||||
|
||||
SetAbsVelocity(vecVelocity);
|
||||
|
||||
if (flAltitude < 600)
|
||||
{
|
||||
QAngle angles = GetLocalAngles();
|
||||
|
||||
// Level out quickly.
|
||||
angles.x = UTIL_Approach(0.0, angles.x, 0.2);
|
||||
angles.z = UTIL_Approach(0.0, angles.z, 0.2);
|
||||
|
||||
SetLocalAngles(angles);
|
||||
}
|
||||
else
|
||||
{
|
||||
// randomly move as if buffeted by ground effects
|
||||
// gently flatten ship from starting pitch/yaw
|
||||
m_existPitch = UTIL_Approach(0.0, m_existPitch, 1);
|
||||
m_existRoll = UTIL_Approach(0.0, m_existRoll, 1);
|
||||
|
||||
QAngle angles = GetLocalAngles();
|
||||
angles.x = m_existPitch + (sin(gpGlobals->curtime * 3.5f) * DROPSHIP_MAX_LAND_TILT);
|
||||
angles.z = m_existRoll + (sin(gpGlobals->curtime * 3.75f) * DROPSHIP_MAX_LAND_TILT);
|
||||
SetLocalAngles(angles);
|
||||
}
|
||||
|
||||
DoRotorWash();
|
||||
|
||||
if (!bStillOrienting && flAltitude < STRIDER_LANDING_HEIGHT)
|
||||
{
|
||||
QAngle angles = GetAbsAngles();
|
||||
|
||||
m_hContainer->SetParent(NULL, 0);
|
||||
m_hContainer->SetOwnerEntity(NULL);
|
||||
m_hContainer->SetAbsAngles(angles);
|
||||
m_hContainer->SetAbsVelocity(vec3_origin);
|
||||
|
||||
m_hContainer = NULL;
|
||||
|
||||
m_flTimeTakeOff = gpGlobals->curtime + 3.5f;
|
||||
SetLandingState(LANDING_UNLOADING);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LANDING_UNLOADING:
|
||||
{
|
||||
// If we've got no specified takeoff time, we're still waiting for troops to exit. Idle.
|
||||
@ -2817,7 +3015,11 @@ void CNPC_CombineDropship::UpdatePickupNavigation( void )
|
||||
void CNPC_CombineDropship::UpdateLandTargetNavigation( void )
|
||||
{
|
||||
Vector vecPickup = m_hLandTarget->WorldSpaceCenter();
|
||||
#ifdef MAPBASE
|
||||
vecPickup.z += ( m_iCrateType == CRATE_STRIDER ) ? 732 : 256;
|
||||
#else
|
||||
vecPickup.z += 256;
|
||||
#endif
|
||||
SetDesiredPosition( vecPickup );
|
||||
|
||||
//NDebugOverlay::Cross3D( GetDesiredPosition(), -Vector(32,32,32), Vector(32,32,32), 0, 255, 255, true, 0.1f );
|
||||
@ -2850,7 +3052,11 @@ void CNPC_CombineDropship::Hunt( void )
|
||||
// Face our desired position.
|
||||
m_vecDesiredFaceDir = desiredDir;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || GetLandingState() == LANDING_STRIDER || IsHovering() )
|
||||
#else
|
||||
if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || IsHovering() )
|
||||
#endif
|
||||
{
|
||||
if ( m_hLandTarget )
|
||||
{
|
||||
@ -3150,6 +3356,19 @@ void CNPC_CombineDropship::MakeTracer( const Vector &vecTracerSrc, const trace_t
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Need a way to tell if our strider died
|
||||
//-----------------------------------------------------------------------------
|
||||
void CNPC_CombineDropship::DeathNotice( CBaseEntity *pVictim )
|
||||
{
|
||||
if ( m_iCrateType == CRATE_STRIDER && GetLandingState() == LANDING_NO )
|
||||
{
|
||||
m_OnContainerShotDownBeforeDropoff.Set( 1, m_hContainer, this );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
AI_BEGIN_CUSTOM_NPC( npc_combinedropship, CNPC_CombineDropship )
|
||||
|
||||
DECLARE_ACTIVITY( ACT_DROPSHIP_FLY_IDLE );
|
||||
|
@ -187,15 +187,29 @@ public:
|
||||
{
|
||||
return m_bDisabled;
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
void GunshipCrashedOnTarget( CBaseHelicopter *pGunship )
|
||||
{
|
||||
m_OnCrashed.FireOutput( pGunship, this );
|
||||
}
|
||||
void GunshipAcquiredCrashTarget( CBaseHelicopter *pGunship )
|
||||
{
|
||||
m_OnBeginCrash.FireOutput( pGunship, this );
|
||||
}
|
||||
#else
|
||||
void GunshipCrashedOnTarget( void )
|
||||
{
|
||||
m_OnCrashed.FireOutput( this, this );
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_bDisabled;
|
||||
|
||||
COutputEvent m_OnCrashed;
|
||||
#ifdef MAPBASE
|
||||
COutputEvent m_OnBeginCrash;
|
||||
#endif
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( info_target_gunshipcrash, CTargetGunshipCrash );
|
||||
@ -209,6 +223,9 @@ BEGIN_DATADESC( CTargetGunshipCrash )
|
||||
|
||||
// Outputs
|
||||
DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_OUTPUT( m_OnBeginCrash, "OnBeginCrash" ),
|
||||
#endif
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
@ -1564,7 +1581,11 @@ void CNPC_CombineGunship::PrescheduleThink( void )
|
||||
{
|
||||
BeginDestruct();
|
||||
m_OnCrashed.FireOutput( this, this );
|
||||
#ifdef MAPBASE
|
||||
m_hCrashTarget->GunshipCrashedOnTarget( this );
|
||||
#else
|
||||
m_hCrashTarget->GunshipCrashedOnTarget();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1976,6 +1997,10 @@ bool CNPC_CombineGunship::FindNearestGunshipCrash( void )
|
||||
m_flNextGunshipCrashFind = gpGlobals->curtime + 0.5;
|
||||
m_flEndDestructTime = 0;
|
||||
|
||||
#ifdef MAPBASE
|
||||
m_hCrashTarget->GunshipAcquiredCrashTarget( this );
|
||||
#endif
|
||||
|
||||
if ( g_debug_gunship.GetInt() )
|
||||
{
|
||||
NDebugOverlay::Line(GetAbsOrigin(), m_hCrashTarget->GetAbsOrigin(), 0,255,0, true, 0.5);
|
||||
|
@ -1327,6 +1327,15 @@ void CNPC_Strider::BuildScheduleTestBits()
|
||||
//---------------------------------------------------------
|
||||
int CNPC_Strider::SelectSchedule()
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if( GetMoveType() == MOVETYPE_NONE )
|
||||
{
|
||||
// Dropship just released me.
|
||||
AddFlag(FL_FLY);
|
||||
SetMoveType( MOVETYPE_STEP );
|
||||
return SCHED_STRIDER_FALL_TO_GROUND;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
if( GetMoveType() != MOVETYPE_FLY )
|
||||
{
|
||||
@ -1511,6 +1520,26 @@ int CNPC_Strider::TranslateSchedule( int scheduleType )
|
||||
return SCHED_COMBAT_PATROL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
extern ConVar ai_enemy_memory_fixes;
|
||||
|
||||
// Striders convert TASK_GET_PATH_TO_ENEMY_LOS to TASK_GET_PATH_TO_ENEMY_LKP_LOS, a task which incorrectly
|
||||
// acts identically to the former. This is detailed in CAI_BaseNPC::StartTask and fixed by ai_enemy_memory_fixes.
|
||||
//
|
||||
// However, SCHED_ESTABLISH_LINE_OF_FIRE only stops being used once the NPC has LOS to its target.
|
||||
// Since the fixed task now uses the enemy's last known position instead of the enemy's actual position,
|
||||
// this schedule risks getting stuck in a loop.
|
||||
//
|
||||
// This code chains back up to SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK, which is what's supposed to happen when a
|
||||
// strider is eluded in this way.
|
||||
if ( ai_enemy_memory_fixes.GetBool() && FVisible( GetEnemyLKP() ) )
|
||||
{
|
||||
return TranslateSchedule( SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -5818,6 +5847,18 @@ AI_BEGIN_CUSTOM_NPC( npc_strider, CNPC_Strider )
|
||||
" COND_STRIDER_SHOULD_STAND"
|
||||
)
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_STRIDER_FALL_TO_GROUND,
|
||||
|
||||
" Tasks "
|
||||
" TASK_SOUND_WAKE 0"
|
||||
" TASK_PLAY_SEQUENCE ACTIVITY:ACT_STRIDER_DEPLOY"
|
||||
""
|
||||
" Interrupts "
|
||||
)
|
||||
#else
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_STRIDER_FALL_TO_GROUND,
|
||||
@ -5827,7 +5868,7 @@ AI_BEGIN_CUSTOM_NPC( npc_strider, CNPC_Strider )
|
||||
""
|
||||
" Interrupts "
|
||||
)
|
||||
|
||||
#endif
|
||||
|
||||
AI_END_CUSTOM_NPC()
|
||||
|
||||
|
@ -188,6 +188,7 @@ public:
|
||||
bool HasPass() { return m_PlayerFreePass.HasPass(); }
|
||||
|
||||
bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
|
||||
bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); }
|
||||
Vector BodyTarget( const Vector &posSrc, bool bNoisy );
|
||||
|
||||
bool IsValidEnemy( CBaseEntity *pTarget );
|
||||
|
@ -2645,16 +2645,19 @@ Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget )
|
||||
{
|
||||
// By default, aim for the center
|
||||
Vector vecTarget = pTarget->WorldSpaceCenter();
|
||||
const Vector vecBulletOrigin = GetBulletOrigin();
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if (m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope(m_ScriptScope))
|
||||
if ( m_ScriptScope.IsInitialized() && g_Hook_GetActualShootPosition.CanRunInScope( m_ScriptScope ) )
|
||||
{
|
||||
ScriptVariant_t functionReturn;
|
||||
ScriptVariant_t args[] = { GetBulletOrigin(), ToHScript( pTarget ) };
|
||||
if (g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ))
|
||||
ScriptVariant_t args[] = { vecBulletOrigin, ToHScript( pTarget ) };
|
||||
if ( g_Hook_GetActualShootPosition.Call( m_ScriptScope, &functionReturn, args ) )
|
||||
{
|
||||
if (functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f)
|
||||
if ( functionReturn.m_type == FIELD_VECTOR && functionReturn.m_pVector->LengthSqr() != 0.0f )
|
||||
{
|
||||
return *functionReturn.m_pVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -2682,12 +2685,12 @@ Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget )
|
||||
{
|
||||
if( flTimeSinceLastMiss > 0.0f && flTimeSinceLastMiss < 4.0f && hl2_episodic.GetBool() )
|
||||
{
|
||||
vecTarget = pTarget->BodyTarget( GetBulletOrigin(), false );
|
||||
vecTarget = pTarget->BodyTarget( vecBulletOrigin, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shoot zombies in the headcrab
|
||||
vecTarget = pTarget->HeadTarget( GetBulletOrigin() );
|
||||
vecTarget = pTarget->HeadTarget( vecBulletOrigin );
|
||||
}
|
||||
}
|
||||
else if( pTarget->Classify() == CLASS_ANTLION )
|
||||
|
985
sp/src/game/server/mapbase/choreosentence.cpp
Normal file
985
sp/src/game/server/mapbase/choreosentence.cpp
Normal file
@ -0,0 +1,985 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: VCD-based sentences.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "utlhashtable.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "soundchars.h"
|
||||
#include "choreosentence.h"
|
||||
#include "mapbase/matchers.h"
|
||||
#include "ai_speech_new.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define IsVirtualWord(pszWord) (pszWord[0] == 'V' && pszWord[1] == '_')
|
||||
#define RemoveVirtualPrefix(pszWord) IsVirtualWord(pszWord) ? pszWord + 2 : pszWord
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class CChoreoSentenceSystem : public CAutoGameSystem
|
||||
{
|
||||
public:
|
||||
|
||||
struct VirtualWord_t;
|
||||
struct VirtualWordDefinition_t;
|
||||
struct VirtualWordDefinitionList_t;
|
||||
struct SentenceContextPrerequisite_t;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
CChoreoSentenceSystem() : m_Strings( 256, 0, &StringLessThan ) { }
|
||||
~CChoreoSentenceSystem() { PurgeSentences(); }
|
||||
|
||||
bool Init()
|
||||
{
|
||||
// Load the default choreo sentences files
|
||||
LoadChoreoSentenceManifest( "scripts/choreosentences_manifest.txt" );
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
PurgeSentences();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void LoadChoreoSentenceManifest( const char *pszFile )
|
||||
{
|
||||
KeyValues *pManifest = new KeyValues( "ChoreoSentencesManifest" );
|
||||
if (pManifest->LoadFromFile( filesystem, pszFile ))
|
||||
{
|
||||
FOR_EACH_SUBKEY( pManifest, pSubKey )
|
||||
{
|
||||
LoadChoreoSentenceFile( pSubKey->GetString() );
|
||||
}
|
||||
}
|
||||
pManifest->deleteThis();
|
||||
|
||||
//m_Strings.Compact( true );
|
||||
}
|
||||
|
||||
void LoadChoreoSentenceFile( const char *pszFile )
|
||||
{
|
||||
KeyValues *pManifest = new KeyValues( "ChoreoSentences" );
|
||||
if (pManifest->LoadFromFile( filesystem, pszFile ))
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
// Context Prerequisites
|
||||
//----------------------------------------------------------------------------
|
||||
KeyValues *pSentenceContextPrerequisites = pManifest->FindKey( "SentenceContextPrerequisites" );
|
||||
FOR_EACH_SUBKEY( pSentenceContextPrerequisites, pSubKey )
|
||||
{
|
||||
KeyValues *pCondition = pSubKey->GetFirstSubKey();
|
||||
if (pCondition)
|
||||
{
|
||||
//
|
||||
// Only add if there is a subkey for condition
|
||||
//
|
||||
int i = m_ContextPrerequisites.AddToTail();
|
||||
m_ContextPrerequisites[i].nConditionType = DeduceCondition( pCondition->GetName(), V_strlen( pCondition->GetName() ) );
|
||||
|
||||
m_ContextPrerequisites[i].pszContextName = AllocateString( pSubKey->GetName() );
|
||||
m_ContextPrerequisites[i].pszCondition = AllocateString( pCondition->GetString() );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Virtual Words
|
||||
//----------------------------------------------------------------------------
|
||||
KeyValues *pVirtualWords = pManifest->FindKey( "VirtualWords" );
|
||||
FOR_EACH_SUBKEY( pVirtualWords, pSubKey )
|
||||
{
|
||||
//
|
||||
// Determine if this has nested virtual words or not
|
||||
//
|
||||
KeyValues *pMatches = pSubKey->FindKey( "matches" );
|
||||
if (pMatches)
|
||||
{
|
||||
//
|
||||
// It has nested virtual words
|
||||
//
|
||||
int i = m_VirtualWordLists.Insert( RemoveVirtualPrefix( pSubKey->GetName() ) );
|
||||
m_VirtualWordLists[i].pszCriterion = AllocateString( pSubKey->GetString( "criterion" ) );
|
||||
|
||||
bool bFirst = true;
|
||||
FOR_EACH_SUBKEY( pMatches, pWordList )
|
||||
{
|
||||
if (bFirst)
|
||||
{
|
||||
// First one is always default
|
||||
if (LoadVirtualWordDefinitionFromKV( pWordList, m_VirtualWordLists[i].m_DefaultWordDefinition, pSubKey->GetName() ))
|
||||
bFirst = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i2 = m_VirtualWordLists[i].m_WordDefinitions.Insert( pWordList->GetName() );
|
||||
if (!LoadVirtualWordDefinitionFromKV( pWordList, m_VirtualWordLists[i].m_WordDefinitions[i2], pSubKey->GetName() ))
|
||||
m_VirtualWordLists[i].m_WordDefinitions.RemoveAt( i2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// It is a virtual word
|
||||
//
|
||||
int i = m_VirtualWords.Insert( RemoveVirtualPrefix( pSubKey->GetName() ) );
|
||||
if (!LoadVirtualWordDefinitionFromKV( pSubKey, m_VirtualWords[i], pSubKey->GetName() ))
|
||||
m_VirtualWords.RemoveAt( i );
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Sentences
|
||||
//----------------------------------------------------------------------------
|
||||
KeyValues *pSentences = pManifest->FindKey( "Sentences" );
|
||||
FOR_EACH_SUBKEY( pSentences, pSetKey )
|
||||
{
|
||||
FOR_EACH_SUBKEY( pSetKey, pSubKey )
|
||||
{
|
||||
if (pSubKey->GetName() && *pSubKey->GetString())
|
||||
{
|
||||
int i = m_Sentences.Insert( pSubKey->GetName() );
|
||||
|
||||
char szPathName[MAX_PATH];
|
||||
V_strncpy( szPathName, pSetKey->GetName(), sizeof( szPathName ) );
|
||||
V_FixSlashes( szPathName );
|
||||
m_Sentences[i].pszPrefix = AllocateString( szPathName );
|
||||
|
||||
//m_Sentences[i].pszPrefix = AllocateString( pSetKey->GetName() );
|
||||
|
||||
ParseChoreoSentence( NULL, pSubKey->GetString(), m_Sentences[i] );
|
||||
m_Sentences[i].pszName = m_Sentences.GetElementName( i );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pManifest->deleteThis();
|
||||
}
|
||||
|
||||
bool LoadVirtualWordDefinitionFromKV( KeyValues *pWordList, VirtualWordDefinition_t &wordDefinition, const char *pszWordName )
|
||||
{
|
||||
//
|
||||
// Get the condition for this virtual word
|
||||
//
|
||||
KeyValues *pCondition = pWordList->FindKey( "condition" );
|
||||
if (pCondition)
|
||||
{
|
||||
int nStrLen = V_strlen( pCondition->GetString() );
|
||||
const char *pColon = V_strnchr( pCondition->GetString(), ':', nStrLen );
|
||||
if (pColon)
|
||||
{
|
||||
wordDefinition.pszCondition = AllocateString( pColon + 1 );
|
||||
wordDefinition.nConditionType = DeduceCondition( pCondition->GetString(), pColon - pCondition->GetString() );
|
||||
}
|
||||
else
|
||||
{
|
||||
wordDefinition.nConditionType = DeduceCondition( pCondition->GetString(), nStrLen );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wordDefinition.nConditionType = 0;
|
||||
wordDefinition.pszCondition = "";
|
||||
}
|
||||
|
||||
//
|
||||
// Get the words themselves
|
||||
//
|
||||
KeyValues *pWords = pWordList->FindKey( "words" );
|
||||
if (pWords)
|
||||
{
|
||||
FOR_EACH_SUBKEY( pWords, pWord )
|
||||
{
|
||||
int i = wordDefinition.m_Words.AddToTail();
|
||||
V_strncpy( wordDefinition.m_Words[i].szWord, pWord->GetString(), sizeof( wordDefinition.m_Words[i].szWord ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pWords = pWordList->FindKey( "words_from" );
|
||||
if (pWords)
|
||||
{
|
||||
const char *pszWordsTarget = RemoveVirtualPrefix( pWords->GetString() );
|
||||
|
||||
//
|
||||
// Get from another virtual word
|
||||
//
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWords.GetElementName( i ), pszWordsTarget ))
|
||||
{
|
||||
wordDefinition.m_Words.AddVectorToTail( m_VirtualWords[i].m_Words );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wordDefinition.m_Words.Count() <= 0)
|
||||
{
|
||||
Warning( "WARNING: No words found on virtual word %s\n", pszWordName );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void PurgeSentences()
|
||||
{
|
||||
m_ContextPrerequisites.RemoveAll();
|
||||
m_VirtualWordLists.RemoveAll();
|
||||
m_VirtualWords.RemoveAll();
|
||||
m_Sentences.RemoveAll();
|
||||
|
||||
for (unsigned int i = 0; i < m_Strings.Count(); i++)
|
||||
{
|
||||
delete m_Strings[i];
|
||||
}
|
||||
m_Strings.Purge();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void PrintEverything()
|
||||
{
|
||||
Msg( "CONTEXT PREREQUISITES\n\n" );
|
||||
|
||||
FOR_EACH_VEC( m_ContextPrerequisites, i )
|
||||
{
|
||||
Msg( "\t\"%s\"\n\t\tCondition: %i (\"%s\")\n\n", m_ContextPrerequisites[i].pszContextName, m_ContextPrerequisites[i].nConditionType, m_ContextPrerequisites[i].pszCondition );
|
||||
}
|
||||
|
||||
Msg( "VIRTUAL WORDS\n\n" );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
char szWords[256] = { 0 };
|
||||
FOR_EACH_VEC( m_VirtualWords[i].m_Words, nWord )
|
||||
{
|
||||
V_strncat( szWords, "\t\t\t\"", sizeof( szWords ) );
|
||||
V_strncat( szWords, m_VirtualWords[i].m_Words[nWord].szWord, sizeof( szWords ) );
|
||||
V_strncat( szWords, "\"\n", sizeof( szWords ) );
|
||||
}
|
||||
|
||||
Msg( "\t\"%s\"\n\t\tCondition: %i (\"%s\")\n\t\tWords:\n%s\n\n", m_VirtualWords.GetElementName( i ), m_VirtualWords[i].nConditionType, m_VirtualWords[i].pszCondition, szWords );
|
||||
}
|
||||
|
||||
Msg( "SENTENCES\n\n" );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_Sentences, i )
|
||||
{
|
||||
char szWords[128] = { 0 };
|
||||
FOR_EACH_VEC( m_Sentences[i].m_Words, nWord )
|
||||
{
|
||||
if (m_Sentences[i].m_Words[nWord].nPitch != 100)
|
||||
{
|
||||
V_snprintf( szWords, sizeof( szWords ), "%s(p%i) ", szWords, m_Sentences[i].m_Words[nWord].nPitch );
|
||||
}
|
||||
|
||||
if (m_Sentences[i].m_Words[nWord].nVol != 100)
|
||||
{
|
||||
V_snprintf( szWords, sizeof( szWords ), "%s(v%i) ", szWords, m_Sentences[i].m_Words[nWord].nVol );
|
||||
}
|
||||
|
||||
V_strncat( szWords, "\"", sizeof( szWords ) );
|
||||
V_strncat( szWords, m_Sentences[i].m_Words[nWord].pszWord, sizeof( szWords ) );
|
||||
V_strncat( szWords, "\" ", sizeof( szWords ) );
|
||||
}
|
||||
|
||||
Msg( "\t\"%s\"\n\t\tPrefix: \"%s\"\n\t\tCaption: \"%s\"\n\t\tWords: %s\n\n", m_Sentences.GetElementName( i ), m_Sentences[i].pszPrefix, m_Sentences[i].pszCaption ? m_Sentences[i].pszCaption : "N/A", szWords);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintStrings()
|
||||
{
|
||||
CUtlVector<const char*> strings( 0, m_Strings.Count() );
|
||||
for ( UtlHashHandle_t i = m_Strings.FirstInorder(); i != m_Strings.InvalidIndex(); i = m_Strings.NextInorder(i) )
|
||||
{
|
||||
strings.AddToTail( m_Strings[i] );
|
||||
}
|
||||
|
||||
struct _Local {
|
||||
static int __cdecl F(const char * const *a, const char * const *b) { return strcmp(*a, *b); }
|
||||
};
|
||||
strings.Sort( _Local::F );
|
||||
|
||||
for ( int i = 0; i < strings.Count(); ++i )
|
||||
{
|
||||
Msg( " %d (0x%p) : %s\n", i, strings[i], strings[i] );
|
||||
}
|
||||
Msg( "\n" );
|
||||
Msg( "Size: %d items\n", strings.Count() );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const ChoreoSentence_t *LookupChoreoSentence( CBaseEntity *pSpeaker, const char *pszSentenceName )
|
||||
{
|
||||
FOR_EACH_DICT_FAST( m_Sentences, i )
|
||||
{
|
||||
if (FStrEq( m_Sentences.GetElementName( i ), pszSentenceName ))
|
||||
{
|
||||
return &m_Sentences[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void PrecacheVirtualWord( const char *pszWord, const char *pszPrefix, const char *pszSuffix )
|
||||
{
|
||||
pszWord = RemoveVirtualPrefix( pszWord );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWords.GetElementName( i ), pszWord ))
|
||||
{
|
||||
// Precache all words
|
||||
FOR_EACH_VEC( m_VirtualWords[i].m_Words, i2 )
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( UTIL_VarArgs( "%s%s%s", pszPrefix, m_VirtualWords[i].m_Words[i2].szWord, pszSuffix ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWordLists, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWordLists.GetElementName( i ), pszWord ))
|
||||
{
|
||||
// Precache all words in default definition
|
||||
FOR_EACH_VEC( m_VirtualWordLists[i].m_DefaultWordDefinition.m_Words, i2 )
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( UTIL_VarArgs( "%s%s%s", pszPrefix, m_VirtualWordLists[i].m_DefaultWordDefinition.m_Words[i2].szWord, pszSuffix));
|
||||
}
|
||||
|
||||
// Precache all words in nested definitions
|
||||
FOR_EACH_DICT( m_VirtualWordLists[i].m_WordDefinitions, i2 )
|
||||
{
|
||||
FOR_EACH_VEC( m_VirtualWordLists[i].m_WordDefinitions[i2].m_Words, i3 )
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( UTIL_VarArgs( "%s%s%s", pszPrefix, m_VirtualWordLists[i].m_WordDefinitions[i2].m_Words[i3].szWord, pszSuffix ) );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline const VirtualWord_t &ResolveVirtualWordDefinition( CBaseEntity *pSpeaker, const VirtualWordDefinition_t &wordDefinition )
|
||||
{
|
||||
// Resolve this condition
|
||||
int nIndex = ResolveVirtualCondition( pSpeaker, wordDefinition.nConditionType, wordDefinition.pszCondition, wordDefinition.m_Words.Count() );
|
||||
Assert( nIndex >= 0 && nIndex < wordDefinition.m_Words.Count() );
|
||||
|
||||
return wordDefinition.m_Words[nIndex];
|
||||
}
|
||||
|
||||
const char *ResolveVirtualWord( CBaseEntity *pSpeaker, const char *pszWord )
|
||||
{
|
||||
pszWord = RemoveVirtualPrefix( pszWord );
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWords, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWords.GetElementName( i ), pszWord ))
|
||||
{
|
||||
return ResolveVirtualWordDefinition( pSpeaker, m_VirtualWords[i] ).szWord;
|
||||
}
|
||||
}
|
||||
|
||||
FOR_EACH_DICT_FAST( m_VirtualWordLists, i )
|
||||
{
|
||||
if (FStrEq( m_VirtualWordLists.GetElementName( i ), pszWord ))
|
||||
{
|
||||
AI_CriteriaSet set;
|
||||
if (pSpeaker)
|
||||
pSpeaker->ModifyOrAppendCriteria( set );
|
||||
|
||||
int nCriterion = set.FindCriterionIndex( m_VirtualWordLists[i].pszCriterion );
|
||||
if (set.IsValidIndex( nCriterion ))
|
||||
{
|
||||
const char *pszValue = set.GetValue( nCriterion );
|
||||
|
||||
// Find the set of virtual words that matches the criterion
|
||||
FOR_EACH_DICT( m_VirtualWordLists[i].m_WordDefinitions, i2 )
|
||||
{
|
||||
if (Matcher_Match( m_VirtualWordLists[i].m_WordDefinitions.GetElementName(i2), pszValue ))
|
||||
{
|
||||
return ResolveVirtualWordDefinition( pSpeaker, m_VirtualWordLists[i].m_WordDefinitions[i2] ).szWord;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the default
|
||||
return ResolveVirtualWordDefinition( pSpeaker, m_VirtualWordLists[i].m_DefaultWordDefinition ).szWord;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGWarning( 0, CON_GROUP_CHOREO, "Choreo sentence can't find virtual word \"%s\"\n", pszWord );
|
||||
return "";
|
||||
}
|
||||
|
||||
int ResolveVirtualCondition( CBaseEntity *pSpeaker, int nConditionType, const char *pszCondition, int nWordCount )
|
||||
{
|
||||
switch (nConditionType)
|
||||
{
|
||||
default:
|
||||
case ConditionType_None:
|
||||
// Randomize between each word
|
||||
return RandomInt( 0, nWordCount - 1 );
|
||||
break;
|
||||
|
||||
case ConditionType_Context:
|
||||
// Return context as integer
|
||||
if (pSpeaker)
|
||||
{
|
||||
if (pSpeaker->FindContextByName( pszCondition ) == -1)
|
||||
{
|
||||
// Check if this is a prerequisite, and if it is, then apply it
|
||||
FOR_EACH_VEC( m_ContextPrerequisites, i )
|
||||
{
|
||||
if (FStrEq( m_ContextPrerequisites[i].pszContextName, pszCondition ))
|
||||
{
|
||||
pSpeaker->AddContext( pszCondition, UTIL_VarArgs("%i", ResolveVirtualCondition(pSpeaker, m_ContextPrerequisites[i].nConditionType, m_ContextPrerequisites[i].pszCondition, nWordCount)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nContext = clamp( atoi( pSpeaker->GetContextValue( pszCondition ) ), 0, nWordCount - 1 );
|
||||
return nContext;
|
||||
}
|
||||
break;
|
||||
|
||||
case ConditionType_VScript:
|
||||
{
|
||||
// Return VScript code result
|
||||
g_pScriptVM->SetValue( "_choreo_val", "" );
|
||||
|
||||
HSCRIPT hCreateChainScript = g_pScriptVM->CompileScript( UTIL_VarArgs( "_choreo_val = (%s)", pszCondition ) );
|
||||
g_pScriptVM->Run( hCreateChainScript, pSpeaker ? pSpeaker->GetOrCreatePrivateScriptScope() : NULL );
|
||||
|
||||
ScriptVariant_t scriptVar;
|
||||
g_pScriptVM->GetValue( "_choreo_val", &scriptVar );
|
||||
|
||||
g_pScriptVM->ClearValue( "_choreo_val" );
|
||||
|
||||
if (scriptVar.m_int < 0 || scriptVar.m_int >= nWordCount)
|
||||
{
|
||||
Warning("Choreo sentence script var %i from '%s' out of range\n", scriptVar.m_int, pszCondition );
|
||||
scriptVar.m_int = 0;
|
||||
}
|
||||
|
||||
return scriptVar.m_int;
|
||||
}
|
||||
break;
|
||||
|
||||
case ConditionType_DistTo:
|
||||
case ConditionType_DirTo:
|
||||
case ConditionType_GridX:
|
||||
case ConditionType_GridY:
|
||||
{
|
||||
CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, pszCondition, pSpeaker );
|
||||
if (pSpeaker && pTarget)
|
||||
{
|
||||
if (nConditionType == ConditionType_DistTo)
|
||||
{
|
||||
// Convert to meters
|
||||
return (pSpeaker->GetAbsOrigin() - pTarget->GetAbsOrigin()).Length() / 52.49344;
|
||||
}
|
||||
else if (nConditionType == ConditionType_DirTo)
|
||||
{
|
||||
Vector vecDir = (pSpeaker->GetAbsOrigin() - pTarget->GetAbsOrigin());
|
||||
return vecDir.y;
|
||||
}
|
||||
else if (nConditionType == ConditionType_GridX)
|
||||
{
|
||||
return (int)(pTarget->GetAbsOrigin().x / 10.0f) % 20;
|
||||
}
|
||||
else if (nConditionType == ConditionType_GridY)
|
||||
{
|
||||
return (int)(pTarget->GetAbsOrigin().y / 10.0f) % 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
enum
|
||||
{
|
||||
ConditionType_None, // No condition (random)
|
||||
ConditionType_Context, // Word should match value from specified context
|
||||
ConditionType_VScript, // Word should match value returned from specified VScript code
|
||||
|
||||
// HL2 sentence parameters
|
||||
ConditionType_DistTo, // Word should match distance to specified target
|
||||
ConditionType_DirTo, // Word should match direction to specified target
|
||||
ConditionType_GridX, // Word should match world X axis grid of specified target
|
||||
ConditionType_GridY, // Word should match world Y axis grid of specified target
|
||||
};
|
||||
|
||||
int DeduceCondition( const char *pszCondition, int nNumChars )
|
||||
{
|
||||
if (V_strncmp( pszCondition, "context", nNumChars ) == 0)
|
||||
return ConditionType_Context;
|
||||
else if (V_strncmp( pszCondition, "vscript", nNumChars ) == 0)
|
||||
return ConditionType_VScript;
|
||||
else if (V_strncmp( pszCondition, "dist_to", nNumChars ) == 0)
|
||||
return ConditionType_DistTo;
|
||||
else if (V_strncmp( pszCondition, "dir_to", nNumChars ) == 0)
|
||||
return ConditionType_DirTo;
|
||||
else if (V_strncmp( pszCondition, "gridx", nNumChars ) == 0)
|
||||
return ConditionType_GridX;
|
||||
else if (V_strncmp( pszCondition, "gridy", nNumChars ) == 0)
|
||||
return ConditionType_GridY;
|
||||
|
||||
return ConditionType_None;
|
||||
}
|
||||
|
||||
struct VirtualWord_t
|
||||
{
|
||||
char szWord[MAX_CHOREO_SENTENCE_VIRTUAL_WORD_LEN];
|
||||
};
|
||||
|
||||
struct VirtualWordDefinition_t
|
||||
{
|
||||
VirtualWordDefinition_t() {}
|
||||
VirtualWordDefinition_t( const VirtualWordDefinition_t &src )
|
||||
{
|
||||
pszCondition = src.pszCondition;
|
||||
nConditionType = src.nConditionType;
|
||||
m_Words.RemoveAll();
|
||||
m_Words.AddVectorToTail( src.m_Words );
|
||||
}
|
||||
|
||||
const char *pszCondition;
|
||||
int nConditionType;
|
||||
|
||||
CUtlVector< VirtualWord_t > m_Words;
|
||||
};
|
||||
|
||||
struct VirtualWordDefinitionList_t
|
||||
{
|
||||
VirtualWordDefinitionList_t() {}
|
||||
VirtualWordDefinitionList_t( const VirtualWordDefinitionList_t &src )
|
||||
{
|
||||
pszCriterion = src.pszCriterion;
|
||||
m_DefaultWordDefinition = src.m_DefaultWordDefinition;
|
||||
|
||||
m_WordDefinitions.RemoveAll();
|
||||
m_WordDefinitions.EnsureCapacity( src.m_WordDefinitions.Count() );
|
||||
FOR_EACH_DICT_FAST( src.m_WordDefinitions, i )
|
||||
m_WordDefinitions.Insert( src.m_WordDefinitions.GetElementName( i ), src.m_WordDefinitions[i] );
|
||||
}
|
||||
|
||||
const char *pszCriterion;
|
||||
|
||||
VirtualWordDefinition_t m_DefaultWordDefinition;
|
||||
CUtlDict< VirtualWordDefinition_t, int > m_WordDefinitions;
|
||||
};
|
||||
|
||||
struct SentenceContextPrerequisite_t
|
||||
{
|
||||
SentenceContextPrerequisite_t() {}
|
||||
SentenceContextPrerequisite_t( const SentenceContextPrerequisite_t &src )
|
||||
{
|
||||
pszContextName = src.pszContextName;
|
||||
pszCondition = src.pszCondition;
|
||||
nConditionType = src.nConditionType;
|
||||
}
|
||||
|
||||
const char *pszContextName;
|
||||
const char *pszCondition;
|
||||
int nConditionType;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const char *FindString( const char *string )
|
||||
{
|
||||
unsigned short i = m_Strings.Find( string );
|
||||
return i == m_Strings.InvalidIndex() ? NULL : m_Strings[i];
|
||||
}
|
||||
|
||||
const char *AllocateString( const char *string )
|
||||
{
|
||||
int i = m_Strings.Find( string );
|
||||
if ( i != m_Strings.InvalidIndex() )
|
||||
{
|
||||
return m_Strings[i];
|
||||
}
|
||||
|
||||
int len = Q_strlen( string );
|
||||
char *out = new char[ len + 1 ];
|
||||
Q_memcpy( out, string, len );
|
||||
out[ len ] = 0;
|
||||
|
||||
return m_Strings[ m_Strings.Insert( out ) ];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const CUtlDict< ChoreoSentence_t, int > &GetSentences() { return m_Sentences; }
|
||||
|
||||
private:
|
||||
|
||||
// Context prerequisites to be applied if not already applied
|
||||
CUtlVector< SentenceContextPrerequisite_t > m_ContextPrerequisites;
|
||||
|
||||
// Embedded lists of virtual words based on a criterion
|
||||
CUtlDict< VirtualWordDefinitionList_t, int > m_VirtualWordLists;
|
||||
|
||||
// Lists of virtual words (does not include nested ones)
|
||||
CUtlDict< VirtualWordDefinition_t, int > m_VirtualWords;
|
||||
|
||||
// Sentences themselves
|
||||
CUtlDict< ChoreoSentence_t, int > m_Sentences;
|
||||
|
||||
// Dedicated strings, copied from game string pool
|
||||
CUtlRBTree<const char *> m_Strings;
|
||||
|
||||
};
|
||||
|
||||
static CChoreoSentenceSystem g_ChoreoSentenceSystem;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CON_COMMAND( choreosentence_reload, "Reloads choreo sentences" )
|
||||
{
|
||||
//int nStringCount = g_ChoreoSentenceSystem.GetStringCount();
|
||||
g_ChoreoSentenceSystem.PurgeSentences();
|
||||
|
||||
//g_ChoreoSentenceSystem.ReserveStrings( nStringCount );
|
||||
g_ChoreoSentenceSystem.LoadChoreoSentenceManifest( "scripts/choreosentences_manifest.txt" );
|
||||
}
|
||||
|
||||
CON_COMMAND( choreosentence_dump, "Prints all choreo sentence stuff" )
|
||||
{
|
||||
g_ChoreoSentenceSystem.PrintEverything();
|
||||
}
|
||||
|
||||
CON_COMMAND( choreosentence_dump_strings, "Prints all strings allocated by choreo sentences" )
|
||||
{
|
||||
g_ChoreoSentenceSystem.PrintStrings();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
//------------------------------------------------------------------------------
|
||||
static int AutoCompleteChoreoSentences(const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0)
|
||||
{
|
||||
FOR_EACH_DICT_FAST( g_ChoreoSentenceSystem.GetSentences(), i )
|
||||
{
|
||||
CUtlString sym = g_ChoreoSentenceSystem.GetSentences().GetElementName( i );
|
||||
|
||||
if (Q_strnicmp( sym, substring, checklen ) != 0)
|
||||
continue;
|
||||
|
||||
int idx = symbols.Find( sym );
|
||||
if (idx == symbols.InvalidIndex())
|
||||
{
|
||||
symbols.Insert( sym );
|
||||
}
|
||||
|
||||
// Too many
|
||||
if (symbols.Count() >= COMMAND_COMPLETION_MAXITEMS)
|
||||
break;
|
||||
}
|
||||
|
||||
// Now fill in the results
|
||||
for (int i = symbols.FirstInorder(); i != symbols.InvalidIndex(); i = symbols.NextInorder(i))
|
||||
{
|
||||
const char *name = symbols[i].String();
|
||||
|
||||
char buf[512];
|
||||
Q_snprintf( buf, sizeof( buf ), "%s %s", cmdname, name );
|
||||
Q_strlower( buf );
|
||||
|
||||
CUtlString command;
|
||||
command = buf;
|
||||
commands.AddToTail(command);
|
||||
}
|
||||
|
||||
return symbols.Count();
|
||||
}
|
||||
|
||||
class CChoreoSentenceAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback
|
||||
{
|
||||
public:
|
||||
virtual void CommandCallback( const CCommand &command )
|
||||
{
|
||||
if (command.ArgC() != 2)
|
||||
{
|
||||
Msg( "Format: choreosentence_play <sentence name>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
|
||||
if (pPlayer)
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( pPlayer, command.Arg( 1 ) );
|
||||
if (pSentence)
|
||||
PrecacheChoreoSentence( *pSentence );
|
||||
|
||||
pPlayer->PlayChoreoSentenceScene( command.Arg( 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
virtual int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands )
|
||||
{
|
||||
if ( !g_pGameRules )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *cmdname = "choreosentence_play";
|
||||
|
||||
char *substring = (char *)partial;
|
||||
if ( Q_strstr( partial, cmdname ) )
|
||||
{
|
||||
substring = (char *)partial + strlen( cmdname ) + 1;
|
||||
}
|
||||
|
||||
int checklen = Q_strlen( substring );
|
||||
|
||||
extern bool UtlStringLessFunc( const CUtlString & lhs, const CUtlString & rhs );
|
||||
CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc );
|
||||
|
||||
return AutoCompleteChoreoSentences(cmdname, commands, symbols, substring, checklen);
|
||||
}
|
||||
};
|
||||
|
||||
static CChoreoSentenceAutoCompletionFunctor g_ChoreoSentenceAutoComplete;
|
||||
static ConCommand choreosentence_play("choreosentence_play", &g_ChoreoSentenceAutoComplete, "Plays the specified choreo sentence on the player", FCVAR_CHEAT, &g_ChoreoSentenceAutoComplete );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *ChoreoSentence_t::GetWordString( CBaseEntity *pSpeaker, int i ) const
|
||||
{
|
||||
const char *pszExtension = "";
|
||||
if (V_strrchr( pszPrefix, CORRECT_PATH_SEPARATOR ))
|
||||
{
|
||||
// Use waves if our prefix is a path
|
||||
pszExtension = ".wav";
|
||||
}
|
||||
|
||||
// TODO: Something more elaborate than UTIL_VarArgs?
|
||||
if (m_Words[i].bVirtual)
|
||||
{
|
||||
const char *pszVirtualWord = g_ChoreoSentenceSystem.ResolveVirtualWord( pSpeaker, m_Words[i].pszWord );
|
||||
return UTIL_VarArgs( "%s%s%s", pszPrefix, pszVirtualWord, pszExtension );
|
||||
}
|
||||
|
||||
return UTIL_VarArgs( "%s%s%s", pszPrefix, m_Words[i].pszWord, pszExtension );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void LoadChoreoSentenceFile( const char *pszFile )
|
||||
{
|
||||
g_ChoreoSentenceSystem.LoadChoreoSentenceFile( pszFile );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const ChoreoSentence_t *LookupChoreoSentence( CBaseEntity *pSpeaker, const char *pszSentenceName )
|
||||
{
|
||||
return g_ChoreoSentenceSystem.LookupChoreoSentence( pSpeaker, pszSentenceName );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void PrecacheChoreoSentence( const ChoreoSentence_t &sentence )
|
||||
{
|
||||
FOR_EACH_VEC( sentence.m_Words, i )
|
||||
{
|
||||
if (sentence.m_Words[i].bVirtual)
|
||||
{
|
||||
// Precache all virtual words
|
||||
const char *pszExtension = "";
|
||||
if (V_strrchr( sentence.pszPrefix, CORRECT_PATH_SEPARATOR ))
|
||||
pszExtension = ".wav";
|
||||
|
||||
g_ChoreoSentenceSystem.PrecacheVirtualWord( sentence.m_Words[i].pszWord, sentence.pszPrefix, pszExtension );
|
||||
}
|
||||
else
|
||||
{
|
||||
CBaseEntity::PrecacheScriptSound( sentence.GetWordString( NULL, i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ParseChoreoSentence( CBaseEntity *pSpeaker, const char *pszRawSentence, ChoreoSentence_t &sentence )
|
||||
{
|
||||
if (pszRawSentence == NULL || *pszRawSentence == NULL)
|
||||
return false;
|
||||
|
||||
char szSentence[256];
|
||||
|
||||
// First, try getting the prefix
|
||||
const char *pColon = V_strnchr( pszRawSentence, ':', V_strlen( pszRawSentence ) );
|
||||
if (pColon)
|
||||
{
|
||||
// Sentence is everything after colon
|
||||
Q_strncpy( szSentence, pColon + 1, sizeof( szSentence ) );
|
||||
|
||||
// Copy everything before colon for prefix
|
||||
char szPathName[MAX_PATH];
|
||||
V_strncpy( szPathName, pszRawSentence, pColon - pszRawSentence + 1 );
|
||||
V_FixSlashes( szPathName );
|
||||
sentence.pszPrefix = g_ChoreoSentenceSystem.AllocateString( szPathName );
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's all one sentence
|
||||
Q_strncpy( szSentence, pszRawSentence, sizeof( szSentence ) );
|
||||
}
|
||||
|
||||
// Now get any parameters
|
||||
const char *pSemiColon = V_strnchr( szSentence, ';', sizeof( szSentence ) );
|
||||
if (pSemiColon)
|
||||
{
|
||||
// Caption is whatever's after the semicolon
|
||||
const char *pszCaption = pSemiColon+1;
|
||||
if (pszCaption[0] == ' ')
|
||||
pszCaption++;
|
||||
|
||||
sentence.pszCaption = g_ChoreoSentenceSystem.AllocateString( pszCaption );
|
||||
|
||||
// Replace semicolon with null terminator
|
||||
szSentence[pSemiColon - szSentence] = '\0';
|
||||
}
|
||||
|
||||
// Next, split up the sentence itself
|
||||
bool success = ParseChoreoSentenceContents( pSpeaker, szSentence, sentence );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ParseChoreoSentenceContents( CBaseEntity *pSpeaker, char *pszSentence, ChoreoSentence_t &sentence )
|
||||
{
|
||||
int nCurVol = 100, nCurPitch = 100;
|
||||
|
||||
char *pszToken = strtok( pszSentence, " " );
|
||||
for (; pszToken != NULL; pszToken = strtok( NULL, " " ))
|
||||
{
|
||||
if (!pszToken || !*pszToken)
|
||||
continue;
|
||||
|
||||
// Check if this is a command number
|
||||
if (pszToken[0] == '(')
|
||||
{
|
||||
pszToken++;
|
||||
|
||||
// Remove closing parentheses
|
||||
//int end = V_strlen( pszToken )-1;
|
||||
//if (pszToken[end] == ')')
|
||||
// pszToken[end] = '\0';
|
||||
|
||||
int nNum = atoi( pszToken + 1 );
|
||||
if (nNum > 0)
|
||||
{
|
||||
switch (pszToken[0])
|
||||
{
|
||||
// TODO: Recognize e, t, etc.?
|
||||
case 'v': nCurVol = nNum; break;
|
||||
case 'p': nCurPitch = nNum; break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Msg( "Zero command number in %s\n", pszSentence );
|
||||
}
|
||||
}
|
||||
|
||||
int nWord = sentence.m_Words.AddToTail();
|
||||
|
||||
sentence.m_Words[nWord].nVol = nCurVol;
|
||||
sentence.m_Words[nWord].nPitch = nCurPitch;
|
||||
|
||||
// Check if this is virtual
|
||||
if (IsVirtualWord( pszToken ))
|
||||
sentence.m_Words[nWord].bVirtual = true;
|
||||
|
||||
// Check for periods or commas
|
||||
int end = V_strlen( pszToken )-1;
|
||||
if (pszToken[end] == ',')
|
||||
{
|
||||
int nWord2 = sentence.m_Words.AddToTail();
|
||||
sentence.m_Words[nWord2].pszWord = g_ChoreoSentenceSystem.AllocateString( "_comma" );
|
||||
sentence.m_Words[nWord2].nVol = nCurVol;
|
||||
sentence.m_Words[nWord2].nPitch = nCurPitch;
|
||||
pszToken[end] = '\0';
|
||||
}
|
||||
else if (pszToken[end] == '.')
|
||||
{
|
||||
int nWord2 = sentence.m_Words.AddToTail();
|
||||
sentence.m_Words[nWord2].pszWord = g_ChoreoSentenceSystem.AllocateString( "_period" );
|
||||
sentence.m_Words[nWord2].nVol = nCurVol;
|
||||
sentence.m_Words[nWord2].nPitch = nCurPitch;
|
||||
pszToken[end] = '\0';
|
||||
}
|
||||
|
||||
sentence.m_Words[nWord].pszWord = g_ChoreoSentenceSystem.AllocateString( pszToken );
|
||||
}
|
||||
|
||||
return sentence.m_Words.Count() > 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float GetChoreoSentenceDuration( CBaseFlex *pSpeaker, const ChoreoSentence_t &sentence )
|
||||
{
|
||||
const char *actormodel = (pSpeaker ? STRING( pSpeaker->GetModelName() ) : NULL);
|
||||
float flLength = 0.0f;
|
||||
|
||||
FOR_EACH_VEC( sentence.m_Words, i )
|
||||
{
|
||||
//float duration = CBaseEntity::GetSoundDuration( sentence.GetWordString(pSpeaker, i), actormodel );
|
||||
|
||||
float duration;
|
||||
const char *pszWord = sentence.GetWordString( pSpeaker, i );
|
||||
|
||||
// For now, call the engine functions manually instead of using CBaseEntity::GetSoundDuration so that we could get around the WaveTrace warning
|
||||
if ( V_stristr( pszWord, ".wav" ) || V_stristr( pszWord, ".mp3" ) )
|
||||
{
|
||||
duration = enginesound->GetSoundDuration( PSkipSoundChars( pszWord ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
extern ISoundEmitterSystemBase *soundemitterbase;
|
||||
duration = enginesound->GetSoundDuration( PSkipSoundChars( soundemitterbase->GetWavFileForSound( pszWord, actormodel ) ) );
|
||||
}
|
||||
|
||||
flLength += duration;
|
||||
}
|
||||
|
||||
return flLength;
|
||||
}
|
67
sp/src/game/server/mapbase/choreosentence.h
Normal file
67
sp/src/game/server/mapbase/choreosentence.h
Normal file
@ -0,0 +1,67 @@
|
||||
//========= Mapbase - https://github.com/mapbase-source/source-sdk-2013 ============//
|
||||
//
|
||||
// Purpose: VCD-based sentences.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef CHOREOSENTENCE_H
|
||||
#define CHOREOSENTENCE_H
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
|
||||
#define MAX_CHOREO_SENTENCE_PREFIX_LEN 64
|
||||
#define MAX_CHOREO_SENTENCE_WORD_LEN 32
|
||||
#define MAX_CHOREO_SENTENCE_CAPTION_LEN 64
|
||||
|
||||
#define MAX_CHOREO_SENTENCE_VIRTUAL_WORD_LEN 32
|
||||
|
||||
struct ChoreoSentenceWord_t
|
||||
{
|
||||
ChoreoSentenceWord_t() {}
|
||||
ChoreoSentenceWord_t( const ChoreoSentenceWord_t &src )
|
||||
{
|
||||
pszWord = src.pszWord;
|
||||
nPitch = src.nPitch; nVol = src.nVol;
|
||||
bVirtual = src.bVirtual;
|
||||
}
|
||||
|
||||
const char *pszWord;
|
||||
int nPitch, nVol = 100;
|
||||
bool bVirtual = false;
|
||||
};
|
||||
|
||||
struct ChoreoSentence_t
|
||||
{
|
||||
ChoreoSentence_t() {}
|
||||
ChoreoSentence_t( const ChoreoSentence_t &src )
|
||||
{
|
||||
pszName = src.pszName;
|
||||
pszPrefix = src.pszPrefix;
|
||||
pszCaption = src.pszCaption;
|
||||
m_Words.RemoveAll();
|
||||
m_Words.AddVectorToTail( src.m_Words );
|
||||
}
|
||||
|
||||
const char *GetWordString( CBaseEntity *pSpeaker, int i ) const;
|
||||
|
||||
CUtlVector< ChoreoSentenceWord_t > m_Words;
|
||||
const char *pszName;
|
||||
const char *pszPrefix;
|
||||
const char *pszCaption;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
extern void LoadChoreoSentenceFile( const char *pszFile );
|
||||
|
||||
extern const ChoreoSentence_t *LookupChoreoSentence( CBaseEntity *pSpeaker, const char *pszSentenceName );
|
||||
|
||||
extern void PrecacheChoreoSentence( const ChoreoSentence_t &sentence );
|
||||
|
||||
bool ParseChoreoSentence( CBaseEntity *pSpeaker, const char *pszRawSentence, ChoreoSentence_t &sentence );
|
||||
bool ParseChoreoSentenceContents( CBaseEntity *pSpeaker, char *pszSentence, ChoreoSentence_t &sentence );
|
||||
|
||||
extern float GetChoreoSentenceDuration( CBaseFlex *pSpeaker, const ChoreoSentence_t &sentence );
|
||||
|
||||
#endif // CHOREOSENTENCE_H
|
@ -38,8 +38,8 @@ public:
|
||||
void InputReload( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
HSCRIPT ScriptGetKeyValues( void );
|
||||
HSCRIPT ScriptGetKeyValueBlock( void );
|
||||
HSCRIPT_RC ScriptGetKeyValues( void );
|
||||
HSCRIPT_RC ScriptGetKeyValueBlock( void );
|
||||
|
||||
void ScriptSetKeyValues( HSCRIPT hKV );
|
||||
void ScriptSetKeyValueBlock( HSCRIPT hKV );
|
||||
@ -275,7 +275,7 @@ void CLogicExternalData::InputReload( inputdata_t &inputdata )
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CLogicExternalData::ScriptGetKeyValues( void )
|
||||
HSCRIPT_RC CLogicExternalData::ScriptGetKeyValues( void )
|
||||
{
|
||||
if (m_bReloadBeforeEachAction)
|
||||
LoadFile();
|
||||
@ -283,8 +283,9 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValues( void )
|
||||
HSCRIPT hScript = NULL;
|
||||
if (m_pRoot)
|
||||
{
|
||||
// Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't.
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, m_pRoot, false );
|
||||
KeyValues *pCopy = new KeyValues( NULL );
|
||||
*pCopy = *m_pRoot;
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pCopy );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
@ -292,7 +293,7 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValues( void )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CLogicExternalData::ScriptGetKeyValueBlock( void )
|
||||
HSCRIPT_RC CLogicExternalData::ScriptGetKeyValueBlock( void )
|
||||
{
|
||||
if (m_bReloadBeforeEachAction)
|
||||
LoadFile();
|
||||
@ -300,8 +301,9 @@ HSCRIPT CLogicExternalData::ScriptGetKeyValueBlock( void )
|
||||
HSCRIPT hScript = NULL;
|
||||
if (m_pBlock)
|
||||
{
|
||||
// Does this need to be destructed or freed? m_pScriptModelKeyValues apparently doesn't.
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, m_pBlock, false );
|
||||
KeyValues *pCopy = new KeyValues( NULL );
|
||||
*pCopy = *m_pBlock;
|
||||
hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pCopy );
|
||||
}
|
||||
|
||||
return hScript;
|
||||
@ -321,7 +323,8 @@ void CLogicExternalData::ScriptSetKeyValues( HSCRIPT hKV )
|
||||
KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV );
|
||||
if (pKV)
|
||||
{
|
||||
m_pRoot = pKV;
|
||||
m_pRoot = new KeyValues( NULL );
|
||||
*m_pRoot = *pKV;
|
||||
}
|
||||
}
|
||||
|
||||
@ -336,7 +339,8 @@ void CLogicExternalData::ScriptSetKeyValueBlock( HSCRIPT hKV )
|
||||
KeyValues *pKV = scriptmanager->GetKeyValuesFromScriptKV( g_pScriptVM, hKV );
|
||||
if (pKV)
|
||||
{
|
||||
m_pBlock = pKV;
|
||||
m_pBlock = new KeyValues( NULL );
|
||||
*m_pBlock = *pKV;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,7 @@ public:
|
||||
virtual Activity GetPrimaryAttackActivity(void) { return m_CustomData.m_bHitUsesMissAnim ? ACT_VM_MISSCENTER : BaseClass::GetPrimaryAttackActivity(); }
|
||||
|
||||
const char* GetWeaponScriptName() { return m_iszWeaponScriptName.Get(); }
|
||||
const char* GetName( void ) const { return STRING( m_iClassname ); }
|
||||
virtual int GetDamageType() { return g_nDamageClassTypeBits[m_CustomData.m_nDamageClass]; }
|
||||
|
||||
virtual void InitCustomWeaponFromData(const void* pData, const char* pszWeaponScript);
|
||||
@ -381,6 +382,7 @@ public:
|
||||
CHLCustomWeaponGun();
|
||||
virtual void InitCustomWeaponFromData(const void* pData, const char* pszWeaponScript);
|
||||
const char* GetWeaponScriptName() { return m_iszWeaponScriptName.Get(); }
|
||||
const char* GetName( void ) const { return STRING( m_iClassname ); }
|
||||
|
||||
// Weapon behaviour
|
||||
virtual void ItemPostFrame(void); // called each frame by the player PostThink
|
||||
|
@ -7964,7 +7964,7 @@ Activity CBasePlayer::Weapon_TranslateActivity( Activity baseAct, bool *pRequire
|
||||
{
|
||||
Activity weaponTranslation = BaseClass::Weapon_TranslateActivity( baseAct, pRequired );
|
||||
|
||||
if ( GetActiveWeapon() && GetActiveWeapon()->IsEffectActive(EF_NODRAW) && baseAct != ACT_ARM )
|
||||
if ( GetActiveWeapon() && !GetActiveWeapon()->IsWeaponVisible() && baseAct != ACT_ARM )
|
||||
{
|
||||
// Our weapon is holstered. Use the base activity.
|
||||
return baseAct;
|
||||
@ -8871,6 +8871,7 @@ void SendProxy_ShiftPlayerSpawnflags( const SendProp *pProp, const void *pStruct
|
||||
// See baseplayer_shared.h for more details.
|
||||
SendPropInt ( SENDINFO( m_spawnflags ), 3, SPROP_UNSIGNED, SendProxy_ShiftPlayerSpawnflags ),
|
||||
|
||||
SendPropBool ( SENDINFO( m_bDrawPlayerLegs ) ),
|
||||
SendPropBool ( SENDINFO( m_bDrawPlayerModelExternally ) ),
|
||||
SendPropBool ( SENDINFO( m_bInTriggerFall ) ),
|
||||
#endif
|
||||
|
@ -1179,6 +1179,9 @@ public:
|
||||
int m_nNumCrateHudHints;
|
||||
|
||||
#ifdef MAPBASE
|
||||
bool GetDrawPlayerLegs( void ) { return m_bDrawPlayerLegs; }
|
||||
void SetDrawPlayerLegs( bool bToggle ) { m_bDrawPlayerLegs.Set( bToggle ); }
|
||||
|
||||
bool GetDrawPlayerModelExternally( void ) { return m_bDrawPlayerModelExternally; }
|
||||
void SetDrawPlayerModelExternally( bool bToggle ) { m_bDrawPlayerModelExternally.Set( bToggle ); }
|
||||
#endif
|
||||
@ -1222,6 +1225,7 @@ private:
|
||||
char m_szNetname[MAX_PLAYER_NAME_LENGTH];
|
||||
|
||||
#ifdef MAPBASE
|
||||
CNetworkVar( bool, m_bDrawPlayerLegs );
|
||||
CNetworkVar( bool, m_bDrawPlayerModelExternally );
|
||||
#endif
|
||||
|
||||
|
@ -393,7 +393,7 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper
|
||||
if ( weapon )
|
||||
{
|
||||
VPROF( "player->SelectItem()" );
|
||||
player->SelectItem( weapon->GetClassname(), ucmd->weaponsubtype );
|
||||
player->SelectItem( weapon->GetName(), ucmd->weaponsubtype );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,10 @@
|
||||
#include "npc_alyx_episodic.h"
|
||||
#endif // HL2_EPISODIC
|
||||
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/choreosentence.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
@ -57,6 +61,10 @@ class CBaseFlex;
|
||||
static ConVar scene_forcecombined( "scene_forcecombined", "0", 0, "When playing back, force use of combined .wav files even in english." );
|
||||
static ConVar scene_maxcaptionradius( "scene_maxcaptionradius", "1200", 0, "Only show closed captions if recipient is within this many units of speaking actor (0==disabled)." );
|
||||
|
||||
#ifdef MAPBASE
|
||||
static ConVar scene_resume_use_last_speaking( "scene_resume_use_last_speaking", "1", 0, "Uses the last actor who spoke for resume scene calls, rather than the first actor of the scene" );
|
||||
#endif
|
||||
|
||||
// Assume sound system is 100 msec lagged (only used if we can't find snd_mixahead cvar!)
|
||||
#define SOUND_SYSTEM_LATENCY_DEFAULT ( 0.1f )
|
||||
|
||||
@ -412,6 +420,10 @@ public:
|
||||
// If this scene is waiting on an actor, give up and quit trying.
|
||||
void InputStopWaitingForActor( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void InputPauseAtLastInterrupt( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
virtual void StartPlayback( void );
|
||||
virtual void PausePlayback( void );
|
||||
virtual void ResumePlayback( void );
|
||||
@ -482,6 +494,9 @@ public:
|
||||
bool InvolvesActor( CBaseEntity *pActor ); // NOTE: returns false if scene hasn't loaded yet
|
||||
|
||||
void GenerateSoundScene( CBaseFlex *pActor, const char *soundname );
|
||||
#ifdef MAPBASE
|
||||
void GenerateChoreoSentenceScene( CBaseFlex *pActor, const char *pszSentenceName );
|
||||
#endif
|
||||
|
||||
virtual float GetPostSpeakDelay() { return 1.0; }
|
||||
|
||||
@ -489,6 +504,7 @@ public:
|
||||
bool HasFlexAnimation( void );
|
||||
#ifdef MAPBASE
|
||||
bool IsPlayingSpeech( void );
|
||||
CBaseFlex *GetLastSpeakingActor( void );
|
||||
#endif
|
||||
|
||||
void SetCurrentTime( float t, bool forceClientSync );
|
||||
@ -594,6 +610,9 @@ private:
|
||||
void PrecacheScene( CChoreoScene *scene );
|
||||
|
||||
CChoreoScene *GenerateSceneForSound( CBaseFlex *pFlexActor, const char *soundname );
|
||||
#ifdef MAPBASE
|
||||
CChoreoScene *GenerateSceneForSentenceName( CBaseFlex *pFlexActor, const char *pszSentenceName );
|
||||
#endif
|
||||
|
||||
bool CheckActors();
|
||||
|
||||
@ -643,6 +662,9 @@ private:
|
||||
bool m_bGenerated;
|
||||
string_t m_iszSoundName;
|
||||
CHandle< CBaseFlex > m_hActor;
|
||||
#ifdef MAPBASE
|
||||
bool m_bChoreoSentence;
|
||||
#endif
|
||||
|
||||
EHANDLE m_hActivator;
|
||||
|
||||
@ -736,6 +758,9 @@ BEGIN_DATADESC( CSceneEntity )
|
||||
DEFINE_FIELD( m_bGenerated, FIELD_BOOLEAN ),
|
||||
DEFINE_FIELD( m_iszSoundName, FIELD_STRING ),
|
||||
DEFINE_FIELD( m_hActor, FIELD_EHANDLE ),
|
||||
#ifdef MAPBASE
|
||||
DEFINE_FIELD( m_bChoreoSentence, FIELD_BOOLEAN ),
|
||||
#endif
|
||||
DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ),
|
||||
|
||||
// DEFINE_FIELD( m_bSceneMissing, FIELD_BOOLEAN ),
|
||||
@ -757,8 +782,9 @@ BEGIN_DATADESC( CSceneEntity )
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "InterjectResponse", InputInterjectResponse ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "StopWaitingForActor", InputStopWaitingForActor ),
|
||||
DEFINE_INPUTFUNC( FIELD_INTEGER, "Trigger", InputTriggerEvent ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "PauseAtLastInterrupt", InputPauseAtLastInterrupt ),
|
||||
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget1", InputSetTarget1 ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget2", InputSetTarget2 ),
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget3", InputSetTarget3 ),
|
||||
@ -953,6 +979,146 @@ CChoreoScene *CSceneEntity::GenerateSceneForSound( CBaseFlex *pFlexActor, const
|
||||
return scene;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *actor -
|
||||
// *pszSentenceName -
|
||||
// Output : CChoreoScene
|
||||
//-----------------------------------------------------------------------------
|
||||
CChoreoScene *CSceneEntity::GenerateSceneForSentenceName( CBaseFlex *pFlexActor, const char *pszSentenceName )
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( pFlexActor, pszSentenceName );
|
||||
if ( !pSentence )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Couldn't find sentence '%s'\n", pszSentenceName );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: Raw sentence support?
|
||||
// ChoreoSentence_t sentence;
|
||||
// if ( !ParseChoreoSentence( pFlexActor, pszSentence, sentence ) )
|
||||
// {
|
||||
// Warning( "CSceneEntity::GenerateSceneForSentence: Couldn't parse sentence from '%s'\n", pszSentence );
|
||||
// return NULL;
|
||||
// }
|
||||
|
||||
CChoreoScene *scene = new CChoreoScene( this );
|
||||
if ( !scene )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Failed to allocated new scene!!!\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
scene->SetPrintFunc( LocalScene_Printf );
|
||||
|
||||
CChoreoActor *actor = scene->AllocActor();
|
||||
CChoreoChannel *channel = scene->AllocChannel();
|
||||
|
||||
Assert( actor );
|
||||
Assert( channel );
|
||||
|
||||
if ( !actor || !channel )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Alloc of actor or channel failed!!!\n" );
|
||||
delete scene;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set us up the actorz
|
||||
actor->SetName( "!self" ); // Could be pFlexActor->GetName()?
|
||||
actor->SetActive( true );
|
||||
|
||||
// Set us up the channelz
|
||||
channel->SetName( STRING( m_iszSceneFile ) );
|
||||
channel->SetActor( actor );
|
||||
|
||||
// Add to actor
|
||||
actor->AddChannel( channel );
|
||||
|
||||
// Set us up the eventz
|
||||
const char *actormodel = (pFlexActor ? STRING( pFlexActor->GetModelName() ) : NULL);
|
||||
float flCurTime = 0.0f;
|
||||
FOR_EACH_VEC( pSentence->m_Words, i )
|
||||
{
|
||||
const char *pszWord = pSentence->GetWordString( pFlexActor, i );
|
||||
|
||||
float duration = CBaseEntity::GetSoundDuration( pszWord, actormodel );
|
||||
if (duration <= 0.0f)
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Couldn't determine duration of %s\n", pszWord );
|
||||
}
|
||||
|
||||
CChoreoEvent *event = scene->AllocEvent();
|
||||
Assert( event );
|
||||
|
||||
if ( !event )
|
||||
{
|
||||
Warning( "CSceneEntity::GenerateSceneForSentenceName: Alloc of event failed!!!\n" );
|
||||
delete scene;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pSentence->pszCaption)
|
||||
{
|
||||
// First word gets the caption, others fall back to it
|
||||
if (i == 0)
|
||||
{
|
||||
event->SetCloseCaptionType( CChoreoEvent::CC_MASTER );
|
||||
event->SetCloseCaptionToken( pSentence->pszCaption );
|
||||
}
|
||||
else
|
||||
{
|
||||
event->SetCloseCaptionType( CChoreoEvent::CC_SLAVE );
|
||||
}
|
||||
}
|
||||
//else if (pSentence->pszName)
|
||||
//{
|
||||
// // TODO: Caption from name?
|
||||
//}
|
||||
|
||||
if (pSentence->m_Words[i].nVol != 100)
|
||||
{
|
||||
event->SetYaw( pSentence->m_Words[i].nVol );
|
||||
}
|
||||
|
||||
if (pSentence->m_Words[i].nPitch != 100)
|
||||
{
|
||||
duration *= (100.0f / ((float)pSentence->m_Words[i].nPitch));
|
||||
event->SetPitch( pSentence->m_Words[i].nPitch );
|
||||
}
|
||||
|
||||
// HACKHACK: Need to be spaced away from repeated sound to avoid changing the previous sound's pitch instead
|
||||
if (i+1 < pSentence->m_Words.Count() && pSentence->m_Words[i+1].pszWord == pSentence->m_Words[i].pszWord
|
||||
&& pSentence->m_Words[i + 1].nPitch != 100)
|
||||
duration += 0.1f;
|
||||
|
||||
event->SetType( CChoreoEvent::SPEAK );
|
||||
event->SetName( pszWord );
|
||||
event->SetParameters( pszWord );
|
||||
event->SetStartTime( flCurTime );
|
||||
event->SetUsingRelativeTag( false );
|
||||
event->SetEndTime( flCurTime + duration );
|
||||
event->SnapTimes();
|
||||
|
||||
//Msg( "%i %s: %f -> %f (%f)\n", i, pszWord, flCurTime, flCurTime + duration, duration );
|
||||
|
||||
// Add to channel
|
||||
channel->AddEvent( event );
|
||||
|
||||
// Point back to our owners
|
||||
event->SetChannel( channel );
|
||||
event->SetActor( actor );
|
||||
|
||||
flCurTime += duration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return scene;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -960,6 +1126,13 @@ void CSceneEntity::Activate()
|
||||
{
|
||||
if ( m_bGenerated && !m_pScene )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (m_bChoreoSentence)
|
||||
{
|
||||
m_pScene = GenerateSceneForSentenceName( m_hActor, STRING( m_iszSoundName ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
m_pScene = GenerateSceneForSound( m_hActor, STRING( m_iszSoundName ) );
|
||||
}
|
||||
|
||||
@ -1138,6 +1311,22 @@ void CSceneEntity::GenerateSoundScene( CBaseFlex *pActor, const char *soundname
|
||||
m_hActor = pActor;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pActor -
|
||||
// *pszSentenceName -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::GenerateChoreoSentenceScene( CBaseFlex *pActor, const char *pszSentenceName )
|
||||
{
|
||||
m_bGenerated = true;
|
||||
m_iszSoundName = MAKE_STRING( pszSentenceName );
|
||||
m_hActor = pActor;
|
||||
|
||||
m_bChoreoSentence = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
@ -1185,6 +1374,33 @@ bool CSceneEntity::IsPlayingSpeech( void )
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBaseFlex *CSceneEntity::GetLastSpeakingActor( void )
|
||||
{
|
||||
if ( m_pScene )
|
||||
{
|
||||
CChoreoActor *pLastActor = NULL;
|
||||
float flTime = m_pScene->GetTime();
|
||||
for ( int i = 0; i < m_pScene->GetNumEvents(); i++ )
|
||||
{
|
||||
CChoreoEvent *e = m_pScene->GetEvent( i );
|
||||
if ( e->GetType() == CChoreoEvent::SPEAK )
|
||||
{
|
||||
if ( flTime >= e->GetStartTime() )
|
||||
pLastActor = e->GetActor();
|
||||
}
|
||||
}
|
||||
|
||||
if (pLastActor)
|
||||
return FindNamedActor( pLastActor );
|
||||
}
|
||||
|
||||
// Fall back to the first actor
|
||||
return FindNamedActor( 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -1930,6 +2146,26 @@ void CSceneEntity::DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CC
|
||||
|
||||
// Warning( "Speak %s\n", soundname );
|
||||
|
||||
#ifdef MAPBASE
|
||||
if ( m_fPitch != 1.0f || event->GetPitch() != 0 )
|
||||
{
|
||||
if ( es.m_nPitch && es.m_nPitch != 100 )
|
||||
es.m_nPitch = static_cast<float>( es.m_nPitch ) * m_fPitch;
|
||||
else
|
||||
{
|
||||
float flPitch = (event->GetPitch() != 0 ? event->GetPitch() : 100.0f);
|
||||
es.m_nPitch = flPitch * m_fPitch;
|
||||
}
|
||||
|
||||
es.m_nFlags |= SND_CHANGE_PITCH;
|
||||
}
|
||||
|
||||
if ( event->GetYaw() != 0 )
|
||||
{
|
||||
es.m_flVolume = (((float)event->GetYaw()) / 100.0f);
|
||||
es.m_nFlags |= SND_CHANGE_VOL;
|
||||
}
|
||||
#else
|
||||
if ( m_fPitch != 1.0f )
|
||||
{
|
||||
if ( es.m_nPitch )
|
||||
@ -1939,6 +2175,7 @@ void CSceneEntity::DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CC
|
||||
|
||||
es.m_nFlags |= SND_CHANGE_PITCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
EmitSound( filter2, actor->entindex(), es );
|
||||
actor->AddSceneEvent( scene, event );
|
||||
@ -2468,6 +2705,39 @@ void CSceneEntity::InputInterjectResponse( inputdata_t &inputdata )
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::InputPauseAtLastInterrupt( inputdata_t &inputdata )
|
||||
{
|
||||
PausePlayback();
|
||||
m_bPausedViaInput = true;
|
||||
|
||||
if ( m_pScene )
|
||||
{
|
||||
float flLastInterrupt = 0.0f;
|
||||
float flTime = m_pScene->GetTime();
|
||||
for ( int i = 0; i < m_pScene->GetNumEvents(); i++ )
|
||||
{
|
||||
CChoreoEvent *e = m_pScene->GetEvent( i );
|
||||
if ( e->GetType() == CChoreoEvent::INTERRUPT )
|
||||
{
|
||||
if ( flTime > e->GetEndTime() && e->GetEndTime() > flLastInterrupt )
|
||||
{
|
||||
// Set the scene's time to the last interrupt point's end time
|
||||
flLastInterrupt = e->GetEndTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flLastInterrupt != 0.0f)
|
||||
{
|
||||
// Set the scene's time to the last interrupt point's end time
|
||||
m_pScene->SetTime( flLastInterrupt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::SetTarget( int nTarget, string_t pTargetName, CBaseEntity *pActivator, CBaseEntity *pCaller )
|
||||
@ -3096,13 +3366,22 @@ void CSceneEntity::QueueResumePlayback( void )
|
||||
// If it has ".vcd" somewhere in the string, try using it as a scene file first
|
||||
if ( Q_stristr( STRING(m_iszResumeSceneFile), ".vcd" ) )
|
||||
{
|
||||
bStartedScene = InstancedScriptedScene( NULL, STRING(m_iszResumeSceneFile), &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
#ifdef MAPBASE
|
||||
CBaseFlex *pActor = scene_resume_use_last_speaking.GetBool() ? GetLastSpeakingActor() : FindNamedActor( 0 );
|
||||
#else
|
||||
CBaseFlex *pActor = NULL;
|
||||
#endif
|
||||
bStartedScene = InstancedScriptedScene( pActor, STRING(m_iszResumeSceneFile), &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
}
|
||||
|
||||
// HACKHACK: For now, get the first target, and see if we can find a response for him
|
||||
if ( !bStartedScene )
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
CBaseFlex *pActor = scene_resume_use_last_speaking.GetBool() ? GetLastSpeakingActor() : FindNamedActor( 0 );
|
||||
#else
|
||||
CBaseFlex *pActor = FindNamedActor( 0 );
|
||||
#endif
|
||||
if ( pActor )
|
||||
{
|
||||
CAI_BaseActor *pBaseActor = dynamic_cast<CAI_BaseActor*>(pActor);
|
||||
@ -3115,7 +3394,7 @@ void CSceneEntity::QueueResumePlayback( void )
|
||||
if ( result )
|
||||
{
|
||||
const char* szResponse = response.GetResponsePtr();
|
||||
bStartedScene = InstancedScriptedScene( NULL, szResponse, &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
bStartedScene = InstancedScriptedScene( pActor, szResponse, &m_hWaitingForThisResumeScene, 0, false ) != 0;
|
||||
}
|
||||
#else
|
||||
AI_Response *result = pBaseActor->SpeakFindResponse( STRING(m_iszResumeSceneFile), NULL );
|
||||
@ -5667,6 +5946,62 @@ void CInstancedSceneEntity::OnLoaded()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
float InstancedChoreoSentenceScene( CBaseFlex *pActor, const char *pszSentence, EHANDLE *phSceneEnt,
|
||||
float flPostDelay, bool bIsBackground, AI_Response *response,
|
||||
bool bMultiplayer, IRecipientFilter *filter /* = NULL */ )
|
||||
{
|
||||
if ( !pActor )
|
||||
{
|
||||
Warning( "InstancedChoreoSentenceScene: Expecting non-NULL pActor for sound %s\n", pszSentence );
|
||||
return 0;
|
||||
}
|
||||
|
||||
CInstancedSceneEntity *pScene = (CInstancedSceneEntity *)CBaseEntity::CreateNoSpawn( "instanced_scripted_scene", vec3_origin, vec3_angle );
|
||||
|
||||
Q_strncpy( pScene->m_szInstanceFilename, UTIL_VarArgs( "AutoGenerated(%s)", pszSentence ), sizeof( pScene->m_szInstanceFilename ) );
|
||||
pScene->m_iszSceneFile = MAKE_STRING( pScene->m_szInstanceFilename );
|
||||
|
||||
pScene->m_hOwner = pActor;
|
||||
pScene->m_bHadOwner = pActor != NULL;
|
||||
|
||||
pScene->GenerateChoreoSentenceScene( pActor, pszSentence );
|
||||
|
||||
pScene->m_bMultiplayer = bMultiplayer;
|
||||
pScene->SetPostSpeakDelay( flPostDelay );
|
||||
DispatchSpawn( pScene );
|
||||
pScene->Activate();
|
||||
pScene->m_bIsBackground = bIsBackground;
|
||||
|
||||
pScene->SetBackground( bIsBackground );
|
||||
pScene->SetRecipientFilter( filter );
|
||||
|
||||
if ( response )
|
||||
{
|
||||
float flPreDelay = response->GetPreDelay();
|
||||
if ( flPreDelay )
|
||||
{
|
||||
pScene->SetPreDelay( flPreDelay );
|
||||
}
|
||||
}
|
||||
|
||||
pScene->StartPlayback();
|
||||
|
||||
if ( response )
|
||||
{
|
||||
// If the response wants us to abort on NPC state switch, remember that
|
||||
pScene->SetBreakOnNonIdle( response->ShouldBreakOnNonIdle() );
|
||||
}
|
||||
|
||||
if ( phSceneEnt )
|
||||
{
|
||||
*phSceneEnt = pScene;
|
||||
}
|
||||
|
||||
return pScene->EstimateLength();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool g_bClientFlex = true;
|
||||
|
||||
LINK_ENTITY_TO_CLASS( scene_manager, CSceneManager );
|
||||
|
@ -28,6 +28,7 @@ int GetRecentNPCSpeech( recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ] );
|
||||
float InstancedScriptedScene( CBaseFlex *pActor, const char *pszScene, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
|
||||
#ifdef MAPBASE
|
||||
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
|
||||
float InstancedChoreoSentenceScene( CBaseFlex *pActor, char const *pszSentence, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL );
|
||||
#else
|
||||
float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt = NULL );
|
||||
#endif
|
||||
|
@ -46,8 +46,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\mapbase_playeranimstate.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\mapbase_playeranimstate.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.cpp"
|
||||
$File "$SRCDIR\game\shared\mapbase\protagonist_system.h"
|
||||
$File "$SRCDIR\game\shared\mapbase\vscript_funcs_shared.cpp" [$MAPBASE_VSCRIPT]
|
||||
@ -65,6 +65,8 @@ $Project
|
||||
$File "mapbase\ai_grenade.h"
|
||||
$File "mapbase\ai_monitor.cpp"
|
||||
$File "mapbase\ai_weaponmodifier.cpp"
|
||||
$File "mapbase\choreosentence.cpp"
|
||||
$File "mapbase\choreosentence.h"
|
||||
$File "mapbase\custom_weapon_factory.cpp"
|
||||
$File "mapbase\custom_weapon_factory.h"
|
||||
$File "mapbase\closecaption_entity.cpp"
|
||||
|
@ -66,6 +66,7 @@ BEGIN_SCRIPTDESC_ROOT( CSound, "A sound NPCs can hear." )
|
||||
DEFINE_SCRIPTFUNC( ValidateOwner, "Returns true if the sound's owner is still valid or if the sound never had an owner in the first place." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetOwner, "GetOwner", "Gets the sound's owner." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetTarget, "GetTarget", "Gets the sound's target." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFreeSound, "FreeSound", "Frees the sound from the sound list." )
|
||||
|
||||
END_SCRIPTDESC();
|
||||
#endif
|
||||
|
@ -140,6 +140,8 @@ public:
|
||||
// For VScript functions
|
||||
HSCRIPT ScriptGetOwner() const { return ToHScript( m_hOwner ); }
|
||||
HSCRIPT ScriptGetTarget() const { return ToHScript( m_hTarget ); }
|
||||
|
||||
void ScriptFreeSound() { m_flExpireTime = gpGlobals->curtime; m_bNoExpirationTime = false; }
|
||||
#endif
|
||||
|
||||
EHANDLE m_hOwner; // sound's owner
|
||||
|
@ -22,6 +22,10 @@
|
||||
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
extern int vscript_debugger_port;
|
||||
#endif
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
@ -663,6 +667,14 @@ bool VScriptServerInit()
|
||||
RegisterSharedScriptFunctions();
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
if ( vscript_debugger_port )
|
||||
{
|
||||
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
|
||||
vscript_debugger_port = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scriptLanguage == SL_SQUIRREL)
|
||||
{
|
||||
g_pScriptVM->Run( g_Script_vscript_server );
|
||||
|
@ -72,16 +72,16 @@ function ImpulseScale( flTargetMass, flDesiredSpeed )
|
||||
}
|
||||
__Documentation.RegisterHelp( "ImpulseScale", "float ImpulseScale(float, float)", "Returns an impulse scale required to push an object." );
|
||||
|
||||
local PrecacheModel = PrecacheModel
|
||||
local PrecacheModel = DoPrecacheModel
|
||||
function PrecacheModel( a, b = true )
|
||||
{
|
||||
return PrecacheModel( a, b )
|
||||
}
|
||||
|
||||
local PrecacheOther = PrecacheOther
|
||||
local PrecacheOther = DoPrecacheOther
|
||||
function PrecacheOther( a, b = "" )
|
||||
{
|
||||
PrecacheOther( a, b )
|
||||
return PrecacheOther( a, b )
|
||||
}
|
||||
|
||||
function __ReplaceClosures( script, scope )
|
||||
@ -106,10 +106,9 @@ function __ReplaceClosures( script, scope )
|
||||
}
|
||||
}
|
||||
|
||||
local __OutputsPattern = regexp("^On.*Output$");
|
||||
|
||||
function ConnectOutputs( table )
|
||||
{
|
||||
local __OutputsPattern = regexp("^On.*Output$");
|
||||
local nCharsToStrip = 6;
|
||||
foreach( key, val in table )
|
||||
{
|
||||
|
@ -2694,6 +2694,18 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_PISTOL );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SHOTGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_PHYSGUN );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_GRENADE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_RPG );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_CROSSBOW );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_MELEE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SLAM );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_RUN_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_WALK_REVOLVER );
|
||||
@ -2702,6 +2714,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_REVOLVER );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_REVOLVER );
|
||||
|
||||
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
|
||||
@ -2713,6 +2726,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_AR1 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_AR3 );
|
||||
@ -2723,6 +2737,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_AR3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_AR3 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SMG2 );
|
||||
@ -2733,6 +2748,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG2 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SMG2 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SMG3 );
|
||||
@ -2743,6 +2759,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SMG3 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SMG3 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_HMG1 );
|
||||
@ -2753,6 +2770,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_HMG1 );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_HMG1 );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_SNIPER_RIFLE );
|
||||
@ -2763,6 +2781,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_SNIPER_RIFLE );
|
||||
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_IDLE_DUAL_PISTOLS );
|
||||
@ -2773,6 +2792,7 @@ void ActivityList_RegisterSharedActivities( void )
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS );
|
||||
REGISTER_SHARED_ACTIVITY( ACT_HL2MP_JUMP_DUAL_PISTOLS );
|
||||
#endif
|
||||
|
||||
|
@ -2598,6 +2598,18 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_MELEE,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SLAM,
|
||||
|
||||
ACT_HL2MP_GESTURE_RELAX,
|
||||
ACT_HL2MP_GESTURE_RELAX_PISTOL,
|
||||
ACT_HL2MP_GESTURE_RELAX_SHOTGUN,
|
||||
ACT_HL2MP_GESTURE_RELAX_SMG1,
|
||||
ACT_HL2MP_GESTURE_RELAX_AR2,
|
||||
ACT_HL2MP_GESTURE_RELAX_PHYSGUN,
|
||||
ACT_HL2MP_GESTURE_RELAX_GRENADE,
|
||||
ACT_HL2MP_GESTURE_RELAX_RPG,
|
||||
ACT_HL2MP_GESTURE_RELAX_CROSSBOW,
|
||||
ACT_HL2MP_GESTURE_RELAX_MELEE,
|
||||
ACT_HL2MP_GESTURE_RELAX_SLAM,
|
||||
|
||||
ACT_HL2MP_IDLE_REVOLVER,
|
||||
ACT_HL2MP_RUN_REVOLVER,
|
||||
ACT_HL2MP_WALK_REVOLVER,
|
||||
@ -2606,6 +2618,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_REVOLVER,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_REVOLVER,
|
||||
ACT_HL2MP_GESTURE_RELOAD_REVOLVER,
|
||||
ACT_HL2MP_GESTURE_RELAX_REVOLVER,
|
||||
ACT_HL2MP_JUMP_REVOLVER,
|
||||
|
||||
#if EXPANDED_HL2_UNUSED_WEAPON_ACTIVITIES
|
||||
@ -2618,6 +2631,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_AR1,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR1,
|
||||
ACT_HL2MP_GESTURE_RELOAD_AR1,
|
||||
ACT_HL2MP_GESTURE_RELAX_AR1,
|
||||
ACT_HL2MP_JUMP_AR1,
|
||||
|
||||
ACT_HL2MP_IDLE_AR3,
|
||||
@ -2628,6 +2642,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_AR3,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_AR3,
|
||||
ACT_HL2MP_GESTURE_RELOAD_AR3,
|
||||
ACT_HL2MP_GESTURE_RELAX_AR3,
|
||||
ACT_HL2MP_JUMP_AR3,
|
||||
|
||||
ACT_HL2MP_IDLE_SMG2,
|
||||
@ -2638,6 +2653,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG2,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG2,
|
||||
ACT_HL2MP_GESTURE_RELOAD_SMG2,
|
||||
ACT_HL2MP_GESTURE_RELAX_SMG2,
|
||||
ACT_HL2MP_JUMP_SMG2,
|
||||
|
||||
ACT_HL2MP_IDLE_SMG3,
|
||||
@ -2648,6 +2664,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG3,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SMG3,
|
||||
ACT_HL2MP_GESTURE_RELOAD_SMG3,
|
||||
ACT_HL2MP_GESTURE_RELAX_SMG3,
|
||||
ACT_HL2MP_JUMP_SMG3,
|
||||
|
||||
ACT_HL2MP_IDLE_HMG1,
|
||||
@ -2658,6 +2675,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_HMG1,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_HMG1,
|
||||
ACT_HL2MP_GESTURE_RELOAD_HMG1,
|
||||
ACT_HL2MP_GESTURE_RELAX_HMG1,
|
||||
ACT_HL2MP_JUMP_HMG1,
|
||||
|
||||
ACT_HL2MP_IDLE_SNIPER_RIFLE,
|
||||
@ -2668,6 +2686,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_SNIPER_RIFLE,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_SNIPER_RIFLE,
|
||||
ACT_HL2MP_GESTURE_RELOAD_SNIPER_RIFLE,
|
||||
ACT_HL2MP_GESTURE_RELAX_SNIPER_RIFLE,
|
||||
ACT_HL2MP_JUMP_SNIPER_RIFLE,
|
||||
|
||||
ACT_HL2MP_IDLE_DUAL_PISTOLS,
|
||||
@ -2678,6 +2697,7 @@ typedef enum
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK_DUAL_PISTOLS,
|
||||
ACT_HL2MP_GESTURE_RANGE_ATTACK2_DUAL_PISTOLS,
|
||||
ACT_HL2MP_GESTURE_RELOAD_DUAL_PISTOLS,
|
||||
ACT_HL2MP_GESTURE_RELAX_DUAL_PISTOLS,
|
||||
ACT_HL2MP_JUMP_DUAL_PISTOLS,
|
||||
#endif
|
||||
|
||||
|
@ -31,6 +31,9 @@
|
||||
|
||||
#ifdef GAME_DLL
|
||||
#include "sceneentity.h"
|
||||
#ifdef MAPBASE
|
||||
#include "mapbase/choreosentence.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "networkstringtabledefs.h"
|
||||
@ -492,6 +495,17 @@ void CGameResponseSystem::Precache()
|
||||
CBaseEntity::PrecacheScriptSound( response.value );
|
||||
}
|
||||
break;
|
||||
#ifdef MAPBASE
|
||||
case RESPONSE_CHOREOSENTENCE:
|
||||
{
|
||||
const ChoreoSentence_t *pSentence = LookupChoreoSentence( NULL, response.value );
|
||||
if (pSentence)
|
||||
PrecacheChoreoSentence( *pSentence );
|
||||
else
|
||||
Msg( "Choreo scene '%s' not found\n", response.value );
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,12 +18,12 @@
|
||||
#include "c_baseplayer.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
|
||||
ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." );
|
||||
ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "Show the (client) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." );
|
||||
#else
|
||||
#include "player.h"
|
||||
ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (server) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." );
|
||||
ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "Show the (server) animation state for the specified entity (-1 for none)." );
|
||||
ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT /*| FCVAR_DEVELOPMENTONLY*/, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." );
|
||||
#endif
|
||||
|
||||
|
||||
@ -654,9 +654,11 @@ void CBasePlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr )
|
||||
|
||||
if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY )
|
||||
{
|
||||
#ifndef MAPBASE // This causes problems with entities that rely on the player having a pitch (TODO: gate behind virtual function?)
|
||||
#ifndef CLIENT_DLL
|
||||
//Adrian: Make the model's angle match the legs so the hitboxes match on both sides.
|
||||
GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int iMoveX = GetOuter()->LookupPoseParameter( pStudioHdr, "move_x" );
|
||||
@ -942,6 +944,15 @@ void CBasePlayerAnimState::GetOuterAbsVelocity( Vector& vel ) const
|
||||
#else
|
||||
vel = GetOuter()->GetAbsVelocity();
|
||||
#endif
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (GetOuter()->IsPlayer())
|
||||
{
|
||||
CBasePlayer *pPlayer = ToBasePlayer( GetOuter() );
|
||||
if (pPlayer->GetLaggedMovementValue() != 1.0f)
|
||||
vel *= pPlayer->GetLaggedMovementValue();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1024,9 +1035,15 @@ void CBasePlayerAnimState::DebugShowAnimState( int iStartLine )
|
||||
(float)pLayer->m_flWeight );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
|
||||
{
|
||||
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( i );
|
||||
#else
|
||||
for ( int i=0; i < m_pOuter->GetNumAnimOverlays()-1; i++ )
|
||||
{
|
||||
CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( AIMSEQUENCE_LAYER + i );
|
||||
#endif
|
||||
#ifdef CLIENT_DLL
|
||||
AnimStatePrintf( iLine++, "%s(%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)",
|
||||
!pLayer->IsActive() ? "-- ": (pLayer->m_nSequence == 0 ? "-- " : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ) ),
|
||||
|
@ -307,6 +307,10 @@ public:
|
||||
virtual bool ShouldBlockPrimaryFire() { return false; }
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#ifdef MAPBASE
|
||||
virtual bool DispatchMuzzleEffect( const char *options, bool isFirstPerson );
|
||||
#endif
|
||||
|
||||
virtual void CreateMove( float flInputSampleTime, CUserCmd *pCmd, const QAngle &vecOldViewAngles ) {}
|
||||
virtual int CalcOverrideModelIndex() OVERRIDE;
|
||||
#endif
|
||||
|
@ -3033,7 +3033,7 @@ void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, f
|
||||
|
||||
float nextthink = gpGlobals->curtime + flTime;
|
||||
|
||||
pf->m_hfnThink = hFunc;
|
||||
pf->m_hfnThink = g_pScriptVM->CopyObject( hFunc );
|
||||
pf->m_flNextThink = nextthink;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
@ -255,7 +255,7 @@ inline HSCRIPT ToHScript(CBaseEntity* pEnt)
|
||||
return (pEnt) ? pEnt->GetScriptInstance() : NULL;
|
||||
}
|
||||
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*);
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*, bool);
|
||||
inline CBaseEntity* ToEnt(HSCRIPT hScript)
|
||||
{
|
||||
return (hScript) ? (CBaseEntity*)g_pScriptVM->GetInstanceValue(hScript, GetScriptDescForClass(CBaseEntity)) : NULL;
|
||||
|
@ -15,7 +15,7 @@
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "singleplayer_animstate.h"
|
||||
#include "mapbase_playeranimstate.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "animation.h"
|
||||
#include "studio.h"
|
||||
@ -23,25 +23,33 @@
|
||||
#include "utldict.h"
|
||||
#include "filesystem.h"
|
||||
#include "in_buttons.h"
|
||||
#include "gamemovement.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#ifdef CLIENT_DLL
|
||||
#include "input.h"
|
||||
#endif
|
||||
|
||||
extern ConVar mp_facefronttime, mp_feetyawrate, mp_ik;
|
||||
extern ConVar mp_facefronttime, mp_feetyawrate;
|
||||
|
||||
ConVar sv_playeranimstate_animtype( "sv_playeranimstate_animtype", "0", FCVAR_NONE, "The leg animation type used by the singleplayer animation state. 9way = 0, 8way = 1, GoldSrc = 2" );
|
||||
ConVar sv_playeranimstate_bodyyaw( "sv_playeranimstate_bodyyaw", "45.0", FCVAR_NONE, "The maximum body yaw used by the singleplayer animation state." );
|
||||
ConVar sv_playeranimstate_use_aim_sequences( "sv_playeranimstate_use_aim_sequences", "1", FCVAR_NONE, "Allows the singleplayer animation state to use aim sequences." );
|
||||
ConVar sv_playeranimstate_animtype( "sv_playeranimstate_animtype", "0", FCVAR_NONE, "The leg animation type used by the Mapbase animation state. 9way = 0, 8way = 1, GoldSrc = 2" );
|
||||
ConVar sv_playeranimstate_bodyyaw( "sv_playeranimstate_bodyyaw", "45.0", FCVAR_NONE, "The maximum body yaw used by the Mapbase animation state." );
|
||||
ConVar sv_playeranimstate_use_aim_sequences( "sv_playeranimstate_use_aim_sequences", "0", FCVAR_NONE, "Allows the Mapbase animation state to use aim sequences." );
|
||||
ConVar sv_playeranimstate_use_walk_anims( "sv_playeranimstate_use_walk_anims", "0", FCVAR_NONE, "Allows the Mapbase animation state to use walk animations when the player is walking." );
|
||||
|
||||
#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f
|
||||
|
||||
#define WEAPON_RELAX_TIME 0.5f
|
||||
|
||||
#define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS)
|
||||
#define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1)
|
||||
#define NUM_LAYERS_WANTED (RELOADSEQUENCE_LAYER + 1)
|
||||
#define MISCSEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1)
|
||||
#define NUM_LAYERS_WANTED (MISCSEQUENCE_LAYER + 1)
|
||||
|
||||
CSinglePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer )
|
||||
CMapbasePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer )
|
||||
{
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
CSinglePlayerAnimState *pState = new CSinglePlayerAnimState( pPlayer );
|
||||
CMapbasePlayerAnimState *pState = new CMapbasePlayerAnimState( pPlayer );
|
||||
|
||||
// Setup the movement data.
|
||||
CModAnimConfig movementData;
|
||||
@ -65,22 +73,25 @@ CSinglePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer )
|
||||
extern ConVar sv_backspeed;
|
||||
extern ConVar mp_feetyawrate;
|
||||
extern ConVar mp_facefronttime;
|
||||
extern ConVar mp_ik;
|
||||
|
||||
CSinglePlayerAnimState::CSinglePlayerAnimState( CBasePlayer *pPlayer ): m_pPlayer( pPlayer )
|
||||
CMapbasePlayerAnimState::CMapbasePlayerAnimState( CBasePlayer *pPlayer ): m_pPlayer( pPlayer )
|
||||
{
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CSinglePlayerAnimState::CalcMainActivity()
|
||||
Activity CMapbasePlayerAnimState::CalcMainActivity()
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
return ACT_IDLE;
|
||||
#else
|
||||
float speed = GetOuter()->GetAbsVelocity().Length2D();
|
||||
|
||||
if (m_pPlayer->GetLaggedMovementValue() != 1.0f)
|
||||
speed *= m_pPlayer->GetLaggedMovementValue();
|
||||
|
||||
// May not always be precise
|
||||
if (speed < 0.01f)
|
||||
speed = 0.0f;
|
||||
|
||||
if ( HandleJumping() )
|
||||
{
|
||||
return ACT_HL2MP_JUMP;
|
||||
@ -95,7 +106,24 @@ Activity CSinglePlayerAnimState::CalcMainActivity()
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( GetOuter()->GetFlags() & FL_DUCKING )
|
||||
bool bDucking = (GetOuter()->GetFlags() & FL_DUCKING) ? true : false;
|
||||
|
||||
// (currently singleplayer-exclusive since clients can't read whether other players are holding down IN_DUCK)
|
||||
if (m_pPlayer->m_Local.m_flDucktime > 0 && gpGlobals->maxClients == 1)
|
||||
{
|
||||
// Consider ducking if half-way through duck time
|
||||
bDucking = (m_pPlayer->m_Local.m_flDucktime < (GAMEMOVEMENT_DUCK_TIME * 0.9f));
|
||||
|
||||
// Unducking
|
||||
#ifdef CLIENT_DLL
|
||||
if (!((m_pPlayer->IsLocalPlayer() ? input->GetButtonBits( 0 ) : m_pPlayer->GetCurrentUserCommand()->buttons) & IN_DUCK))
|
||||
#else
|
||||
if (!(m_pPlayer->m_nButtons & IN_DUCK))
|
||||
#endif
|
||||
bDucking = !bDucking;
|
||||
}
|
||||
|
||||
if ( bDucking )
|
||||
{
|
||||
if ( speed > 0 )
|
||||
{
|
||||
@ -111,7 +139,7 @@ Activity CSinglePlayerAnimState::CalcMainActivity()
|
||||
if ( speed > 0 )
|
||||
{
|
||||
#if EXPANDED_HL2DM_ACTIVITIES
|
||||
if ( m_pPlayer->GetButtons() & IN_WALK )
|
||||
if ( m_pPlayer->m_nButtons & IN_WALK && sv_playeranimstate_use_walk_anims.GetBool() )
|
||||
{
|
||||
idealActivity = ACT_HL2MP_WALK;
|
||||
}
|
||||
@ -132,19 +160,22 @@ Activity CSinglePlayerAnimState::CalcMainActivity()
|
||||
}
|
||||
|
||||
//return m_pPlayer->GetActivity();
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim )
|
||||
void CMapbasePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim )
|
||||
{
|
||||
if ( playerAnim == PLAYER_ATTACK1 )
|
||||
{
|
||||
m_iFireSequence = SelectWeightedSequence( TranslateActivity( ACT_HL2MP_GESTURE_RANGE_ATTACK ) );
|
||||
m_bFiring = m_iFireSequence != -1;
|
||||
m_flFireCycle = 0;
|
||||
|
||||
// Be sure to stop reloading
|
||||
m_bReloading = false;
|
||||
m_flReloadCycle = 0;
|
||||
}
|
||||
else if ( playerAnim == PLAYER_ATTACK2 )
|
||||
{
|
||||
@ -155,6 +186,10 @@ void CSinglePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim )
|
||||
#endif
|
||||
m_bFiring = m_iFireSequence != -1;
|
||||
m_flFireCycle = 0;
|
||||
|
||||
// Be sure to stop reloading
|
||||
m_bReloading = false;
|
||||
m_flReloadCycle = 0;
|
||||
}
|
||||
else if ( playerAnim == PLAYER_JUMP )
|
||||
{
|
||||
@ -162,6 +197,7 @@ void CSinglePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim )
|
||||
if (!m_bJumping)
|
||||
{
|
||||
m_bJumping = true;
|
||||
m_bDuckJumping = (GetOuter()->GetFlags() & FL_DUCKING) ? true : false; //m_pPlayer->m_nButtons & IN_DUCK;
|
||||
m_bFirstJumpFrame = true;
|
||||
m_flJumpStartTime = gpGlobals->curtime;
|
||||
}
|
||||
@ -184,13 +220,13 @@ void CSinglePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim )
|
||||
if (m_iWeaponSwitchSequence != -1)
|
||||
{
|
||||
// clear other events that might be playing in our layer
|
||||
m_bPlayingMisc = false;
|
||||
//m_bPlayingMisc = false;
|
||||
m_bReloading = false;
|
||||
|
||||
m_bWeaponSwitching = true;
|
||||
m_flWeaponSwitchCycle = 0;
|
||||
m_flMiscBlendOut = 0.1f;
|
||||
m_flMiscBlendIn = 0.1f;
|
||||
//m_flMiscBlendOut = 0.1f;
|
||||
//m_flMiscBlendIn = 0.1f;
|
||||
m_bMiscNoOverride = false;
|
||||
}
|
||||
}
|
||||
@ -199,10 +235,10 @@ void CSinglePlayerAnimState::SetPlayerAnimation( PLAYER_ANIM playerAnim )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
Activity CSinglePlayerAnimState::TranslateActivity( Activity actDesired )
|
||||
Activity CMapbasePlayerAnimState::TranslateActivity( Activity actDesired )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
return actDesired;
|
||||
#if defined(CLIENT_DLL) && !defined(MAPBASE_MP)
|
||||
return actDesired;
|
||||
#else
|
||||
return m_pPlayer->Weapon_TranslateActivity( actDesired );
|
||||
#endif
|
||||
@ -211,7 +247,7 @@ Activity CSinglePlayerAnimState::TranslateActivity( Activity actDesired )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSinglePlayerAnimState::HandleJumping()
|
||||
bool CMapbasePlayerAnimState::HandleJumping()
|
||||
{
|
||||
if ( m_bJumping )
|
||||
{
|
||||
@ -230,6 +266,7 @@ bool CSinglePlayerAnimState::HandleJumping()
|
||||
if ( m_pOuter->GetFlags() & FL_ONGROUND || GetOuter()->GetGroundEntity() != NULL)
|
||||
{
|
||||
m_bJumping = false;
|
||||
m_bDuckJumping = false;
|
||||
RestartMainSequence(); // Reset the animation.
|
||||
}
|
||||
}
|
||||
@ -242,20 +279,21 @@ bool CSinglePlayerAnimState::HandleJumping()
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
|
||||
void CMapbasePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
CBasePlayerAnimState::ComputeSequences(pStudioHdr);
|
||||
|
||||
ComputeFireSequence();
|
||||
ComputeMiscSequence();
|
||||
ComputeReloadSequence();
|
||||
ComputeWeaponSwitchSequence();
|
||||
ComputeWeaponSwitchSequence();
|
||||
ComputeRelaxSequence();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::AddMiscSequence( int iSequence, float flBlendIn, float flBlendOut, float flPlaybackRate, bool bHoldAtEnd, bool bOnlyWhenStill )
|
||||
void CMapbasePlayerAnimState::AddMiscSequence( int iSequence, float flBlendIn, float flBlendOut, float flPlaybackRate, bool bHoldAtEnd, bool bOnlyWhenStill )
|
||||
{
|
||||
Assert( iSequence != -1 );
|
||||
|
||||
@ -265,7 +303,7 @@ void CSinglePlayerAnimState::AddMiscSequence( int iSequence, float flBlendIn, fl
|
||||
|
||||
m_bPlayingMisc = true;
|
||||
m_bMiscHoldAtEnd = bHoldAtEnd;
|
||||
m_bReloading = false;
|
||||
//m_bReloading = false;
|
||||
m_flMiscCycle = 0;
|
||||
m_bMiscOnlyWhenStill = bOnlyWhenStill;
|
||||
m_bMiscNoOverride = true;
|
||||
@ -275,12 +313,36 @@ void CSinglePlayerAnimState::AddMiscSequence( int iSequence, float flBlendIn, fl
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::ClearAnimationState()
|
||||
void CMapbasePlayerAnimState::StartWeaponRelax()
|
||||
{
|
||||
if (m_bWeaponRelaxing)
|
||||
return;
|
||||
|
||||
m_bWeaponRelaxing = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMapbasePlayerAnimState::StopWeaponRelax()
|
||||
{
|
||||
if (!m_bWeaponRelaxing)
|
||||
return;
|
||||
|
||||
m_bWeaponRelaxing = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CMapbasePlayerAnimState::ClearAnimationState()
|
||||
{
|
||||
m_bJumping = false;
|
||||
m_bDuckJumping = false;
|
||||
m_bFiring = false;
|
||||
m_bReloading = false;
|
||||
m_bWeaponSwitching = false;
|
||||
m_bWeaponRelaxing = false;
|
||||
m_bPlayingMisc = false;
|
||||
m_flReloadBlendIn = 0.0f;
|
||||
m_flReloadBlendOut = 0.0f;
|
||||
@ -289,32 +351,42 @@ void CSinglePlayerAnimState::ClearAnimationState()
|
||||
CBasePlayerAnimState::ClearAnimationState();
|
||||
}
|
||||
|
||||
void CSinglePlayerAnimState::ClearAnimationLayers()
|
||||
void CMapbasePlayerAnimState::ClearAnimationLayers()
|
||||
{
|
||||
VPROF( "CBasePlayerAnimState::ClearAnimationLayers" );
|
||||
|
||||
// In c_baseanimatingoverlay.cpp, this sometimes desyncs from the interpolated overlays and causes a crash in ResizeAnimationLayerCallback when the player dies. (pVec->Count() != pVecIV->Count())
|
||||
// Is there a better way of getting around this issue?
|
||||
#ifndef CLIENT_DLL
|
||||
if ( !m_pOuter )
|
||||
return;
|
||||
|
||||
m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
|
||||
for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
|
||||
{
|
||||
// If we're not using aim sequences, leave the aim layers alone
|
||||
// (allows them to be used outside of anim state)
|
||||
if ( !m_AnimConfig.m_bUseAimSequences && i <= NUM_AIMSEQUENCE_LAYERS )
|
||||
continue;
|
||||
|
||||
m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
|
||||
#ifndef CLIENT_DLL
|
||||
m_pOuter->GetAnimOverlay( i )->m_fFlags = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CSinglePlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
|
||||
int CMapbasePlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
|
||||
{
|
||||
// TODO?
|
||||
return m_pOuter->LookupSequence( "soldier_Aim_9_directions" );
|
||||
}
|
||||
|
||||
void CSinglePlayerAnimState::UpdateLayerSequenceGeneric( int iLayer, bool &bEnabled,
|
||||
void CMapbasePlayerAnimState::UpdateLayerSequenceGeneric( int iLayer, bool &bEnabled,
|
||||
float &flCurCycle, int &iSequence, bool bWaitAtEnd,
|
||||
float fBlendIn, float fBlendOut, bool bMoveBlend, float fPlaybackRate, bool bUpdateCycle /* = true */ )
|
||||
{
|
||||
@ -383,7 +455,7 @@ void CSinglePlayerAnimState::UpdateLayerSequenceGeneric( int iLayer, bool &bEnab
|
||||
pLayer->m_flPlaybackRate = fPlaybackRate;
|
||||
pLayer->m_flWeight = 1.0f;
|
||||
|
||||
if (iLayer == RELOADSEQUENCE_LAYER)
|
||||
if (fBlendIn > 0.0f || fBlendOut > 0.0f)
|
||||
{
|
||||
// blend this layer in and out for smooth reloading
|
||||
if (flCurCycle < fBlendIn && fBlendIn>0)
|
||||
@ -418,25 +490,91 @@ void CSinglePlayerAnimState::UpdateLayerSequenceGeneric( int iLayer, bool &bEnab
|
||||
pLayer->SetOrder( iLayer );
|
||||
}
|
||||
|
||||
void CSinglePlayerAnimState::ComputeFireSequence()
|
||||
void CMapbasePlayerAnimState::ComputeFireSequence()
|
||||
{
|
||||
UpdateLayerSequenceGeneric( FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
|
||||
}
|
||||
|
||||
void CSinglePlayerAnimState::ComputeReloadSequence()
|
||||
void CMapbasePlayerAnimState::ComputeReloadSequence()
|
||||
{
|
||||
UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false, m_flReloadBlendIn, m_flReloadBlendOut, false, m_fReloadPlaybackRate );
|
||||
}
|
||||
|
||||
void CSinglePlayerAnimState::ComputeWeaponSwitchSequence()
|
||||
void CMapbasePlayerAnimState::ComputeWeaponSwitchSequence()
|
||||
{
|
||||
UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bWeaponSwitching, m_flWeaponSwitchCycle, m_iWeaponSwitchSequence, false, 0, 0.5f );
|
||||
}
|
||||
|
||||
// does misc gestures if we're not firing
|
||||
void CSinglePlayerAnimState::ComputeMiscSequence()
|
||||
void CMapbasePlayerAnimState::ComputeRelaxSequence()
|
||||
{
|
||||
UpdateLayerSequenceGeneric( RELOADSEQUENCE_LAYER, m_bPlayingMisc, m_flMiscCycle, m_iMiscSequence, m_bMiscHoldAtEnd, m_flMiscBlendIn, m_flMiscBlendOut, m_bMiscOnlyWhenStill, m_fMiscPlaybackRate );
|
||||
bool bRelaxing = m_bWeaponRelaxing;
|
||||
float flRelaxSpeed = 0.05f;
|
||||
|
||||
if ((m_bFiring && m_flFireCycle < 1.0f) || m_bReloading)
|
||||
{
|
||||
// Keep weapon raised
|
||||
bRelaxing = false;
|
||||
flRelaxSpeed = 0.5f;
|
||||
//GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), 0.0f );
|
||||
}
|
||||
|
||||
if (bRelaxing ? m_flWeaponRelaxAmount != 1.0f : m_flWeaponRelaxAmount != 0.0f)
|
||||
{
|
||||
if (bRelaxing)
|
||||
m_flWeaponRelaxAmount += flRelaxSpeed;
|
||||
else
|
||||
m_flWeaponRelaxAmount -= flRelaxSpeed;
|
||||
|
||||
m_flWeaponRelaxAmount = clamp( m_flWeaponRelaxAmount, 0.0f, 1.0f );
|
||||
|
||||
GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), m_flWeaponRelaxAmount );
|
||||
|
||||
/*int nPose = GetOuter()->LookupPoseParameter( "weapon_lower" );
|
||||
if (nPose != -1)
|
||||
{
|
||||
float flValue = RemapValClamped( (m_flWeaponRelaxTime - gpGlobals->curtime), 0.0f, 0.5f, 0.0f, 1.0f );
|
||||
|
||||
if (flValue <= 0.0f)
|
||||
{
|
||||
// All done
|
||||
m_flWeaponRelaxTime = FLT_MAX;
|
||||
}
|
||||
|
||||
if (m_bWeaponRelaxing)
|
||||
flValue = 1.0f - flValue;
|
||||
|
||||
GetOuter()->SetPoseParameter( nPose, SimpleSpline( flValue ) );
|
||||
}*/
|
||||
}
|
||||
else if (bRelaxing)
|
||||
{
|
||||
GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "weapon_lower" ), 1.0f );
|
||||
}
|
||||
|
||||
/*bool bEnabled = m_bWeaponRelaxing;
|
||||
bool bUpdateCycle = true;
|
||||
if (bEnabled)
|
||||
{
|
||||
if (m_flWeaponRelaxCycle >= 0.5f)
|
||||
{
|
||||
// Pause at 0.5
|
||||
m_flWeaponRelaxCycle = 0.5f;
|
||||
bUpdateCycle = false;
|
||||
}
|
||||
}
|
||||
else if (m_flWeaponRelaxCycle < 1.0f)
|
||||
{
|
||||
// Make sure we exit the relax
|
||||
bEnabled = true;
|
||||
}
|
||||
|
||||
UpdateLayerSequenceGeneric( AIMSEQUENCE_LAYER, bEnabled, m_flWeaponRelaxCycle, m_iWeaponRelaxSequence, false, 0.5f, 0.5f, false, 1.0f, bUpdateCycle );*/
|
||||
}
|
||||
|
||||
// does misc gestures if we're not firing
|
||||
void CMapbasePlayerAnimState::ComputeMiscSequence()
|
||||
{
|
||||
UpdateLayerSequenceGeneric( MISCSEQUENCE_LAYER, m_bPlayingMisc, m_flMiscCycle, m_iMiscSequence, m_bMiscHoldAtEnd, m_flMiscBlendIn, m_flMiscBlendOut, m_bMiscOnlyWhenStill, m_fMiscPlaybackRate );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -444,7 +582,7 @@ void CSinglePlayerAnimState::ComputeMiscSequence()
|
||||
// Input : -
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float CSinglePlayerAnimState::GetCurrentMaxGroundSpeed()
|
||||
float CMapbasePlayerAnimState::GetCurrentMaxGroundSpeed()
|
||||
{
|
||||
CStudioHdr *pStudioHdr = GetOuter()->GetModelPtr();
|
||||
|
||||
@ -481,11 +619,42 @@ float CSinglePlayerAnimState::GetCurrentMaxGroundSpeed()
|
||||
return speed;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool CMapbasePlayerAnimState::ShouldUseAimPoses( void ) const
|
||||
{
|
||||
return GetAimPoseBlend() > 0.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CMapbasePlayerAnimState::GetAimPoseBlend( void ) const
|
||||
{
|
||||
if (!GetOuter()->MyCombatCharacterPointer() || !GetOuter()->MyCombatCharacterPointer()->GetActiveWeapon()
|
||||
|| GetOuter()->MyCombatCharacterPointer()->GetActiveWeapon()->IsEffectActive( EF_NODRAW ))
|
||||
return 0.0f;
|
||||
|
||||
return 1.0f - m_flWeaponRelaxAmount;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CMapbasePlayerAnimState::SetOuterBodyYaw( float flValue )
|
||||
{
|
||||
float flAimPoseBlend = GetAimPoseBlend();
|
||||
|
||||
GetOuter()->SetPoseParameter( GetOuter()->LookupPoseParameter( "aim_yaw" ), flValue * flAimPoseBlend );
|
||||
return CBasePlayerAnimState::SetOuterBodyYaw( flValue * (1.0f - flAimPoseBlend) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Override for backpeddling
|
||||
// Input : dt -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::ComputePoseParam_BodyYaw( void )
|
||||
void CMapbasePlayerAnimState::ComputePoseParam_BodyYaw( void )
|
||||
{
|
||||
CBasePlayerAnimState::ComputePoseParam_BodyYaw();
|
||||
|
||||
@ -495,7 +664,7 @@ void CSinglePlayerAnimState::ComputePoseParam_BodyYaw( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::ComputePoseParam_BodyLookYaw( void )
|
||||
void CMapbasePlayerAnimState::ComputePoseParam_BodyLookYaw( void )
|
||||
{
|
||||
// See if we even have a blender for pitch
|
||||
int upper_body_yaw = GetOuter()->LookupPoseParameter( "aim_yaw" );
|
||||
@ -632,7 +801,7 @@ void CSinglePlayerAnimState::ComputePoseParam_BodyLookYaw( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
|
||||
void CMapbasePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
// Get pitch from v_angle
|
||||
float flPitch = m_flEyePitch;
|
||||
@ -643,16 +812,19 @@ void CSinglePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr
|
||||
}
|
||||
flPitch = clamp( flPitch, -90, 90 );
|
||||
|
||||
//float flAimPoseBlend = GetAimPoseBlend();
|
||||
|
||||
// See if we have a blender for pitch
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch );
|
||||
GetOuter()->SetPoseParameter( pStudioHdr, "head_pitch", flPitch );
|
||||
|
||||
ComputePoseParam_HeadPitch( pStudioHdr );
|
||||
//ComputePoseParam_HeadPitch( pStudioHdr );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSinglePlayerAnimState::ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr )
|
||||
void CMapbasePlayerAnimState::ComputePoseParam_HeadPitch( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
// Get pitch from v_angle
|
||||
int iHeadPitch = GetOuter()->LookupPoseParameter("head_pitch");
|
@ -14,8 +14,8 @@
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SINGLEPLAYER_ANIMSTATE_H
|
||||
#define SINGLEPLAYER_ANIMSTATE_H
|
||||
#ifndef MAPBASE_PLAYERANIMSTATE_H
|
||||
#define MAPBASE_PLAYERANIMSTATE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
@ -34,10 +34,10 @@
|
||||
#define SP_ANIM_STATE 1
|
||||
#endif
|
||||
|
||||
class CSinglePlayerAnimState : public CBasePlayerAnimState
|
||||
class CMapbasePlayerAnimState : public CBasePlayerAnimState
|
||||
{
|
||||
public:
|
||||
CSinglePlayerAnimState( CBasePlayer *pPlayer );
|
||||
CMapbasePlayerAnimState( CBasePlayer *pPlayer );
|
||||
|
||||
Activity CalcMainActivity();
|
||||
int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
|
||||
@ -49,10 +49,16 @@ public:
|
||||
void ComputeSequences( CStudioHdr *pStudioHdr );
|
||||
|
||||
void AddMiscSequence( int iSequence, float flBlendIn = 0.0f, float flBlendOut = 0.0f, float flPlaybackRate = 1.0f, bool bHoldAtEnd = false, bool bOnlyWhenStill = false );
|
||||
|
||||
void StartWeaponRelax();
|
||||
void StopWeaponRelax();
|
||||
|
||||
void ClearAnimationState();
|
||||
void ClearAnimationLayers();
|
||||
|
||||
inline bool IsJumping() const { return m_bJumping; }
|
||||
inline bool IsDuckJumping() const { return m_bDuckJumping; }
|
||||
|
||||
private:
|
||||
|
||||
bool HandleJumping();
|
||||
@ -60,13 +66,19 @@ private:
|
||||
void ComputeFireSequence();
|
||||
void ComputeReloadSequence();
|
||||
void ComputeWeaponSwitchSequence();
|
||||
void ComputeRelaxSequence();
|
||||
void ComputeMiscSequence();
|
||||
|
||||
void UpdateLayerSequenceGeneric( int iLayer, bool &bEnabled, float &flCurCycle,
|
||||
int &iSequence, bool bWaitAtEnd,
|
||||
float fBlendIn=0.15f, float fBlendOut=0.15f, bool bMoveBlend = false,
|
||||
float fBlendIn=0.0f, float fBlendOut=0.0f, bool bMoveBlend = false,
|
||||
float fPlaybackRate=1.0f, bool bUpdateCycle = true );
|
||||
|
||||
bool ShouldUseAimPoses() const;
|
||||
float GetAimPoseBlend() const;
|
||||
|
||||
float SetOuterBodyYaw( float flValue );
|
||||
|
||||
void ComputePoseParam_BodyYaw( void );
|
||||
void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr );
|
||||
void ComputePoseParam_BodyLookYaw( void );
|
||||
@ -76,6 +88,7 @@ private:
|
||||
|
||||
// Current state variables.
|
||||
bool m_bJumping; // Set on a jump event.
|
||||
bool m_bDuckJumping; // Jump started while ducking
|
||||
float m_flJumpStartTime;
|
||||
bool m_bFirstJumpFrame;
|
||||
|
||||
@ -90,6 +103,9 @@ private:
|
||||
float m_flWeaponSwitchCycle;
|
||||
int m_iWeaponSwitchSequence;
|
||||
|
||||
bool m_bWeaponRelaxing;
|
||||
float m_flWeaponRelaxAmount;
|
||||
|
||||
bool m_bPlayingMisc;
|
||||
float m_flMiscCycle, m_flMiscBlendOut, m_flMiscBlendIn;
|
||||
int m_iMiscSequence;
|
||||
@ -105,6 +121,6 @@ private:
|
||||
float m_flFireCycle;
|
||||
};
|
||||
|
||||
CSinglePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer );
|
||||
CMapbasePlayerAnimState *CreatePlayerAnimationState( CBasePlayer *pPlayer );
|
||||
|
||||
#endif // SINGLEPLAYER_ANIMSTATE_H
|
||||
#endif // MAPBASE_PLAYERANIMSTATE_H
|
@ -29,6 +29,7 @@
|
||||
#include "AI_ResponseSystem.h"
|
||||
#include "mapbase/SystemConvarMod.h"
|
||||
#include "gameinterface.h"
|
||||
#include "mapbase/choreosentence.h"
|
||||
#endif
|
||||
#if defined(HL2_DLL) || defined(HL2_CLIENT_DLL)
|
||||
#include "protagonist_system.h"
|
||||
@ -88,6 +89,7 @@ char g_iszGameName[128];
|
||||
#ifdef GAME_DLL
|
||||
// Default player configuration
|
||||
char g_szDefaultPlayerModel[MAX_PATH];
|
||||
bool g_bDefaultPlayerLegs;
|
||||
bool g_bDefaultPlayerDrawExternally;
|
||||
|
||||
char g_szDefaultHandsModel[MAX_PATH];
|
||||
@ -115,7 +117,7 @@ enum
|
||||
MANIFEST_HUDLAYOUT,
|
||||
#else
|
||||
MANIFEST_TALKER,
|
||||
//MANIFEST_SENTENCES,
|
||||
MANIFEST_CHOREOSENTENCES,
|
||||
MANIFEST_ACTBUSY,
|
||||
#endif
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
@ -158,7 +160,7 @@ static const ManifestType_t gm_szManifestFileStrings[MANIFEST_NUM_TYPES] = {
|
||||
{ "hudlayout", "mapbase_load_hudlayout", "Should we load map-specific HUD layout overrides? e.g. \"maps/<mapname>_hudlayout.res\"" },
|
||||
#else
|
||||
{ "talker", "mapbase_load_talker", "Should we load map-specific talker files? e.g. \"maps/<mapname>_talker.txt\"" },
|
||||
//{ "sentences", "mapbase_load_sentences", "Should we load map-specific sentences? e.g. \"maps/<mapname>_sentences.txt\"" },
|
||||
{ "choreosentences", "mapbase_load_choreosentences", "Should we load map-specific choreo sentences? e.g. \"maps/<mapname>_choreosentences.txt\"" },
|
||||
{ "actbusy", "mapbase_load_actbusy", "Should we load map-specific actbusy files? e.g. \"maps/<mapname>_actbusy.txt\"" },
|
||||
#endif
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
@ -249,6 +251,7 @@ public:
|
||||
|
||||
#ifdef GAME_DLL
|
||||
Q_strncpy( g_szDefaultPlayerModel, gameinfo->GetString( "player_default_model", "models/player.mdl" ), sizeof( g_szDefaultPlayerModel ) );
|
||||
g_bDefaultPlayerLegs = gameinfo->GetBool( "player_default_legs", false );
|
||||
g_bDefaultPlayerDrawExternally = gameinfo->GetBool( "player_default_draw_externally", false );
|
||||
|
||||
Q_strncpy( g_szDefaultHandsModel, gameinfo->GetString( "player_default_hands", "models/weapons/v_hands.mdl" ), sizeof( g_szDefaultHandsModel ) );
|
||||
@ -483,7 +486,7 @@ public:
|
||||
LoadResponseSystemFile(value); //PrecacheCustomResponseSystem( value );
|
||||
} break;
|
||||
//case MANIFEST_SOUNDSCAPES: { g_SoundscapeSystem.AddSoundscapeFile(value); } break;
|
||||
//case MANIFEST_SENTENCES: { engine->PrecacheSentenceFile(value); } break;
|
||||
case MANIFEST_CHOREOSENTENCES: { LoadChoreoSentenceFile(value); } break;
|
||||
case MANIFEST_ACTBUSY: { ParseCustomActbusyFile(value); } break;
|
||||
#endif
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
@ -631,6 +634,7 @@ public:
|
||||
#else
|
||||
void LoadCustomTalkerFile( const char *szScript ) { LoadFromValue( szScript, MANIFEST_TALKER, false ); }
|
||||
void LoadCustomActbusyFile( const char *szScript ) { LoadFromValue( szScript, MANIFEST_ACTBUSY, false ); }
|
||||
void LoadCustomChoreoSentenceFile( const char *szScript ) { LoadFromValue( szScript, MANIFEST_CHOREOSENTENCES, false ); }
|
||||
#endif
|
||||
|
||||
const char *GetModName() { return g_iszGameName; }
|
||||
@ -679,6 +683,7 @@ BEGIN_SCRIPTDESC_ROOT( CMapbaseSystem, SCRIPT_SINGLETON "All-purpose Mapbase sys
|
||||
#else
|
||||
DEFINE_SCRIPTFUNC( LoadCustomTalkerFile, "Loads a custom talker file." )
|
||||
DEFINE_SCRIPTFUNC( LoadCustomActbusyFile, "Loads a custom actbusy file." )
|
||||
DEFINE_SCRIPTFUNC( LoadCustomChoreoSentenceFile, "Loads a custom choreo sentence file." )
|
||||
#endif
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetModName, "Gets the name of the mod. This is the name which shows up on Steam, RPC, etc." )
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "c_ai_basenpc.h"
|
||||
#else
|
||||
#include "ai_basenpc.h"
|
||||
#include "ai_senses.h"
|
||||
#include "globalstate.h"
|
||||
#endif
|
||||
|
||||
@ -357,7 +358,8 @@ void RegisterSharedScriptConstants()
|
||||
ScriptRegisterConstant( g_pScriptVM, ROPE_NO_GRAVITY, "Disable gravity on this rope. (for use in rope flags)" );
|
||||
ScriptRegisterConstant( g_pScriptVM, ROPE_NUMFLAGS, "The number of rope flags recognized by the game." );
|
||||
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, Vector( ROPE_GRAVITY ), "ROPE_GRAVITY", "Default rope gravity vector." );
|
||||
static Vector vecRopeGravity( ROPE_GRAVITY );
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, vecRopeGravity, "ROPE_GRAVITY", "Default rope gravity vector." );
|
||||
|
||||
//
|
||||
// Sounds
|
||||
@ -427,8 +429,8 @@ void RegisterSharedScriptConstants()
|
||||
|
||||
#ifdef GAME_DLL
|
||||
//
|
||||
// AI Sounds
|
||||
// (QueryHearSound hook can use these)
|
||||
// AI Senses
|
||||
// (NPC hooks can use these)
|
||||
//
|
||||
ScriptRegisterConstant( g_pScriptVM, SOUND_NONE, "Sound type used in QueryHearSound hooks, etc." );
|
||||
ScriptRegisterConstant( g_pScriptVM, SOUND_COMBAT, "Sound type used in QueryHearSound hooks, etc." );
|
||||
@ -481,6 +483,11 @@ void RegisterSharedScriptConstants()
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, (int)SOUNDENT_VOLUME_PISTOL, "SOUNDENT_VOLUME_PISTOL", "Sound volume preset for use in InsertAISound, etc." );
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, (int)SOUNDENT_VOLUME_EMPTY, "SOUNDENT_VOLUME_PISTOL", "Sound volume preset for use in InsertAISound, etc." );
|
||||
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, (int)SEEN_ALL, "SEEN_ALL", "All NPC sight arrays. Used in GetFirstSeenEntity, etc." );
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, (int)SEEN_HIGH_PRIORITY, "SEEN_HIGH_PRIORITY", "NPC sight array for players. Used in GetFirstSeenEntity, etc." );
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, (int)SEEN_NPCS, "SEEN_NPCS", "NPC sight array for other NPCs. Used in GetFirstSeenEntity, etc." );
|
||||
ScriptRegisterConstantNamed( g_pScriptVM, (int)SEEN_MISC, "SEEN_MISC", "NPC sight array for objects. Used in GetFirstSeenEntity, etc." );
|
||||
|
||||
//
|
||||
// Capabilities
|
||||
//
|
||||
|
@ -255,11 +255,10 @@ void ScriptDispatchSpawn( HSCRIPT hEntity )
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
static HSCRIPT CreateDamageInfo( HSCRIPT hInflictor, HSCRIPT hAttacker, const Vector &vecForce, const Vector &vecDamagePos, float flDamage, int iDamageType )
|
||||
static HSCRIPT_RC CreateDamageInfo( HSCRIPT hInflictor, HSCRIPT hAttacker, const Vector &vecForce, const Vector &vecDamagePos, float flDamage, int iDamageType )
|
||||
{
|
||||
// The script is responsible for deleting this via DestroyDamageInfo().
|
||||
CTakeDamageInfo *damageInfo = new CTakeDamageInfo( ToEnt(hInflictor), ToEnt(hAttacker), flDamage, iDamageType );
|
||||
HSCRIPT hScript = g_pScriptVM->RegisterInstance( damageInfo );
|
||||
HSCRIPT hScript = g_pScriptVM->RegisterInstance( damageInfo, true );
|
||||
|
||||
damageInfo->SetDamagePosition( vecDamagePos );
|
||||
damageInfo->SetDamageForce( vecForce );
|
||||
@ -267,14 +266,8 @@ static HSCRIPT CreateDamageInfo( HSCRIPT hInflictor, HSCRIPT hAttacker, const Ve
|
||||
return hScript;
|
||||
}
|
||||
|
||||
static void DestroyDamageInfo( HSCRIPT hDamageInfo )
|
||||
static void DestroyDamageInfo( HSCRIPT )
|
||||
{
|
||||
CTakeDamageInfo *pInfo = HScriptToClass< CTakeDamageInfo >( hDamageInfo );
|
||||
if ( pInfo )
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( hDamageInfo );
|
||||
delete pInfo;
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptCalculateExplosiveDamageForce( HSCRIPT info, const Vector &vecDir, const Vector &vecForceOrigin, float flScale )
|
||||
@ -317,6 +310,8 @@ void ScriptGuessDamageForce( HSCRIPT info, const Vector &vecForceDir, const Vect
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptGameTrace, "CGameTrace", "trace_t" )
|
||||
DEFINE_SCRIPT_REFCOUNTED_INSTANCE()
|
||||
|
||||
DEFINE_SCRIPTFUNC( DidHitWorld, "Returns whether the trace hit the world entity or not." )
|
||||
DEFINE_SCRIPTFUNC( DidHitNonWorldEntity, "Returns whether the trace hit something other than the world entity." )
|
||||
DEFINE_SCRIPTFUNC( GetEntityIndex, "Returns the index of whatever entity this trace hit." )
|
||||
@ -347,7 +342,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptGameTrace, "CGameTrace", "trace_t" )
|
||||
DEFINE_SCRIPTFUNC( Surface, "" )
|
||||
DEFINE_SCRIPTFUNC( Plane, "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( Destroy, "Deletes this instance. Important for preventing memory leaks." )
|
||||
DEFINE_SCRIPTFUNC( Destroy, SCRIPT_HIDE )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED( scriptsurfacedata_t, "surfacedata_t", "" )
|
||||
@ -376,37 +371,28 @@ END_SCRIPTDESC();
|
||||
|
||||
CPlaneTInstanceHelper g_PlaneTInstanceHelper;
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT( cplane_t, "" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_PlaneTInstanceHelper )
|
||||
BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( cplane_t, "", &g_PlaneTInstanceHelper )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
static HSCRIPT ScriptTraceLineComplex( const Vector &vecStart, const Vector &vecEnd, HSCRIPT entIgnore, int iMask, int iCollisionGroup )
|
||||
static HSCRIPT_RC ScriptTraceLineComplex( const Vector &vecStart, const Vector &vecEnd, HSCRIPT entIgnore, int iMask, int iCollisionGroup )
|
||||
{
|
||||
// The script is responsible for deleting this via Destroy().
|
||||
CScriptGameTrace *tr = new CScriptGameTrace();
|
||||
|
||||
CBaseEntity *pIgnore = ToEnt( entIgnore );
|
||||
UTIL_TraceLine( vecStart, vecEnd, iMask, pIgnore, iCollisionGroup, tr );
|
||||
|
||||
tr->RegisterSurface();
|
||||
tr->RegisterPlane();
|
||||
|
||||
return tr->GetScriptInstance();
|
||||
return g_pScriptVM->RegisterInstance( tr, true );
|
||||
}
|
||||
|
||||
static HSCRIPT ScriptTraceHullComplex( const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin, const Vector &hullMax,
|
||||
static HSCRIPT_RC ScriptTraceHullComplex( const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin, const Vector &hullMax,
|
||||
HSCRIPT entIgnore, int iMask, int iCollisionGroup )
|
||||
{
|
||||
// The script is responsible for deleting this via Destroy().
|
||||
CScriptGameTrace *tr = new CScriptGameTrace();
|
||||
|
||||
CBaseEntity *pIgnore = ToEnt( entIgnore );
|
||||
UTIL_TraceHull( vecStart, vecEnd, hullMin, hullMax, iMask, pIgnore, iCollisionGroup, tr );
|
||||
|
||||
tr->RegisterSurface();
|
||||
tr->RegisterPlane();
|
||||
|
||||
return tr->GetScriptInstance();
|
||||
return g_pScriptVM->RegisterInstance( tr, true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -477,12 +463,11 @@ void FireBulletsInfo_t::ScriptSetAdditionalIgnoreEnt( HSCRIPT value )
|
||||
m_pAdditionalIgnoreEnt = ToEnt( value );
|
||||
}
|
||||
|
||||
static HSCRIPT CreateFireBulletsInfo( int cShots, const Vector &vecSrc, const Vector &vecDirShooting,
|
||||
static HSCRIPT_RC CreateFireBulletsInfo( int cShots, const Vector &vecSrc, const Vector &vecDirShooting,
|
||||
const Vector &vecSpread, float iDamage, HSCRIPT pAttacker )
|
||||
{
|
||||
// The script is responsible for deleting this via DestroyFireBulletsInfo().
|
||||
FireBulletsInfo_t *info = new FireBulletsInfo_t();
|
||||
HSCRIPT hScript = g_pScriptVM->RegisterInstance( info );
|
||||
HSCRIPT hScript = g_pScriptVM->RegisterInstance( info, true );
|
||||
|
||||
info->SetShots( cShots );
|
||||
info->SetSource( vecSrc );
|
||||
@ -494,14 +479,8 @@ static HSCRIPT CreateFireBulletsInfo( int cShots, const Vector &vecSrc, const Ve
|
||||
return hScript;
|
||||
}
|
||||
|
||||
static void DestroyFireBulletsInfo( HSCRIPT hBulletsInfo )
|
||||
static void DestroyFireBulletsInfo( HSCRIPT )
|
||||
{
|
||||
FireBulletsInfo_t *pInfo = HScriptToClass< FireBulletsInfo_t >( hBulletsInfo );
|
||||
if ( pInfo )
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( hBulletsInfo );
|
||||
delete pInfo;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -509,9 +488,7 @@ static void DestroyFireBulletsInfo( HSCRIPT hBulletsInfo )
|
||||
//-----------------------------------------------------------------------------
|
||||
CAnimEventTInstanceHelper g_AnimEventTInstanceHelper;
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT( scriptanimevent_t, "" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_AnimEventTInstanceHelper )
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( scriptanimevent_t, "", &g_AnimEventTInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC( GetEvent, "" )
|
||||
DEFINE_SCRIPTFUNC( SetEvent, "" )
|
||||
|
||||
@ -535,7 +512,7 @@ bool CAnimEventTInstanceHelper::Get( void *p, const char *pszKey, ScriptVariant_
|
||||
{
|
||||
DevWarning( "VScript animevent_t.%s: animevent_t metamethod members are deprecated! Use 'script_help animevent_t' to see the correct functions.\n", pszKey );
|
||||
|
||||
animevent_t *ani = ((animevent_t *)p);
|
||||
animevent_t *ani = &((scriptanimevent_t *)p)->event;
|
||||
if (FStrEq( pszKey, "event" ))
|
||||
variant = ani->event;
|
||||
else if (FStrEq( pszKey, "options" ))
|
||||
@ -558,18 +535,28 @@ bool CAnimEventTInstanceHelper::Set( void *p, const char *pszKey, ScriptVariant_
|
||||
{
|
||||
DevWarning( "VScript animevent_t.%s: animevent_t metamethod members are deprecated! Use 'script_help animevent_t' to see the correct functions.\n", pszKey );
|
||||
|
||||
animevent_t *ani = ((animevent_t *)p);
|
||||
scriptanimevent_t *script_ani = ((scriptanimevent_t *)p);
|
||||
animevent_t *ani = &script_ani->event;
|
||||
if (FStrEq( pszKey, "event" ))
|
||||
ani->event = variant;
|
||||
{
|
||||
return variant.AssignTo( &ani->event );
|
||||
}
|
||||
else if (FStrEq( pszKey, "options" ))
|
||||
ani->options = variant;
|
||||
{
|
||||
char *szOptions;
|
||||
if (!variant.AssignTo( &szOptions ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
script_ani->SetOptions( szOptions );
|
||||
}
|
||||
else if (FStrEq( pszKey, "cycle" ))
|
||||
ani->cycle = variant;
|
||||
return variant.AssignTo( &ani->cycle );
|
||||
else if (FStrEq( pszKey, "eventtime" ))
|
||||
ani->eventtime = variant;
|
||||
return variant.AssignTo( &ani->eventtime );
|
||||
else if (FStrEq( pszKey, "type" ))
|
||||
ani->type = variant;
|
||||
else if (FStrEq( pszKey, "source" ))
|
||||
return variant.AssignTo( &ani->type );
|
||||
else if (FStrEq( pszKey, "source" ) && variant.m_type == FIELD_HSCRIPT)
|
||||
{
|
||||
CBaseEntity *pEnt = ToEnt( variant.m_hScript );
|
||||
if (pEnt)
|
||||
@ -1046,14 +1033,14 @@ void RegisterSharedScriptFunctions()
|
||||
#endif
|
||||
|
||||
ScriptRegisterFunction( g_pScriptVM, CreateDamageInfo, "" );
|
||||
ScriptRegisterFunction( g_pScriptVM, DestroyDamageInfo, "" );
|
||||
ScriptRegisterFunction( g_pScriptVM, DestroyDamageInfo, SCRIPT_HIDE );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalculateExplosiveDamageForce, "CalculateExplosiveDamageForce", "Fill out a damage info handle with a damage force for an explosive." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalculateBulletDamageForce, "CalculateBulletDamageForce", "Fill out a damage info handle with a damage force for a bullet impact." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCalculateMeleeDamageForce, "CalculateMeleeDamageForce", "Fill out a damage info handle with a damage force for a melee impact." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptGuessDamageForce, "GuessDamageForce", "Try and guess the physics force to use." );
|
||||
|
||||
ScriptRegisterFunction( g_pScriptVM, CreateFireBulletsInfo, "" );
|
||||
ScriptRegisterFunction( g_pScriptVM, DestroyFireBulletsInfo, "" );
|
||||
ScriptRegisterFunction( g_pScriptVM, DestroyFireBulletsInfo, SCRIPT_HIDE );
|
||||
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptTraceLineComplex, "TraceLineComplex", "Complex version of TraceLine which takes 2 points, an ent to ignore, a trace mask, and a collision group. Returns a handle which can access all trace info." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptTraceHullComplex, "TraceHullComplex", "Takes 2 points, min/max hull bounds, an ent to ignore, a trace mask, and a collision group to trace to a point using a hull. Returns a handle which can access all trace info." );
|
||||
@ -1071,10 +1058,10 @@ void RegisterSharedScriptFunctions()
|
||||
//
|
||||
// Precaching
|
||||
//
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptPrecacheModel, "PrecacheModel", "Precaches a model for later usage." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptPrecacheModel, "DoPrecacheModel", SCRIPT_ALIAS( "PrecacheModel", "Precaches a model for later usage." ) );
|
||||
ScriptRegisterFunction( g_pScriptVM, PrecacheMaterial, "Precaches a material for later usage." );
|
||||
ScriptRegisterFunction( g_pScriptVM, PrecacheParticleSystem, "Precaches a particle system for later usage." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptPrecacheOther, "PrecacheOther", "Precaches an entity class for later usage." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptPrecacheOther, "DoPrecacheOther", SCRIPT_ALIAS( "PrecacheOther", "Precaches an entity class for later usage." ) );
|
||||
|
||||
//
|
||||
// NPCs
|
||||
|
@ -46,12 +46,14 @@ public:
|
||||
class CSurfaceScriptHelper
|
||||
{
|
||||
public:
|
||||
// This class is owned by CScriptGameTrace, and cannot be accessed without being initialised in CScriptGameTrace::RegisterSurface()
|
||||
//CSurfaceScriptHelper() : m_pSurface(NULL), m_hSurfaceData(NULL) {}
|
||||
CSurfaceScriptHelper() : m_pSurface(NULL), m_hSurfaceData(NULL) {}
|
||||
|
||||
~CSurfaceScriptHelper()
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( m_hSurfaceData );
|
||||
if ( m_hSurfaceData )
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( m_hSurfaceData );
|
||||
}
|
||||
}
|
||||
|
||||
void Init( csurface_t *surf )
|
||||
@ -98,16 +100,10 @@ class CScriptGameTrace : public CGameTrace
|
||||
public:
|
||||
CScriptGameTrace() : m_surfaceAccessor(NULL), m_planeAccessor(NULL)
|
||||
{
|
||||
m_hScriptInstance = g_pScriptVM->RegisterInstance( this );
|
||||
}
|
||||
|
||||
~CScriptGameTrace()
|
||||
{
|
||||
if ( m_hScriptInstance )
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( m_hScriptInstance );
|
||||
}
|
||||
|
||||
if ( m_surfaceAccessor )
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( m_surfaceAccessor );
|
||||
@ -119,22 +115,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterSurface()
|
||||
{
|
||||
m_surfaceHelper.Init( &surface );
|
||||
m_surfaceAccessor = g_pScriptVM->RegisterInstance( &m_surfaceHelper );
|
||||
}
|
||||
|
||||
void RegisterPlane()
|
||||
{
|
||||
m_planeAccessor = g_pScriptVM->RegisterInstance( &plane );
|
||||
}
|
||||
|
||||
HSCRIPT GetScriptInstance() const
|
||||
{
|
||||
return m_hScriptInstance;
|
||||
}
|
||||
|
||||
public:
|
||||
float FractionLeftSolid() const { return fractionleftsolid; }
|
||||
int HitGroup() const { return hitgroup; }
|
||||
@ -154,15 +134,30 @@ public:
|
||||
bool AllSolid() const { return allsolid; }
|
||||
bool StartSolid() const { return startsolid; }
|
||||
|
||||
HSCRIPT Surface() const { return m_surfaceAccessor; }
|
||||
HSCRIPT Plane() const { return m_planeAccessor; }
|
||||
HSCRIPT Surface()
|
||||
{
|
||||
if ( !m_surfaceAccessor )
|
||||
{
|
||||
m_surfaceHelper.Init( &surface );
|
||||
m_surfaceAccessor = g_pScriptVM->RegisterInstance( &m_surfaceHelper );
|
||||
}
|
||||
|
||||
void Destroy() { delete this; }
|
||||
return m_surfaceAccessor;
|
||||
}
|
||||
|
||||
HSCRIPT Plane()
|
||||
{
|
||||
if ( !m_planeAccessor )
|
||||
m_planeAccessor = g_pScriptVM->RegisterInstance( &plane );
|
||||
|
||||
return m_planeAccessor;
|
||||
}
|
||||
|
||||
void Destroy() {}
|
||||
|
||||
private:
|
||||
HSCRIPT m_surfaceAccessor;
|
||||
HSCRIPT m_planeAccessor;
|
||||
HSCRIPT m_hScriptInstance;
|
||||
|
||||
CSurfaceScriptHelper m_surfaceHelper;
|
||||
|
||||
@ -172,30 +167,47 @@ private:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exposes animevent_t to VScript
|
||||
//-----------------------------------------------------------------------------
|
||||
struct scriptanimevent_t : public animevent_t
|
||||
struct scriptanimevent_t
|
||||
{
|
||||
int GetEvent() { return event; }
|
||||
void SetEvent( int nEvent ) { event = nEvent; }
|
||||
friend class CAnimEventTInstanceHelper;
|
||||
|
||||
const char *GetOptions() { return options; }
|
||||
void SetOptions( const char *pOptions ) { options = pOptions; }
|
||||
public:
|
||||
scriptanimevent_t( animevent_t &event ) : event( event ), options( NULL ) { }
|
||||
~scriptanimevent_t( ) { delete[] options; }
|
||||
|
||||
float GetCycle() { return cycle; }
|
||||
void SetCycle( float flCycle ) { cycle = flCycle; }
|
||||
int GetEvent() { return event.event; }
|
||||
void SetEvent( int nEvent ) { event.event = nEvent; }
|
||||
|
||||
float GetEventTime() { return eventtime; }
|
||||
void SetEventTime( float flEventTime ) { eventtime = flEventTime; }
|
||||
const char *GetOptions() { return event.options; }
|
||||
void SetOptions( const char *pOptions )
|
||||
{
|
||||
size_t len = strlen( pOptions );
|
||||
delete[] options;
|
||||
event.options = options = new char[len + 1];
|
||||
memcpy( options, pOptions, len + 1 );
|
||||
}
|
||||
|
||||
int GetType() { return type; }
|
||||
void SetType( int nType ) { eventtime = type; }
|
||||
float GetCycle() { return event.cycle; }
|
||||
void SetCycle( float flCycle ) { event.cycle = flCycle; }
|
||||
|
||||
HSCRIPT GetSource() { return ToHScript( pSource ); }
|
||||
float GetEventTime() { return event.eventtime; }
|
||||
void SetEventTime( float flEventTime ) { event.eventtime = flEventTime; }
|
||||
|
||||
int GetType() { return event.type; }
|
||||
void SetType( int nType ) { event.type = nType; }
|
||||
|
||||
HSCRIPT GetSource() { return ToHScript( event.pSource ); }
|
||||
void SetSource( HSCRIPT hSource )
|
||||
{
|
||||
CBaseEntity *pEnt = ToEnt( hSource );
|
||||
if (pEnt)
|
||||
pSource = pEnt->GetBaseAnimating();
|
||||
event.pSource = pEnt->GetBaseAnimating();
|
||||
}
|
||||
|
||||
private:
|
||||
animevent_t &event;
|
||||
// storage for ScriptVariant_t string, which may be temporary
|
||||
char *options;
|
||||
};
|
||||
|
||||
class CAnimEventTInstanceHelper : public IScriptInstanceHelper
|
||||
|
@ -2920,7 +2920,7 @@ int CScriptGameEventListener::ListenToGameEvent( const char* szEvent, HSCRIPT hF
|
||||
if ( bValid )
|
||||
{
|
||||
m_iContextHash = HashContext( szContext );
|
||||
m_hCallback = hFunc;
|
||||
m_hCallback = g_pScriptVM->CopyObject( hFunc );
|
||||
m_bActive = true;
|
||||
|
||||
s_Listeners.AddToTail( this );
|
||||
@ -3247,7 +3247,7 @@ public:
|
||||
|
||||
// NOTE: These two functions are new with Mapbase and have no Valve equivalent
|
||||
static bool KeyValuesWrite( const char *szFile, HSCRIPT hInput );
|
||||
static HSCRIPT KeyValuesRead( const char *szFile );
|
||||
static HSCRIPT_RC KeyValuesRead( const char *szFile );
|
||||
|
||||
void LevelShutdownPostEntity()
|
||||
{
|
||||
@ -3433,7 +3433,7 @@ bool CScriptReadWriteFile::KeyValuesWrite( const char *szFile, HSCRIPT hInput )
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CScriptReadWriteFile::KeyValuesRead( const char *szFile )
|
||||
HSCRIPT_RC CScriptReadWriteFile::KeyValuesRead( const char *szFile )
|
||||
{
|
||||
char pszFullName[MAX_PATH];
|
||||
V_snprintf( pszFullName, sizeof(pszFullName), SCRIPT_RW_FULL_PATH_FMT, szFile );
|
||||
@ -3458,7 +3458,7 @@ HSCRIPT CScriptReadWriteFile::KeyValuesRead( const char *szFile )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HSCRIPT hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV, true ); // bAllowDestruct is supposed to automatically remove the involved KV
|
||||
HSCRIPT hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV );
|
||||
|
||||
return hScript;
|
||||
}
|
||||
@ -4609,9 +4609,9 @@ public:
|
||||
CScriptConCommand( const char *name, HSCRIPT fn, const char *helpString, int flags, ConCommand *pLinked = NULL )
|
||||
: BaseClass( name, this, helpString, flags, 0 ),
|
||||
m_pLinked(pLinked),
|
||||
m_hCallback(fn),
|
||||
m_hCompletionCallback(NULL)
|
||||
{
|
||||
m_hCallback = g_pScriptVM->CopyObject( fn );
|
||||
m_nCmdNameLen = V_strlen(name) + 1;
|
||||
Assert( m_nCmdNameLen - 1 <= 128 );
|
||||
}
|
||||
@ -4701,7 +4701,7 @@ public:
|
||||
|
||||
BaseClass::m_pCommandCompletionCallback = this;
|
||||
BaseClass::m_bHasCompletionCallback = true;
|
||||
m_hCompletionCallback = fn;
|
||||
m_hCompletionCallback = g_pScriptVM->CopyObject( fn );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4720,7 +4720,8 @@ public:
|
||||
|
||||
if ( m_hCallback )
|
||||
g_pScriptVM->ReleaseScript( m_hCallback );
|
||||
m_hCallback = fn;
|
||||
|
||||
m_hCallback = g_pScriptVM->CopyObject( fn );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4781,7 +4782,7 @@ public:
|
||||
|
||||
if (fn)
|
||||
{
|
||||
m_hCallback = fn;
|
||||
m_hCallback = g_pScriptVM->CopyObject( fn );
|
||||
BaseClass::InstallChangeCallback( (FnChangeCallback_t)ScriptConVarCallback );
|
||||
}
|
||||
else
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
bool IsPredicted( void ) const { return m_iszClientScripts[0] != '\0'; }
|
||||
|
||||
const char* GetWeaponScriptName() { return m_iszWeaponScriptName[0] != '\0' ? m_iszWeaponScriptName : BaseClass::GetWeaponScriptName(); }
|
||||
const char* GetName() const { return m_iszWeaponScriptName[0] != '\0' ? STRING( m_iClassname ) : BaseClass::GetName(); }
|
||||
|
||||
// Weapon selection
|
||||
bool HasAnyAmmo( void ); // Returns true is weapon has ammo
|
||||
|
@ -33,6 +33,8 @@ END_DATADESC()
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
BEGIN_SCRIPTDESC_ROOT( CTakeDamageInfo, "Damage information handler." )
|
||||
DEFINE_SCRIPT_REFCOUNTED_INSTANCE()
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetInflictor, "GetInflictor", "Gets the inflictor." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetInflictor, "SetInflictor", "Sets the inflictor." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetWeapon, "GetWeapon", "Gets the weapon." )
|
||||
@ -590,4 +592,4 @@ void CTakeDamageInfo::DebugGetDamageTypeString(unsigned int damageType, char *ou
|
||||
#define DMG_BLAST_SURFACE (1<<27) // A blast on the surface of water that cannot harm things underwater
|
||||
#define DMG_DIRECT (1<<28)
|
||||
#define DMG_BUCKSHOT (1<<29) // not quite a bullet. Little, rounder, different.
|
||||
*/
|
||||
*/
|
||||
|
@ -37,6 +37,7 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// This is to ensure a dependency exists between the vscript library and the game DLLs
|
||||
extern int vscript_token;
|
||||
extern int vscript_debugger_port;
|
||||
int vscript_token_hack = vscript_token;
|
||||
#endif
|
||||
|
||||
@ -390,12 +391,30 @@ CON_COMMAND_F( script_debug, "Connect the vscript VM to the script debugger", FC
|
||||
if ( !IsCommandIssuedByServerAdmin() )
|
||||
return;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
#ifdef GAME_DLL
|
||||
int port = 1212;
|
||||
#else
|
||||
int port = 1213;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
vscript_debugger_port = port;
|
||||
CGMsg( 0, CON_GROUP_VSCRIPT, "VScript VM is not running, waiting for it to attach the debugger to port %d...\n", port );
|
||||
#else
|
||||
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
g_pScriptVM->ConnectDebugger( port );
|
||||
#else
|
||||
g_pScriptVM->ConnectDebugger();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
@ -507,7 +526,7 @@ void RunAutorunScripts()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static short VSCRIPT_SERVER_SAVE_RESTORE_VERSION = 2;
|
||||
static short VSCRIPT_SERVER_SAVE_RESTORE_VERSION = 3;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -21,12 +21,16 @@ inline bool VScriptRunScript( const char *pszScriptName, bool bWarnMissing = fal
|
||||
|
||||
#define DECLARE_ENT_SCRIPTDESC() ALLOW_SCRIPT_ACCESS(); virtual ScriptClassDesc_t *GetScriptDesc()
|
||||
|
||||
#define BEGIN_ENT_SCRIPTDESC( className, baseClass, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC( className, baseClass, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT( className, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT( className, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC( className, baseClass, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC( className, baseClass, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_WITH_HELPER( className, baseClass, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_WITH_HELPER( className, baseClass, description, helper )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT( className, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT( className, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT_WITH_HELPER( className, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( className, description, helper )
|
||||
#define BEGIN_ENT_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, scriptName, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, scriptName, description, helper )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, helper ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, helper )
|
||||
|
||||
#define _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ) template <> ScriptClassDesc_t * GetScriptDesc<className>( className * ); ScriptClassDesc_t *className::GetScriptDesc() { return ::GetScriptDesc( this ); }
|
||||
#define _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ) template <> ScriptClassDesc_t * GetScriptDesc<className>( className *, bool ); ScriptClassDesc_t *className::GetScriptDesc() { return ::GetScriptDesc( this ); }
|
||||
|
||||
// Only allow scripts to create entities during map initialization
|
||||
bool IsEntityCreationAllowedInScripts( void );
|
||||
|
@ -767,16 +767,7 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad
|
||||
|
||||
pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );
|
||||
|
||||
#ifdef MAPBASE
|
||||
// The original code makes it seem like we have the opportunity to support both $bumptransform and $detail at the same time,
|
||||
// and that may or may not have been Valve's intention, but we'd need to add another texcoord for this and it's already
|
||||
// a limitation with the non-skin shader anyway.
|
||||
if ( bHasBump )
|
||||
{
|
||||
pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform );
|
||||
}
|
||||
else
|
||||
#else
|
||||
#ifndef MAPBASE // See below
|
||||
if( bHasBump )
|
||||
{
|
||||
pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
|
||||
@ -794,6 +785,15 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad
|
||||
info.m_nBaseTextureTransform,
|
||||
info.m_nDetailScale );
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
// The original code makes it seem like we have the opportunity to support both $bumptransform and $detail at the same time,
|
||||
// and that may or may not have been Valve's intention, but we'd need to add another texcoord for this and it's already
|
||||
// a limitation with the non-skin shader anyway.
|
||||
else if ( bHasBump )
|
||||
{
|
||||
pShader->SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, info.m_nBumpTransform );
|
||||
}
|
||||
#endif
|
||||
|
||||
pShader->SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
|
||||
pShader->SetPixelShaderConstant_W( PSREG_SELFILLUMTINT, info.m_nSelfIllumTint, fBlendFactor );
|
||||
|
@ -49,6 +49,14 @@ BEGIN_VS_SHADER( SDK_Cable_DX9, "Help for SplineRope" )
|
||||
{
|
||||
bool bShaderSrgbRead = ( IsX360() && params[SHADERSRGBREAD360]->GetIntValue() );
|
||||
bool bShadowDepth = ( params[SHADOWDEPTH]->GetIntValue() != 0 );
|
||||
|
||||
#ifdef MAPBASE
|
||||
BlendType_t nBlendType = EvaluateBlendRequirements( BASETEXTURE, true );
|
||||
bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ); //dest alpha is free for special use
|
||||
#else
|
||||
bool bFullyOpaque = true;
|
||||
#endif
|
||||
|
||||
SHADOW_STATE
|
||||
{
|
||||
// draw back-facing because of yaw spin
|
||||
@ -65,8 +73,19 @@ BEGIN_VS_SHADER( SDK_Cable_DX9, "Help for SplineRope" )
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MAPBASE
|
||||
if (IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT ))
|
||||
{
|
||||
pShaderShadow->EnableDepthWrites( false );
|
||||
pShaderShadow->EnableBlending( true );
|
||||
pShaderShadow->BlendFunc( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
|
||||
pShaderShadow->EnableAlphaTest( IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) );
|
||||
#endif
|
||||
|
||||
// We need to write to dest alpha for depth feathering.
|
||||
pShaderShadow->EnableAlphaWrites( true );
|
||||
pShaderShadow->EnableAlphaWrites( bFullyOpaque );
|
||||
|
||||
// base texture
|
||||
pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
|
||||
@ -150,7 +169,7 @@ BEGIN_VS_SHADER( SDK_Cable_DX9, "Help for SplineRope" )
|
||||
if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
|
||||
{
|
||||
DECLARE_DYNAMIC_PIXEL_SHADER( sdk_splinerope_ps20b );
|
||||
SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, pShaderAPI->ShouldWriteDepthToDestAlpha() );
|
||||
SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bFullyOpaque && pShaderAPI->ShouldWriteDepthToDestAlpha() );
|
||||
//SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
|
||||
SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() );
|
||||
SET_DYNAMIC_PIXEL_SHADER( sdk_splinerope_ps20b );
|
||||
|
@ -99,6 +99,7 @@ namespace ResponseRules
|
||||
#ifdef MAPBASE
|
||||
RESPONSE_VSCRIPT, // Run VScript code
|
||||
RESPONSE_VSCRIPT_FILE, // Run a VScript file (bypasses ugliness and character limits when just using IncludeScript() with RESPONSE_VSCRIPT)
|
||||
RESPONSE_CHOREOSENTENCE, // Sentences put together as VCDs, see choreosentence.h for more information
|
||||
#endif
|
||||
|
||||
NUM_RESPONSES,
|
||||
|
@ -141,6 +141,20 @@ class KeyValues;
|
||||
DECLARE_POINTER_HANDLE( HSCRIPT );
|
||||
#define INVALID_HSCRIPT ((HSCRIPT)-1)
|
||||
|
||||
// Reference counted HSCRIPT return value
|
||||
//
|
||||
// This is an alias for HSCRIPT that is converted back to HSCRIPT on return
|
||||
// from vscript function bindings; it signals the vscript implementation to
|
||||
// release its hold and let the script control the lifetime
|
||||
// of the registered instance.
|
||||
struct HSCRIPT_RC
|
||||
{
|
||||
HSCRIPT val;
|
||||
HSCRIPT_RC( HSCRIPT v ) { val = v; }
|
||||
HSCRIPT operator=( HSCRIPT v ) { val = v; return val; }
|
||||
operator HSCRIPT() { return val; }
|
||||
};
|
||||
|
||||
typedef unsigned int HScriptRaw;
|
||||
#endif
|
||||
|
||||
@ -162,7 +176,7 @@ public:
|
||||
virtual void DestroyVM( IScriptVM * ) = 0;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual HSCRIPT CreateScriptKeyValues( IScriptVM *pVM, KeyValues *pKV, bool bAllowDestruct ) = 0;
|
||||
virtual HSCRIPT CreateScriptKeyValues( IScriptVM *pVM, KeyValues *pKV, bool bBorrow = false ) = 0;
|
||||
virtual KeyValues *GetKeyValuesFromScriptKV( IScriptVM *pVM, HSCRIPT hSKV ) = 0;
|
||||
#endif
|
||||
};
|
||||
@ -177,6 +191,9 @@ enum ExtendedFieldType
|
||||
FIELD_CSTRING,
|
||||
FIELD_HSCRIPT,
|
||||
FIELD_VARIANT,
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
FIELD_HSCRIPT_RC,
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef int ScriptDataType_t;
|
||||
@ -197,6 +214,7 @@ DECLARE_DEDUCE_FIELDTYPE( FIELD_CHARACTER, char );
|
||||
DECLARE_DEDUCE_FIELDTYPE( FIELD_HSCRIPT, HSCRIPT );
|
||||
DECLARE_DEDUCE_FIELDTYPE( FIELD_VARIANT, ScriptVariant_t );
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
DECLARE_DEDUCE_FIELDTYPE( FIELD_HSCRIPT_RC, HSCRIPT_RC );
|
||||
DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, QAngle );
|
||||
DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, const QAngle& );
|
||||
#endif
|
||||
@ -298,9 +316,13 @@ struct ScriptMemberDesc_t
|
||||
enum ScriptFuncBindingFlags_t
|
||||
{
|
||||
SF_MEMBER_FUNC = 0x01,
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
SF_REFCOUNTED_RET = 0x02,
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef bool (*ScriptBindingFunc_t)( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn );
|
||||
union ScriptVariantTemporaryStorage_t;
|
||||
typedef bool (*ScriptBindingFunc_t)( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage );
|
||||
|
||||
struct ScriptFunctionBinding_t
|
||||
{
|
||||
@ -321,11 +343,6 @@ public:
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual bool Get( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; }
|
||||
virtual bool Set( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; }
|
||||
|
||||
virtual ScriptVariant_t *Add( void *p, ScriptVariant_t &variant ) { return NULL; }
|
||||
virtual ScriptVariant_t *Subtract( void *p, ScriptVariant_t &variant ) { return NULL; }
|
||||
virtual ScriptVariant_t *Multiply( void *p, ScriptVariant_t &variant ) { return NULL; }
|
||||
virtual ScriptVariant_t *Divide( void *p, ScriptVariant_t &variant ) { return NULL; }
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -360,6 +377,7 @@ struct ScriptClassDesc_t
|
||||
IScriptInstanceHelper * pHelper; // optional helper
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
public:
|
||||
static CUtlVector<ScriptClassDesc_t*>& AllClassesDesc()
|
||||
{
|
||||
static CUtlVector<ScriptClassDesc_t*> classes;
|
||||
@ -389,13 +407,17 @@ struct ScriptVariant_t
|
||||
ScriptVariant_t( bool val ) : m_flags( 0 ), m_type( FIELD_BOOLEAN ) { m_bool = val; }
|
||||
ScriptVariant_t( HSCRIPT val ) : m_flags( 0 ), m_type( FIELD_HSCRIPT ) { m_hScript = val; }
|
||||
|
||||
ScriptVariant_t( const Vector &val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = &val; } else { m_pVector = new Vector( val ); m_flags |= SV_FREE; } }
|
||||
ScriptVariant_t( const Vector *val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = val; } else { m_pVector = new Vector( *val ); m_flags |= SV_FREE; } }
|
||||
ScriptVariant_t( const char *val , bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_CSTRING ) { if ( !bCopy ) { m_pszString = val; } else { m_pszString = strdup( val ); m_flags |= SV_FREE; } }
|
||||
ScriptVariant_t( const Vector &val ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { m_pVector = &val; }
|
||||
ScriptVariant_t( const Vector *val ) : ScriptVariant_t( *val ) { }
|
||||
|
||||
ScriptVariant_t( const char *val ) : m_flags( 0 ), m_type( FIELD_CSTRING ) { m_pszString = val; }
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
ScriptVariant_t( const QAngle &val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pAngle = &val; } else { m_pAngle = new QAngle( val ); m_flags |= SV_FREE; } }
|
||||
ScriptVariant_t( const QAngle *val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pAngle = val; } else { m_pAngle = new QAngle( *val ); m_flags |= SV_FREE; } }
|
||||
ScriptVariant_t( const QAngle &val ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { m_pAngle = &val; }
|
||||
ScriptVariant_t( const QAngle *val ) : ScriptVariant_t( *val ) { }
|
||||
|
||||
ScriptVariant_t( Vector &&val ) = delete;
|
||||
ScriptVariant_t( QAngle &&val ) = delete;
|
||||
#endif
|
||||
|
||||
bool IsNull() const { return (m_type == FIELD_VOID ); }
|
||||
@ -403,74 +425,41 @@ struct ScriptVariant_t
|
||||
operator int() const { Assert( m_type == FIELD_INTEGER ); return m_int; }
|
||||
operator float() const { Assert( m_type == FIELD_FLOAT ); return m_float; }
|
||||
operator const char *() const { Assert( m_type == FIELD_CSTRING ); return ( m_pszString ) ? m_pszString : ""; }
|
||||
operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); static Vector vecNull(0, 0, 0); return (m_pVector) ? *m_pVector : vecNull; }
|
||||
operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); return (m_pVector) ? *m_pVector : vec3_origin; }
|
||||
operator char() const { Assert( m_type == FIELD_CHARACTER ); return m_char; }
|
||||
operator bool() const { Assert( m_type == FIELD_BOOLEAN ); return m_bool; }
|
||||
operator HSCRIPT() const { Assert( m_type == FIELD_HSCRIPT ); return m_hScript; }
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
operator const QAngle &() const { Assert( m_type == FIELD_VECTOR ); static QAngle vecNull(0, 0, 0); return (m_pAngle) ? *m_pAngle : vecNull; }
|
||||
operator const QAngle &() const { Assert( m_type == FIELD_VECTOR ); return (m_pAngle) ? *m_pAngle : vec3_angle; }
|
||||
#endif
|
||||
|
||||
void operator=( int i ) { m_type = FIELD_INTEGER; m_int = i; }
|
||||
void operator=( float f ) { m_type = FIELD_FLOAT; m_float = f; }
|
||||
void operator=( double f ) { m_type = FIELD_FLOAT; m_float = (float)f; }
|
||||
void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; m_pVector = &vec; }
|
||||
void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_pVector = vec; }
|
||||
void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_pszString = psz; }
|
||||
void operator=( char c ) { m_type = FIELD_CHARACTER; m_char = c; }
|
||||
void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_bool = b; }
|
||||
void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_hScript = h; }
|
||||
void operator=( int i ) { m_type = FIELD_INTEGER; m_flags = 0; m_int = i; }
|
||||
void operator=( float f ) { m_type = FIELD_FLOAT; m_flags = 0; m_float = f; }
|
||||
void operator=( double f ) { m_type = FIELD_FLOAT; m_flags = 0; m_float = (float)f; }
|
||||
void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; m_flags = 0; m_pVector = &vec; }
|
||||
void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_flags = 0; m_pVector = vec; }
|
||||
void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_flags = 0; m_pszString = psz; }
|
||||
void operator=( char c ) { m_type = FIELD_CHARACTER; m_flags = 0; m_char = c; }
|
||||
void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_flags = 0; m_bool = b; }
|
||||
void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_flags = 0; m_hScript = h; }
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
void operator=( const QAngle &vec ) { m_type = FIELD_VECTOR; m_pAngle = &vec; }
|
||||
void operator=( const QAngle *vec ) { m_type = FIELD_VECTOR; m_pAngle = vec; }
|
||||
void operator=( const QAngle &ang ) { m_type = FIELD_VECTOR; m_flags = 0; m_pAngle = ∠ }
|
||||
void operator=( const QAngle *ang ) { m_type = FIELD_VECTOR; m_flags = 0; m_pAngle = ang; }
|
||||
|
||||
void operator=( Vector &&vec ) = delete;
|
||||
void operator=( QAngle &&ang ) = delete;
|
||||
#endif
|
||||
|
||||
void Free() { if ( ( m_flags & SV_FREE ) && ( m_type == FIELD_HSCRIPT || m_type == FIELD_VECTOR || m_type == FIELD_CSTRING ) ) delete m_pszString; } // Generally only needed for return results
|
||||
|
||||
template <typename T>
|
||||
T Get()
|
||||
void Free()
|
||||
{
|
||||
T value;
|
||||
AssignTo( &value );
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool AssignTo( T *pDest )
|
||||
{
|
||||
ScriptDataType_t destType = ScriptDeduceType( T );
|
||||
if ( destType == FIELD_TYPEUNKNOWN )
|
||||
// Generally only needed for return results
|
||||
if ( ! ( m_flags & SV_FREE ) )
|
||||
{
|
||||
DevWarning( "Unable to convert script variant to unknown type\n" );
|
||||
}
|
||||
if ( destType == m_type )
|
||||
{
|
||||
*pDest = *this;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_type != FIELD_VECTOR && m_type != FIELD_CSTRING && destType != FIELD_VECTOR && destType != FIELD_CSTRING )
|
||||
{
|
||||
switch ( m_type )
|
||||
{
|
||||
case FIELD_VOID: *pDest = 0; break;
|
||||
case FIELD_INTEGER: *pDest = m_int; return true;
|
||||
case FIELD_FLOAT: *pDest = m_float; return true;
|
||||
case FIELD_CHARACTER: *pDest = m_char; return true;
|
||||
case FIELD_BOOLEAN: *pDest = m_bool; return true;
|
||||
case FIELD_HSCRIPT: *pDest = m_hScript; return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DevWarning( "No free conversion of %s script variant to %s right now\n",
|
||||
ScriptFieldTypeName( m_type ), ScriptFieldTypeName<T>() );
|
||||
if ( destType != FIELD_VECTOR )
|
||||
{
|
||||
*pDest = 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
AssertMsg( m_type == FIELD_CSTRING || m_type == FIELD_VECTOR, "Don't know how to free script variant of type %d", m_type );
|
||||
free( (void*)m_pszString );
|
||||
}
|
||||
|
||||
bool AssignTo( float *pDest )
|
||||
@ -525,25 +514,38 @@ struct ScriptVariant_t
|
||||
|
||||
bool AssignTo( ScriptVariant_t *pDest )
|
||||
{
|
||||
pDest->Free();
|
||||
pDest->m_type = m_type;
|
||||
if ( m_type == FIELD_VECTOR )
|
||||
if ( m_flags & SV_FREE )
|
||||
{
|
||||
pDest->m_pVector = new Vector;
|
||||
((Vector *)(pDest->m_pVector))->Init( m_pVector->x, m_pVector->y, m_pVector->z );
|
||||
pDest->m_flags |= SV_FREE;
|
||||
}
|
||||
else if ( m_type == FIELD_CSTRING )
|
||||
{
|
||||
pDest->m_pszString = strdup( m_pszString );
|
||||
pDest->m_flags |= SV_FREE;
|
||||
if ( m_type == FIELD_VECTOR )
|
||||
{
|
||||
pDest->m_pVector = (Vector*)malloc( sizeof( Vector ) );
|
||||
pDest->EmplaceAllocedVector( *m_pVector );
|
||||
m_flags |= SV_FREE;
|
||||
}
|
||||
else if ( m_type == FIELD_CSTRING )
|
||||
{
|
||||
pDest->m_pszString = strdup( m_pszString );
|
||||
pDest->m_flags |= SV_FREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( false );
|
||||
pDest->m_int = m_int;
|
||||
pDest->m_flags &= ~SV_FREE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pDest->m_int = m_int;
|
||||
pDest->m_flags &= ~SV_FREE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EmplaceAllocedVector( const Vector &vec );
|
||||
|
||||
union
|
||||
{
|
||||
int m_int;
|
||||
@ -565,8 +567,25 @@ struct ScriptVariant_t
|
||||
private:
|
||||
};
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
inline void ScriptVariant_t::EmplaceAllocedVector( const Vector &vec )
|
||||
{
|
||||
new ( (Vector*)m_pVector ) Vector( vec );
|
||||
}
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define SCRIPT_VARIANT_NULL ScriptVariant_t()
|
||||
|
||||
union ScriptVariantTemporaryStorage_t
|
||||
{
|
||||
// members must be initialized via placement-new
|
||||
ScriptVariantTemporaryStorage_t() { }
|
||||
|
||||
// members must have trivial destructor, since no destructor will be invoked
|
||||
Vector m_vec;
|
||||
QAngle m_ang;
|
||||
};
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
//---------------------------------------------------------
|
||||
struct ScriptConstantBinding_t
|
||||
@ -618,6 +637,15 @@ struct ScriptEnumDesc_t
|
||||
#define ScriptInitMemberFunctionBindingNamed( pScriptFunction, class, func, scriptName ) ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, scriptName )
|
||||
#define ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, scriptName ) do { ScriptInitMemberFuncDescriptor_( (&(pScriptFunction)->m_desc), class, func, scriptName ); (pScriptFunction)->m_pfnBinding = ScriptCreateBinding( ((class *)0), &class::func ); (pScriptFunction)->m_pFunction = ScriptConvertFuncPtrToVoid( &class::func ); (pScriptFunction)->m_flags = SF_MEMBER_FUNC; } while (0)
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// Convert HSCRIPT_RC return type into HSCRIPT return with SF_REFCOUNTED_RET binding flag
|
||||
#undef ScriptInitFunctionBindingNamed
|
||||
#define ScriptInitFunctionBindingNamed( pScriptFunction, func, scriptName ) do { ScriptInitFuncDescriptorNamed( (&(pScriptFunction)->m_desc), func, scriptName ); (pScriptFunction)->m_pfnBinding = ScriptCreateBinding( &func ); (pScriptFunction)->m_pFunction = (void *)&func; if ( (pScriptFunction)->m_desc.m_ReturnType == FIELD_HSCRIPT_RC ) { (pScriptFunction)->m_desc.m_ReturnType = FIELD_HSCRIPT; (pScriptFunction)->m_flags |= SF_REFCOUNTED_RET; } } while (0)
|
||||
|
||||
#undef ScriptInitMemberFunctionBinding_
|
||||
#define ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, scriptName ) do { ScriptInitMemberFuncDescriptor_( (&(pScriptFunction)->m_desc), class, func, scriptName ); (pScriptFunction)->m_pfnBinding = ScriptCreateBinding( ((class *)0), &class::func ); (pScriptFunction)->m_pFunction = ScriptConvertFuncPtrToVoid( &class::func ); (pScriptFunction)->m_flags = SF_MEMBER_FUNC; if ( (pScriptFunction)->m_desc.m_ReturnType == FIELD_HSCRIPT_RC ) { (pScriptFunction)->m_desc.m_ReturnType = FIELD_HSCRIPT; (pScriptFunction)->m_flags |= SF_REFCOUNTED_RET; } } while (0)
|
||||
#endif
|
||||
|
||||
#define ScriptInitClassDesc( pClassDesc, class, pBaseClassDesc ) ScriptInitClassDescNamed( pClassDesc, class, pBaseClassDesc, #class )
|
||||
#define ScriptInitClassDescNamed( pClassDesc, class, pBaseClassDesc, scriptName ) ScriptInitClassDescNamed_( pClassDesc, class, pBaseClassDesc, scriptName )
|
||||
#define ScriptInitClassDescNoBase( pClassDesc, class ) ScriptInitClassDescNoBaseNamed( pClassDesc, class, #class )
|
||||
@ -659,7 +687,7 @@ static inline int ToConstantVariant(int value)
|
||||
// This is used for registering variants (particularly vectors) not tied to existing variables.
|
||||
// The principal difference is that m_data is initted with bCopy set to true.
|
||||
#define ScriptRegisterConstantFromTemp( pVM, constant, description ) ScriptRegisterConstantFromTempNamed( pVM, constant, #constant, description )
|
||||
#define ScriptRegisterConstantFromTempNamed( pVM, constant, scriptName, description ) do { static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = ScriptVariant_t( constant, true ); pVM->RegisterConstant( &binding ); } while (0)
|
||||
#define ScriptRegisterConstantFromTempNamed( pVM, constant, scriptName, description ) do { static const auto constantStorage = constant; static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = ScriptVariant_t( constantStorage ); pVM->RegisterConstant( &binding ); } while (0)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
@ -697,37 +725,48 @@ static inline int ToConstantVariant(int value)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define ALLOW_SCRIPT_ACCESS() template <typename T> friend ScriptClassDesc_t *GetScriptDesc(T *);
|
||||
#define ALLOW_SCRIPT_ACCESS() template <typename T> friend ScriptClassDesc_t *GetScriptDesc(T *, bool);
|
||||
|
||||
#define BEGIN_SCRIPTDESC( className, baseClass, description ) BEGIN_SCRIPTDESC_NAMED( className, baseClass, #className, description )
|
||||
#define BEGIN_SCRIPTDESC_ROOT( className, description ) BEGIN_SCRIPTDESC_ROOT_NAMED( className, #className, description )
|
||||
#define BEGIN_SCRIPTDESC( className, baseClass, description ) BEGIN_SCRIPTDESC_WITH_HELPER( className, baseClass, description, NULL )
|
||||
#define BEGIN_SCRIPTDESC_WITH_HELPER( className, baseClass, description, helper ) BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, #className, description, helper )
|
||||
#define BEGIN_SCRIPTDESC_ROOT( className, description ) BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( className, description, NULL )
|
||||
#define BEGIN_SCRIPTDESC_ROOT_WITH_HELPER( className, description, helper ) BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, #className, description, helper )
|
||||
|
||||
#define BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) \
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<baseClass>(baseClass*); \
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*); \
|
||||
ScriptClassDesc_t & g_##className##_ScriptDesc = *GetScriptDesc<className>(nullptr); \
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*) \
|
||||
#define BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, baseClass, scriptName, description, helper ) \
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<baseClass>(baseClass*, bool); \
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*, bool); \
|
||||
ScriptClassDesc_t & g_##className##_ScriptDesc = *GetScriptDesc<className>(nullptr, true); \
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<className>(className*, bool init) \
|
||||
{ \
|
||||
static ScriptClassDesc_t g_##className##_ScriptDesc; \
|
||||
typedef className _className; \
|
||||
ScriptClassDesc_t *pDesc = &g_##className##_ScriptDesc; \
|
||||
if (pDesc->m_pszClassname) return pDesc; \
|
||||
pDesc->m_pszDescription = description; \
|
||||
ScriptInitClassDescNamed( pDesc, className, GetScriptDescForClass( baseClass ), scriptName ); \
|
||||
ScriptClassDesc_t *pInstanceHelperBase = pDesc->m_pBaseDesc; \
|
||||
while ( pInstanceHelperBase ) \
|
||||
if (!pDesc->m_pszClassname) \
|
||||
{ \
|
||||
if ( pInstanceHelperBase->pHelper ) \
|
||||
pDesc->m_pszDescription = description; \
|
||||
ScriptClassDesc_t *pBaseDesc = GetScriptDescForClass( baseClass ); \
|
||||
ScriptInitClassDescNamed( pDesc, className, pBaseDesc, scriptName ); \
|
||||
pDesc->pHelper = helper; \
|
||||
if ( !pDesc->pHelper ) \
|
||||
{ \
|
||||
pDesc->pHelper = pInstanceHelperBase->pHelper; \
|
||||
break; \
|
||||
while ( pBaseDesc ) \
|
||||
{ \
|
||||
if ( pBaseDesc->pHelper ) \
|
||||
{ \
|
||||
pDesc->pHelper = pBaseDesc->pHelper; \
|
||||
break; \
|
||||
} \
|
||||
pBaseDesc = pBaseDesc->m_pBaseDesc; \
|
||||
} \
|
||||
} \
|
||||
pInstanceHelperBase = pInstanceHelperBase->m_pBaseDesc; \
|
||||
}
|
||||
} \
|
||||
if (!init) return pDesc;
|
||||
|
||||
|
||||
#define BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) \
|
||||
BEGIN_SCRIPTDESC_NAMED( className, ScriptNoBase_t, scriptName, description )
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, NULL )
|
||||
#define BEGIN_SCRIPTDESC_ROOT_NAMED_WITH_HELPER( className, scriptName, description, helper ) \
|
||||
BEGIN_SCRIPTDESC_NAMED_WITH_HELPER( className, ScriptNoBase_t, scriptName, description, helper )
|
||||
|
||||
#define END_SCRIPTDESC() \
|
||||
return pDesc; \
|
||||
@ -736,9 +775,13 @@ static inline int ToConstantVariant(int value)
|
||||
#define DEFINE_SCRIPTFUNC( func, description ) DEFINE_SCRIPTFUNC_NAMED( func, #func, description )
|
||||
#define DEFINE_SCRIPTFUNC_NAMED( func, scriptName, description ) ScriptAddFunctionToClassDescNamed( pDesc, _className, func, scriptName, description );
|
||||
#define DEFINE_SCRIPT_CONSTRUCTOR() ScriptAddConstructorToClassDesc( pDesc, _className );
|
||||
#define DEFINE_SCRIPT_INSTANCE_HELPER( p ) pDesc->pHelper = (p);
|
||||
#define DEFINE_SCRIPT_INSTANCE_HELPER( p ) MUST_USE_BEGIN_SCRIPTDESC_WITH_HELPER_INSTEAD
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// Allow instance to be deleted but not constructed
|
||||
// Not needed if the class has a constructor
|
||||
#define DEFINE_SCRIPT_REFCOUNTED_INSTANCE() do { pDesc->m_pfnDestruct = &CScriptConstructor<_className>::Destruct; } while (0);
|
||||
|
||||
// Use this for hooks which have no parameters
|
||||
#define DEFINE_SIMPLE_SCRIPTHOOK( hook, hookName, returnType, description ) \
|
||||
if (!hook.m_bDefined) \
|
||||
@ -781,10 +824,10 @@ static inline int ToConstantVariant(int value)
|
||||
do { ScriptMemberDesc_t *pBinding = &((pDesc)->m_Members[(pDesc)->m_Members.AddToTail()]); pBinding->m_pszScriptName = varName; pBinding->m_pszDescription = description; pBinding->m_ReturnType = returnType; } while (0);
|
||||
#endif
|
||||
|
||||
template <typename T> ScriptClassDesc_t *GetScriptDesc(T *);
|
||||
template <typename T> ScriptClassDesc_t *GetScriptDesc(T *, bool = false);
|
||||
|
||||
struct ScriptNoBase_t;
|
||||
template <> inline ScriptClassDesc_t *GetScriptDesc<ScriptNoBase_t>( ScriptNoBase_t *) { return NULL; }
|
||||
template <> inline ScriptClassDesc_t *GetScriptDesc<ScriptNoBase_t>( ScriptNoBase_t *, bool ) { return NULL; }
|
||||
|
||||
#define GetScriptDescForClass( className ) GetScriptDesc( ( className *)NULL )
|
||||
|
||||
@ -838,7 +881,11 @@ public:
|
||||
virtual bool Init() = 0;
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual bool ConnectDebugger( int port = 0 ) = 0;
|
||||
#else
|
||||
virtual bool ConnectDebugger() = 0;
|
||||
#endif
|
||||
virtual void DisconnectDebugger() = 0;
|
||||
|
||||
virtual ScriptLanguage_t GetLanguage() = 0;
|
||||
@ -927,14 +974,13 @@ public:
|
||||
//--------------------------------------------------------
|
||||
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
// When a RegisterInstance instance is deleted, VScript normally treats it as a strong reference and only deregisters the instance itself, preserving the registered data
|
||||
// it points to so the game can continue to use it.
|
||||
// bAllowDestruct is supposed to allow VScript to treat it as a weak reference created by the script, destructing the registered data automatically like any other type.
|
||||
// This is useful for classes pretending to be primitive types.
|
||||
virtual HSCRIPT RegisterInstance( ScriptClassDesc_t *pDesc, void *pInstance, bool bAllowDestruct = false ) = 0;
|
||||
// if bRefCounted is true, pInstance memory will be deleted by the script,
|
||||
// returning the result will then behave as if the instance was constructed in script.
|
||||
// Functions that return the result of this need to return HSCRIPT_RC
|
||||
virtual HSCRIPT RegisterInstance( ScriptClassDesc_t *pDesc, void *pInstance, bool bRefCounted = false ) = 0;
|
||||
virtual void SetInstanceUniqeId( HSCRIPT hInstance, const char *pszId ) = 0;
|
||||
template <typename T> HSCRIPT RegisterInstance( T *pInstance, bool bAllowDestruct = false ) { return RegisterInstance( GetScriptDesc( pInstance ), pInstance, bAllowDestruct ); }
|
||||
template <typename T> HSCRIPT RegisterInstance( T *pInstance, const char *pszInstance, HSCRIPT hScope = NULL, bool bAllowDestruct = false) { HSCRIPT hInstance = RegisterInstance( GetScriptDesc( pInstance ), pInstance, bAllowDestruct ); SetValue( hScope, pszInstance, hInstance ); return hInstance; }
|
||||
template <typename T> HSCRIPT RegisterInstance( T *pInstance, bool bRefCounted = false ) { return RegisterInstance( GetScriptDesc( pInstance ), pInstance, bRefCounted ); }
|
||||
template <typename T> HSCRIPT RegisterInstance( T *pInstance, const char *pszInstance, HSCRIPT hScope = NULL, bool bRefCounted = false) { HSCRIPT hInstance = RegisterInstance( GetScriptDesc( pInstance ), pInstance, bRefCounted ); SetValue( hScope, pszInstance, hInstance ); return hInstance; }
|
||||
#else
|
||||
virtual HSCRIPT RegisterInstance( ScriptClassDesc_t *pDesc, void *pInstance ) = 0;
|
||||
virtual void SetInstanceUniqeId( HSCRIPT hInstance, const char *pszId ) = 0;
|
||||
@ -983,6 +1029,8 @@ public:
|
||||
#ifdef MAPBASE_VSCRIPT
|
||||
virtual void CreateArray(ScriptVariant_t &arr, int size = 0) = 0;
|
||||
virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) = 0;
|
||||
// To hold strong references to script objects
|
||||
virtual HSCRIPT CopyObject(HSCRIPT obj) = 0;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -326,8 +326,8 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
||||
class CNonMemberScriptBinding##N \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
{ \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( !pContext ); \
|
||||
@ -337,17 +337,15 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
||||
return false; \
|
||||
} \
|
||||
*pReturn = ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \
|
||||
if ( pReturn->m_type == FIELD_VECTOR ) \
|
||||
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
|
||||
return true; \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CNonMemberScriptBinding##N<FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( !pReturn ); \
|
||||
@ -362,12 +360,52 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CNonMemberScriptBinding##N<FUNC_TYPE, Vector FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( !pContext ); \
|
||||
\
|
||||
if ( nArguments != N || !pReturn || pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
new ( &temporaryReturnStorage.m_vec ) Vector( ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||
*pReturn = temporaryReturnStorage.m_vec; \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CNonMemberScriptBinding##N<FUNC_TYPE, QAngle FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( !pContext ); \
|
||||
\
|
||||
if ( nArguments != N || !pReturn || pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
new ( &temporaryReturnStorage.m_ang ) QAngle( ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||
*pReturn = temporaryReturnStorage.m_ang; \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CMemberScriptBinding##N \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
{ \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( pContext ); \
|
||||
@ -377,17 +415,15 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
||||
return false; \
|
||||
} \
|
||||
*pReturn = (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
|
||||
if ( pReturn->m_type == FIELD_VECTOR ) \
|
||||
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
|
||||
return true; \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( !pReturn ); \
|
||||
@ -402,6 +438,46 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, Vector FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( pContext ); \
|
||||
\
|
||||
if ( nArguments != N || !pReturn || !pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
new ( &temporaryReturnStorage.m_vec ) Vector( (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||
*pReturn = temporaryReturnStorage.m_vec; \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, QAngle FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn, ScriptVariantTemporaryStorage_t &temporaryReturnStorage ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( pContext ); \
|
||||
\
|
||||
if ( nArguments != N || !pReturn || !pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
new ( &temporaryReturnStorage.m_ang ) QAngle( (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ) ); \
|
||||
*pReturn = temporaryReturnStorage.m_ang; \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
inline ScriptBindingFunc_t ScriptCreateBinding(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
|
||||
{ \
|
||||
@ -423,7 +499,11 @@ inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
||||
return &CMemberScriptBinding##N<OBJECT_TYPE_PTR, Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
|
||||
}
|
||||
|
||||
//note: no memory is actually allocated in the functions that get defined,
|
||||
// it merely uses placement-new for which we need to disable this
|
||||
#include "tier0/memdbgoff.h"
|
||||
FUNC_GENERATE_ALL( DEFINE_SCRIPT_BINDINGS );
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -1494,23 +1494,35 @@ void CResponseSystem::ParseInclude()
|
||||
#ifdef MAPBASE
|
||||
char scriptfile[256];
|
||||
GetCurrentScript( scriptfile, sizeof( scriptfile ) );
|
||||
V_RemoveDotSlashes( scriptfile );
|
||||
|
||||
const char *pScriptFile = scriptfile;
|
||||
if (pScriptFile[0] == CORRECT_PATH_SEPARATOR || pScriptFile[0] == INCORRECT_PATH_SEPARATOR)
|
||||
pScriptFile++;
|
||||
|
||||
// Gets first path
|
||||
// (for example, an #include from a file in resource/script/resp will return resource)
|
||||
size_t len = strlen(scriptfile)-1;
|
||||
size_t len = strlen( pScriptFile )-1;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
if (scriptfile[i] == CORRECT_PATH_SEPARATOR || scriptfile[i] == INCORRECT_PATH_SEPARATOR)
|
||||
if (pScriptFile[i] == CORRECT_PATH_SEPARATOR || pScriptFile[i] == INCORRECT_PATH_SEPARATOR)
|
||||
{
|
||||
len = i;
|
||||
}
|
||||
}
|
||||
Q_strncpy(includefile, scriptfile, len+1);
|
||||
Q_strncpy(includefile, pScriptFile, len+1);
|
||||
|
||||
if (len+1 != strlen(scriptfile))
|
||||
if (len+1 != strlen( pScriptFile ))
|
||||
{
|
||||
Q_strncat( includefile, "/", sizeof( includefile ) );
|
||||
Q_strncat( includefile, token, sizeof( includefile ) );
|
||||
if (!includefile[0])
|
||||
{
|
||||
CGMsg( 1, CON_GROUP_RESPONSE_SYSTEM, "%s: Unable to parse first folder from parent script \"%s\", falling back to 'scripts/'\n", token, pScriptFile );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_strncat( includefile, CORRECT_PATH_SEPARATOR_S, sizeof( includefile ) );
|
||||
Q_strncat( includefile, token, sizeof( includefile ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
includefile[0] = '\0';
|
||||
@ -1643,6 +1655,8 @@ inline ResponseType_t ComputeResponseType( const char *s )
|
||||
return RESPONSE_VSCRIPT_FILE;
|
||||
else
|
||||
return RESPONSE_VSCRIPT;
|
||||
case 'c':
|
||||
return RESPONSE_CHOREOSENTENCE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -260,6 +260,8 @@ const char *CRR_Response::DescribeResponse( ResponseType_t type )
|
||||
return "RESPONSE_VSCRIPT";
|
||||
case ResponseRules::RESPONSE_VSCRIPT_FILE:
|
||||
return "RESPONSE_VSCRIPT_FILE";
|
||||
case ResponseRules::RESPONSE_CHOREOSENTENCE:
|
||||
return "RESPONSE_CHOREOSENTENCE";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1354,6 +1354,15 @@ int RunVBSP( int argc, char **argv )
|
||||
" -replacematerials : Substitute materials according to materialsub.txt in content\\maps\n"
|
||||
" -FullMinidumps : Write large minidumps on crash.\n"
|
||||
" -nohiddenmaps : Exclude manifest maps if they are currently hidden.\n"
|
||||
#ifdef MAPBASE
|
||||
" -defaultcubemap : Makes a dummy cubemap.\n"
|
||||
" -skyboxcubemap : Makes a skybox cubemaps for LDR cubemaps. (HDR skybox cubemaps are not supported)\n"
|
||||
" -defaultcubemapres : Sets the dummy cubemap resolution. (Default 32)\n"
|
||||
" -defaultproppermodelsstatic : Inserts propper_model into the level.\n"
|
||||
" -strippropperentities : Strip out any entities with 'propper_' in their classname, as they don't actually exist in-game.\n"
|
||||
" -scripting : Vscript vbsp system.\n"
|
||||
" -doc : Prints all the related documentation of vbsp Vscript.\n"
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static HSCRIPT VMFKV_CreateBlank()
|
||||
static HSCRIPT_RC VMFKV_CreateBlank()
|
||||
{
|
||||
KeyValues *pKV = new KeyValues("VMF");
|
||||
|
||||
@ -28,7 +28,7 @@ static HSCRIPT VMFKV_CreateBlank()
|
||||
pWorld->SetString( "classname", "worldspawn" );
|
||||
}
|
||||
|
||||
return scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV, true );
|
||||
return scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV );
|
||||
}
|
||||
|
||||
static bool VMFKV_SaveToFile( const char *szFile, HSCRIPT hKV )
|
||||
@ -69,7 +69,7 @@ static bool VMFKV_SaveToFile( const char *szFile, HSCRIPT hKV )
|
||||
return res;
|
||||
}
|
||||
|
||||
static HSCRIPT VMFKV_LoadFromFile( const char *szFile )
|
||||
static HSCRIPT_RC VMFKV_LoadFromFile( const char *szFile )
|
||||
{
|
||||
char pszFullName[MAX_PATH];
|
||||
V_snprintf( pszFullName, sizeof(pszFullName), NULL, szFile );
|
||||
@ -87,7 +87,7 @@ static HSCRIPT VMFKV_LoadFromFile( const char *szFile )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HSCRIPT hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV, true ); // bAllowDestruct is supposed to automatically remove the involved KV
|
||||
HSCRIPT hScript = scriptmanager->CreateScriptKeyValues( g_pScriptVM, pKV );
|
||||
|
||||
return hScript;
|
||||
}
|
||||
@ -142,7 +142,7 @@ static HSCRIPT VMFKV_AddEntityFromTables( HSCRIPT hVMF, HSCRIPT hKV, HSCRIPT hIO
|
||||
}
|
||||
}
|
||||
|
||||
return scriptmanager->CreateScriptKeyValues( g_pScriptVM, pEnt, false );
|
||||
return scriptmanager->CreateScriptKeyValues( g_pScriptVM, pEnt, true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -2471,6 +2471,15 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail )
|
||||
{
|
||||
do_fast = true;
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if(!Q_stricmp(argv[i], "-ultrafast"))
|
||||
{
|
||||
do_fast = true;
|
||||
g_bFastAmbient = true;
|
||||
do_extra = false;
|
||||
numbounce = 1;
|
||||
}
|
||||
#endif
|
||||
else if (!Q_stricmp(argv[i],"-noskyboxrecurse"))
|
||||
{
|
||||
g_bNoSkyRecurse = true;
|
||||
@ -2491,6 +2500,26 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail )
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#ifdef MAPBASE
|
||||
else if (!Q_stricmp(argv[i], "-extrapasses"))
|
||||
{
|
||||
if (++i < argc)
|
||||
{
|
||||
int extrapassesParam = atoi(argv[i]);
|
||||
if (extrapassesParam < 0)
|
||||
{
|
||||
Warning("Error: expected non-negative value after '-extrapasses'\n");
|
||||
return 1;
|
||||
}
|
||||
extrapasses = extrapassesParam;
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning("Error: expected a value after '-extrapasses'\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (!Q_stricmp(argv[i],"-centersamples"))
|
||||
{
|
||||
do_centersamples = true;
|
||||
@ -2777,9 +2806,15 @@ void PrintUsage( int argc, char **argv )
|
||||
" -v (or -verbose): Turn on verbose output (also shows more command\n"
|
||||
" -bounce # : Set max number of bounces (default: 100).\n"
|
||||
" -fast : Quick and dirty lighting.\n"
|
||||
#ifdef MAPBASE
|
||||
" -ultrafast : Very quick and dirty lighting, same as -fast -fastambient -noextra -bounce 1\n"
|
||||
#endif
|
||||
" -fastambient : Per-leaf ambient sampling is lower quality to save compute time.\n"
|
||||
" -final : High quality processing. equivalent to -extrasky 16.\n"
|
||||
" -extrasky n : trace N times as many rays for indirect light and sky ambient.\n"
|
||||
" -extrasky # : trace # times as many rays for indirect light and sky ambient.\n"
|
||||
#ifdef MAPBASE
|
||||
" -extrapasses # : Lets you scale how many extra passes you want your map to go through (default 4), differences above this value are minimal.\n"
|
||||
#endif
|
||||
" -low : Run as an idle-priority process.\n"
|
||||
" -mpi : Use VMPI to distribute computations.\n"
|
||||
" -rederror : Show errors in red.\n"
|
||||
@ -2813,7 +2848,7 @@ void PrintUsage( int argc, char **argv )
|
||||
" -loghash : Log the sample hash table to samplehash.txt.\n"
|
||||
" -onlydetail : Only light detail props and per-leaf lighting.\n"
|
||||
" -maxdispsamplesize #: Set max displacement sample size (default: 512).\n"
|
||||
" -softsun <n> : Treat the sun as an area light source of size <n> degrees."
|
||||
" -softsun # : Treat the sun as an area light source of size # degrees."
|
||||
" Produces soft shadows.\n"
|
||||
" Recommended values are between 0 and 5. Default is 0.\n"
|
||||
" -FullMinidumps : Write large minidumps on crash.\n"
|
||||
|
@ -847,34 +847,40 @@ void RichText::Paint()
|
||||
|
||||
// 3.
|
||||
// Calculate the range of text to draw all at once
|
||||
int iLim = m_TextStream.Count();
|
||||
int iLim = m_TextStream.Count() - 1;
|
||||
|
||||
// Stop at the next line break
|
||||
if ( m_LineBreaks.IsValidIndex( lineBreakIndexIndex ) && m_LineBreaks[lineBreakIndexIndex] <= iLim )
|
||||
iLim = m_LineBreaks[lineBreakIndexIndex] - 1;
|
||||
|
||||
// Stop at the next format change
|
||||
if ( m_FormatStream.IsValidIndex(renderState.formatStreamIndex) &&
|
||||
m_FormatStream[renderState.formatStreamIndex].textStreamIndex < iLim &&
|
||||
m_FormatStream[renderState.formatStreamIndex].textStreamIndex <= iLim &&
|
||||
m_FormatStream[renderState.formatStreamIndex].textStreamIndex >= i &&
|
||||
m_FormatStream[renderState.formatStreamIndex].textStreamIndex )
|
||||
{
|
||||
iLim = m_FormatStream[renderState.formatStreamIndex].textStreamIndex;
|
||||
iLim = m_FormatStream[renderState.formatStreamIndex].textStreamIndex - 1;
|
||||
}
|
||||
|
||||
// Stop at the next line break
|
||||
if ( m_LineBreaks.IsValidIndex( lineBreakIndexIndex ) && m_LineBreaks[lineBreakIndexIndex] < iLim )
|
||||
iLim = m_LineBreaks[lineBreakIndexIndex];
|
||||
// Stop when entering or exiting the selected range
|
||||
if ( i < selection0 && iLim >= selection0 )
|
||||
iLim = selection0 - 1;
|
||||
if ( i >= selection0 && i < selection1 && iLim >= selection1 )
|
||||
iLim = selection1 - 1;
|
||||
|
||||
// Handle non-drawing characters specially
|
||||
for ( int iT = i; iT < iLim; iT++ )
|
||||
for ( int iT = i; iT <= iLim; iT++ )
|
||||
{
|
||||
if ( iswcntrl(m_TextStream[iT]) )
|
||||
{
|
||||
iLim = iT;
|
||||
iLim = iT - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 4.
|
||||
// Draw the current text range
|
||||
if ( iLim <= i )
|
||||
if ( iLim < i )
|
||||
{
|
||||
if ( m_TextStream[i] == '\t' )
|
||||
{
|
||||
@ -887,8 +893,8 @@ void RichText::Paint()
|
||||
}
|
||||
else
|
||||
{
|
||||
renderState.x += DrawString(i, iLim - 1, renderState, hFontCurrent );
|
||||
i = iLim;
|
||||
renderState.x += DrawString(i, iLim, renderState, hFontCurrent );
|
||||
i = iLim + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,10 @@ $Conditional VS2017 "0" // Toggles Visual Studio 2017 (v141) toolset
|
||||
$Conditional VS2019 "0" // Toggles Visual Studio 2019 (v142) toolset
|
||||
$Conditional VS2022 "0" // Toggles Visual Studio 2022 (v143) toolset
|
||||
|
||||
//
|
||||
// WARNING: If you do not have Visual Studio 2013 installed and try to use VPC, it may produce an error about a missing RegKey.
|
||||
// You can fix this without installing VS2013 by running newer_vs_toolsets_regkey_fix.reg, which is in the same directory as this file.
|
||||
// This .reg file adds a registry key which is normally created by installing VS2013. You will only have to do this once per machine.
|
||||
//
|
||||
// VPC may still say "Generating for Visual Studio 2013" even when using one of the above toolsets. This message is irrelevant and can be ignored.
|
||||
//
|
||||
|
7
sp/src/vpc_scripts/newer_vs_toolsets_regkey_fix.reg
Normal file
7
sp/src/vpc_scripts/newer_vs_toolsets_regkey_fix.reg
Normal file
@ -0,0 +1,7 @@
|
||||
Windows Registry Editor Version 5.00
|
||||
|
||||
; https://github.com/ValveSoftware/source-sdk-2013/issues/72#issuecomment-326633328
|
||||
; If you are running a 32-bit system, you may need to remove WOW6432Node from the path.
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\10.0\Projects\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}]
|
||||
"DefaultProjectExtension"="vcproj"
|
70
sp/src/vscript/sqdbg/include/sqdbg.h
Normal file
70
sp/src/vscript/sqdbg/include/sqdbg.h
Normal file
@ -0,0 +1,70 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// github.com/samisalreadytaken/sqdbg
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Squirrel Debugger
|
||||
//
|
||||
|
||||
#ifndef SQDBG_H
|
||||
#define SQDBG_H
|
||||
|
||||
#include <squirrel.h>
|
||||
|
||||
#define SQDBG_SV_API_VER 1
|
||||
|
||||
#ifndef SQDBG_API
|
||||
#ifdef SQDBG_DLL
|
||||
#if defined(_WIN32)
|
||||
#ifdef SQDBG_DLL_EXPORT
|
||||
#define SQDBG_API __declspec(dllexport)
|
||||
#else
|
||||
#define SQDBG_API __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#ifdef SQDBG_DLL_EXPORT
|
||||
#define SQDBG_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define SQDBG_API extern
|
||||
#endif
|
||||
#else
|
||||
#define SQDBG_API extern
|
||||
#endif
|
||||
#else
|
||||
#define SQDBG_API extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct SQDebugServer;
|
||||
typedef SQDebugServer* HSQDEBUGSERVER;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Create and attach a new debugger
|
||||
// Memory is owned by the VM, it is freed when the VM dies or
|
||||
// the debugger is disconnected via sqdbg_destroy_debugger()
|
||||
SQDBG_API HSQDEBUGSERVER sqdbg_attach_debugger( HSQUIRRELVM vm );
|
||||
|
||||
// Detach and destroy the debugger attached to this VM
|
||||
// Invalidates the handle returned from sqdbg_attach_debugger()
|
||||
SQDBG_API void sqdbg_destroy_debugger( HSQUIRRELVM vm );
|
||||
|
||||
// Open specified port and allow client connections
|
||||
// If port is 0, the system will choose a unique available port
|
||||
// Returns 0 on success
|
||||
SQDBG_API int sqdbg_listen_socket( HSQDEBUGSERVER dbg, unsigned short port );
|
||||
|
||||
// Process client connections and incoming messages
|
||||
// Blocks on script breakpoints while a client is connected
|
||||
SQDBG_API void sqdbg_frame( HSQDEBUGSERVER dbg );
|
||||
|
||||
// Copies the script to be able to source it to debugger clients
|
||||
SQDBG_API void sqdbg_on_script_compile( HSQDEBUGSERVER dbg, const SQChar *script, SQInteger size,
|
||||
const SQChar *sourcename, SQInteger sourcenamelen );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SQDBG_H
|
131
sp/src/vscript/sqdbg/sqdbg/debug.h
Normal file
131
sp/src/vscript/sqdbg/sqdbg/debug.h
Normal file
@ -0,0 +1,131 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// github.com/samisalreadytaken/sqdbg
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#ifndef SQDBG_DEBUG_H
|
||||
#define SQDBG_DEBUG_H
|
||||
|
||||
#if 0
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef _WIN32
|
||||
#include <crtdbg.h>
|
||||
|
||||
bool __IsDebuggerPresent();
|
||||
const char *GetModuleBaseName();
|
||||
|
||||
#define DebuggerBreak() do { if ( __IsDebuggerPresent() ) __debugbreak(); } while(0)
|
||||
|
||||
#define Assert( x ) \
|
||||
do { \
|
||||
__CAT( L, __LINE__ ): \
|
||||
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), #x)) ) \
|
||||
{ \
|
||||
if ( !__IsDebuggerPresent() ) \
|
||||
goto __CAT( L, __LINE__ ); \
|
||||
__debugbreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertMsg( x, msg ) \
|
||||
do { \
|
||||
__CAT( L, __LINE__ ): \
|
||||
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg)) ) \
|
||||
{ \
|
||||
if ( !__IsDebuggerPresent() ) \
|
||||
goto __CAT( L, __LINE__ ); \
|
||||
__debugbreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertMsg1( x, msg, a1 ) \
|
||||
do { \
|
||||
__CAT( L, __LINE__ ): \
|
||||
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg, a1)) ) \
|
||||
{ \
|
||||
if ( !__IsDebuggerPresent() ) \
|
||||
goto __CAT( L, __LINE__ ); \
|
||||
__debugbreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertMsg2( x, msg, a1, a2 ) \
|
||||
do { \
|
||||
__CAT( L, __LINE__ ): \
|
||||
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg, a1, a2)) ) \
|
||||
{ \
|
||||
if ( !__IsDebuggerPresent() ) \
|
||||
goto __CAT( L, __LINE__ ); \
|
||||
__debugbreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
extern "C" int printf(const char *, ...);
|
||||
|
||||
#define DebuggerBreak() asm("int3")
|
||||
|
||||
#define Assert( x ) \
|
||||
do { \
|
||||
if ( !(x) ) \
|
||||
{ \
|
||||
::printf("Assertion failed %s:%d: %s\n", __FILE__, __LINE__, #x); \
|
||||
DebuggerBreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertMsg( x, msg ) \
|
||||
do { \
|
||||
if ( !(x) ) \
|
||||
{ \
|
||||
::printf("Assertion failed %s:%d: %s\n", __FILE__, __LINE__, msg); \
|
||||
DebuggerBreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertMsg1( x, msg, a1 ) \
|
||||
do { \
|
||||
if ( !(x) ) \
|
||||
{ \
|
||||
::printf("Assertion failed %s:%d: ", __FILE__, __LINE__); \
|
||||
::printf(msg, a1); \
|
||||
::printf("\n"); \
|
||||
DebuggerBreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define AssertMsg2( x, msg, a1, a2 ) \
|
||||
do { \
|
||||
if ( !(x) ) \
|
||||
{ \
|
||||
::printf("Assertion failed %s:%d: ", __FILE__, __LINE__); \
|
||||
::printf(msg, a1, a2); \
|
||||
::printf("\n"); \
|
||||
DebuggerBreak(); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
#define Verify( x ) Assert(x)
|
||||
#else
|
||||
#define DebuggerBreak() ((void)0)
|
||||
#define Assert( x ) ((void)0)
|
||||
#define AssertMsg( x, msg ) ((void)0)
|
||||
#define AssertMsg1( x, msg, a1 ) ((void)0)
|
||||
#define AssertMsg2( x, msg, a1, a2 ) ((void)0)
|
||||
#define Verify( x ) x
|
||||
#endif // _DEBUG
|
||||
|
||||
#endif
|
||||
|
||||
#include <tier0/dbg.h>
|
||||
|
||||
// Misdefined for GCC in platform.h
|
||||
#undef UNREACHABLE
|
||||
|
||||
#ifdef _WIN32
|
||||
#define UNREACHABLE() do { Assert(!"UNREACHABLE"); __assume(0); } while(0)
|
||||
#else
|
||||
#define UNREACHABLE() do { Assert(!"UNREACHABLE"); __builtin_unreachable(); } while(0)
|
||||
#endif
|
||||
|
||||
#endif // SQDBG_DEBUG_H
|
1200
sp/src/vscript/sqdbg/sqdbg/json.h
Normal file
1200
sp/src/vscript/sqdbg/sqdbg/json.h
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user