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 01:11:43 +02:00
parent bd3b9c3807
commit bf182e1c5d
33 changed files with 1745 additions and 566 deletions

View File

@ -451,6 +451,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelName, "GetModelName", "Returns the name of the model" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopSound, "StopSound", "Stops a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptEmitSound, "EmitSound", "Plays a sound from this entity." )
DEFINE_SCRIPTFUNC_NAMED( VScriptPrecacheScriptSound, "PrecacheSoundScript", "Precache a sound for later playing." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSoundDuration, "GetSoundDuration", "Returns float duration of the sound. Takes soundname and optional actormodelname." )
@ -472,6 +473,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( GetAbsAngles, "GetAngles", "Get entity pitch, yaw, roll as a vector" )
DEFINE_SCRIPTFUNC_NAMED( SetAbsAngles, "SetAngles", "Set entity pitch, yaw, roll" )
DEFINE_SCRIPTFUNC( SetSize, "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMins, "GetBoundingMins", "Get a vector containing min bounds, centered on object" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetBoundingMaxs, "GetBoundingMaxs", "Get a vector containing max bounds, centered on object" )
@ -541,7 +543,13 @@ BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities
DEFINE_SCRIPTFUNC_NAMED( IsBaseCombatWeapon, "IsWeapon", "Returns true if this entity is a weapon." )
DEFINE_SCRIPTFUNC( IsWorld, "Returns true if this entity is the world." )
DEFINE_SCRIPTFUNC( SetModel, "Set client-only entity model" )
//DEFINE_SCRIPTFUNC_NAMED( ScriptInitializeAsClientEntity, "InitializeAsClientEntity", "" )
DEFINE_SCRIPTFUNC_NAMED( Remove, "Destroy", "Remove clientside entity" )
DEFINE_SCRIPTFUNC_NAMED( GetEntityIndex, "entindex", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
#endif
END_SCRIPTDESC();
@ -1333,6 +1341,15 @@ void C_BaseEntity::Term()
{
g_pScriptVM->RemoveInstance( m_hScriptInstance );
m_hScriptInstance = NULL;
#ifdef MAPBASE_VSCRIPT
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
HSCRIPT h = m_ScriptThinkFuncs[i]->m_hfnThink;
if ( h ) g_pScriptVM->ReleaseScript( h );
}
m_ScriptThinkFuncs.PurgeAndDeleteElements();
#endif
}
}

View File

@ -161,6 +161,16 @@ struct thinkfunc_t
int m_nLastThinkTick;
};
#ifdef MAPBASE_VSCRIPT
struct scriptthinkfunc_t
{
int m_nNextThinkTick;
HSCRIPT m_hfnThink;
unsigned short m_iContextHash;
bool m_bNoParam;
};
#endif
#define CREATE_PREDICTED_ENTITY( className ) \
C_BaseEntity::CreatePredictedEntityByName( className, __FILE__, __LINE__ );
@ -1173,6 +1183,7 @@ public:
#ifdef MAPBASE_VSCRIPT
const char* ScriptGetModelName( void ) const { return STRING(GetModelName()); }
void ScriptStopSound(const char* soundname);
void ScriptEmitSound(const char* soundname);
float ScriptSoundDuration(const char* soundname, const char* actormodel);
@ -1518,6 +1529,15 @@ protected:
CUtlVector< thinkfunc_t > m_aThinkFunctions;
int m_iCurrentThinkContext;
#ifdef MAPBASE_VSCRIPT
public:
void ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float time );
void ScriptContextThink();
private:
CUtlVector< scriptthinkfunc_t* > m_ScriptThinkFuncs;
public:
#endif
// Object eye position
Vector m_vecViewOffset;

View File

@ -49,6 +49,8 @@ public:
#endif
#ifdef MAPBASE_VSCRIPT
void ClientThink() { ScriptContextThink(); }
// -2 = Use server language
ScriptLanguage_t GetScriptLanguage() { return (ScriptLanguage_t)(m_iScriptLanguageClient != -2 ? m_iScriptLanguageClient : m_iScriptLanguageServer); }
#endif

View File

@ -461,6 +461,11 @@ bool DoIncludeScript( const char *pszScript, HSCRIPT hScope )
}
#ifdef MAPBASE_VSCRIPT
static float FrameTime()
{
return gpGlobals->frametime;
}
static bool Con_IsVisible()
{
return engine->Con_IsVisible();
@ -585,6 +590,7 @@ bool VScriptClientInit()
ScriptRegisterFunction( g_pScriptVM, DoUniqueString, SCRIPT_ALIAS( "UniqueString", "Generate a string guaranteed to be unique across the life of the script VM, with an optional root string." ) );
ScriptRegisterFunction( g_pScriptVM, DoIncludeScript, "Execute a script (internal)" );
#ifdef MAPBASE_VSCRIPT
ScriptRegisterFunction( g_pScriptVM, FrameTime, "Get the time spent on the client in the last frame" );
ScriptRegisterFunction( g_pScriptVM, Con_IsVisible, "Returns true if the console is visible" );
ScriptRegisterFunction( g_pScriptVM, ScreenWidth, "Width of the screen in pixels" );
ScriptRegisterFunction( g_pScriptVM, ScreenHeight, "Height of the screen in pixels" );

View File

@ -5,18 +5,26 @@ static char g_Script_vscript_client[] = R"vscript(
//
//=============================================================================
local DoUniqueString = DoUniqueString
local DoDispatchParticleEffect = DoDispatchParticleEffect
function UniqueString( string = "" )
{
return DoUniqueString( string.tostring() );
return DoUniqueString( "" + string );
}
function IncludeScript( name, scope = null )
{
if ( scope == null )
if ( !scope )
{
scope = this;
}
return ::DoIncludeScript( name, scope );
}
function DispatchParticleEffect( particleName, origin, angles, entity = null )
{
DoDispatchParticleEffect( particleName, origin, angles, entity );
}
)vscript";

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

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

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

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

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:

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 )

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

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 )

View File

@ -1226,6 +1226,11 @@ void CBaseEntity::ScriptEmitSound( const char *soundname )
EmitSound( soundname );
}
void CBaseEntity::ScriptStopSound( const char *soundname )
{
StopSound( soundname );
}
float CBaseEntity::ScriptSoundDuration( const char *soundname, const char *actormodel )
{
float duration = CBaseEntity::GetSoundDuration( soundname, actormodel );

View File

@ -2712,4 +2712,296 @@ HSCRIPT CBaseEntity::ScriptGetPhysicsObject( void )
else
return NULL;
}
static inline void ScriptStopContextThink( scriptthinkfunc_t *context )
{
Assert( context->m_hfnThink );
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 = 0; 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.
// Find the shortest schedule
if ( !nScheduledTick || nScheduledTick > cur->m_nNextThinkTick )
{
nScheduledTick = cur->m_nNextThinkTick;
}
continue;
}
#ifdef _DEBUG
// going to run the script func
cur->m_nNextThinkTick = 0;
#endif
ScriptVariant_t varReturn;
if ( !cur->m_bNoParam )
{
ScriptVariant_t arg = m_hScriptInstance;
if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, &arg, 1, &varReturn, NULL, true ) == SCRIPT_ERROR )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
}
else
{
if ( g_pScriptVM->ExecuteFunction( cur->m_hfnThink, NULL, 0, &varReturn, NULL, true ) == SCRIPT_ERROR )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
}
if ( cur->m_nNextThinkTick == TICK_NEVER_THINK )
{
// stopped from script while thinking
continue;
}
float flReturn;
if ( !varReturn.AssignTo( &flReturn ) )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
if ( flReturn < 0.0f )
{
cur->m_nNextThinkTick = TICK_NEVER_THINK;
continue;
}
if ( flReturn < flNextThink )
{
flNextThink = flReturn;
}
cur->m_nNextThinkTick = TIME_TO_TICKS( gpGlobals->curtime + flReturn );
}
// deferred safe removal
for ( int i = 0; i < m_ScriptThinkFuncs.Count(); )
{
if ( m_ScriptThinkFuncs[i]->m_nNextThinkTick == TICK_NEVER_THINK )
{
ScriptStopContextThink( m_ScriptThinkFuncs[i] );
delete m_ScriptThinkFuncs[i];
m_ScriptThinkFuncs.Remove(i);
}
else ++i;
}
bool bNewNext = 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 ( nScheduledTick )
{
float flScheduledTime = TICKS_TO_TIME( nScheduledTick );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, flScheduledTime );
}
else
{
flNextThink = flScheduledTime;
}
}
else
{
if ( bNewNext )
{
flNextThink = gpGlobals->curtime + flNextThink;
}
else
{
#ifdef GAME_DLL
flNextThink = TICK_NEVER_THINK;
#else
flNextThink = CLIENT_THINK_NEVER;
#endif
}
}
#ifdef _DEBUG
}
else
{
// Next think was set (from script) to a sooner tick while thinking?
Assert(0);
if ( nScheduledTick )
{
int nNextSchedule = min( nScheduledTick, nNextThinkTick );
float flNextSchedule = TICKS_TO_TIME( nNextSchedule );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, flNextSchedule );
}
else
{
flNextThink = flNextSchedule;
}
}
else
{
float nextthink = TICKS_TO_TIME( nNextThinkTick );
if ( bNewNext )
{
flNextThink = min( gpGlobals->curtime + flNextThink, nextthink );
}
else
{
flNextThink = nextthink;
}
}
}
#endif
#ifdef GAME_DLL
SetNextThink( flNextThink, "ScriptContextThink" );
#else
SetNextClientThink( flNextThink );
#endif
}
// see ScriptSetThink
static bool s_bScriptContextThinkNoParam = false;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float flTime )
{
#ifdef CLIENT_DLL
// Context thinking is not yet supported on client, entities can only have 1 think function.
// C_World does not have one by default, so it is safe to set its.
if ( !IsWorld() )
{
g_pScriptVM->RaiseException("SetContextThink is only supported on C_World");
return;
}
#endif
scriptthinkfunc_t *pf = NULL;
unsigned short hash = ( szContext && *szContext ) ? HashString( szContext ) : 0;
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
scriptthinkfunc_t *f = m_ScriptThinkFuncs[i];
if ( hash == f->m_iContextHash )
{
pf = f;
break;
}
}
if ( hFunc )
{
// add new
if ( !pf )
{
pf = new scriptthinkfunc_t;
m_ScriptThinkFuncs.SetGrowSize(1);
m_ScriptThinkFuncs.AddToTail( pf );
pf->m_bNoParam = s_bScriptContextThinkNoParam;
pf->m_iContextHash = hash;
}
// update existing
else
{
#ifdef _DEBUG
if ( pf->m_nNextThinkTick == 0 )
{
Warning("Script think ('%s') was changed while it was thinking!\n", szContext);
}
#endif
g_pScriptVM->ReleaseScript( pf->m_hfnThink );
}
float nextthink = gpGlobals->curtime + flTime;
pf->m_hfnThink = hFunc;
pf->m_nNextThinkTick = TIME_TO_TICKS( nextthink );
#ifdef GAME_DLL
int nexttick = GetNextThinkTick( RegisterThinkContext( "ScriptContextThink" ) );
#else
int nexttick = GetNextThinkTick();
#endif
// sooner than next think
if ( nexttick <= 0 || nexttick > pf->m_nNextThinkTick )
{
#ifdef GAME_DLL
SetContextThink( &CBaseEntity::ScriptContextThink, nextthink, "ScriptContextThink" );
#else
SetNextClientThink( nextthink );
#endif
}
}
// null func input, think exists
else if ( pf )
{
pf->m_nNextThinkTick = TICK_NEVER_THINK;
}
}
//-----------------------------------------------------------------------------
// 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 )
// }
//-----------------------------------------------------------------------------
#ifndef CLIENT_DLL
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
#endif

View File

@ -178,7 +178,7 @@ public:
#ifdef GAME_DLL
if (g_bMapContainsCustomTalker && mapbase_flush_talker.GetBool())
{
CGMsg( 1, "Mapbase Misc.", "Mapbase: Reloading response system to flush custom talker\n" );
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "Mapbase: Reloading response system to flush custom talker\n" );
ReloadResponseSystem();
g_bMapContainsCustomTalker = false;
}
@ -188,7 +188,7 @@ public:
virtual void LevelInitPreEntity()
{
#ifdef GAME_DLL
CGMsg( 0, "Mapbase Misc.", "Mapbase system loaded\n" );
CGMsg( 0, CON_GROUP_MAPBASE_MISC, "Mapbase system loaded\n" );
#endif
// Checks gameinfo.txt for Mapbase-specific options
@ -352,11 +352,11 @@ public:
return;
}
CGMsg( 1, "Mapbase Misc.", "===== Mapbase Manifest: Loading manifest file %s =====\n", file );
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "===== Mapbase Manifest: Loading manifest file %s =====\n", file );
AddManifestFile(pKV, false);
CGMsg( 1, "Mapbase Misc.", "==============================================================================\n" );
CGMsg( 1, CON_GROUP_MAPBASE_MISC, "==============================================================================\n" );
pKV->deleteThis();
}
@ -591,7 +591,7 @@ public:
const char *scriptfile = STRING(m_target);
if ( filesystem->FileExists( scriptfile, "MOD" ) )
{
CGMsg(0, "Mapbase Misc.", "Mapbase: Adding manifest file \"%s\"\n", scriptfile);
CGMsg(0, CON_GROUP_MAPBASE_MISC, "Mapbase: Adding manifest file \"%s\"\n", scriptfile);
g_MapbaseSystem.AddManifestFile(scriptfile);
}
else

View File

@ -66,7 +66,7 @@ BEGIN_SCRIPTENUM( RenderMode, "Render modes used by Get/SetRenderMode" )
DEFINE_ENUMCONST_NAMED( kRenderTransAdd, "Additive", "" )
DEFINE_ENUMCONST_NAMED( kRenderEnvironmental, "Environmental", "" )
DEFINE_ENUMCONST_NAMED( kRenderTransAddFrameBlend, "AdditiveFractionalFrame", "" )
DEFINE_ENUMCONST_NAMED( kRenderTransAlphaAdd, "Alpha Add", "" )
DEFINE_ENUMCONST_NAMED( kRenderTransAlphaAdd, "AlphaAdd", "" )
DEFINE_ENUMCONST_NAMED( kRenderWorldGlow, "WorldSpaceGlow", "" )
DEFINE_ENUMCONST_NAMED( kRenderNone, "None", "" )

View File

@ -164,18 +164,18 @@ HSCRIPT SpawnEntityFromTable( const char *pszClassname, HSCRIPT hKV )
HSCRIPT EntIndexToHScript( int index )
{
#ifdef GAME_DLL
edict_t *e = INDEXENT(index);
if ( e && !e->IsFree() )
{
return ToHScript( GetContainingEntity( e ) );
}
edict_t *e = INDEXENT(index);
if ( e && !e->IsFree() )
{
return ToHScript( GetContainingEntity( e ) );
}
#else // CLIENT_DLL
if ( index < NUM_ENT_ENTRIES )
{
return ToHScript( CBaseEntity::Instance( index ) );
}
if ( index < NUM_ENT_ENTRIES )
{
return ToHScript( CBaseEntity::Instance( index ) );
}
#endif
return NULL;
return NULL;
}
//-----------------------------------------------------------------------------
@ -740,20 +740,29 @@ void NPrint( int pos, const char* fmt )
void NXPrint( int pos, int r, int g, int b, bool fixed, float ftime, const char* fmt )
{
static con_nprint_t *info = new con_nprint_t;
con_nprint_t info;
info->index = pos;
info->time_to_live = ftime;
info->color[0] = r / 255.f;
info->color[1] = g / 255.f;
info->color[2] = b / 255.f;
info->fixed_width_font = fixed;
info.index = pos;
info.time_to_live = ftime;
info.color[0] = r / 255.f;
info.color[1] = g / 255.f;
info.color[2] = b / 255.f;
info.fixed_width_font = fixed;
engine->Con_NXPrintf(info, fmt);
// delete info;
engine->Con_NXPrintf( &info, fmt );
}
static float IntervalPerTick()
{
return gpGlobals->interval_per_tick;
}
static int GetFrameCount()
{
return gpGlobals->framecount;
}
//=============================================================================
//=============================================================================
@ -850,6 +859,9 @@ void RegisterSharedScriptFunctions()
#endif
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsServer, "IsServer", "Returns true if the script is being run on the server." );
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptIsClient, "IsClient", "Returns true if the script is being run on the client." );
ScriptRegisterFunction( g_pScriptVM, IntervalPerTick, "Simulation tick interval" );
ScriptRegisterFunction( g_pScriptVM, GetFrameCount, "Absolute frame counter" );
//ScriptRegisterFunction( g_pScriptVM, GetTickCount, "Simulation ticks" );
RegisterScriptSingletons();
}

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
// $NoKeywords: $
//=============================================================================
#ifndef VSCRIPT_SINGLETONS
#define VSCRIPT_SINGLETONS
#ifndef VSCRIPT_SINGLETONS_H
#define VSCRIPT_SINGLETONS_H
#ifdef _WIN32
#pragma once
#endif
@ -29,21 +29,24 @@ class CNetMsgScriptHelper : public CAutoGameSystem
class CNetMsgScriptHelper
#endif
{
#ifdef CLIENT_DLL
public:
bool m_bWriteReady; // dt ready to send
#endif
private:
#ifdef GAME_DLL
CRecipientFilter m_filter;
bf_read *m_MsgIn;
CRecipientFilter m_filter;
#else
bf_read m_MsgIn;
#endif
HSCRIPT m_Hooks;
bf_write m_MsgOut;
byte m_MsgData[ PAD_NUMBER( SCRIPT_NETMSG_DATA_SIZE, 4 ) ];
HSCRIPT m_Hooks;
public:
#ifdef CLIENT_DLL
bool m_bWriteReady; // dt ready to send
CNetMsgScriptHelper() : m_Hooks(NULL), m_bWriteReady(false) {}
#else
CNetMsgScriptHelper() : m_Hooks(NULL) {}
@ -100,14 +103,14 @@ public:
void WriteShort( int iValue ); // 16 bit short
void WriteWord( int iValue ); // 16 bit unsigned short
void WriteLong( int iValue ); // 32 bit long
void WriteFloat( float flValue );
void WriteNormal( float flValue ); // 12 bit
void WriteFloat( float flValue ); // 32 bit float
void WriteNormal( float flValue ); // 12 bit (1 + NORMAL_FRACTIONAL_BITS)
void WriteAngle( float flValue ); // 8 bit unsigned char
void WriteCoord( float flValue );
void WriteVec3Coord( const Vector& rgflValue );
void WriteVec3Normal( const Vector& rgflValue ); // 27 bit ( 3 + 2 * (1 + NORMAL_FRACTIONAL_BITS) )
void WriteAngles( const QAngle& rgflValue );
void WriteString( const char *sz ); // max 512 bytes at once
void WriteString( const char *sz );
void WriteBool( bool bValue ); // 1 bit
void WriteEntity( HSCRIPT hEnt ); // 11 bit (entindex)
void WriteEHandle( HSCRIPT hEnt ); // 32 bit long

View File

@ -5,8 +5,8 @@
// $NoKeywords: $
//=============================================================================
#ifndef VSCRIPT_FUNCS_MATH
#define VSCRIPT_FUNCS_MATH
#ifndef WEAPON_CUSTOM_SCRIPTED_H
#define WEAPON_CUSTOM_SCRIPTED_H
#ifdef _WIN32
#pragma once
#endif

View File

@ -440,13 +440,17 @@ ISaveRestoreBlockHandler *GetVScriptSaveRestoreBlockHandler()
bool CBaseEntityScriptInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
{
CBaseEntity *pEntity = (CBaseEntity *)p;
#ifdef CLIENT_DLL
if ( pEntity->GetEntityName() && pEntity->GetEntityName()[0] )
#else
if ( pEntity->GetEntityName() != NULL_STRING )
#endif
{
V_snprintf( pBuf, bufSize, "([%d] %s: %s)", pEntity->entindex(), STRING(pEntity->m_iClassname), STRING( pEntity->GetEntityName() ) );
V_snprintf( pBuf, bufSize, "([%d] %s: %s)", pEntity->entindex(), pEntity->GetClassname(), STRING( pEntity->GetEntityName() ) );
}
else
{
V_snprintf( pBuf, bufSize, "([%d] %s)", pEntity->entindex(), STRING(pEntity->m_iClassname) );
V_snprintf( pBuf, bufSize, "([%d] %s)", pEntity->entindex(), pEntity->GetClassname() );
}
return true;
}

View File

@ -301,6 +301,10 @@ private:
ICommandCallback *m_pCommandCallback;
};
#ifdef MAPBASE_VSCRIPT
// Allow late modification of the completion callback.
public:
#endif
union
{
FnCommandCompletionCallback m_fnCompletionCallback;
@ -308,6 +312,9 @@ private:
};
bool m_bHasCompletionCallback : 1;
#ifdef MAPBASE_VSCRIPT
private:
#endif
bool m_bUsingNewCommandCallback : 1;
bool m_bUsingCommandCallbackInterface : 1;
};

View File

@ -17,21 +17,23 @@
//static const Color CON_COLOR_DEV_VERBOSE( 192, 128, 192, 255 );
// General
#define CON_GROUP_MAPBASE_MISC "Mapbase Misc."
#define CON_GROUP_PHYSICS "Physics"
#define CON_GROUP_MAPBASE_MISC 0 // "Mapbase Misc."
#define CON_GROUP_PHYSICS 1 // "Physics"
// Server
#define CON_GROUP_IO_SYSTEM "I/O System"
#define CON_GROUP_NPC_AI "NPC AI"
#define CON_GROUP_NPC_SCRIPTS "NPC Scripts"
#define CON_GROUP_CHOREO "Choreo"
#define CON_GROUP_IO_SYSTEM 2 // "Entity I/O"
#define CON_GROUP_NPC_AI 3 // "NPC AI"
#define CON_GROUP_NPC_SCRIPTS 4 // "NPC Scripts"
#define CON_GROUP_CHOREO 5 // "Choreo"
// VScript
#define CON_GROUP_VSCRIPT "VScript"
#define CON_GROUP_VSCRIPT_PRINT "VScript Print"
#define CON_GROUP_VSCRIPT 6 // "VScript"
#define CON_GROUP_VSCRIPT_PRINT 7 // "VScript Print"
#define CON_GROUP_MAX 8 // must always be at the end
// Mapbase console group message.
void CGMsg( int level, const char *pszGroup, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
void CGMsg( int level, int nGroup, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
#define CGWarning CGMsg

View File

@ -749,9 +749,6 @@ struct ScriptEnumDesc_t
#define DEFINE_SCRIPTHOOK_PARAM( paramName, type ) pHook->AddParameter( paramName, type );
// Define actual parameters instead of global variables
#define DEFINE_SCRIPTHOOK_REALPARAM( paramName, type )
#define END_SCRIPTHOOK() \
pDesc->m_Hooks.AddToTail(pHook); \
}
@ -944,7 +941,7 @@ public:
#endif
#ifdef MAPBASE_VSCRIPT
// virtual void CreateArray(ScriptVariant_t &arr, int size = 0) = 0;
virtual void CreateArray(ScriptVariant_t &arr, int size = 0) = 0;
virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) = 0;
#endif

View File

@ -65,46 +65,35 @@ DEFINE_CON_GROUP_CVAR( vscript_print, "80 186 255", "Messages from VScript's 'pr
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#define DEFINE_CON_GROUP(name, codename) { name, &con_group_##codename##_color }
#define DEFINE_CON_GROUP(id, name, codename) { name, &con_group_##codename##_color }
ConGroup_t g_ConGroups[] = {
ConGroup_t g_ConGroups[CON_GROUP_MAX] = {
// General
DEFINE_CON_GROUP( CON_GROUP_MAPBASE_MISC, mapbase_misc ),
DEFINE_CON_GROUP( CON_GROUP_PHYSICS, physics ),
DEFINE_CON_GROUP( CON_GROUP_MAPBASE_MISC, "Mapbase misc.", mapbase_misc ),
DEFINE_CON_GROUP( CON_GROUP_PHYSICS, "Physics", physics ),
// Server
DEFINE_CON_GROUP( CON_GROUP_IO_SYSTEM, inputoutput ),
DEFINE_CON_GROUP( CON_GROUP_NPC_AI, npc_ai ),
DEFINE_CON_GROUP( CON_GROUP_NPC_SCRIPTS, npc_scripts ),
DEFINE_CON_GROUP( CON_GROUP_CHOREO, choreo ),
DEFINE_CON_GROUP( CON_GROUP_IO_SYSTEM, "Entity IO", inputoutput ),
DEFINE_CON_GROUP( CON_GROUP_NPC_AI, "NPC AI", npc_ai ),
DEFINE_CON_GROUP( CON_GROUP_NPC_SCRIPTS, "NPC scripts", npc_scripts ),
DEFINE_CON_GROUP( CON_GROUP_CHOREO, "Choreo", choreo ),
// VScript
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT, vscript ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT_PRINT, vscript_print ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT, "VScript", vscript ),
DEFINE_CON_GROUP( CON_GROUP_VSCRIPT_PRINT, "VScript print", vscript_print ),
};
void CV_ColorChanged( IConVar *pConVar, const char *pOldString, float flOldValue )
{
for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++)
for (int i = 0; i < CON_GROUP_MAX; i++)
{
// Reset the alpha to indicate it needs to be refreshed
g_ConGroups[i]._clr[3] = 0;
}
}
ConGroup_t *FindConGroup( const char *pszGroup )
{
for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++)
{
if (V_strcmp(pszGroup, g_ConGroups[i].pszName) == 0)
return &g_ConGroups[i];
}
return NULL;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@ -113,7 +102,7 @@ ConVar con_group_include_name( "con_group_include_name", "0", FCVAR_NONE, "Inclu
CON_COMMAND( con_group_list, "Prints a list of all console groups." )
{
Msg( "============================================================\n" );
for (int i = 0; i < ARRAYSIZE( g_ConGroups ); i++)
for (int i = 0; i < CON_GROUP_MAX; i++)
{
Msg( " # " );
ConColorMsg( g_ConGroups[i].GetColor(), "%s", g_ConGroups[i].pszName );
@ -146,7 +135,7 @@ CON_COMMAND( con_group_toggle, "Toggles a console group." )
}
*/
void CGMsg( int level, const char *pszGroup, const tchar* pMsg, ... )
void CGMsg( int level, int nGroup, const tchar* pMsg, ... )
{
// Return early if we're not at this level
if (!IsSpewActive("developer", level))
@ -158,22 +147,21 @@ void CGMsg( int level, const char *pszGroup, const tchar* pMsg, ... )
Q_vsnprintf( string, sizeof(string), pMsg, argptr );
va_end( argptr );
ConGroup_t *pGroup = FindConGroup( pszGroup );
if (pGroup)
Assert( nGroup >= 0 );
Assert( nGroup < CON_GROUP_MAX );
ConGroup_t *pGroup = &g_ConGroups[nGroup];
/*if (pGroup->bDisabled)
{
/*if (pGroup->bDisabled)
{
// Do nothing
}
else*/ if (con_group_include_name.GetBool())
{
ConColorMsg( level, pGroup->GetColor(), "[%s] %s", pGroup->pszName, string );
}
else
{
ConColorMsg( level, pGroup->GetColor(), string );
}
// Do nothing
}
else*/ if (con_group_include_name.GetBool())
{
ConColorMsg(level, pGroup->GetColor(), "[%s] %s", pGroup->pszName, string);
}
else
DevMsg( level, string );
{
ConColorMsg(level, pGroup->GetColor(), string);
}
}

View File

@ -83,6 +83,7 @@ static HSCRIPT VMFKV_LoadFromFile( const char *szFile )
KeyValues *pKV = new KeyValues( szFile );
if ( !pKV->LoadFromFile( g_pFullFileSystem, pszFullName, NULL ) )
{
pKV->deleteThis();
return NULL;
}

View File

@ -11,6 +11,7 @@
#include "vbsp.h"
#include "map.h"
#include "fgdlib/fgdlib.h"
#include "convar.h"
#include "vscript_vbsp.h"
#include "vscript_vbsp.nut"
@ -183,6 +184,28 @@ BEGIN_SCRIPTDESC_ROOT( CMapFile, "Map file" )
END_SCRIPTDESC();
static float cvar_getf( const char* sz )
{
ConVarRef cvar(sz);
if ( cvar.IsFlagSet( FCVAR_SERVER_CANNOT_QUERY ) )
return NULL;
return cvar.GetFloat();
}
static bool cvar_setf( const char* sz, float val )
{
ConVarRef cvar(sz);
if ( !cvar.IsValid() )
return false;
if ( cvar.IsFlagSet( FCVAR_SERVER_CANNOT_QUERY ) )
return false;
cvar.SetValue(val);
return true;
}
static const char *GetSource()
{
return source;
@ -244,6 +267,9 @@ bool VScriptVBSPInit()
{
Log( "VSCRIPT VBSP: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() );
ScriptRegisterFunction( g_pScriptVM, cvar_getf, "Gets the value of the given cvar, as a float." );
ScriptRegisterFunction( g_pScriptVM, cvar_setf, "Sets the value of the given cvar, as a float." );
ScriptRegisterFunction( g_pScriptVM, GetSource, "Gets the base directory of the first map loaded." );
ScriptRegisterFunction( g_pScriptVM, GetMapBase, "Gets the base name of the first map loaded." );
ScriptRegisterFunction( g_pScriptVM, GetMainMap, "Gets the first map loaded." );

View File

@ -50,100 +50,6 @@ static void ScriptColorPrintL( int r, int g, int b, const char *pszMsg )
ConColorMsg( clr, "%s\n", pszMsg );
}
//=============================================================================
//
// Convar Lookup
//
//=============================================================================
class CScriptConvarLookup
{
public:
float GetFloat( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetFloat();
}
int GetInt( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetInt();
}
bool GetBool( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetBool();
}
const char *GetStr( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetString();
}
const char *GetDefaultValue( const char *pszConVar )
{
ConVarRef cvar( pszConVar );
return cvar.GetDefault();
}
bool IsFlagSet( const char *pszConVar, int nFlags )
{
ConVarRef cvar( pszConVar );
return cvar.IsFlagSet( nFlags );
}
void SetFloat( const char *pszConVar, float value )
{
SetValue( pszConVar, value );
}
void SetInt( const char *pszConVar, int value )
{
SetValue( pszConVar, value );
}
void SetBool( const char *pszConVar, bool value )
{
SetValue( pszConVar, value );
}
void SetStr( const char *pszConVar, const char *value )
{
SetValue( pszConVar, value );
}
template <typename T>
void SetValue( const char *pszConVar, T value )
{
ConVarRef cvar( pszConVar );
if (!cvar.IsValid())
return;
// FCVAR_NOT_CONNECTED can be used to protect specific convars from nefarious interference
if (cvar.IsFlagSet(FCVAR_NOT_CONNECTED))
return;
cvar.SetValue( value );
}
private:
} g_ScriptConvarLookup;
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptConvarLookup, "CConvars", SCRIPT_SINGLETON "Provides an interface for getting and setting convars." )
DEFINE_SCRIPTFUNC( GetFloat, "Returns the convar as a float. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetInt, "Returns the convar as an int. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetBool, "Returns the convar as a bool. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetStr, "Returns the convar as a string. May return null if no such convar." )
DEFINE_SCRIPTFUNC( GetDefaultValue, "Returns the convar's default value as a string. May return null if no such convar." )
DEFINE_SCRIPTFUNC( IsFlagSet, "Returns the convar's flags. May return null if no such convar." )
DEFINE_SCRIPTFUNC( SetFloat, "Sets the value of the convar as a float." )
DEFINE_SCRIPTFUNC( SetInt, "Sets the value of the convar as an int." )
DEFINE_SCRIPTFUNC( SetBool, "Sets the value of the convar as a bool." )
DEFINE_SCRIPTFUNC( SetStr, "Sets the value of the convar as a string." )
END_SCRIPTDESC();
//=============================================================================
//
@ -203,6 +109,7 @@ BEGIN_SCRIPTDESC_ROOT( CScriptKeyValues, "Wrapper class over KeyValues instance"
DEFINE_SCRIPTFUNC_NAMED( ScriptReleaseKeyValues, "ReleaseKeyValues", "Given a root KeyValues object, release its contents" );
DEFINE_SCRIPTFUNC( TableToSubKeys, "Converts a script table to KeyValues." );
DEFINE_SCRIPTFUNC( SubKeysToTable, "Converts to script table." );
DEFINE_SCRIPTFUNC_NAMED( ScriptFindOrCreateKey, "FindOrCreateKey", "Given a KeyValues object and a key name, find or create a KeyValues object associated with the key name" );
@ -319,6 +226,19 @@ void CScriptKeyValues::TableToSubKeys( HSCRIPT hTable )
}
}
void CScriptKeyValues::SubKeysToTable( HSCRIPT hTable )
{
FOR_EACH_SUBKEY( m_pKeyValues, key )
{
switch ( key->GetDataType() )
{
case KeyValues::TYPE_STRING: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetString() ); break;
case KeyValues::TYPE_INT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetInt() ); break;
case KeyValues::TYPE_FLOAT: g_pScriptVM->SetValue( hTable, key->GetName(), key->GetFloat() ); break;
}
}
}
HSCRIPT CScriptKeyValues::ScriptFindOrCreateKey( const char *pszName )
{
KeyValues *pKeyValues = m_pKeyValues->FindKey(pszName, true);
@ -529,7 +449,6 @@ void RegisterBaseBindings( IScriptVM *pVM )
//-----------------------------------------------------------------------------
pVM->RegisterInstance( &g_ScriptConvarLookup, "Convars" );
pVM->RegisterInstance( &g_ScriptGlobalSys, "GlobalSys" );
//-----------------------------------------------------------------------------

View File

@ -35,6 +35,7 @@ public:
// Functions below are new with Mapbase
void TableToSubKeys( HSCRIPT hTable );
void SubKeysToTable( HSCRIPT hTable );
HSCRIPT ScriptFindOrCreateKey( const char *pszName );

View File

@ -181,7 +181,7 @@ END_SCRIPTDESC();
bool CScriptQuaternionInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
{
Quaternion *pQuat = ((Quaternion *)p);
V_snprintf( pBuf, bufSize, "(quaternion: (%f, %f, %f, %f))", pQuat->x, pQuat->y, pQuat->z, pQuat->w );
V_snprintf( pBuf, bufSize, "(Quaternion %p [%f %f %f %f])", (void*)pQuat, pQuat->x, pQuat->y, pQuat->z, pQuat->w );
return true;
}
@ -390,6 +390,11 @@ float ScriptCalcDistanceToLineSegment( const Vector &point, const Vector &vLineA
return CalcDistanceToLineSegment( point, vLineA, vLineB );
}
inline float ScriptExponentialDecay( float decayTo, float decayTime, float dt )
{
return ExponentialDecay( decayTo, decayTime, dt );
}
void RegisterMathBaseBindings( IScriptVM *pVM )
{
ScriptRegisterConstantNamed( pVM, ((float)(180.f / M_PI_F)), "RAD2DEG", "" );
@ -453,4 +458,12 @@ void RegisterMathBaseBindings( IScriptVM *pVM )
ScriptRegisterFunctionNamed( pVM, ScriptCalcClosestPointOnLine, "CalcClosestPointOnLine", "Returns the closest point on a line." );
ScriptRegisterFunctionNamed( pVM, ScriptCalcDistanceToLineSegment, "CalcDistanceToLineSegment", "Returns the distance to a line segment." );
ScriptRegisterFunctionNamed( pVM, ScriptCalcClosestPointOnLineSegment, "CalcClosestPointOnLineSegment", "Returns the closest point on a line segment." );
ScriptRegisterFunction( pVM, SimpleSplineRemapVal, "remaps a value in [startInterval, startInterval+rangeInterval] from linear to spline using SimpleSpline" );
ScriptRegisterFunction( pVM, SimpleSplineRemapValClamped, "remaps a value in [startInterval, startInterval+rangeInterval] from linear to spline using SimpleSpline" );
ScriptRegisterFunction( pVM, Bias, "The curve is biased towards 0 or 1 based on biasAmt, which is between 0 and 1." );
ScriptRegisterFunction( pVM, Gain, "Gain is similar to Bias, but biasAmt biases towards or away from 0.5." );
ScriptRegisterFunction( pVM, SmoothCurve, "SmoothCurve maps a 0-1 value into another 0-1 value based on a cosine wave" );
ScriptRegisterFunction( pVM, SmoothCurve_Tweak, "SmoothCurve peaks at flPeakPos, flPeakSharpness controls the sharpness of the peak" );
ScriptRegisterFunctionNamed( pVM, ScriptExponentialDecay, "ExponentialDecay", "decayTo is factor the value should decay to in decayTime" );
}

View File

@ -214,7 +214,7 @@ public:
virtual bool ClearValue(HSCRIPT hScope, const char* pszKey) override;
virtual bool ClearValue( HSCRIPT hScope, ScriptVariant_t pKey ) override;
// virtual void CreateArray(ScriptVariant_t &arr, int size = 0) override;
virtual void CreateArray(ScriptVariant_t &arr, int size = 0) override;
virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) override;
//----------------------------------------------------------------------------
@ -270,7 +270,7 @@ namespace SQVector
return 0;
}
SQInteger Get(HSQUIRRELVM vm)
SQInteger _get(HSQUIRRELVM vm)
{
const char* key = nullptr;
sq_getstring(vm, 2, &key);
@ -296,7 +296,7 @@ namespace SQVector
return 1;
}
SQInteger Set(HSQUIRRELVM vm)
SQInteger _set(HSQUIRRELVM vm)
{
const char* key = nullptr;
sq_getstring(vm, 2, &key);
@ -328,7 +328,7 @@ namespace SQVector
return 0;
}
SQInteger Add(HSQUIRRELVM vm)
SQInteger _add(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
@ -350,7 +350,7 @@ namespace SQVector
return 1;
}
SQInteger Sub(HSQUIRRELVM vm)
SQInteger _sub(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
@ -372,23 +372,20 @@ namespace SQVector
return 1;
}
SQInteger Multiply(HSQUIRRELVM vm)
SQInteger _multiply(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQObjectType paramType = sq_gettype(vm, 2);
float s = 0.0;
Vector* v2 = nullptr;
if ((paramType & SQOBJECT_NUMERIC) &&
SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
if ( SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -399,8 +396,7 @@ namespace SQVector
return 1;
}
else if (paramType == OT_INSTANCE &&
SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
else if ( SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -413,27 +409,24 @@ namespace SQVector
}
else
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
}
SQInteger Divide(HSQUIRRELVM vm)
SQInteger _divide(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQObjectType paramType = sq_gettype(vm, 2);
float s = 0.0;
Vector* v2 = nullptr;
if ((paramType & SQOBJECT_NUMERIC) &&
SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
if ( SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -444,8 +437,7 @@ namespace SQVector
return 1;
}
else if (paramType == OT_INSTANCE &&
SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
else if ( SQ_SUCCEEDED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
@ -458,10 +450,221 @@ namespace SQVector
}
else
{
return sq_throwerror(vm, "Expected (Vector, float) or (Vector, Vector)");
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
}
SQInteger _unm(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 1 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector)");
}
v1->Negate();
return 1;
}
// multi purpose - copy from input vector, or init with 3 float input
SQInteger Set(HSQUIRRELVM vm)
{
SQInteger top = sq_gettop(vm);
Vector* v1 = nullptr;
if ( top < 2 || SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) )
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
Vector* v2 = nullptr;
if ( SQ_SUCCEEDED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
if ( top != 2 )
return sq_throwerror(vm, "Expected (Vector, Vector)");
VectorCopy( *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
float x, y, z;
if ( top == 4 &&
SQ_SUCCEEDED(sq_getfloat(vm, 2, &x)) &&
SQ_SUCCEEDED(sq_getfloat(vm, 3, &y)) &&
SQ_SUCCEEDED(sq_getfloat(vm, 4, &z)) )
{
v1->Init( x, y, z );
sq_pop( vm, 3 );
return 1;
}
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
SQInteger Add(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
VectorAdd( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
SQInteger Subtract(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
VectorSubtract( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
SQInteger Multiply(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
Vector* v2 = nullptr;
if ( SQ_SUCCEEDED(sq_getinstanceup( vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR )) )
{
VectorMultiply( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
float flInput;
if ( SQ_SUCCEEDED(sq_getfloat( vm, 2, &flInput )) )
{
VectorMultiply( *v1, flInput, *v1 );
sq_remove( vm, -1 );
return 1;
}
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQInteger Divide(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
Vector* v2 = nullptr;
if ( SQ_SUCCEEDED(sq_getinstanceup( vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR )) )
{
VectorDivide( *v1, *v2, *v1 );
sq_remove( vm, -1 );
return 1;
}
float flInput;
if ( SQ_SUCCEEDED(sq_getfloat( vm, 2, &flInput )) )
{
VectorDivide( *v1, flInput, *v1 );
sq_remove( vm, -1 );
return 1;
}
return sq_throwerror(vm, "Expected (Vector, Vector|float)");
}
SQInteger DistTo(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
sq_pushfloat( vm, v1->DistTo(*v2) );
return 1;
}
SQInteger DistToSqr(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector)");
}
sq_pushfloat( vm, v1->DistToSqr(*v2) );
return 1;
}
SQInteger IsEqualTo(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* v2 = nullptr;
if (sq_gettop(vm) < 2 || // bother checking > 3?
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&v2, TYPETAG_VECTOR)) )
{
return sq_throwerror(vm, "Expected (Vector, Vector, float)");
}
float tolerance = 0.0f;
sq_getfloat( vm, 3, &tolerance );
sq_pushbool( vm, VectorsAreEqual( *v1, *v2, tolerance ) );
return 1;
}
SQInteger Length(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
@ -557,30 +760,23 @@ namespace SQVector
SQInteger Scale(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
float s = 0.0f;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)))
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
{
return sq_throwerror(vm, "Expected (Vector, float)");
}
float s = 0.0;
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
SQUserPointer p;
sq_getinstanceup(vm, -1, &p, 0);
new(p) Vector((*v1) * s);
sq_remove(vm, -2);
if (SQ_SUCCEEDED(sq_getfloat(vm, 2, &s)))
{
sq_getclass(vm, 1);
sq_createinstance(vm, -1);
SQUserPointer p;
sq_getinstanceup(vm, -1, &p, 0);
new(p) Vector((*v1) * s);
sq_remove(vm, -2);
return 1;
}
else
{
return sq_throwerror(vm, "Expected (Vector, float)");
}
return 1;
}
SQInteger Dot(HSQUIRRELVM vm)
@ -613,6 +809,42 @@ namespace SQVector
return 1;
}
SQInteger FromKVString(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
const char* szInput;
if (sq_gettop(vm) != 2 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getstring(vm, 2, &szInput)) )
{
return sq_throwerror(vm, "Expected (Vector, string)");
}
float x = 0.0f, y = 0.0f, z = 0.0f;
if ( sscanf( szInput, "%f %f %f", &x, &y, &z ) < 3 ) // UTIL_StringToVector
{
// Don't throw, return null while invalidating the input vector.
// This allows the user to easily check for input errors without halting.
//return sq_throwerror(vm, "invalid KV string");
sq_pushnull(vm);
*v1 = vec3_invalid;
return 1;
}
v1->x = x;
v1->y = y;
v1->z = z;
// return input vector
sq_remove( vm, -1 );
return 1;
}
SQInteger Cross(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
@ -635,6 +867,25 @@ namespace SQVector
return 1;
}
SQInteger WithinAABox(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
Vector* mins = nullptr;
Vector* maxs = nullptr;
if (sq_gettop(vm) != 3 ||
SQ_FAILED(sq_getinstanceup(vm, 1, (SQUserPointer*)&v1, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 2, (SQUserPointer*)&mins, TYPETAG_VECTOR)) ||
SQ_FAILED(sq_getinstanceup(vm, 3, (SQUserPointer*)&maxs, TYPETAG_VECTOR)))
{
return sq_throwerror(vm, "Expected (Vector, Vector, Vector)");
}
sq_pushbool( vm, v1->WithinAABox( *mins, *maxs ) );
return 1;
}
SQInteger ToString(HSQUIRRELVM vm)
{
Vector* v1 = nullptr;
@ -645,7 +896,7 @@ namespace SQVector
return sq_throwerror(vm, "Expected (Vector)");
}
sqstd_pushstringf(vm, "(vector: (%f, %f, %f))", v1->x, v1->y, v1->z);
sqstd_pushstringf(vm, "(Vector %p [%f %f %f])", (void*)v1, v1->x, v1->y, v1->z);
return 1;
}
@ -701,22 +952,33 @@ namespace SQVector
static const SQRegFunction funcs[] = {
{_SC("constructor"), Construct,0,nullptr},
{_SC("_get"), Get, 2, _SC(".s")},
{_SC("_set"), Set, 3, _SC(".sn")},
{_SC("_add"), Add, 2, _SC("..")},
{_SC("_sub"), Sub, 2, _SC("..")},
{_SC("_mul"), Multiply, 2, _SC("..")},
{_SC("_div"), Divide, 2, _SC("..")},
{_SC("_get"), _get, 2, _SC(".s")},
{_SC("_set"), _set, 3, _SC(".sn")},
{_SC("_add"), _add, 2, _SC("..")},
{_SC("_sub"), _sub, 2, _SC("..")},
{_SC("_mul"), _multiply, 2, _SC("..")},
{_SC("_div"), _divide, 2, _SC("..")},
{_SC("_unm"), _unm, 1, _SC(".")},
{_SC("Set"), Set, -2, _SC("..nn")},
{_SC("Add"), Add, 2, _SC("..")},
{_SC("Subtract"), Subtract, 2, _SC("..")},
{_SC("Multiply"), Multiply, 2, _SC("..")},
{_SC("Divide"), Divide, 2, _SC("..")},
{_SC("DistTo"), DistTo, 2, _SC("..")},
{_SC("DistToSqr"), DistToSqr, 2, _SC("..")},
{_SC("IsEqualTo"), IsEqualTo, -2, _SC("..n")},
{_SC("Length"), Length, 1, _SC(".")},
{_SC("LengthSqr"), LengthSqr, 1, _SC(".")},
{_SC("Length2D"), Length2D, 1, _SC(".")},
{_SC("Length2DSqr"), Length2DSqr, 1, _SC(".")},
{_SC("Normalized"), Normalized, 1, _SC(".")},
{_SC("Norm"), Norm, 1, _SC(".")},
{_SC("Scale"), Scale, 2, _SC("..")},
{_SC("Scale"), Scale, 2, _SC(".n")}, // identical to _multiply
{_SC("Dot"), Dot, 2, _SC("..")},
{_SC("Cross"), Cross, 2, _SC("..")},
{_SC("WithinAABox"), WithinAABox, 3, _SC("...")},
{_SC("ToKVString"), ToKVString, 1, _SC(".")},
{_SC("FromKVString"), FromKVString, 2, _SC(".s")},
{_SC("_tostring"), ToString, 1, _SC(".")},
{_SC("_typeof"), TypeOf, 1, _SC(".")},
{_SC("_nexti"), Nexti, 2, _SC("..")},
@ -2698,7 +2960,7 @@ bool SquirrelVM::ClearValue(HSCRIPT hScope, ScriptVariant_t pKey)
return true;
}
/*
void SquirrelVM::CreateArray(ScriptVariant_t &arr, int size)
{
SquirrelSafeCheck safeCheck(vm_);
@ -2713,16 +2975,14 @@ void SquirrelVM::CreateArray(ScriptVariant_t &arr, int size)
arr = (HSCRIPT)obj;
}
*/
bool SquirrelVM::ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val)
{
SquirrelSafeCheck safeCheck(vm_);
HSQOBJECT arr = *(HSQOBJECT*)hArray;
if ( !sq_isarray(arr) )
return false;
HSQOBJECT *arr = (HSQOBJECT*)hArray;
sq_pushobject(vm_, arr);
sq_pushobject(vm_, *arr);
PushVariant(vm_, val);
bool ret = sq_arrayappend(vm_, -2) == SQ_OK;
sq_pop(vm_, 1);

View File

@ -65,6 +65,22 @@ function AngleDistance( next, cur )
return delta
}
function FLerp( f1, f2, i1, i2, x )
{
return f1+(f2-f1)*(x-i1)/(i2-i1);
}
function Lerp( f, A, B )
{
return A + ( B - A ) * f
}
function SimpleSpline( f )
{
local ff = f * f;
return 3.0 * ff - 2.0 * ff * f;
}
function printl( text )
{
return ::print(text + "\n");