vscript additions and fixes:

baseentity_shared.cpp
baseentity.cpp
c_baseentity.h
c_baseentity.cpp
c_world.h
   - Fixed critical ScriptSetContextThink bugs
   - Added C_BaseEntity::SetContextThink (ScriptSetContextThink)
   - Added C_BaseEntity::SetSize
   - Added C_BaseEntity::SetModel
   - Added C_BaseEntity::Destroy

baseentity.h
baseentity.cpp
   - Removed duplicate functions ScriptSetSize and ScriptUtilRemove

player.cpp
   - Moved player script instance registration before player_spawn event

vscript_server.cpp
   - Added CEntities::FindByClassNearestFacing

vscript_funcs_shared.cpp
   - Added GetFrameCount
   - Added IntervalPerTick

vscript_singletons.cpp
   - Better game event descriptors for CScriptGameEventListener
   - Added ::effects (CEffectsScriptHelper)
   - Added ::Convars (CScriptConvarAccessor)

vscript_shared.cpp
   - Fixed clientside entity printing in script VM

mapbase_con_groups.h
mapbase_con_groups.cpp
   - Improved performance by changing string comparisons to direct array access

vscript_bindings_base.h
vscript_bindings_base.cpp
   - Added CScriptKeyValues::SubKeysToTable

vscript_bindings_math.cpp
   - Added ::SimpleSplineRemapVal
   - Added ::SimpleSplineRemapValClamped
   - Added ::Bias
   - Added ::Gain
   - Added ::SmoothCurve
   - Added ::SmoothCurve_Tweak
   - Added ::ExponentialDecay

vscript_squirrel.nut
   - Added ::Lerp
   - Added ::FLerp
   - Added ::SimpleSpline

vscript_squirrel.cpp
   - Added Vector::_unm
   - Added Vector::Set
   - Added Vector::Add
   - Added Vector::Subtract
   - Added Vector::Multiply
   - Added Vector::Divide
   - Added Vector::DistTo
   - Added Vector::DistToSqr
   - Added Vector::IsEqualTo
   - Added Vector::WithinAABox
   - Added Vector::FromKVString
   - Changed vector print syntax
This commit is contained in:
samisalreadytaken
2021-03-06 02:04:55 +02:00
parent bd3b9c3807
commit bf182e1c5d
33 changed files with 1745 additions and 566 deletions
+1 -1
View File
@@ -1210,7 +1210,7 @@ void CAI_Expresser::SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... )
}
else
{
CGMsg( 1, CON_GROUP_CHOREO "%s", string );
CGMsg( 1, CON_GROUP_CHOREO, "%s", string );
}
UTIL_LogPrintf( string );
}
+5 -171
View File
@@ -2218,6 +2218,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC( SetModel, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelName, "GetModelName", "Returns the name of the model" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopSound, "StopSound", "Stops a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptEmitSound, "EmitSound", "Plays a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( VScriptPrecacheScriptSound, "PrecacheSoundScript", "Precache a sound for later playing." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSoundDuration, "GetSoundDuration", "Returns float duration of the sound. Takes soundname and optional actormodelname.")
@@ -2278,11 +2279,11 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC_NAMED( ScriptSetAngles, "SetAngles", "Set entity pitch, yaw, roll")
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAngles, "GetAngles", "Get entity pitch, yaw, roll as a vector")
DEFINE_SCRIPTFUNC_NAMED( ScriptSetSize, "SetSize", "" )
DEFINE_SCRIPTFUNC( SetSize, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMins, "GetBoundingMins", "Get a vector containing min bounds, centered on object")
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMaxs, "GetBoundingMaxs", "Get a vector containing max bounds, centered on object")
DEFINE_SCRIPTFUNC_NAMED( ScriptUtilRemove, "Destroy", "" )
DEFINE_SCRIPTFUNC_NAMED( Remove, "Destroy", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetOwner, "SetOwner", "" )
DEFINE_SCRIPTFUNC_NAMED( GetTeamNumber, "GetTeam", "" )
DEFINE_SCRIPTFUNC_NAMED( ChangeTeam, "SetTeam", "" )
@@ -2583,10 +2584,10 @@ void CBaseEntity::UpdateOnRemove( void )
#ifdef MAPBASE_VSCRIPT
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
HSCRIPT h = m_ScriptThinkFuncs[i].m_hfnThink;
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
if ( h ) g_pScriptVM->ReleaseScript( h );
}
m_ScriptThinkFuncs.Purge();
m_ScriptThinkFuncs.PurgeAndDeleteElements();
#endif // MAPBASE_VSCRIPT
}
}
@@ -8644,173 +8645,6 @@ void CBaseEntity::ScriptStopThinkFunction()
m_iszScriptThinkFunction = NULL_STRING;
SetContextThink( NULL, TICK_NEVER_THINK, "ScriptThink" );
}
static inline void ScriptStopContextThink( scriptthinkfunc_t *context )
{
g_pScriptVM->ReleaseScript( context->m_hfnThink );
context->m_hfnThink = NULL;
context->m_nNextThinkTick = TICK_NEVER_THINK;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptContextThink()
{
float flNextThink = FLT_MAX;
int nScheduledTick = 0;
for ( int i = m_ScriptThinkFuncs.Count(); i--; )
{
scriptthinkfunc_t *cur = &m_ScriptThinkFuncs[i];
if ( cur->m_nNextThinkTick == TICK_NEVER_THINK )
continue;
if ( cur->m_nNextThinkTick > gpGlobals->tickcount )
{
// There is more to execute, don't stop thinking if the rest are done.
// also find the shortest schedule
if ( !nScheduledTick || nScheduledTick > cur->m_nNextThinkTick )
{
nScheduledTick = cur->m_nNextThinkTick;
}
continue;
}
ScriptVariant_t varReturn;
if ( cur->m_bNoParam )
{
if ( g_pScriptVM->Call( cur->m_hfnThink, NULL, true, &varReturn ) == SCRIPT_ERROR )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
}
else
{
if ( g_pScriptVM->Call( cur->m_hfnThink, NULL, true, &varReturn, m_hScriptInstance ) == SCRIPT_ERROR )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
}
float flReturn;
if ( !varReturn.AssignTo( &flReturn ) )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
if ( flReturn < 0.0f )
{
ScriptStopContextThink(cur);
m_ScriptThinkFuncs.Remove(i);
continue;
}
// find the shortest delay
if ( flReturn < flNextThink )
{
flNextThink = flReturn;
}
cur->m_nNextThinkTick = TIME_TO_TICKS( gpGlobals->curtime + flReturn );
}
if ( flNextThink < FLT_MAX )
{
SetNextThink( gpGlobals->curtime + flNextThink, "ScriptContextThink" );
}
else if ( nScheduledTick )
{
SetNextThink( TICKS_TO_TIME( nScheduledTick ), "ScriptContextThink" );
}
else
{
SetNextThink( TICK_NEVER_THINK, "ScriptContextThink" );
}
}
// see ScriptSetThink
static bool s_bScriptContextThinkNoParam = false;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float flTime )
{
scriptthinkfunc_t th;
V_memset( &th, 0x0, sizeof(scriptthinkfunc_t) );
unsigned short hash = ( szContext && *szContext ) ? HashString( szContext ) : 0;
bool bFound = false;
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
scriptthinkfunc_t f = m_ScriptThinkFuncs[i];
if ( hash == f.m_iContextHash )
{
th = f;
m_ScriptThinkFuncs.Remove(i); // reorder
bFound = true;
break;
}
}
if ( hFunc )
{
float nextthink = gpGlobals->curtime + flTime;
th.m_bNoParam = s_bScriptContextThinkNoParam;
th.m_hfnThink = hFunc;
th.m_iContextHash = hash;
th.m_nNextThinkTick = TIME_TO_TICKS( nextthink );
m_ScriptThinkFuncs.AddToHead( th );
int nexttick = GetNextThinkTick( RegisterThinkContext( "ScriptContextThink" ) );
// sooner than next think
if ( nexttick <= 0 || nexttick > th.m_nNextThinkTick )
{
SetContextThink( &CBaseEntity::ScriptContextThink, nextthink, "ScriptContextThink" );
}
}
// null func input, think exists
else if ( bFound )
{
ScriptStopContextThink( &th );
}
}
//-----------------------------------------------------------------------------
// m_bNoParam and s_bScriptContextThinkNoParam exist only to keep backwards compatibility
// and are an alternative to this script closure:
//
// function CBaseEntity::SetThink( func, time )
// {
// SetContextThink( "", function(_){ return func() }, time )
// }
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetThink( HSCRIPT hFunc, float time )
{
s_bScriptContextThinkNoParam = true;
ScriptSetContextThink( NULL, hFunc, time );
s_bScriptContextThinkNoParam = false;
}
void CBaseEntity::ScriptStopThink()
{
ScriptSetContextThink( NULL, NULL, 0.0f );
}
#endif // MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
+5 -2
View File
@@ -341,9 +341,9 @@ struct thinkfunc_t
#ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t
{
int m_nNextThinkTick;
HSCRIPT m_hfnThink;
unsigned short m_iContextHash;
int m_nNextThinkTick;
bool m_bNoParam;
};
#endif
@@ -2003,7 +2003,7 @@ public:
void ScriptStopThink();
void ScriptContextThink();
private:
CUtlVector< scriptthinkfunc_t > m_ScriptThinkFuncs;
CUtlVector< scriptthinkfunc_t* > m_ScriptThinkFuncs;
public:
#endif
const char* GetScriptId();
@@ -2034,8 +2034,10 @@ public:
const Vector& ScriptGetAngles(void) { static Vector vec; QAngle qa = GetAbsAngles(); vec.x = qa.x; vec.y = qa.y; vec.z = qa.z; return vec; }
#endif
#ifndef MAPBASE_VSCRIPT
void ScriptSetSize(const Vector& mins, const Vector& maxs) { UTIL_SetSize(this, mins, maxs); }
void ScriptUtilRemove(void) { UTIL_Remove(this); }
#endif
void ScriptSetOwner(HSCRIPT hEntity) { SetOwnerEntity(ToEnt(hEntity)); }
void ScriptSetOrigin(const Vector& v) { Teleport(&v, NULL, NULL); }
void ScriptSetForward(const Vector& v) { QAngle angles; VectorAngles(v, angles); Teleport(NULL, &angles, NULL); }
@@ -2061,6 +2063,7 @@ public:
const char* ScriptGetModelName(void) const;
HSCRIPT ScriptGetModelKeyValues(void);
void ScriptStopSound(const char* soundname);
void ScriptEmitSound(const char* soundname);
float ScriptSoundDuration(const char* soundname, const char* actormodel);
+6 -4
View File
@@ -850,7 +850,7 @@ void CEventQueue::Dump( void )
// Purpose: adds the action into the correct spot in the priority queue, targeting entity via string name
//-----------------------------------------------------------------------------
#ifdef MAPBASE_VSCRIPT
intptr_t
int
#else
void
#endif
@@ -874,6 +874,7 @@ CEventQueue::AddEvent( const char *target, const char *targetInput, variant_t Va
AddEvent( newEvent );
#ifdef MAPBASE_VSCRIPT
Assert( sizeof(EventQueuePrioritizedEvent_t*) == sizeof(int) );
return reinterpret_cast<intptr_t>(newEvent); // POINTER_TO_INT
#endif
}
@@ -882,7 +883,7 @@ CEventQueue::AddEvent( const char *target, const char *targetInput, variant_t Va
// Purpose: adds the action into the correct spot in the priority queue, targeting entity via pointer
//-----------------------------------------------------------------------------
#ifdef MAPBASE_VSCRIPT
intptr_t
int
#else
void
#endif
@@ -906,6 +907,7 @@ CEventQueue::AddEvent( CBaseEntity *target, const char *targetInput, variant_t V
AddEvent( newEvent );
#ifdef MAPBASE_VSCRIPT
Assert( sizeof(EventQueuePrioritizedEvent_t*) == sizeof(int) );
return reinterpret_cast<intptr_t>(newEvent); // POINTER_TO_INT
#endif
}
@@ -1293,7 +1295,7 @@ void CEventQueue::CancelEventsByInput( CBaseEntity *pTarget, const char *szInput
}
}
bool CEventQueue::RemoveEvent( intptr_t event )
bool CEventQueue::RemoveEvent( int event )
{
EventQueuePrioritizedEvent_t *pe = reinterpret_cast<EventQueuePrioritizedEvent_t*>(event); // INT_TO_POINTER
@@ -1310,7 +1312,7 @@ bool CEventQueue::RemoveEvent( intptr_t event )
return false;
}
float CEventQueue::GetTimeLeft( intptr_t event )
float CEventQueue::GetTimeLeft( int event )
{
EventQueuePrioritizedEvent_t *pe = reinterpret_cast<EventQueuePrioritizedEvent_t*>(event); // INT_TO_POINTER
+4 -4
View File
@@ -41,8 +41,8 @@ class CEventQueue
public:
// pushes an event into the queue, targeting a string name (m_iName), or directly by a pointer
#ifdef MAPBASE_VSCRIPT
intptr_t AddEvent( const char *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
intptr_t AddEvent( CBaseEntity *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
int AddEvent( const char *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
int AddEvent( CBaseEntity *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
#else
void AddEvent( const char *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
void AddEvent( CBaseEntity *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 );
@@ -73,8 +73,8 @@ public:
#ifdef MAPBASE_VSCRIPT
void CancelEventsByInput( CBaseEntity *pTarget, const char *szInput );
bool RemoveEvent( intptr_t event );
float GetTimeLeft( intptr_t event );
bool RemoveEvent( int event );
float GetTimeLeft( int event );
#endif // MAPBASE_VSCRIPT
private:
+7 -7
View File
@@ -526,8 +526,8 @@ BEGIN_ENT_SCRIPTDESC( CBasePlayer, CBaseCombatCharacter, "The player entity." )
DEFINE_SCRIPTFUNC( GetButtonForced, "Gets the player's currently forced buttons." )
DEFINE_SCRIPTFUNC( GetFOV, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFOVOwner, "GetFOVOwner", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetFOV, "SetFOV", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFOVOwner, "GetFOVOwner", "Gets current view owner." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetFOV, "SetFOV", "Sets player FOV regardless of view owner." )
DEFINE_SCRIPTFUNC( ViewPunch, "Punches the player's view with the specified vector." )
DEFINE_SCRIPTFUNC( SetMuzzleFlashTime, "Sets the player's muzzle flash time for AI." )
@@ -5251,6 +5251,11 @@ void CBasePlayer::Spawn( void )
m_vecSmoothedVelocity = vec3_origin;
InitVCollision( GetAbsOrigin(), GetAbsVelocity() );
if ( !g_pGameRules->IsMultiplayer() && g_pScriptVM )
{
g_pScriptVM->SetValue( "player", GetScriptInstance() );
}
#if !defined( TF_DLL )
IGameEvent *event = gameeventmanager->CreateEvent( "player_spawn" );
@@ -5275,11 +5280,6 @@ void CBasePlayer::Spawn( void )
UpdateLastKnownArea();
m_weaponFiredTimer.Invalidate();
if ( !g_pGameRules->IsMultiplayer() && g_pScriptVM )
{
g_pScriptVM->SetValue( "player", GetScriptInstance() );
}
}
void CBasePlayer::Activate( void )
+10 -13
View File
@@ -110,6 +110,11 @@ public:
{
return ToHScript( gEntList.FindEntityByClassnameWithin( ToEnt( hStartEntity ), szName, vecMins, vecMaxs ) );
}
HSCRIPT FindByClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, const char *classname )
{
return ToHScript( gEntList.FindEntityClassNearestFacing( origin, facing, threshold, const_cast<char*>(classname) ) );
}
#endif
private:
} g_ScriptEntityIterator;
@@ -132,6 +137,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptEntityIterator, "CEntities", SCRIPT_SINGLETO
DEFINE_SCRIPTFUNC( FindByClassnameWithin, "Find entities by class name within a radius. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC( FindByClassnameWithinBox, "Find entities by class name within an AABB. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
DEFINE_SCRIPTFUNC( FindByClassNearestFacing, "Find the nearest entity along the facing direction from the given origin within the angular threshold with the given classname." )
#endif
END_SCRIPTDESC();
@@ -265,11 +271,6 @@ static int MaxPlayers()
return gpGlobals->maxClients;
}
static float IntervalPerTick()
{
return gpGlobals->interval_per_tick;
}
static int GetLoadType()
{
return gpGlobals->eLoadType;
@@ -328,7 +329,11 @@ static void DoEntFire( const char *pszTarget, const char *pszAction, const char
// ent_fire point_servercommand command "rcon_password mynewpassword"
if ( gpGlobals->maxClients > 1 && V_stricmp( target, "point_servercommand" ) == 0 )
{
#ifdef MAPBASE_VSCRIPT
return 0;
#else
return;
#endif
}
if ( *pszAction )
@@ -447,12 +452,6 @@ static float GetEntityIOEventTimeLeft( int event )
{
return g_EventQueue.GetTimeLeft(event);
}
// vscript_server.nut adds this to the base CConvars class
static const char *ScriptGetClientConvarValue( const char *pszConVar, int entindex )
{
return engine->GetClientConVarValue( entindex, pszConVar );
}
#endif // MAPBASE_VSCRIPT
bool VScriptServerInit()
@@ -537,7 +536,6 @@ bool VScriptServerInit()
#ifdef MAPBASE_VSCRIPT
ScriptRegisterFunction( g_pScriptVM, SendToConsoleServer, "Send a string to the server console as a command" );
ScriptRegisterFunction( g_pScriptVM, MaxPlayers, "Get the maximum number of players allowed on this server" );
ScriptRegisterFunction( g_pScriptVM, IntervalPerTick, "Get the interval used between each tick" );
ScriptRegisterFunction( g_pScriptVM, GetLoadType, "Get the way the current game was loaded (corresponds to the MapLoad enum)" );
ScriptRegisterFunction( g_pScriptVM, DoEntFire, SCRIPT_ALIAS( "EntFire", "Generate an entity i/o event" ) );
ScriptRegisterFunction( g_pScriptVM, DoEntFireByInstanceHandle, SCRIPT_ALIAS( "EntFireByHandle", "Generate an entity i/o event. First parameter is an entity instance." ) );
@@ -545,7 +543,6 @@ bool VScriptServerInit()
ScriptRegisterFunction( g_pScriptVM, CancelEntityIOEvent, "Remove entity I/O event." );
ScriptRegisterFunction( g_pScriptVM, GetEntityIOEventTimeLeft, "Get time left on entity I/O event." );
ScriptRegisterFunction( g_pScriptVM, ScriptGetClientConvarValue, SCRIPT_HIDE );
#else
ScriptRegisterFunction( g_pScriptVM, DoEntFire, SCRIPT_ALIAS( "EntFire", "Generate and entity i/o event" ) );
ScriptRegisterFunctionNamed( g_pScriptVM, DoEntFireByInstanceHandle, "EntFireByHandle", "Generate and entity i/o event. First parameter is an entity instance." );
+7 -14
View File
@@ -5,15 +5,14 @@ static char g_Script_vscript_server[] = R"vscript(
//
//=============================================================================
local DoEntFire = ::DoEntFire
local DoEntFireByInstanceHandle = ::DoEntFireByInstanceHandle
local DoDispatchParticleEffect = ::DoDispatchParticleEffect
local DoUniqueString = ::DoUniqueString
local ScriptGetClientConvarValue = ::ScriptGetClientConvarValue
local DoEntFire = DoEntFire
local DoEntFireByInstanceHandle = DoEntFireByInstanceHandle
local DoDispatchParticleEffect = DoDispatchParticleEffect
local DoUniqueString = DoUniqueString
function UniqueString( string = "" )
{
return DoUniqueString( string.tostring() );
return DoUniqueString( "" + string );
}
function EntFire( target, action, value = null, delay = 0.0, activator = null, caller = null )
@@ -36,7 +35,7 @@ function EntFire( target, action, value = null, delay = 0.0, activator = null, c
}
}
return DoEntFire( target.tostring(), action.tostring(), value.tostring(), delay, activator, caller );
return DoEntFire( "" + target, "" + action, "" + value, delay, activator, caller );
}
function EntFireByHandle( target, action, value = null, delay = 0.0, activator = null, caller = null )
@@ -59,7 +58,7 @@ function EntFireByHandle( target, action, value = null, delay = 0.0, activator =
}
}
return DoEntFireByInstanceHandle( target, action.tostring(), value.tostring(), delay, activator, caller );
return DoEntFireByInstanceHandle( target, "" + action, "" + value, delay, activator, caller );
}
function DispatchParticleEffect( particleName, origin, angles, entity = null )
@@ -67,12 +66,6 @@ function DispatchParticleEffect( particleName, origin, angles, entity = null )
DoDispatchParticleEffect( particleName, origin, angles, entity );
}
// CConvars is declared within the library
function CConvars::GetClientConvarValue(cvar,idx)
{
return ScriptGetClientConvarValue(cvar,idx);
}
__Documentation.RegisterHelp( "CConvars::GetClientConvarValue", "CConvars::GetClientConvarValue(string, int)", "Returns the convar value for the entindex as a string. Only works with client convars with the FCVAR_USERINFO flag." );
function __ReplaceClosures( script, scope )