Merge pull request #114 from samisalreadytaken/dev6

vscript additions
This commit is contained in:
Blixibon 2021-04-23 22:31:04 -05:00 committed by GitHub
commit ea98b2cd1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 361 additions and 143 deletions

View File

@ -428,6 +428,10 @@ BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_AnimTimeMustBeFirst )
RecvPropInt( RECVINFO(m_flAnimTime), 0, RecvProxy_AnimTime ), RecvPropInt( RECVINFO(m_flAnimTime), 0, RecvProxy_AnimTime ),
END_RECV_TABLE() END_RECV_TABLE()
#ifdef MAPBASE_VSCRIPT
ScriptHook_t CBaseEntity::g_Hook_UpdateOnRemove;
#endif
BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" ) BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" )
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper ) DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" ) DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
@ -550,7 +554,10 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." ) DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
#endif
DEFINE_SIMPLE_SCRIPTHOOK( CBaseEntity::g_Hook_UpdateOnRemove, "UpdateOnRemove", FIELD_VOID, "Called when the entity is being removed." )
#endif // MAPBASE_VSCRIPT
END_SCRIPTDESC(); END_SCRIPTDESC();
@ -1340,6 +1347,12 @@ void C_BaseEntity::Term()
if ( m_hScriptInstance ) if ( m_hScriptInstance )
{ {
#ifdef MAPBASE_VSCRIPT
if ( m_ScriptScope.IsInitialized() )
{
g_Hook_UpdateOnRemove.Call( m_ScriptScope, NULL, NULL );
}
#endif
g_pScriptVM->RemoveInstance( m_hScriptInstance ); g_pScriptVM->RemoveInstance( m_hScriptInstance );
m_hScriptInstance = NULL; m_hScriptInstance = NULL;

View File

@ -164,10 +164,9 @@ struct thinkfunc_t
#ifdef MAPBASE_VSCRIPT #ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t struct scriptthinkfunc_t
{ {
int m_nNextThinkTick; float m_flNextThink;
HSCRIPT m_hfnThink; HSCRIPT m_hfnThink;
unsigned short m_iContextHash; unsigned m_iContextHash;
bool m_bNoParam;
}; };
#endif #endif
@ -295,6 +294,8 @@ public:
string_t m_iszScriptId; string_t m_iszScriptId;
#ifdef MAPBASE_VSCRIPT #ifdef MAPBASE_VSCRIPT
CScriptScope m_ScriptScope; CScriptScope m_ScriptScope;
static ScriptHook_t g_Hook_UpdateOnRemove;
#endif #endif
// IClientUnknown overrides. // IClientUnknown overrides.

View File

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

View File

@ -2314,6 +2314,8 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelKeyValues, "GetModelKeyValues", "Get a KeyValue class instance on this entity's model") DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelKeyValues, "GetModelKeyValues", "Get a KeyValue class instance on this entity's model")
#ifdef MAPBASE_VSCRIPT #ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC( Activate, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptIsVisible, "IsVisible", "Check if the specified position can be visible to this entity." ) DEFINE_SCRIPTFUNC_NAMED( ScriptIsVisible, "IsVisible", "Check if the specified position can be visible to this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptIsEntVisible, "IsEntVisible", "Check if the specified entity can be visible to this entity." ) DEFINE_SCRIPTFUNC_NAMED( ScriptIsEntVisible, "IsEntVisible", "Check if the specified entity can be visible to this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptIsVisibleWithMask, "IsVisibleWithMask", "Check if the specified position can be visible to this entity with a specific trace mask." ) DEFINE_SCRIPTFUNC_NAMED( ScriptIsVisibleWithMask, "IsVisibleWithMask", "Check if the specified position can be visible to this entity with a specific trace mask." )
@ -2411,7 +2413,10 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC( SetFriction, "" ) DEFINE_SCRIPTFUNC( SetFriction, "" )
DEFINE_SCRIPTFUNC( GetMass, "" ) DEFINE_SCRIPTFUNC( GetMass, "" )
DEFINE_SCRIPTFUNC( SetMass, "" ) DEFINE_SCRIPTFUNC( SetMass, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSolid, "GetSolid", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetSolid, "SetSolid", "" )
DEFINE_SCRIPTFUNC( GetSolidFlags, "Get solid flags" ) DEFINE_SCRIPTFUNC( GetSolidFlags, "Get solid flags" )
DEFINE_SCRIPTFUNC( AddSolidFlags, "Add solid flags" ) DEFINE_SCRIPTFUNC( AddSolidFlags, "Add solid flags" )
DEFINE_SCRIPTFUNC( RemoveSolidFlags, "Remove solid flags" ) DEFINE_SCRIPTFUNC( RemoveSolidFlags, "Remove solid flags" )

View File

@ -352,10 +352,10 @@ struct thinkfunc_t
#ifdef MAPBASE_VSCRIPT #ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t struct scriptthinkfunc_t
{ {
int m_nNextThinkTick; float m_flNextThink;
HSCRIPT m_hfnThink; HSCRIPT m_hfnThink;
unsigned short m_iContextHash; unsigned m_iContextHash;
bool m_bNoParam; bool m_bNoParam;
}; };
#endif #endif
@ -2132,6 +2132,9 @@ public:
int ScriptGetMoveType() { return GetMoveType(); } int ScriptGetMoveType() { return GetMoveType(); }
void ScriptSetMoveType( int iMoveType ) { SetMoveType( (MoveType_t)iMoveType ); } void ScriptSetMoveType( int iMoveType ) { SetMoveType( (MoveType_t)iMoveType ); }
int ScriptGetSolid() { return GetSolid(); }
void ScriptSetSolid( int i ) { SetSolid( (SolidType_t)i ); }
bool ScriptDispatchInteraction( int interactionType, HSCRIPT data, HSCRIPT sourceEnt ); bool ScriptDispatchInteraction( int interactionType, HSCRIPT data, HSCRIPT sourceEnt );
int ScriptGetTakeDamage() { return m_takedamage; } int ScriptGetTakeDamage() { return m_takedamage; }

View File

@ -2713,13 +2713,20 @@ HSCRIPT CBaseEntity::ScriptGetPhysicsObject( void )
return NULL; return NULL;
} }
#ifdef GAME_DLL
#define SCRIPT_NEVER_THINK TICK_NEVER_THINK
#else
#define SCRIPT_NEVER_THINK CLIENT_THINK_NEVER
#endif
static inline void ScriptStopContextThink( scriptthinkfunc_t *context ) static inline void ScriptStopContextThink( scriptthinkfunc_t *context )
{ {
Assert( context->m_hfnThink ); Assert( context->m_hfnThink );
Assert( context->m_flNextThink == SCRIPT_NEVER_THINK );
g_pScriptVM->ReleaseScript( context->m_hfnThink ); g_pScriptVM->ReleaseScript( context->m_hfnThink );
context->m_hfnThink = NULL; context->m_hfnThink = NULL;
//context->m_nNextThinkTick = TICK_NEVER_THINK;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2728,55 +2735,56 @@ static inline void ScriptStopContextThink( scriptthinkfunc_t *context )
void CBaseEntity::ScriptContextThink() void CBaseEntity::ScriptContextThink()
{ {
float flNextThink = FLT_MAX; float flNextThink = FLT_MAX;
int nScheduledTick = 0; float flScheduled = 0.0f;
for ( int i = 0; i < m_ScriptThinkFuncs.Count(); ++i ) for ( int i = 0; i < m_ScriptThinkFuncs.Count(); ++i )
{ {
scriptthinkfunc_t *cur = m_ScriptThinkFuncs[i]; scriptthinkfunc_t *cur = m_ScriptThinkFuncs[i];
if ( cur->m_nNextThinkTick == TICK_NEVER_THINK ) if ( cur->m_flNextThink == SCRIPT_NEVER_THINK )
{ {
continue; continue;
} }
if ( cur->m_nNextThinkTick > gpGlobals->tickcount ) if ( cur->m_flNextThink > gpGlobals->curtime )
{ {
// There is more to execute, don't stop thinking if the rest are done. if ( ( flScheduled == 0.0f ) || ( flScheduled > cur->m_flNextThink ) )
// Find the shortest schedule
if ( !nScheduledTick || nScheduledTick > cur->m_nNextThinkTick )
{ {
nScheduledTick = cur->m_nNextThinkTick; flScheduled = cur->m_flNextThink;
} }
continue; continue;
} }
#ifdef _DEBUG #ifdef _DEBUG
// going to run the script func // going to run the script func
cur->m_nNextThinkTick = 0; cur->m_flNextThink = 0;
#endif #endif
ScriptVariant_t varReturn; ScriptVariant_t varReturn;
#ifndef CLIENT_DLL
if ( !cur->m_bNoParam ) if ( !cur->m_bNoParam )
{ {
#endif
ScriptVariant_t arg = m_hScriptInstance; ScriptVariant_t arg = m_hScriptInstance;
if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, &arg, 1, &varReturn, NULL, true ) == SCRIPT_ERROR ) if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, &arg, 1, &varReturn, NULL, true ) == SCRIPT_ERROR )
{ {
cur->m_nNextThinkTick = TICK_NEVER_THINK; cur->m_flNextThink = SCRIPT_NEVER_THINK;
continue; continue;
} }
#ifndef CLIENT_DLL
} }
else else
{ {
if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, NULL, 0, &varReturn, NULL, true ) == SCRIPT_ERROR ) if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, NULL, 0, &varReturn, NULL, true ) == SCRIPT_ERROR )
{ {
cur->m_nNextThinkTick = TICK_NEVER_THINK; cur->m_flNextThink = SCRIPT_NEVER_THINK;
continue; continue;
} }
} }
#endif
if ( cur->m_nNextThinkTick == TICK_NEVER_THINK ) if ( cur->m_flNextThink == SCRIPT_NEVER_THINK )
{ {
// stopped from script while thinking // stopped from script while thinking
continue; continue;
@ -2785,13 +2793,13 @@ void CBaseEntity::ScriptContextThink()
float flReturn; float flReturn;
if ( !varReturn.AssignTo( &flReturn ) ) if ( !varReturn.AssignTo( &flReturn ) )
{ {
cur->m_nNextThinkTick = TICK_NEVER_THINK; cur->m_flNextThink = SCRIPT_NEVER_THINK;
continue; continue;
} }
if ( flReturn < 0.0f ) if ( flReturn < 0.0f )
{ {
cur->m_nNextThinkTick = TICK_NEVER_THINK; cur->m_flNextThink = SCRIPT_NEVER_THINK;
continue; continue;
} }
@ -2800,95 +2808,60 @@ void CBaseEntity::ScriptContextThink()
flNextThink = flReturn; flNextThink = flReturn;
} }
cur->m_nNextThinkTick = TIME_TO_TICKS( gpGlobals->curtime + flReturn ); cur->m_flNextThink = gpGlobals->curtime + flReturn - 0.001;
} }
// deferred safe removal // deferred safe removal
for ( int i = 0; i < m_ScriptThinkFuncs.Count(); ) for ( int i = 0; i < m_ScriptThinkFuncs.Count(); )
{ {
if ( m_ScriptThinkFuncs[i]->m_nNextThinkTick == TICK_NEVER_THINK ) scriptthinkfunc_t *cur = m_ScriptThinkFuncs[i];
if ( cur->m_flNextThink == SCRIPT_NEVER_THINK )
{ {
ScriptStopContextThink( m_ScriptThinkFuncs[i] ); ScriptStopContextThink( cur );
delete m_ScriptThinkFuncs[i]; delete cur;
m_ScriptThinkFuncs.Remove(i); m_ScriptThinkFuncs.Remove(i);
} }
else ++i; else ++i;
} }
bool bNewNext = flNextThink < FLT_MAX; if ( flNextThink < FLT_MAX )
#ifdef _DEBUG
#ifdef GAME_DLL
int nNextThinkTick = GetNextThinkTick("ScriptContextThink"); // -1
#else
int nNextThinkTick = GetNextThinkTick(); // 0
#endif
if ( ( nNextThinkTick <= 0 ) || ( nNextThinkTick >= nScheduledTick ) || ( nNextThinkTick == gpGlobals->tickcount ) )
{ {
#endif if ( flScheduled > 0.0f )
if ( nScheduledTick )
{ {
float flScheduledTime = TICKS_TO_TIME( nScheduledTick ); flNextThink = min( gpGlobals->curtime + flNextThink, flScheduled );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, flScheduledTime );
}
else
{
flNextThink = flScheduledTime;
}
} }
else else
{ {
if ( bNewNext ) flNextThink = gpGlobals->curtime + flNextThink;
{
flNextThink = gpGlobals->curtime + flNextThink;
}
else
{
#ifdef GAME_DLL
flNextThink = TICK_NEVER_THINK;
#else
flNextThink = CLIENT_THINK_NEVER;
#endif
}
} }
#ifdef _DEBUG
} }
else else
{ {
// Next think was set (from script) to a sooner tick while thinking? if ( flScheduled > 0.0f )
Assert(0);
if ( nScheduledTick )
{ {
int nNextSchedule = min( nScheduledTick, nNextThinkTick ); flNextThink = flScheduled;
float flNextSchedule = TICKS_TO_TIME( nNextSchedule );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, flNextSchedule );
}
else
{
flNextThink = flNextSchedule;
}
} }
else else
{ {
float nextthink = TICKS_TO_TIME( nNextThinkTick ); flNextThink = SCRIPT_NEVER_THINK;
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, nextthink );
}
else
{
flNextThink = nextthink;
}
} }
} }
#ifdef _DEBUG
#ifdef GAME_DLL
int nNextThinkTick = GetNextThinkTick("ScriptContextThink");
float flNextThinkTime = TICKS_TO_TIME(nNextThinkTick);
// If internal next think tick is earlier than what we have here with flNextThink,
// whoever set that think may fail. In worst case scenario the entity may stop thinking.
if ( nNextThinkTick > gpGlobals->tickcount )
{
if ( flNextThink == SCRIPT_NEVER_THINK )
Assert(0);
if ( flNextThinkTime < flNextThink )
Assert(0);
}
#endif
#endif #endif
#ifdef GAME_DLL #ifdef GAME_DLL
@ -2898,8 +2871,10 @@ void CBaseEntity::ScriptContextThink()
#endif #endif
} }
#ifndef CLIENT_DLL
// see ScriptSetThink // see ScriptSetThink
static bool s_bScriptContextThinkNoParam = false; static bool s_bScriptContextThinkNoParam = false;
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -2917,7 +2892,7 @@ void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, f
#endif #endif
scriptthinkfunc_t *pf = NULL; scriptthinkfunc_t *pf = NULL;
unsigned short hash = ( szContext && *szContext ) ? HashString( szContext ) : 0; unsigned hash = szContext ? HashString( szContext ) : 0;
FOR_EACH_VEC( m_ScriptThinkFuncs, i ) FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{ {
@ -2939,14 +2914,16 @@ void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, f
m_ScriptThinkFuncs.SetGrowSize(1); m_ScriptThinkFuncs.SetGrowSize(1);
m_ScriptThinkFuncs.AddToTail( pf ); m_ScriptThinkFuncs.AddToTail( pf );
pf->m_bNoParam = s_bScriptContextThinkNoParam;
pf->m_iContextHash = hash; pf->m_iContextHash = hash;
#ifndef CLIENT_DLL
pf->m_bNoParam = s_bScriptContextThinkNoParam;
#endif
} }
// update existing // update existing
else else
{ {
#ifdef _DEBUG #ifdef _DEBUG
if ( pf->m_nNextThinkTick == 0 ) if ( pf->m_flNextThink == 0 )
{ {
Warning("Script think ('%s') was changed while it was thinking!\n", szContext); Warning("Script think ('%s') was changed while it was thinking!\n", szContext);
} }
@ -2957,31 +2934,29 @@ void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, f
float nextthink = gpGlobals->curtime + flTime; float nextthink = gpGlobals->curtime + flTime;
pf->m_hfnThink = hFunc; pf->m_hfnThink = hFunc;
pf->m_nNextThinkTick = TIME_TO_TICKS( nextthink ); pf->m_flNextThink = nextthink;
#ifdef GAME_DLL #ifdef GAME_DLL
int nexttick = GetNextThinkTick( RegisterThinkContext( "ScriptContextThink" ) ); int nexttick = GetNextThinkTick( RegisterThinkContext( "ScriptContextThink" ) );
#else if ( nexttick <= 0 || TICKS_TO_TIME(nexttick) > nextthink )
int nexttick = GetNextThinkTick();
#endif
// sooner than next think
if ( nexttick <= 0 || nexttick > pf->m_nNextThinkTick )
{ {
#ifdef GAME_DLL
SetContextThink( &CBaseEntity::ScriptContextThink, nextthink, "ScriptContextThink" ); SetContextThink( &CBaseEntity::ScriptContextThink, nextthink, "ScriptContextThink" );
#else
SetNextClientThink( nextthink );
#endif
} }
#else
{
// let it self adjust
SetNextClientThink( gpGlobals->curtime );
}
#endif
} }
// null func input, think exists // null func input, think exists
else if ( pf ) else if ( pf )
{ {
pf->m_nNextThinkTick = TICK_NEVER_THINK; pf->m_flNextThink = SCRIPT_NEVER_THINK;
} }
} }
#ifndef CLIENT_DLL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// m_bNoParam and s_bScriptContextThinkNoParam exist only to keep backwards compatibility // m_bNoParam and s_bScriptContextThinkNoParam exist only to keep backwards compatibility
// and are an alternative to this script closure: // and are an alternative to this script closure:
@ -2991,7 +2966,6 @@ void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, f
// SetContextThink( "", function(_){ return func() }, time ) // SetContextThink( "", function(_){ return func() }, time )
// } // }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef CLIENT_DLL
void CBaseEntity::ScriptSetThink( HSCRIPT hFunc, float time ) void CBaseEntity::ScriptSetThink( HSCRIPT hFunc, float time )
{ {
s_bScriptContextThinkNoParam = true; s_bScriptContextThinkNoParam = true;

View File

@ -30,6 +30,10 @@
#include "c_te_legacytempents.h" #include "c_te_legacytempents.h"
#include "iefx.h" #include "iefx.h"
#include "dlight.h" #include "dlight.h"
#if !defined(NO_STEAM)
#include "steam/steam_api.h"
#endif
#endif #endif
#include "vscript_singletons.h" #include "vscript_singletons.h"
@ -2183,12 +2187,13 @@ public:
~CScriptConCommand() ~CScriptConCommand()
{ {
Unregister(); Unregister();
delete m_cmd; delete m_pBase;
} }
CScriptConCommand( const char *name, HSCRIPT fn, const char *helpString, int flags ) CScriptConCommand( const char *name, HSCRIPT fn, const char *helpString, int flags, ConCommand *pLinked = NULL )
{ {
m_cmd = new ConCommand( name, this, helpString, flags, 0 ); m_pBase = new ConCommand( name, this, helpString, flags, 0 );
m_pLinked = pLinked;
m_hCallback = fn; m_hCallback = fn;
m_hCompletionCallback = NULL; m_hCompletionCallback = NULL;
m_nCmdNameLen = V_strlen(name) + 1; m_nCmdNameLen = V_strlen(name) + 1;
@ -2204,10 +2209,15 @@ public:
{ {
vArgv[i] = command[i]; vArgv[i] = command[i];
} }
if ( g_pScriptVM->ExecuteFunction( m_hCallback, vArgv, count, NULL, NULL, true ) == SCRIPT_ERROR ) ScriptVariant_t ret;
if ( g_pScriptVM->ExecuteFunction( m_hCallback, vArgv, count, &ret, NULL, true ) == SCRIPT_ERROR )
{ {
DevWarning( 1, "CScriptConCommand: invalid callback for '%s'\n", command[0] ); DevWarning( 1, "CScriptConCommand: invalid callback for '%s'\n", command[0] );
} }
if ( m_pLinked && (ret.m_type == FIELD_BOOLEAN) && ret.m_bool )
{
m_pLinked->Dispatch( command );
}
} }
int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands ) int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands )
@ -2262,17 +2272,17 @@ public:
if (fn) if (fn)
{ {
if ( !m_cmd->IsRegistered() ) if ( !m_pBase->IsRegistered() )
return; return;
m_cmd->m_pCommandCompletionCallback = this; m_pBase->m_pCommandCompletionCallback = this;
m_cmd->m_bHasCompletionCallback = true; m_pBase->m_bHasCompletionCallback = true;
m_hCompletionCallback = fn; m_hCompletionCallback = fn;
} }
else else
{ {
m_cmd->m_pCommandCompletionCallback = NULL; m_pBase->m_pCommandCompletionCallback = NULL;
m_cmd->m_bHasCompletionCallback = false; m_pBase->m_bHasCompletionCallback = false;
m_hCompletionCallback = NULL; m_hCompletionCallback = NULL;
} }
} }
@ -2281,7 +2291,7 @@ public:
{ {
if (fn) if (fn)
{ {
if ( !m_cmd->IsRegistered() ) if ( !m_pBase->IsRegistered() )
Register(); Register();
if ( m_hCallback ) if ( m_hCallback )
@ -2296,8 +2306,8 @@ public:
inline void Unregister() inline void Unregister()
{ {
if ( g_pCVar && m_cmd->IsRegistered() ) if ( g_pCVar && m_pBase->IsRegistered() )
g_pCVar->UnregisterConCommand( m_cmd ); g_pCVar->UnregisterConCommand( m_pBase );
if ( g_pScriptVM ) if ( g_pScriptVM )
{ {
@ -2314,13 +2324,14 @@ public:
inline void Register() inline void Register()
{ {
if ( g_pCVar ) if ( g_pCVar )
g_pCVar->RegisterConCommand( m_cmd ); g_pCVar->RegisterConCommand( m_pBase );
} }
HSCRIPT m_hCallback; HSCRIPT m_hCallback;
HSCRIPT m_hCompletionCallback; HSCRIPT m_hCompletionCallback;
int m_nCmdNameLen; int m_nCmdNameLen;
ConCommand *m_cmd; ConCommand *m_pLinked;
ConCommand *m_pBase;
}; };
class CScriptConVar class CScriptConVar
@ -2329,30 +2340,58 @@ public:
~CScriptConVar() ~CScriptConVar()
{ {
Unregister(); Unregister();
delete m_cvar; delete m_pBase;
} }
CScriptConVar( const char *pName, const char *pDefaultValue, const char *pHelpString, int flags/*, float fMin, float fMax*/ ) CScriptConVar( const char *pName, const char *pDefaultValue, const char *pHelpString, int flags/*, float fMin, float fMax*/ )
{ {
m_cvar = new ConVar( pName, pDefaultValue, flags, pHelpString ); m_pBase = new ConVar( pName, pDefaultValue, flags, pHelpString );
m_hCallback = NULL;
}
void SetChangeCallback( HSCRIPT fn )
{
void ScriptConVarCallback( IConVar*, const char*, float );
if ( m_hCallback )
g_pScriptVM->ReleaseScript( m_hCallback );
if (fn)
{
m_hCallback = fn;
m_pBase->InstallChangeCallback( (FnChangeCallback_t)ScriptConVarCallback );
}
else
{
m_hCallback = NULL;
m_pBase->InstallChangeCallback( NULL );
}
} }
inline void Unregister() inline void Unregister()
{ {
if ( g_pCVar && m_cvar->IsRegistered() ) if ( g_pCVar && m_pBase->IsRegistered() )
g_pCVar->UnregisterConCommand( m_cvar ); g_pCVar->UnregisterConCommand( m_pBase );
if ( g_pScriptVM )
{
SetChangeCallback( NULL );
}
} }
ConVar *m_cvar; HSCRIPT m_hCallback;
ConVar *m_pBase;
}; };
static CUtlMap< unsigned int, bool > g_ConVarsBlocked( DefLessFunc(unsigned int) );
static CUtlMap< unsigned int, bool > g_ConCommandsOverridable( DefLessFunc(unsigned int) );
static CUtlMap< unsigned int, CScriptConCommand* > g_ScriptConCommands( DefLessFunc(unsigned int) );
static CUtlMap< unsigned int, CScriptConVar* > g_ScriptConVars( DefLessFunc(unsigned int) );
class CScriptConvarAccessor : public CAutoGameSystem class CScriptConvarAccessor : public CAutoGameSystem
{ {
public: public:
static CUtlMap< unsigned int, bool > g_ConVarsBlocked;
static CUtlMap< unsigned int, bool > g_ConCommandsOverridable;
static CUtlMap< unsigned int, CScriptConCommand* > g_ScriptConCommands;
static CUtlMap< unsigned int, CScriptConVar* > g_ScriptConVars;
static inline unsigned int Hash( const char*sz ){ return HashStringCaseless(sz); } static inline unsigned int Hash( const char*sz ){ return HashStringCaseless(sz); }
public: public:
@ -2366,7 +2405,7 @@ public:
int idx = g_ConCommandsOverridable.Find( hash ); int idx = g_ConCommandsOverridable.Find( hash );
if ( idx == g_ConCommandsOverridable.InvalidIndex() ) if ( idx == g_ConCommandsOverridable.InvalidIndex() )
return false; return false;
return g_ConCommandsOverridable[idx]; return true;
} }
inline void AddBlockedConVar( const char *name ) inline void AddBlockedConVar( const char *name )
@ -2379,7 +2418,7 @@ public:
int idx = g_ConVarsBlocked.Find( Hash(name) ); int idx = g_ConVarsBlocked.Find( Hash(name) );
if ( idx == g_ConVarsBlocked.InvalidIndex() ) if ( idx == g_ConVarsBlocked.InvalidIndex() )
return false; return false;
return g_ConVarsBlocked[idx]; return true;
} }
public: public:
@ -2387,6 +2426,7 @@ public:
void SetCompletionCallback( const char *name, HSCRIPT fn ); void SetCompletionCallback( const char *name, HSCRIPT fn );
void UnregisterCommand( const char *name ); void UnregisterCommand( const char *name );
void RegisterConvar( const char *name, const char *pDefaultValue, const char *helpString, int flags ); void RegisterConvar( const char *name, const char *pDefaultValue, const char *helpString, int flags );
void SetChangeCallback( const char *name, HSCRIPT fn );
HSCRIPT GetCommandClient() HSCRIPT GetCommandClient()
{ {
@ -2495,18 +2535,14 @@ public:
} g_ScriptConvarAccessor; } g_ScriptConvarAccessor;
CUtlMap< unsigned int, bool > CScriptConvarAccessor::g_ConVarsBlocked( DefLessFunc(unsigned int) );
CUtlMap< unsigned int, bool > CScriptConvarAccessor::g_ConCommandsOverridable( DefLessFunc(unsigned int) );
CUtlMap< unsigned int, CScriptConCommand* > CScriptConvarAccessor::g_ScriptConCommands( DefLessFunc(unsigned int) );
CUtlMap< unsigned int, CScriptConVar* > CScriptConvarAccessor::g_ScriptConVars( DefLessFunc(unsigned int) );
void CScriptConvarAccessor::RegisterCommand( const char *name, HSCRIPT fn, const char *helpString, int flags ) void CScriptConvarAccessor::RegisterCommand( const char *name, HSCRIPT fn, const char *helpString, int flags )
{ {
unsigned int hash = Hash(name); unsigned int hash = Hash(name);
int idx = g_ScriptConCommands.Find(hash); int idx = g_ScriptConCommands.Find(hash);
if ( idx == g_ScriptConCommands.InvalidIndex() ) if ( idx == g_ScriptConCommands.InvalidIndex() )
{ {
if ( g_pCVar->FindVar(name) || ( g_pCVar->FindCommand(name) && !IsOverridable(hash) ) ) ConCommand *pLinked = NULL;
if ( g_pCVar->FindVar(name) || ( ((pLinked = g_pCVar->FindCommand(name)) != NULL) && !IsOverridable(hash) ) )
{ {
DevWarning( 1, "CScriptConvarAccessor::RegisterCommand unable to register blocked ConCommand: %s\n", name ); DevWarning( 1, "CScriptConvarAccessor::RegisterCommand unable to register blocked ConCommand: %s\n", name );
return; return;
@ -2515,14 +2551,13 @@ void CScriptConvarAccessor::RegisterCommand( const char *name, HSCRIPT fn, const
if ( !fn ) if ( !fn )
return; return;
CScriptConCommand *p = new CScriptConCommand( name, fn, helpString, flags ); CScriptConCommand *p = new CScriptConCommand( name, fn, helpString, flags, pLinked );
g_ScriptConCommands.Insert( hash, p ); g_ScriptConCommands.Insert( hash, p );
} }
else else
{ {
CScriptConCommand *pCmd = g_ScriptConCommands[idx]; CScriptConCommand *pCmd = g_ScriptConCommands[idx];
pCmd->SetCallback( fn ); pCmd->SetCallback( fn );
pCmd->m_cmd->AddFlags( flags );
//CGMsg( 1, CON_GROUP_VSCRIPT, "CScriptConvarAccessor::RegisterCommand replacing command already registered: %s\n", name ); //CGMsg( 1, CON_GROUP_VSCRIPT, "CScriptConvarAccessor::RegisterCommand replacing command already registered: %s\n", name );
} }
} }
@ -2565,11 +2600,39 @@ void CScriptConvarAccessor::RegisterConvar( const char *name, const char *pDefau
} }
else else
{ {
g_ScriptConVars[idx]->m_cvar->AddFlags( flags );
//CGMsg( 1, CON_GROUP_VSCRIPT, "CScriptConvarAccessor::RegisterConvar convar %s already registered\n", name ); //CGMsg( 1, CON_GROUP_VSCRIPT, "CScriptConvarAccessor::RegisterConvar convar %s already registered\n", name );
} }
} }
void CScriptConvarAccessor::SetChangeCallback( const char *name, HSCRIPT fn )
{
unsigned int hash = Hash(name);
int idx = g_ScriptConVars.Find(hash);
if ( idx != g_ScriptConVars.InvalidIndex() )
{
g_ScriptConVars[idx]->SetChangeCallback( fn );
}
}
void ScriptConVarCallback( IConVar *var, const char* pszOldValue, float flOldValue )
{
ConVar *cvar = (ConVar*)var;
const char *name = cvar->GetName();
unsigned int hash = CScriptConvarAccessor::Hash( name );
int idx = g_ScriptConVars.Find(hash);
if ( idx != g_ScriptConVars.InvalidIndex() )
{
Assert( g_ScriptConVars[idx]->m_hCallback );
ScriptVariant_t args[5] = { name, pszOldValue, flOldValue, cvar->GetString(), cvar->GetFloat() };
if ( g_pScriptVM->ExecuteFunction( g_ScriptConVars[idx]->m_hCallback, args, 5, NULL, NULL, true ) == SCRIPT_ERROR )
{
DevWarning( 1, "CScriptConVar: invalid change callback for '%s'\n", name );
}
}
}
bool CScriptConvarAccessor::Init() bool CScriptConvarAccessor::Init()
{ {
static bool bExecOnce = false; static bool bExecOnce = false;
@ -2622,6 +2685,8 @@ bool CScriptConvarAccessor::Init()
AddOverridable( "-voicerecord" ); AddOverridable( "-voicerecord" );
AddOverridable( "toggle_duck" ); AddOverridable( "toggle_duck" );
AddOverridable( "impulse" );
AddOverridable( "use" );
AddOverridable( "lastinv" ); AddOverridable( "lastinv" );
AddOverridable( "invnext" ); AddOverridable( "invnext" );
AddOverridable( "invprev" ); AddOverridable( "invprev" );
@ -2643,6 +2708,9 @@ bool CScriptConvarAccessor::Init()
AddOverridable( "save" ); AddOverridable( "save" );
AddOverridable( "load" ); AddOverridable( "load" );
AddOverridable( "say" );
AddOverridable( "say_team" );
AddBlockedConVar( "con_enable" ); AddBlockedConVar( "con_enable" );
AddBlockedConVar( "cl_allowdownload" ); AddBlockedConVar( "cl_allowdownload" );
@ -2655,7 +2723,8 @@ bool CScriptConvarAccessor::Init()
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarAccessor, "CConvars", SCRIPT_SINGLETON "Provides an interface to convars." ) BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarAccessor, "CConvars", SCRIPT_SINGLETON "Provides an interface to convars." )
DEFINE_SCRIPTFUNC( RegisterConvar, "register a new console variable." ) DEFINE_SCRIPTFUNC( RegisterConvar, "register a new console variable." )
DEFINE_SCRIPTFUNC( RegisterCommand, "register a console command." ) DEFINE_SCRIPTFUNC( RegisterCommand, "register a console command." )
DEFINE_SCRIPTFUNC( SetCompletionCallback, "callback is called with 3 parameters (cmdname, partial, commands), user strings must be appended to 'commands' array" ) DEFINE_SCRIPTFUNC( SetCompletionCallback, "callback is called with 3 parameters (cmd, partial, commands), user strings must be appended to 'commands' array" )
DEFINE_SCRIPTFUNC( SetChangeCallback, "callback is called with 5 parameters (var, szOldValue, flOldValue, szNewValue, flNewValue)" )
DEFINE_SCRIPTFUNC( UnregisterCommand, "unregister a console command." ) DEFINE_SCRIPTFUNC( UnregisterCommand, "unregister a console command." )
DEFINE_SCRIPTFUNC( GetCommandClient, "returns the player who issued this console command." ) DEFINE_SCRIPTFUNC( GetCommandClient, "returns the player who issued this console command." )
#ifdef GAME_DLL #ifdef GAME_DLL
@ -2692,9 +2761,6 @@ END_SCRIPTDESC();
class CEffectsScriptHelper class CEffectsScriptHelper
{ {
private:
C_RecipientFilter filter;
public: public:
void DynamicLight( int index, const Vector& origin, int r, int g, int b, int exponent, void DynamicLight( int index, const Vector& origin, int r, int g, int b, int exponent,
float radius, float die, float decay, int style = 0, int flags = 0 ) float radius, float die, float decay, int style = 0, int flags = 0 )
@ -2715,6 +2781,7 @@ public:
void Explosion( const Vector& pos, float scale, int radius, int magnitude, int flags ) void Explosion( const Vector& pos, float scale, int radius, int magnitude, int flags )
{ {
C_RecipientFilter filter;
filter.AddAllPlayers(); filter.AddAllPlayers();
// framerate, modelindex, normal and materialtype are unused // framerate, modelindex, normal and materialtype are unused
// radius for ragdolls // radius for ragdolls
@ -2824,7 +2891,150 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CEffectsScriptHelper, "CEffects", SCRIPT_SINGLETON
DEFINE_SCRIPTFUNC( Sprite, "" ) DEFINE_SCRIPTFUNC( Sprite, "" )
DEFINE_SCRIPTFUNC( ClientProjectile, "" ) DEFINE_SCRIPTFUNC( ClientProjectile, "" )
END_SCRIPTDESC(); END_SCRIPTDESC();
#endif
//=============================================================================
//=============================================================================
extern CGlowObjectManager g_GlowObjectManager;
class CScriptGlowObjectManager : public CAutoGameSystem
{
public:
CUtlVector<int> m_RegisteredObjects;
void LevelShutdownPostEntity()
{
FOR_EACH_VEC( m_RegisteredObjects, i )
g_GlowObjectManager.UnregisterGlowObject( m_RegisteredObjects[i] );
m_RegisteredObjects.Purge();
}
public:
int Register( HSCRIPT hEntity, int r, int g, int b, int a, bool bRenderWhenOccluded, bool bRenderWhenUnoccluded )
{
Vector vGlowColor;
vGlowColor.x = r * ( 1.0f / 255.0f );
vGlowColor.y = g * ( 1.0f / 255.0f );
vGlowColor.z = b * ( 1.0f / 255.0f );
float flGlowAlpha = a * ( 1.0f / 255.0f );
int idx = g_GlowObjectManager.RegisterGlowObject( ToEnt(hEntity), vGlowColor, flGlowAlpha, bRenderWhenOccluded, bRenderWhenUnoccluded, -1 );
m_RegisteredObjects.AddToTail( idx );
return idx;
}
void Unregister( int nGlowObjectHandle )
{
if ( (nGlowObjectHandle < 0) || (nGlowObjectHandle >= g_GlowObjectManager.m_GlowObjectDefinitions.Count()) )
return;
g_GlowObjectManager.UnregisterGlowObject( nGlowObjectHandle );
m_RegisteredObjects.FindAndFastRemove( nGlowObjectHandle );
}
void SetEntity( int nGlowObjectHandle, HSCRIPT hEntity )
{
g_GlowObjectManager.SetEntity( nGlowObjectHandle, ToEnt(hEntity) );
}
void SetColor( int nGlowObjectHandle, int r, int g, int b )
{
Vector vGlowColor;
vGlowColor.x = r * ( 1.0f / 255.0f );
vGlowColor.y = g * ( 1.0f / 255.0f );
vGlowColor.z = b * ( 1.0f / 255.0f );
g_GlowObjectManager.SetColor( nGlowObjectHandle, vGlowColor );
}
void SetAlpha( int nGlowObjectHandle, int a )
{
float flGlowAlpha = a * ( 1.0f / 255.0f );
g_GlowObjectManager.SetAlpha( nGlowObjectHandle, flGlowAlpha );
}
void SetRenderFlags( int nGlowObjectHandle, bool bRenderWhenOccluded, bool bRenderWhenUnoccluded )
{
g_GlowObjectManager.SetRenderFlags( nGlowObjectHandle, bRenderWhenOccluded, bRenderWhenUnoccluded );
}
} g_ScriptGlowObjectManager;
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptGlowObjectManager, "CGlowObjectManager", SCRIPT_SINGLETON "" )
DEFINE_SCRIPTFUNC( Register, "( HSCRIPT hEntity, int r, int g, int b, int a, bool bRenderWhenOccluded, bool bRenderWhenUnoccluded )" )
DEFINE_SCRIPTFUNC( Unregister, "" )
DEFINE_SCRIPTFUNC( SetEntity, "" )
DEFINE_SCRIPTFUNC( SetColor, "" )
DEFINE_SCRIPTFUNC( SetAlpha, "" )
DEFINE_SCRIPTFUNC( SetRenderFlags, "" )
END_SCRIPTDESC();
//=============================================================================
//=============================================================================
#if !defined(NO_STEAM)
class CScriptSteamAPI
{
public:
int GetSecondsSinceComputerActive()
{
if ( !steamapicontext || !steamapicontext->SteamUtils() )
return 0;
return steamapicontext->SteamUtils()->GetSecondsSinceComputerActive();
}
int GetCurrentBatteryPower()
{
if ( !steamapicontext || !steamapicontext->SteamUtils() )
return 0;
return steamapicontext->SteamUtils()->GetCurrentBatteryPower();
}
const char *GetIPCountry()
{
if ( !steamapicontext || !steamapicontext->SteamUtils() )
return NULL;
const char *get = steamapicontext->SteamUtils()->GetIPCountry();
if ( !get )
return NULL;
static char ret[3];
V_strncpy( ret, get, 3 );
return ret;
}
const char *GetCurrentGameLanguage()
{
if ( !steamapicontext || !steamapicontext->SteamApps() )
return NULL;
const char *lang = steamapicontext->SteamApps()->GetCurrentGameLanguage();
if ( !lang )
return NULL;
static char ret[16];
V_strncpy( ret, lang, sizeof(ret) );
return ret;
}
} g_ScriptSteamAPI;
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptSteamAPI, "CSteamAPI", SCRIPT_SINGLETON "" )
//DEFINE_SCRIPTFUNC( IsVACBanned, "" )
DEFINE_SCRIPTFUNC( GetSecondsSinceComputerActive, "Returns the number of seconds since the user last moved the mouse." )
DEFINE_SCRIPTFUNC( GetCurrentBatteryPower, "Return the amount of battery power left in the current system in % [0..100], 255 for being on AC power" )
//DEFINE_SCRIPTFUNC( GetIPCountry, "Returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database)" )
DEFINE_SCRIPTFUNC( GetCurrentGameLanguage, "Gets the current language that the user has set as API language code. This falls back to the Steam UI language if the user hasn't explicitly picked a language for the title." )
END_SCRIPTDESC();
#endif // !NO_STEAM
#endif // CLIENT_DLL
void RegisterScriptSingletons() void RegisterScriptSingletons()
@ -2852,6 +3062,11 @@ void RegisterScriptSingletons()
g_pScriptVM->RegisterInstance( &g_ScriptConvarAccessor, "Convars" ); g_pScriptVM->RegisterInstance( &g_ScriptConvarAccessor, "Convars" );
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
g_pScriptVM->RegisterInstance( &g_ScriptEffectsHelper, "effects" ); g_pScriptVM->RegisterInstance( &g_ScriptEffectsHelper, "effects" );
g_pScriptVM->RegisterInstance( &g_ScriptGlowObjectManager, "GlowObjectManager" );
#if !defined(NO_STEAM)
g_pScriptVM->RegisterInstance( &g_ScriptSteamAPI, "steam" );
#endif
#endif #endif
// Singletons not unique to VScript (not declared or defined here) // Singletons not unique to VScript (not declared or defined here)

View File

@ -688,7 +688,10 @@ ConVar::~ConVar( void )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ConVar::InstallChangeCallback( FnChangeCallback_t callback ) void ConVar::InstallChangeCallback( FnChangeCallback_t callback )
{ {
#ifndef MAPBASE_VSCRIPT
Assert( !m_pParent->m_fnChangeCallback || !callback ); Assert( !m_pParent->m_fnChangeCallback || !callback );
#endif
m_pParent->m_fnChangeCallback = callback; m_pParent->m_fnChangeCallback = callback;
if ( m_pParent->m_fnChangeCallback ) if ( m_pParent->m_fnChangeCallback )