Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vscript additions and fixes 2 #80

Merged
merged 1 commit into from
Dec 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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