Skip to content

Commit

Permalink
vscript additions and fixes:
Browse files Browse the repository at this point in the history
vscript_client.cpp
   - Fixed local player script instance registration
   - Added CEntities::GetLocalPlayer
   - Added Con_IsVisible
   - Added IsWindowedMode
   - Added ScreenWidth
   - Added ScreenHeight
   - Added ScreenTransform
   - Added missing DoUniqueString

gameinterface.cpp
usercmd.h
usercmd.cpp
vscript_singletons.cpp
   - CNetMsgScriptHelper

vscript_singletons.cpp
   - Added hash map for CScriptSaveRestoreUtil
   - Added hash map for CScriptGameEventListener::s_GameEvents
   - Changed CScriptGameEventListener string contexts to hashes
   - Added invalid input condition on CScriptGameEventListener::ListenToGameEvent
   - Moved CDebugOverlayScriptHelper to shared code

ivscript.h
vscript_squirrel.cpp
   - Added IScriptVM::Get/Set/ClearValue (ScriptVariant_t key)

baseentity.h
baseentity.cpp
   - Added CBaseEntity::SetContextThink (ScriptSetContextThink)

vscript_server.cpp
vscript_client.cpp
vscript_funcs_shared.cpp
   - Changed the order user vscript_*.nut files are executed - after internal scripts, before mapspawn

vscript_squirrel.cpp
vscript_squirrel.nut
vscript_server.nut
vscript_shared.cpp
   - Localised all documentation under __Documentation

hl2_usermessages.cpp
   - Added usermessage ScriptMsg

c_baseplayer.cpp
   - Removed redundant check in ~C_BasePlayer
  • Loading branch information
samisalreadytaken committed Dec 26, 2020
1 parent 6ba3cd4 commit ef7d9cc
Show file tree
Hide file tree
Showing 18 changed files with 1,733 additions and 1,008 deletions.
10 changes: 5 additions & 5 deletions sp/src/game/client/c_baseplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,14 +492,14 @@ C_BasePlayer::~C_BasePlayer()
if ( this == s_pLocalPlayer )
{
s_pLocalPlayer = NULL;
}

#ifdef MAPBASE_VSCRIPT
if ( IsLocalPlayer() && g_pScriptVM )
{
g_pScriptVM->SetValue( "player", SCRIPT_VARIANT_NULL );
}
if ( g_pScriptVM )
{
g_pScriptVM->SetValue( "player", SCRIPT_VARIANT_NULL );
}
#endif
}

delete m_pFlashlight;
}
Expand Down
74 changes: 62 additions & 12 deletions sp/src/game/client/vscript_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "proxyentity.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "mapbase/vscript_singletons.h"
#endif

extern IScriptManager *scriptmanager;
Expand All @@ -46,6 +47,11 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
class CScriptClientEntityIterator
{
public:
HSCRIPT GetLocalPlayer()
{
return ToHScript( C_BasePlayer::GetLocalPlayer() );
}

HSCRIPT First() { return Next(NULL); }

HSCRIPT Next( HSCRIPT hStartEntity )
Expand Down Expand Up @@ -94,6 +100,7 @@ class CScriptClientEntityIterator
} g_ScriptEntityIterator;

BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptClientEntityIterator, "CEntities", SCRIPT_SINGLETON "The global list of entities" )
DEFINE_SCRIPTFUNC( GetLocalPlayer, "Get local player" )
DEFINE_SCRIPTFUNC( First, "Begin an iteration over the list of entities" )
DEFINE_SCRIPTFUNC( Next, "Continue an iteration over the list of entities, providing reference to a previously found entity" )
DEFINE_SCRIPTFUNC( CreateByClassname, "Creates an entity by classname" )
Expand Down Expand Up @@ -399,7 +406,7 @@ void CScriptMaterialProxy::SetVarVector( int i, const Vector &value )
}

EXPOSE_INTERFACE( CScriptMaterialProxy, IMaterialProxy, "VScriptProxy" IMATERIAL_PROXY_INTERFACE_VERSION );
#endif
#endif // MAPBASE_VSCRIPT

//-----------------------------------------------------------------------------
//
Expand Down Expand Up @@ -431,6 +438,39 @@ bool DoIncludeScript( const char *pszScript, HSCRIPT hScope )
return true;
}

#ifdef MAPBASE_VSCRIPT
static bool Con_IsVisible()
{
return engine->Con_IsVisible();
}

static bool IsWindowedMode()
{
return engine->IsWindowedMode();
}

int ScreenTransform( const Vector& point, Vector& screen );

//-----------------------------------------------------------------------------
// Input array [x,y], set normalised screen space pos. Return true if on screen
//-----------------------------------------------------------------------------
static bool ScriptScreenTransform( const Vector &pos, HSCRIPT hArray )
{
if ( g_pScriptVM->GetNumTableEntries(hArray) >= 2 )
{
Vector v;
bool r = ScreenTransform( pos, v );
float x = 0.5f * ( 1.0f + v[0] );
float y = 0.5f * ( 1.0f - v[1] );

g_pScriptVM->SetValue( hArray, ScriptVariant_t(0), x );
g_pScriptVM->SetValue( hArray, 1, y );
return !r;
}
return false;
}
#endif

bool VScriptClientInit()
{
VMPROF_START
Expand Down Expand Up @@ -487,14 +527,30 @@ bool VScriptClientInit()
if( g_pScriptVM )
{
#ifdef MAPBASE_VSCRIPT
// Moved here from LevelInitPostEntity, which is executed before local player is spawned.
// This is executed after C_World::OnDataChanged, which is after C_BasePlayer::Spawn
if ( C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer() )
{
g_pScriptVM->SetValue( "player", pPlayer->GetScriptInstance() );
}

CGMsg( 0, CON_GROUP_VSCRIPT, "VSCRIPT CLIENT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() );
#else
Log( "VSCRIPT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() );
#endif
ScriptRegisterFunction( g_pScriptVM, GetMapName, "Get the name of the map.");
ScriptRegisterFunction( g_pScriptVM, Time, "Get the current server time" );
ScriptRegisterFunction( g_pScriptVM, DoUniqueString, SCRIPT_ALIAS( "UniqueString", "Generate a string guaranteed to be unique across the life of the script VM, with an optional root string." ) );
ScriptRegisterFunction( g_pScriptVM, DoIncludeScript, "Execute a script (internal)" );

#ifdef MAPBASE_VSCRIPT
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" );
ScriptRegisterFunction( g_pScriptVM, IsWindowedMode, "" );
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptScreenTransform, "ScreenTransform", "Get the x & y positions of a world position in screen space. Returns true if it's onscreen" );
#endif


if ( GameRules() )
{
GameRules()->RegisterScriptFunctions();
Expand All @@ -519,6 +575,7 @@ bool VScriptClientInit()
g_pScriptVM->Run( g_Script_vscript_client );
}

VScriptRunScript( "vscript_client", true );
VScriptRunScript( "mapspawn", false );

VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );
Expand Down Expand Up @@ -579,20 +636,13 @@ class CVScriptGameSystem : public CAutoGameSystemPerFrame
virtual void LevelInitPostEntity( void )
{
m_bAllowEntityCreationInScripts = false;
#ifdef MAPBASE_VSCRIPT
if (g_pScriptVM)
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if (pPlayer)
{
g_pScriptVM->SetValue( "player", pPlayer->GetScriptInstance() );
}
}
#endif
}

virtual void LevelShutdownPostEntity( void )
{
#ifdef MAPBASE_VSCRIPT
g_ScriptNetMsg->LevelShutdownPreVM();
#endif
VScriptClientTerm();
}

Expand Down
182 changes: 148 additions & 34 deletions sp/src/game/server/baseentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2190,7 +2190,7 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
DEFINE_THINKFUNC( ShadowCastDistThink ),
DEFINE_THINKFUNC( ScriptThink ),
#ifdef MAPBASE_VSCRIPT
DEFINE_THINKFUNC( ScriptThinkH ),
DEFINE_THINKFUNC( ScriptContextThink ),
#endif

#ifdef MAPBASE
Expand Down Expand Up @@ -2442,6 +2442,7 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
#ifdef MAPBASE_VSCRIPT
DEFINE_SCRIPTFUNC_NAMED( ScriptSetThinkFunction, "SetThinkFunction", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopThinkFunction, "StopThinkFunction", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetContextThink, "SetContextThink", "Set a think function on this entity." )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetThink, "SetThink", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptStopThink, "StopThink", "" )

Expand Down Expand Up @@ -2590,11 +2591,12 @@ void CBaseEntity::UpdateOnRemove( void )
m_hScriptInstance = NULL;

#ifdef MAPBASE_VSCRIPT
if ( m_hfnThink )
FOR_EACH_VEC( m_ScriptThinkFuncs, i )
{
g_pScriptVM->ReleaseScript( m_hfnThink );
m_hfnThink = NULL;
HSCRIPT h = m_ScriptThinkFuncs[i].m_hfnThink;
if ( h ) g_pScriptVM->ReleaseScript( h );
}
m_ScriptThinkFuncs.Purge();
#endif // MAPBASE_VSCRIPT
}
}
Expand Down Expand Up @@ -8653,60 +8655,172 @@ void CBaseEntity::ScriptStopThinkFunction()
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::ScriptThinkH()
void CBaseEntity::ScriptContextThink()
{
ScriptVariant_t varThinkRetVal;
if ( g_pScriptVM->ExecuteFunction(m_hfnThink, NULL, 0, &varThinkRetVal, NULL, true) == SCRIPT_ERROR )
float flNextThink = FLT_MAX;
int nScheduledTick = 0;

for ( int i = m_ScriptThinkFuncs.Count(); i--; )
{
DevWarning("%s FAILED to call script think function (invalid closure)!\n", GetDebugName());
ScriptStopThink();
return;
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 );
}

float flThinkFrequency = 0.f;
if ( !varThinkRetVal.AssignTo(&flThinkFrequency) )
if ( flNextThink < FLT_MAX )
{
// no return value stops thinking
ScriptStopThink();
return;
SetNextThink( gpGlobals->curtime + flNextThink, "ScriptContextThink" );
}
else if ( nScheduledTick )
{
SetNextThink( TICKS_TO_TIME( nScheduledTick ), "ScriptContextThink" );
}
else
{
SetNextThink( TICK_NEVER_THINK, "ScriptContextThink" );
}

SetNextThink( gpGlobals->curtime + flThinkFrequency, "ScriptThinkH" );
}

void CBaseEntity::ScriptSetThink( HSCRIPT hFunc, float flTime )
// see ScriptSetThink
static bool s_bScriptContextThinkNoParam = false;

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetContextThink( const char* szContext, HSCRIPT hFunc, float flTime )
{
if ( hFunc )
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 )
{
if ( m_hfnThink )
scriptthinkfunc_t f = m_ScriptThinkFuncs[i];
if ( hash == f.m_iContextHash )
{
// release old func
ScriptStopThink();
th = f;
m_ScriptThinkFuncs.Remove(i); // reorder
bFound = true;
break;
}
}

// no type check here, print error on call instead
m_hfnThink = hFunc;
if ( hFunc )
{
float nextthink = gpGlobals->curtime + flTime;

flTime = max( 0, flTime );
SetContextThink( &CBaseEntity::ScriptThinkH, gpGlobals->curtime + flTime, "ScriptThinkH" );
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" );
}
}
else
// null func input, think exists
else if ( bFound )
{
ScriptStopThink();
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()
{
if (m_hfnThink)
{
g_pScriptVM->ReleaseScript(m_hfnThink);
m_hfnThink = NULL;
}
SetContextThink( NULL, TICK_NEVER_THINK, "ScriptThinkH" );
ScriptSetContextThink( NULL, NULL, 0.0f );
}

#endif // MAPBASE_VSCRIPT

//-----------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit ef7d9cc

Please sign in to comment.