mirror of
https://github.com/mapbase-source/source-sdk-2013.git
synced 2025-01-26 13:47:56 +03:00
Integrating vscript interface code (based on Alien Swarm)
This commit is contained in:
parent
af85131deb
commit
d840c57b4a
@ -281,6 +281,11 @@ BEGIN_DATADESC( C_ClientRagdoll )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( C_BaseAnimating, C_BaseEntity, "Animating models client-side" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetPoseParameter, "SetPoseParameter", "Set the specified pose parameter to the specified value" )
|
||||
DEFINE_SCRIPTFUNC( IsSequenceFinished, "Ask whether the main sequence is done playing" )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
C_ClientRagdoll::C_ClientRagdoll( bool bRestoring )
|
||||
{
|
||||
m_iCurrentFriction = 0;
|
||||
@ -1403,6 +1408,15 @@ float C_BaseAnimating::ClampCycle( float flCycle, bool isLooping )
|
||||
return flCycle;
|
||||
}
|
||||
|
||||
void C_BaseAnimating::ScriptSetPoseParameter(const char* szName, float fValue)
|
||||
{
|
||||
CStudioHdr* pHdr = GetModelPtr();
|
||||
if (pHdr == NULL)
|
||||
return;
|
||||
|
||||
int iPoseParam = LookupPoseParameter(pHdr, szName);
|
||||
SetPoseParameter(pHdr, iPoseParam, fValue);
|
||||
}
|
||||
|
||||
void C_BaseAnimating::GetCachedBoneMatrix( int boneIndex, matrix3x4_t &out )
|
||||
{
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
DECLARE_INTERPOLATION();
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
enum
|
||||
{
|
||||
@ -445,6 +446,7 @@ public:
|
||||
|
||||
virtual bool IsViewModel() const;
|
||||
|
||||
void ScriptSetPoseParameter(const char* szName, float fValue);
|
||||
protected:
|
||||
// View models scale their attachment positions to account for FOV. To get the unmodified
|
||||
// attachment position (like if you're rendering something else during the view model's DrawModel call),
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "viewrender.h"
|
||||
#endif
|
||||
|
||||
#include "gamestringpool.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
@ -423,6 +425,13 @@ BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_AnimTimeMustBeFirst )
|
||||
RecvPropInt( RECVINFO(m_flAnimTime), 0, RecvProxy_AnimTime ),
|
||||
END_RECV_TABLE()
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT( C_BaseEntity, "Root class of all client-side entities" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetForward, "GetForwardVector", "Get the forward vector of the entity" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLeft, "GetLeftVector", "Get the left vector of the entity" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetUp, "GetUpVector", "Get the up vector of the entity" )
|
||||
DEFINE_SCRIPTFUNC( GetTeamNumber, "Gets this entity's team" )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
#ifndef NO_ENTITY_PREDICTION
|
||||
BEGIN_RECV_TABLE_NOBASE( C_BaseEntity, DT_PredictableId )
|
||||
@ -466,6 +475,8 @@ BEGIN_RECV_TABLE_NOBASE(C_BaseEntity, DT_BaseEntity)
|
||||
RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ),
|
||||
RecvPropInt( RECVINFO( m_iParentAttachment ) ),
|
||||
|
||||
RecvPropString(RECVINFO(m_iName)),
|
||||
|
||||
RecvPropInt( "movetype", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveType ),
|
||||
RecvPropInt( "movecollide", 0, SIZEOF_IGNORE, 0, RecvProxy_MoveCollide ),
|
||||
RecvPropDataTable( RECVINFO_DT( m_Collision ), 0, &REFERENCE_RECV_TABLE(DT_CollisionProperty) ),
|
||||
@ -1165,6 +1176,7 @@ void C_BaseEntity::Term()
|
||||
g_Predictables.RemoveFromPredictablesList( GetClientHandle() );
|
||||
}
|
||||
|
||||
|
||||
// If it's play simulated, remove from simulation list if the player still exists...
|
||||
if ( IsPlayerSimulated() && C_BasePlayer::GetLocalPlayer() )
|
||||
{
|
||||
@ -1201,6 +1213,12 @@ void C_BaseEntity::Term()
|
||||
RemoveFromLeafSystem();
|
||||
|
||||
RemoveFromAimEntsList();
|
||||
|
||||
if ( m_hScriptInstance )
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( m_hScriptInstance );
|
||||
m_hScriptInstance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6442,6 +6460,26 @@ int C_BaseEntity::GetCreationTick() const
|
||||
return m_nCreationTick;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT C_BaseEntity::GetScriptInstance()
|
||||
{
|
||||
if (!m_hScriptInstance)
|
||||
{
|
||||
if (m_iszScriptId == NULL_STRING)
|
||||
{
|
||||
char* szName = (char*)stackalloc(1024);
|
||||
g_pScriptVM->GenerateUniqueKey((m_iName != NULL_STRING) ? STRING(GetEntityName()) : GetClassname(), szName, 1024);
|
||||
m_iszScriptId = AllocPooledString(szName);
|
||||
}
|
||||
|
||||
m_hScriptInstance = g_pScriptVM->RegisterInstance(GetScriptDesc(), this);
|
||||
g_pScriptVM->SetInstanceUniqeId(m_hScriptInstance, STRING(m_iszScriptId));
|
||||
}
|
||||
return m_hScriptInstance;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CC_CL_Find_Ent( const CCommand& args )
|
||||
{
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include "toolframework/itoolentity.h"
|
||||
#include "tier0/threadtools.h"
|
||||
|
||||
#include "vscript/ivscript.h"
|
||||
#include "vscript_shared.h"
|
||||
|
||||
class C_Team;
|
||||
class IPhysicsObject;
|
||||
class IClientVehicle;
|
||||
@ -183,6 +186,8 @@ public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_CLIENTCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
// script description
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
C_BaseEntity();
|
||||
virtual ~C_BaseEntity();
|
||||
@ -256,6 +261,11 @@ public:
|
||||
|
||||
string_t m_iClassname;
|
||||
|
||||
HSCRIPT GetScriptInstance();
|
||||
|
||||
HSCRIPT m_hScriptInstance;
|
||||
string_t m_iszScriptId;
|
||||
|
||||
// IClientUnknown overrides.
|
||||
public:
|
||||
|
||||
@ -1119,6 +1129,10 @@ public:
|
||||
virtual int GetBody() { return 0; }
|
||||
virtual int GetSkin() { return 0; }
|
||||
|
||||
const Vector& ScriptGetForward(void) { static Vector vecForward; GetVectors(&vecForward, NULL, NULL); return vecForward; }
|
||||
const Vector& ScriptGetLeft(void) { static Vector vecLeft; GetVectors(NULL, &vecLeft, NULL); return vecLeft; }
|
||||
const Vector& ScriptGetUp(void) { static Vector vecUp; GetVectors(NULL, NULL, &vecUp); return vecUp; }
|
||||
|
||||
// Stubs on client
|
||||
void NetworkStateManualMode( bool activate ) { }
|
||||
void NetworkStateChanged() { }
|
||||
@ -1266,6 +1280,7 @@ public:
|
||||
void SetRenderMode( RenderMode_t nRenderMode, bool bForceUpdate = false );
|
||||
RenderMode_t GetRenderMode() const;
|
||||
|
||||
const char* GetEntityName();
|
||||
public:
|
||||
|
||||
// Determine what entity this corresponds to
|
||||
@ -1648,6 +1663,8 @@ private:
|
||||
// The owner!
|
||||
EHANDLE m_hOwnerEntity;
|
||||
EHANDLE m_hEffectEntity;
|
||||
|
||||
char m_iName[MAX_PATH];
|
||||
|
||||
// This is a random seed used by the networking code to allow client - side prediction code
|
||||
// randon number generators to spit out the same random numbers on both sides for a particular
|
||||
@ -2203,6 +2220,12 @@ inline bool C_BaseEntity::ShouldRecordInTools() const
|
||||
#endif
|
||||
}
|
||||
|
||||
inline const char *C_BaseEntity::GetEntityName()
|
||||
{
|
||||
return m_iName;
|
||||
}
|
||||
|
||||
|
||||
C_BaseEntity *CreateEntityByName( const char *className );
|
||||
|
||||
#endif // C_BASEENTITY_H
|
||||
|
@ -1480,7 +1480,7 @@ bool C_BaseFlex::ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool can
|
||||
// expression -
|
||||
// duration -
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_BaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget, bool bClientSide )
|
||||
void C_BaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget, bool bClientSide, C_SceneEntity* pSceneEntity)
|
||||
{
|
||||
if ( !scene || !event )
|
||||
{
|
||||
@ -1505,6 +1505,7 @@ void C_BaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseE
|
||||
info.m_hTarget = pTarget;
|
||||
info.m_bStarted = false;
|
||||
info.m_bClientSide = bClientSide;
|
||||
info.m_hSceneEntity = pSceneEntity;
|
||||
|
||||
if (StartSceneEvent( &info, scene, event, actor, pTarget ))
|
||||
{
|
||||
|
@ -214,7 +214,7 @@ public:
|
||||
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
|
||||
|
||||
// Add the event to the queue for this actor
|
||||
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL, bool bClientSide = false );
|
||||
void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, C_BaseEntity *pTarget = NULL, bool bClientSide = false, C_SceneEntity* pSceneEntity = NULL);
|
||||
|
||||
// Remove the event from the queue for this actor
|
||||
void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill );
|
||||
|
@ -674,7 +674,7 @@ void C_SceneEntity::DispatchStartSpeak( CChoreoScene *scene, C_BaseFlex *actor,
|
||||
es.m_pSoundName = event->GetParameters();
|
||||
|
||||
EmitSound( filter, actor->entindex(), es );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
|
||||
|
||||
// Close captioning only on master token no matter what...
|
||||
if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER )
|
||||
@ -964,7 +964,7 @@ void C_SceneEntity::UnloadScene( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_SceneEntity::DispatchStartFlexAnimation( CChoreoScene *scene, C_BaseFlex *actor, CChoreoEvent *event )
|
||||
{
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -984,7 +984,7 @@ void C_SceneEntity::DispatchEndFlexAnimation( CChoreoScene *scene, C_BaseFlex *a
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_SceneEntity::DispatchStartExpression( CChoreoScene *scene, C_BaseFlex *actor, CChoreoEvent *event )
|
||||
{
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1008,7 +1008,7 @@ void C_SceneEntity::DispatchStartGesture( CChoreoScene *scene, C_BaseFlex *actor
|
||||
if ( !Q_stricmp( event->GetName(), "NULL" ) )
|
||||
return;
|
||||
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1023,7 +1023,7 @@ void C_SceneEntity::DispatchProcessGesture( CChoreoScene *scene, C_BaseFlex *act
|
||||
return;
|
||||
|
||||
actor->RemoveSceneEvent( scene, event, false );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1046,7 +1046,7 @@ void C_SceneEntity::DispatchEndGesture( CChoreoScene *scene, C_BaseFlex *actor,
|
||||
//-----------------------------------------------------------------------------
|
||||
void C_SceneEntity::DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
|
||||
{
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1056,7 +1056,7 @@ void C_SceneEntity::DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor
|
||||
void C_SceneEntity::DispatchProcessSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event )
|
||||
{
|
||||
actor->RemoveSceneEvent( scene, event, false );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly() );
|
||||
actor->AddSceneEvent( scene, event, NULL, IsClientOnly(), this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -223,6 +223,8 @@ IReplaySystem *g_pReplay = NULL;
|
||||
IVEngineServer *serverengine = NULL;
|
||||
#endif
|
||||
|
||||
IScriptManager *scriptmanager = NULL;
|
||||
|
||||
IHaptics* haptics = NULL;// NVNT haptics system interface singleton
|
||||
|
||||
//=============================================================================
|
||||
@ -964,6 +966,11 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
|
||||
if (!g_pMatSystemSurface)
|
||||
return false;
|
||||
|
||||
if ( !CommandLine()->CheckParm( "-noscripting") )
|
||||
{
|
||||
scriptmanager = (IScriptManager *)appSystemFactory( VSCRIPT_INTERFACE_VERSION, NULL );
|
||||
}
|
||||
|
||||
#ifdef WORKSHOP_IMPORT_ENABLED
|
||||
if ( !ConnectDataModel( appSystemFactory ) )
|
||||
return false;
|
||||
|
@ -493,6 +493,11 @@ $Project
|
||||
$File "viewrender.cpp"
|
||||
$File "$SRCDIR\game\shared\voice_banmgr.cpp"
|
||||
$File "$SRCDIR\game\shared\voice_status.cpp"
|
||||
$File "vscript_client.cpp"
|
||||
$File "vscript_client.h"
|
||||
$File "vscript_client.nut"
|
||||
$File "$SRCDIR\game\shared\vscript_shared.cpp"
|
||||
$File "$SRCDIR\game\shared\vscript_shared.h"
|
||||
$File "warp_overlay.cpp"
|
||||
$File "WaterLODMaterialProxy.cpp"
|
||||
$File "$SRCDIR\game\shared\weapon_parse.cpp"
|
||||
|
190
sp/src/game/client/vscript_client.cpp
Normal file
190
sp/src/game/client/vscript_client.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "vscript_client.h"
|
||||
#include "icommandline.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/fmtstr.h"
|
||||
#include "filesystem.h"
|
||||
#include "characterset.h"
|
||||
#include "isaverestore.h"
|
||||
#include "gamerules.h"
|
||||
#ifdef _WIN32
|
||||
//#include "vscript_client_nut.h"
|
||||
#endif
|
||||
|
||||
extern IScriptManager *scriptmanager;
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
|
||||
#define VMPROF_START float debugStartTime = Plat_FloatTime();
|
||||
#define VMPROF_SHOW( funcname, funcdesc ) DevMsg("***VSCRIPT PROFILE***: %s %s: %6.4f milliseconds\n", (##funcname), (##funcdesc), (Plat_FloatTime() - debugStartTime)*1000.0 );
|
||||
|
||||
#else // !VMPROFILE
|
||||
|
||||
#define VMPROF_START
|
||||
#define VMPROF_SHOW
|
||||
|
||||
#endif // VMPROFILE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
static float Time()
|
||||
{
|
||||
return gpGlobals->curtime;
|
||||
}
|
||||
|
||||
static const char *GetMapName()
|
||||
{
|
||||
return engine->GetLevelName();
|
||||
}
|
||||
|
||||
static const char *DoUniqueString( const char *pszBase )
|
||||
{
|
||||
static char szBuf[512];
|
||||
g_pScriptVM->GenerateUniqueKey( pszBase, szBuf, ARRAYSIZE(szBuf) );
|
||||
return szBuf;
|
||||
}
|
||||
|
||||
bool DoIncludeScript( const char *pszScript, HSCRIPT hScope )
|
||||
{
|
||||
if ( !VScriptRunScript( pszScript, hScope, true ) )
|
||||
{
|
||||
g_pScriptVM->RaiseException( CFmtStr( "Failed to include script \"%s\"", ( pszScript ) ? pszScript : "unknown" ) );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VScriptClientInit()
|
||||
{
|
||||
VMPROF_START
|
||||
|
||||
if( scriptmanager != NULL )
|
||||
{
|
||||
ScriptLanguage_t scriptLanguage = SL_DEFAULT;
|
||||
|
||||
char const *pszScriptLanguage;
|
||||
if ( CommandLine()->CheckParm( "-scriptlang", &pszScriptLanguage ) )
|
||||
{
|
||||
if( !Q_stricmp(pszScriptLanguage, "gamemonkey") )
|
||||
{
|
||||
scriptLanguage = SL_GAMEMONKEY;
|
||||
}
|
||||
else if( !Q_stricmp(pszScriptLanguage, "squirrel") )
|
||||
{
|
||||
scriptLanguage = SL_SQUIRREL;
|
||||
}
|
||||
else if( !Q_stricmp(pszScriptLanguage, "python") )
|
||||
{
|
||||
scriptLanguage = SL_PYTHON;
|
||||
}
|
||||
else
|
||||
{
|
||||
DevWarning("-scriptlang does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage );
|
||||
scriptLanguage = SL_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
if( scriptLanguage != SL_NONE )
|
||||
{
|
||||
if ( g_pScriptVM == NULL )
|
||||
g_pScriptVM = scriptmanager->CreateVM( scriptLanguage );
|
||||
|
||||
if( g_pScriptVM )
|
||||
{
|
||||
Log( "VSCRIPT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() );
|
||||
ScriptRegisterFunction( g_pScriptVM, GetMapName, "Get the name of the map.");
|
||||
ScriptRegisterFunction( g_pScriptVM, Time, "Get the current server time" );
|
||||
ScriptRegisterFunction( g_pScriptVM, DoIncludeScript, "Execute a script (internal)" );
|
||||
|
||||
if ( GameRules() )
|
||||
{
|
||||
GameRules()->RegisterScriptFunctions();
|
||||
}
|
||||
|
||||
//g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
|
||||
|
||||
if ( scriptLanguage == SL_SQUIRREL )
|
||||
{
|
||||
//g_pScriptVM->Run( g_Script_vscript_client );
|
||||
}
|
||||
|
||||
VScriptRunScript( "mapspawn", false );
|
||||
|
||||
VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DevWarning("VM Did not start!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log( "\nVSCRIPT: Scripting is disabled.\n" );
|
||||
}
|
||||
g_pScriptVM = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
void VScriptClientTerm()
|
||||
{
|
||||
if( g_pScriptVM != NULL )
|
||||
{
|
||||
if( g_pScriptVM )
|
||||
{
|
||||
scriptmanager->DestroyVM( g_pScriptVM );
|
||||
g_pScriptVM = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CVScriptGameSystem : public CAutoGameSystemPerFrame
|
||||
{
|
||||
public:
|
||||
// Inherited from IAutoServerSystem
|
||||
virtual void LevelInitPreEntity( void )
|
||||
{
|
||||
m_bAllowEntityCreationInScripts = true;
|
||||
VScriptClientInit();
|
||||
}
|
||||
|
||||
virtual void LevelInitPostEntity( void )
|
||||
{
|
||||
m_bAllowEntityCreationInScripts = false;
|
||||
}
|
||||
|
||||
virtual void LevelShutdownPostEntity( void )
|
||||
{
|
||||
VScriptClientTerm();
|
||||
}
|
||||
|
||||
virtual void FrameUpdatePostEntityThink()
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
g_pScriptVM->Frame( gpGlobals->frametime );
|
||||
}
|
||||
|
||||
bool m_bAllowEntityCreationInScripts;
|
||||
};
|
||||
|
||||
CVScriptGameSystem g_VScriptGameSystem;
|
||||
|
||||
bool IsEntityCreationAllowedInScripts( void )
|
||||
{
|
||||
return g_VScriptGameSystem.m_bAllowEntityCreationInScripts;
|
||||
}
|
||||
|
||||
|
22
sp/src/game/client/vscript_client.h
Normal file
22
sp/src/game/client/vscript_client.h
Normal file
@ -0,0 +1,22 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VSCRIPT_SERVER_H
|
||||
#define VSCRIPT_SERVER_H
|
||||
|
||||
#include "vscript/ivscript.h"
|
||||
#include "vscript_shared.h"
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
extern IScriptVM * g_pScriptVM;
|
||||
|
||||
// Only allow scripts to create entities during map initialization
|
||||
bool IsEntityCreationAllowedInScripts( void );
|
||||
|
||||
#endif // VSCRIPT_SERVER_H
|
19
sp/src/game/client/vscript_client.nut
Normal file
19
sp/src/game/client/vscript_client.nut
Normal file
@ -0,0 +1,19 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
function UniqueString( string = "" )
|
||||
{
|
||||
return DoUniqueString( string.tostring() );
|
||||
}
|
||||
|
||||
function IncludeScript( name, scope = null )
|
||||
{
|
||||
if ( scope == null )
|
||||
{
|
||||
scope = this;
|
||||
}
|
||||
return ::DoIncludeScript( name, scope );
|
||||
}
|
@ -282,6 +282,14 @@ IMPLEMENT_SERVERCLASS_ST(CBaseAnimating, DT_BaseAnimating)
|
||||
|
||||
END_SEND_TABLE()
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( LookupAttachment, "Get the named attachement id" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentOrigin, "GetAttachmentOrigin", "Get the attachement id's origin vector" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetAttachmentAngles, "GetAttachmentAngles", "Get the attachement id's angles as a p,y,r vector" )
|
||||
DEFINE_SCRIPTFUNC( IsSequenceFinished, "Ask whether the main sequence is done playing" )
|
||||
DEFINE_SCRIPTFUNC( SetBodygroup, "Sets a bodygroup")
|
||||
END_SCRIPTDESC();
|
||||
|
||||
CBaseAnimating::CBaseAnimating()
|
||||
{
|
||||
@ -2117,6 +2125,35 @@ bool CBaseAnimating::GetAttachment( int iAttachment, Vector &absOrigin, Vector *
|
||||
return bRet;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns the world location and world angles of an attachment to vscript caller
|
||||
// Input : attachment name
|
||||
// Output : location and angles
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vector& CBaseAnimating::ScriptGetAttachmentOrigin( int iAttachment )
|
||||
{
|
||||
|
||||
static Vector absOrigin;
|
||||
static QAngle qa;
|
||||
|
||||
CBaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
|
||||
|
||||
return absOrigin;
|
||||
}
|
||||
|
||||
const Vector& CBaseAnimating::ScriptGetAttachmentAngles( int iAttachment )
|
||||
{
|
||||
|
||||
static Vector absOrigin;
|
||||
static Vector absAngles;
|
||||
static QAngle qa;
|
||||
|
||||
CBaseAnimating::GetAttachment( iAttachment, absOrigin, qa );
|
||||
absAngles.x = qa.x;
|
||||
absAngles.y = qa.y;
|
||||
absAngles.z = qa.z;
|
||||
return absAngles;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the attachment in local space
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
virtual void SetModel( const char *szModelName );
|
||||
virtual void Activate();
|
||||
@ -186,6 +187,8 @@ public:
|
||||
bool GetAttachment( int iAttachment, Vector &absOrigin, QAngle &absAngles );
|
||||
int GetAttachmentBone( int iAttachment );
|
||||
virtual bool GetAttachment( int iAttachment, matrix3x4_t &attachmentToWorld );
|
||||
const Vector& ScriptGetAttachmentOrigin(int iAttachment);
|
||||
const Vector& ScriptGetAttachmentAngles(int iAttachment);
|
||||
|
||||
// These return the attachment in the space of the entity
|
||||
bool GetAttachmentLocal( const char *szName, Vector &origin, QAngle &angles );
|
||||
|
@ -101,6 +101,9 @@ bool CBaseEntity::s_bAbsQueriesValid = true;
|
||||
|
||||
ConVar sv_netvisdist( "sv_netvisdist", "10000", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Test networking visibility distance" );
|
||||
|
||||
ConVar sv_script_think_interval("sv_script_think_interval", "0.1");
|
||||
|
||||
|
||||
// This table encodes edict data.
|
||||
void SendProxy_AnimTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID )
|
||||
{
|
||||
@ -291,6 +294,8 @@ IMPLEMENT_SERVERCLASS_ST_NOBASE( CBaseEntity, DT_BaseEntity )
|
||||
SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)),
|
||||
SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED),
|
||||
|
||||
SendPropStringT( SENDINFO( m_iName ) ),
|
||||
|
||||
SendPropInt (SENDINFO_NAME( m_MoveType, movetype ), MOVETYPE_MAX_BITS, SPROP_UNSIGNED ),
|
||||
SendPropInt (SENDINFO_NAME( m_MoveCollide, movecollide ), MOVECOLLIDE_MAX_BITS, SPROP_UNSIGNED ),
|
||||
#if PREDICTION_ERROR_CHECK_LEVEL > 1
|
||||
@ -1313,6 +1318,19 @@ void CBaseEntity::FireNamedOutput( const char *pszOutput, variant_t variant, CBa
|
||||
if ( pszOutput == NULL )
|
||||
return;
|
||||
|
||||
CBaseEntityOutput *pOutput = FindNamedOutput( pszOutput );
|
||||
if ( pOutput )
|
||||
{
|
||||
pOutput->FireOutput( variant, pActivator, pCaller, flDelay );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntityOutput *CBaseEntity::FindNamedOutput( const char *pszOutput )
|
||||
{
|
||||
if ( pszOutput == NULL )
|
||||
return NULL;
|
||||
|
||||
datamap_t *dmap = GetDataDescMap();
|
||||
while ( dmap )
|
||||
{
|
||||
@ -1322,17 +1340,16 @@ void CBaseEntity::FireNamedOutput( const char *pszOutput, variant_t variant, CBa
|
||||
typedescription_t *dataDesc = &dmap->dataDesc[i];
|
||||
if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) )
|
||||
{
|
||||
CBaseEntityOutput *pOutput = ( CBaseEntityOutput * )( ( int )this + ( int )dataDesc->fieldOffset[0] );
|
||||
CBaseEntityOutput *pOutput = ( CBaseEntityOutput * )( ( int )this + ( int )dataDesc->fieldOffset );
|
||||
if ( !Q_stricmp( dataDesc->externalName, pszOutput ) )
|
||||
{
|
||||
pOutput->FireOutput( variant, pActivator, pCaller, flDelay );
|
||||
return;
|
||||
return pOutput;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dmap = dmap->baseMap;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CBaseEntity::Activate( void )
|
||||
@ -1822,6 +1839,12 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
|
||||
DEFINE_FIELD( m_flSimulationTime, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_nLastThinkTick, FIELD_TICK ),
|
||||
|
||||
DEFINE_FIELD(m_iszScriptId, FIELD_STRING),
|
||||
// m_ScriptScope;
|
||||
// m_hScriptInstance;
|
||||
|
||||
DEFINE_KEYFIELD(m_iszVScripts, FIELD_STRING, "vscripts"),
|
||||
DEFINE_KEYFIELD(m_iszScriptThinkFunction, FIELD_STRING, "thinkfunction"),
|
||||
DEFINE_KEYFIELD( m_nNextThinkTick, FIELD_TICK, "nextthink" ),
|
||||
DEFINE_KEYFIELD( m_fEffects, FIELD_INTEGER, "effects" ),
|
||||
DEFINE_KEYFIELD( m_clrRender, FIELD_COLOR32, "rendercolor" ),
|
||||
@ -2004,6 +2027,10 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
|
||||
DEFINE_INPUTFUNC( FIELD_STRING, "FireUser4", InputFireUser4 ),
|
||||
#endif
|
||||
|
||||
DEFINE_INPUTFUNC(FIELD_STRING, "RunScriptFile", InputRunScriptFile),
|
||||
DEFINE_INPUTFUNC(FIELD_STRING, "RunScriptCode", InputRunScript),
|
||||
DEFINE_INPUTFUNC(FIELD_STRING, "CallScriptFunction", InputCallScriptFunction),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_OUTPUT( m_OutUser1, "OutUser1" ),
|
||||
DEFINE_OUTPUT( m_OutUser2, "OutUser2" ),
|
||||
@ -2081,6 +2108,7 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
|
||||
DEFINE_FUNCTION( SUB_Vanish ),
|
||||
DEFINE_FUNCTION( SUB_CallUseToggle ),
|
||||
DEFINE_THINKFUNC( ShadowCastDistThink ),
|
||||
DEFINE_THINKFUNC( ScriptThink ),
|
||||
|
||||
#ifdef MAPBASE
|
||||
DEFINE_FUNCTION( SUB_RemoveWhenNotVisible ),
|
||||
@ -2097,6 +2125,81 @@ BEGIN_DATADESC_NO_BASE( CBaseEntity )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities" )
|
||||
DEFINE_SCRIPT_INSTANCE_HELPER( &g_BaseEntityScriptInstanceHelper )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ConnectOutputToScript, "ConnectOutput", "Adds an I/O connection that will call the named function when the specified output fires" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( DisconnectOutputFromScript, "DisconnectOutput", "Removes a connected script function from an I/O event." )
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetHealth, "" )
|
||||
DEFINE_SCRIPTFUNC( SetHealth, "" )
|
||||
DEFINE_SCRIPTFUNC( GetMaxHealth, "" )
|
||||
DEFINE_SCRIPTFUNC( SetMaxHealth, "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC( SetModel, "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelName, "GetModelName", "Returns the name of the model" )
|
||||
|
||||
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.")
|
||||
|
||||
|
||||
DEFINE_SCRIPTFUNC( GetClassname, "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetEntityNameAsCStr, "GetName", "" )
|
||||
DEFINE_SCRIPTFUNC( GetPreTemplateName, "Get the entity name stripped of template unique decoration" )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetAbsOrigin, "GetOrigin", "" )
|
||||
DEFINE_SCRIPTFUNC( SetAbsOrigin, "SetAbsOrigin" )
|
||||
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetOrigin, "SetOrigin", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetForward, "GetForwardVector", "Get the forward vector of the entity" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLeft, "GetLeftVector", "Get the left vector of the entity" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetUp, "GetUpVector", "Get the up vector of the entity" )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetForward, "SetForwardVector", "Set the orientation of the entity to have this forward vector" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetAbsVelocity, "GetVelocity", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SetAbsVelocity, "SetVelocity", "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetLocalAngularVelocity, "SetAngularVelocity", "Set the local angular velocity - takes float pitch,yaw,roll velocities" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetLocalAngularVelocity, "GetAngularVelocity", "Get the local angular velocity - returns a vector of pitch,yaw,roll" )
|
||||
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( WorldSpaceCenter, "GetCenter", "Get vector to center of object - absolute coords")
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptEyePosition, "EyePosition", "Get vector to eye position - absolute coords")
|
||||
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_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( ScriptSetOwner, "SetOwner", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetTeamNumber, "GetTeam", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ChangeTeam, "SetTeam", "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetMoveParent, "GetMoveParent", "If in hierarchy, retrieves the entity's parent" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetRootMoveParent, "GetRootMoveParent", "If in hierarchy, walks up the hierarchy to find the root parent" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFirstMoveChild, "FirstMoveChild", "" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptNextMovePeer, "NextMovePeer", "" )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( KeyValueFromString, "__KeyValueFromString", SCRIPT_HIDE )
|
||||
DEFINE_SCRIPTFUNC_NAMED( KeyValueFromFloat, "__KeyValueFromFloat", SCRIPT_HIDE )
|
||||
DEFINE_SCRIPTFUNC_NAMED( KeyValueFromInt, "__KeyValueFromInt", SCRIPT_HIDE )
|
||||
DEFINE_SCRIPTFUNC_NAMED( KeyValueFromVector, "__KeyValueFromVector", SCRIPT_HIDE )
|
||||
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetModelKeyValues, "GetModelKeyValues", "Get a KeyValue class instance on this entity's model")
|
||||
|
||||
DEFINE_SCRIPTFUNC( ValidateScriptScope, "Ensure that an entity's script scope has been created" )
|
||||
DEFINE_SCRIPTFUNC( GetScriptScope, "Retrieve the script-side data associated with an entity" )
|
||||
DEFINE_SCRIPTFUNC( GetScriptId, "Retrieve the unique identifier used to refer to the entity within the scripting system" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( GetScriptOwnerEntity, "GetOwner", "Gets this entity's owner" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SetScriptOwnerEntity, "SetOwner", "Sets this entity's owner" )
|
||||
DEFINE_SCRIPTFUNC( entindex, "" )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
|
||||
// For code error checking
|
||||
extern bool g_bReceivedChainedUpdateOnRemove;
|
||||
|
||||
@ -2196,6 +2299,12 @@ void CBaseEntity::UpdateOnRemove( void )
|
||||
modelinfo->ReleaseDynamicModel( m_nModelIndex ); // no-op if not dynamic
|
||||
m_nModelIndex = -1;
|
||||
}
|
||||
|
||||
if ( m_hScriptInstance )
|
||||
{
|
||||
g_pScriptVM->RemoveInstance( m_hScriptInstance );
|
||||
m_hScriptInstance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -3925,9 +4034,9 @@ const char *CBaseEntity::GetDebugName(void)
|
||||
if ( this == NULL )
|
||||
return "<<null>>";
|
||||
|
||||
if ( m_iName != NULL_STRING )
|
||||
if ( m_iName.Get() != NULL_STRING )
|
||||
{
|
||||
return STRING(m_iName);
|
||||
return STRING(m_iName.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4108,7 +4217,7 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator,
|
||||
// mapper debug message
|
||||
if (pCaller != NULL)
|
||||
{
|
||||
Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, STRING(pCaller->m_iName), GetDebugName(), szInputName, Value.String() );
|
||||
Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, STRING(pCaller->m_iName.Get()), GetDebugName(), szInputName, Value.String() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4155,7 +4264,7 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator,
|
||||
Warning( "!! ERROR: bad input/output link:\n!! Unable to convert value \"%s\" from %s (%s) to field type %i\n!! Target Entity: %s (%s), Input: %s\n",
|
||||
Value.GetDebug(),
|
||||
( pCaller != NULL ) ? STRING(pCaller->m_iClassname) : "<null>",
|
||||
( pCaller != NULL ) ? STRING(pCaller->m_iName) : "<null>",
|
||||
( pCaller != NULL ) ? STRING(pCaller->m_iName.Get()) : "<null>",
|
||||
dmap->dataDesc[i].fieldType,
|
||||
STRING(m_iClassname), GetDebugName(), szInputName );
|
||||
return false;
|
||||
@ -4168,7 +4277,7 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator,
|
||||
Warning( "!! ERROR: bad input/output link:\n!! %s(%s,%s) doesn't match type from %s(%s)\n",
|
||||
STRING(m_iClassname), GetDebugName(), szInputName,
|
||||
( pCaller != NULL ) ? STRING(pCaller->m_iClassname) : "<null>",
|
||||
( pCaller != NULL ) ? STRING(pCaller->m_iName) : "<null>" );
|
||||
( pCaller != NULL ) ? STRING(pCaller->m_iName.Get()) : "<null>" );
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@ -4187,7 +4296,37 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator,
|
||||
data.value = Value;
|
||||
data.nOutputID = outputID;
|
||||
|
||||
(this->*pfnInput)( data );
|
||||
|
||||
// Now, see if there's a function named Input<Name of Input> in this entity's script file.
|
||||
// If so, execute it and let it decide whether to allow the default behavior to also execute.
|
||||
bool bCallInputFunc = true; // Always assume default behavior (do call the input function)
|
||||
ScriptVariant_t functionReturn;
|
||||
|
||||
if ( m_ScriptScope.IsInitialized() )
|
||||
{
|
||||
char szScriptFunctionName[255];
|
||||
Q_strcpy( szScriptFunctionName, "Input" );
|
||||
Q_strcat( szScriptFunctionName, szInputName, 255 );
|
||||
|
||||
g_pScriptVM->SetValue( "activator", ( pActivator ) ? ScriptVariant_t( pActivator->GetScriptInstance() ) : SCRIPT_VARIANT_NULL );
|
||||
g_pScriptVM->SetValue( "caller", ( pCaller ) ? ScriptVariant_t( pCaller->GetScriptInstance() ) : SCRIPT_VARIANT_NULL );
|
||||
|
||||
if( CallScriptFunction( szScriptFunctionName, &functionReturn ) )
|
||||
{
|
||||
bCallInputFunc = functionReturn.m_bool;
|
||||
}
|
||||
}
|
||||
|
||||
if( bCallInputFunc )
|
||||
{
|
||||
(this->*pfnInput)( data );
|
||||
}
|
||||
|
||||
if ( m_ScriptScope.IsInitialized() )
|
||||
{
|
||||
g_pScriptVM->ClearValue( "activator" );
|
||||
g_pScriptVM->ClearValue( "caller" );
|
||||
}
|
||||
}
|
||||
else if ( dmap->dataDesc[i].flags & FTYPEDESC_KEY )
|
||||
{
|
||||
@ -4210,7 +4349,7 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator,
|
||||
}
|
||||
}
|
||||
|
||||
DevMsg( 2, "unhandled input: (%s) -> (%s,%s)\n", szInputName, STRING(m_iClassname), GetDebugName()/*,", from (%s,%s)" STRING(pCaller->m_iClassname), STRING(pCaller->m_iName)*/ );
|
||||
DevMsg( 2, "unhandled input: (%s) -> (%s,%s)\n", szInputName, STRING(m_iClassname), GetDebugName()/*,", from (%s,%s)" STRING(pCaller->m_iClassname), STRING(pCaller->m_iName.Get())*/ );
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -5300,6 +5439,36 @@ void CC_Ent_Name( const CCommand& args )
|
||||
}
|
||||
static ConCommand ent_name("ent_name", CC_Ent_Name, 0, FCVAR_CHEAT);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
void DumpScriptScope(CBasePlayer* pPlayer, const char* name)
|
||||
{
|
||||
CBaseEntity* pEntity = NULL;
|
||||
while ((pEntity = GetNextCommandEntity(pPlayer, name, pEntity)) != NULL)
|
||||
{
|
||||
if (pEntity->m_ScriptScope.IsInitialized())
|
||||
{
|
||||
Msg("----Script Dump for entity %s\n", pEntity->GetDebugName());
|
||||
HSCRIPT hDumpScopeFunc = g_pScriptVM->LookupFunction("__DumpScope");
|
||||
g_pScriptVM->Call(hDumpScopeFunc, NULL, true, NULL, 1, (HSCRIPT)pEntity->m_ScriptScope);
|
||||
Msg("----End Script Dump\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DevWarning("ent_script_dump: Entity %s has no script scope!\n", pEntity->GetDebugName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void CC_Ent_Script_Dump( const CCommand& args )
|
||||
{
|
||||
DumpScriptScope(UTIL_GetCommandClient(),args[1]);
|
||||
}
|
||||
static ConCommand ent_script_dump("ent_script_dump", CC_Ent_Script_Dump, "Dumps the names and values of this entity's script scope to the console\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef MAPBASE
|
||||
class CEntTextAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback
|
||||
@ -7223,7 +7392,6 @@ void CBaseEntity::InputPassRandomUser( inputdata_t& inputdata )
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets the entity's targetname.
|
||||
@ -7820,6 +7988,256 @@ void CBaseEntity::InputSetThinkNull( inputdata_t& inputdata )
|
||||
#endif
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Use the string as the filename of a script file
|
||||
// that should be loaded from disk, compiled, and run.
|
||||
//---------------------------------------------------------
|
||||
void CBaseEntity::InputRunScriptFile(inputdata_t& inputdata)
|
||||
{
|
||||
RunScriptFile(inputdata.value.String());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Send the string to the VM as source code and execute it
|
||||
//---------------------------------------------------------
|
||||
void CBaseEntity::InputRunScript(inputdata_t& inputdata)
|
||||
{
|
||||
RunScript(inputdata.value.String(), "InputRunScript");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Make an explicit function call.
|
||||
//---------------------------------------------------------
|
||||
void CBaseEntity::InputCallScriptFunction(inputdata_t& inputdata)
|
||||
{
|
||||
CallScriptFunction(inputdata.value.String(), NULL);
|
||||
}
|
||||
|
||||
// #define VMPROFILE // define to profile vscript calls
|
||||
|
||||
#ifdef VMPROFILE
|
||||
float g_debugCumulativeTime = 0.0;
|
||||
float g_debugCounter = 0;
|
||||
|
||||
#define START_VMPROFILE float debugStartTime = Plat_FloatTime();
|
||||
#define UPDATE_VMPROFILE \
|
||||
g_debugCumulativeTime += Plat_FloatTime() - debugStartTime; \
|
||||
g_debugCounter++; \
|
||||
if ( g_debugCounter >= 500 ) \
|
||||
{ \
|
||||
DevMsg("***VSCRIPT PROFILE***: %s %s: %6.4f milliseconds\n", "500 vscript function calls", "", g_debugCumulativeTime*1000.0 ); \
|
||||
g_debugCounter = 0; \
|
||||
g_debugCumulativeTime = 0.0; \
|
||||
} \
|
||||
|
||||
#else
|
||||
|
||||
#define START_VMPROFILE
|
||||
#define UPDATE_VMPROFILE
|
||||
|
||||
#endif // VMPROFILE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns true if the function was located and called. false otherwise.
|
||||
// NOTE: Assumes the function takes no parameters at the moment.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseEntity::CallScriptFunction(const char* pFunctionName, ScriptVariant_t* pFunctionReturn)
|
||||
{
|
||||
START_VMPROFILE
|
||||
|
||||
if (!ValidateScriptScope())
|
||||
{
|
||||
DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
HSCRIPT hFunc = m_ScriptScope.LookupFunction(pFunctionName);
|
||||
|
||||
if (hFunc)
|
||||
{
|
||||
m_ScriptScope.Call(hFunc, pFunctionReturn);
|
||||
m_ScriptScope.ReleaseFunction(hFunc);
|
||||
|
||||
UPDATE_VMPROFILE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseEntity::ConnectOutputToScript(const char* pszOutput, const char* pszScriptFunc)
|
||||
{
|
||||
CBaseEntityOutput* pOutput = FindNamedOutput(pszOutput);
|
||||
if (!pOutput)
|
||||
{
|
||||
DevMsg(2, "Script failed to find output \"%s\"\n", pszOutput);
|
||||
return;
|
||||
}
|
||||
|
||||
string_t iszSelf = AllocPooledString("!self"); // @TODO: cache this [4/25/2008 tom]
|
||||
CEventAction* pAction = pOutput->GetActionList();
|
||||
while (pAction)
|
||||
{
|
||||
if (pAction->m_iTarget == iszSelf &&
|
||||
pAction->m_flDelay == 0 &&
|
||||
pAction->m_nTimesToFire == EVENT_FIRE_ALWAYS &&
|
||||
V_strcmp(STRING(pAction->m_iTargetInput), "CallScriptFunction") == 0 &&
|
||||
V_strcmp(STRING(pAction->m_iParameter), pszScriptFunc) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pAction = pAction->m_pNext;
|
||||
}
|
||||
|
||||
pAction = new CEventAction(NULL);
|
||||
pAction->m_iTarget = iszSelf;
|
||||
pAction->m_iTargetInput = AllocPooledString("CallScriptFunction");
|
||||
pAction->m_iParameter = AllocPooledString(pszScriptFunc);
|
||||
pOutput->AddEventAction(pAction);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseEntity::DisconnectOutputFromScript(const char* pszOutput, const char* pszScriptFunc)
|
||||
{
|
||||
CBaseEntityOutput* pOutput = FindNamedOutput(pszOutput);
|
||||
if (!pOutput)
|
||||
{
|
||||
DevMsg(2, "Script failed to find output \"%s\"\n", pszOutput);
|
||||
return;
|
||||
}
|
||||
|
||||
string_t iszSelf = AllocPooledString("!self"); // @TODO: cache this [4/25/2008 tom]
|
||||
CEventAction* pAction = pOutput->GetActionList();
|
||||
while (pAction)
|
||||
{
|
||||
if (pAction->m_iTarget == iszSelf &&
|
||||
pAction->m_flDelay == 0 &&
|
||||
pAction->m_nTimesToFire == EVENT_FIRE_ALWAYS &&
|
||||
V_strcmp(STRING(pAction->m_iTargetInput), "CallScriptFunction") == 0 &&
|
||||
V_strcmp(STRING(pAction->m_iParameter), pszScriptFunc) == 0)
|
||||
{
|
||||
pOutput->RemoveEventAction(pAction);
|
||||
delete pAction;
|
||||
return;
|
||||
}
|
||||
pAction = pAction->m_pNext;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseEntity::ScriptThink(void)
|
||||
{
|
||||
ScriptVariant_t varThinkRetVal;
|
||||
if (CallScriptFunction(m_iszScriptThinkFunction.ToCStr(), &varThinkRetVal))
|
||||
{
|
||||
float flThinkFrequency = 0.0f;
|
||||
if (!varThinkRetVal.AssignTo(&flThinkFrequency))
|
||||
{
|
||||
// use default think interval if script think function doesn't provide one
|
||||
flThinkFrequency = sv_script_think_interval.GetFloat();
|
||||
}
|
||||
SetContextThink(&CBaseEntity::ScriptThink,
|
||||
gpGlobals->curtime + flThinkFrequency, "ScriptThink");
|
||||
}
|
||||
else
|
||||
{
|
||||
DevWarning("%s FAILED to call script think function %s!\n", GetDebugName(), STRING(m_iszScriptThinkFunction));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* CBaseEntity::GetScriptId()
|
||||
{
|
||||
return STRING(m_iszScriptThinkFunction);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::GetScriptScope()
|
||||
{
|
||||
return m_ScriptScope;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::ScriptGetMoveParent(void)
|
||||
{
|
||||
return ToHScript(GetMoveParent());
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::ScriptGetRootMoveParent()
|
||||
{
|
||||
return ToHScript(GetRootMoveParent());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::ScriptFirstMoveChild(void)
|
||||
{
|
||||
return ToHScript(FirstMoveChild());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::ScriptNextMovePeer(void)
|
||||
{
|
||||
return ToHScript(NextMovePeer());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Load, compile, and run a script file from disk.
|
||||
// Input : *pScriptFile - The filename of the script file.
|
||||
// bUseRootScope - If true, runs this script in the root scope, not
|
||||
// in this entity's private scope.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseEntity::RunScriptFile(const char* pScriptFile, bool bUseRootScope)
|
||||
{
|
||||
if (!ValidateScriptScope())
|
||||
{
|
||||
DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bUseRootScope)
|
||||
{
|
||||
return VScriptRunScript(pScriptFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
return VScriptRunScript(pScriptFile, m_ScriptScope, true);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Compile and execute a discrete string of script source code
|
||||
// Input : *pScriptText - A string containing script code to compile and run
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseEntity::RunScript(const char* pScriptText, const char* pDebugFilename)
|
||||
{
|
||||
if (!ValidateScriptScope())
|
||||
{
|
||||
DevMsg("\n***\nFAILED to create private ScriptScope. ABORTING script\n***\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_ScriptScope.Run(pScriptText, pDebugFilename) == SCRIPT_ERROR)
|
||||
{
|
||||
DevWarning(" Entity %s encountered an error in RunScript()\n", GetDebugName());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *contextName -
|
||||
@ -8796,6 +9214,266 @@ void CBaseEntity::SetCollisionBoundsFromModel()
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::GetScriptInstance()
|
||||
{
|
||||
if (!m_hScriptInstance)
|
||||
{
|
||||
if (m_iszScriptId == NULL_STRING)
|
||||
{
|
||||
char* szName = (char*)stackalloc(1024);
|
||||
g_pScriptVM->GenerateUniqueKey((m_iName.Get() != NULL_STRING) ? STRING(GetEntityName()) : GetClassname(), szName, 1024);
|
||||
m_iszScriptId = AllocPooledString(szName);
|
||||
}
|
||||
|
||||
m_hScriptInstance = g_pScriptVM->RegisterInstance(GetScriptDesc(), this);
|
||||
g_pScriptVM->SetInstanceUniqeId(m_hScriptInstance, STRING(m_iszScriptId));
|
||||
}
|
||||
return m_hScriptInstance;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Using my edict, cook up a unique VScript scope that's private to me, and
|
||||
// persistent.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseEntity::ValidateScriptScope()
|
||||
{
|
||||
if (!m_ScriptScope.IsInitialized())
|
||||
{
|
||||
if (scriptmanager == NULL)
|
||||
{
|
||||
ExecuteOnce(DevMsg("Cannot execute script because scripting is disabled (-scripting)\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_pScriptVM == NULL)
|
||||
{
|
||||
ExecuteOnce(DevMsg(" Cannot execute script because there is no available VM\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Force instance creation
|
||||
GetScriptInstance();
|
||||
|
||||
EHANDLE hThis;
|
||||
hThis.Set(this);
|
||||
|
||||
bool bResult = m_ScriptScope.Init(STRING(m_iszScriptId));
|
||||
|
||||
if (!bResult)
|
||||
{
|
||||
DevMsg("%s couldn't create ScriptScope!\n", GetDebugName());
|
||||
return false;
|
||||
}
|
||||
g_pScriptVM->SetValue(m_ScriptScope, "self", GetScriptInstance());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Run all of the vscript files that are set in this entity's VSCRIPTS
|
||||
// field in Hammer. The list is space-delimited.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseEntity::RunVScripts()
|
||||
{
|
||||
if (m_iszVScripts == NULL_STRING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ValidateScriptScope();
|
||||
|
||||
// All functions we want to have call chained instead of overwritten
|
||||
// by other scripts in this entities list.
|
||||
static const char* sCallChainFunctions[] =
|
||||
{
|
||||
"OnPostSpawn",
|
||||
"Precache"
|
||||
};
|
||||
|
||||
ScriptLanguage_t language = g_pScriptVM->GetLanguage();
|
||||
|
||||
// Make a call chainer for each in this entities scope
|
||||
for (int j = 0; j < ARRAYSIZE(sCallChainFunctions); ++j)
|
||||
{
|
||||
|
||||
if (language == SL_PYTHON)
|
||||
{
|
||||
// UNDONE - handle call chaining in python
|
||||
;
|
||||
}
|
||||
else if (language == SL_SQUIRREL)
|
||||
{
|
||||
//TODO: For perf, this should be precompiled and the %s should be passed as a parameter
|
||||
HSCRIPT hCreateChainScript = g_pScriptVM->CompileScript(CFmtStr("%sCallChain <- CSimpleCallChainer(\"%s\", self.GetScriptScope(), true)", sCallChainFunctions[j], sCallChainFunctions[j]));
|
||||
g_pScriptVM->Run(hCreateChainScript, (HSCRIPT)m_ScriptScope);
|
||||
}
|
||||
}
|
||||
|
||||
char szScriptsList[255];
|
||||
Q_strcpy(szScriptsList, STRING(m_iszVScripts));
|
||||
CUtlStringList szScripts;
|
||||
|
||||
V_SplitString(szScriptsList, " ", szScripts);
|
||||
|
||||
for (int i = 0; i < szScripts.Count(); i++)
|
||||
{
|
||||
Log( "%s executing script: %s\n", GetDebugName(), szScripts[i]);
|
||||
|
||||
RunScriptFile(szScripts[i], IsWorld());
|
||||
|
||||
for (int j = 0; j < ARRAYSIZE(sCallChainFunctions); ++j)
|
||||
{
|
||||
if (language == SL_PYTHON)
|
||||
{
|
||||
// UNDONE - handle call chaining in python
|
||||
;
|
||||
}
|
||||
else if (language == SL_SQUIRREL)
|
||||
{
|
||||
//TODO: For perf, this should be precompiled and the %s should be passed as a parameter.
|
||||
HSCRIPT hRunPostScriptExecute = g_pScriptVM->CompileScript(CFmtStr("%sCallChain.PostScriptExecute()", sCallChainFunctions[j]));
|
||||
g_pScriptVM->Run(hRunPostScriptExecute, (HSCRIPT)m_ScriptScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_iszScriptThinkFunction != NULL_STRING)
|
||||
{
|
||||
SetContextThink(&CBaseEntity::ScriptThink, gpGlobals->curtime + sv_script_think_interval.GetFloat(), "ScriptThink");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// This is called during entity spawning and after restore to allow scripts to precache any
|
||||
// resources they need.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void CBaseEntity::RunPrecacheScripts(void)
|
||||
{
|
||||
if (m_iszVScripts == NULL_STRING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HSCRIPT hScriptPrecache = m_ScriptScope.LookupFunction("DispatchPrecache");
|
||||
if (hScriptPrecache)
|
||||
{
|
||||
g_pScriptVM->Call(hScriptPrecache, m_ScriptScope);
|
||||
m_ScriptScope.ReleaseFunction(hScriptPrecache);
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseEntity::RunOnPostSpawnScripts(void)
|
||||
{
|
||||
if (m_iszVScripts == NULL_STRING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HSCRIPT hFuncConnect = g_pScriptVM->LookupFunction("ConnectOutputs");
|
||||
if (hFuncConnect)
|
||||
{
|
||||
g_pScriptVM->Call(hFuncConnect, NULL, true, NULL, (HSCRIPT)m_ScriptScope);
|
||||
g_pScriptVM->ReleaseFunction(hFuncConnect);
|
||||
}
|
||||
|
||||
HSCRIPT hFuncDisp = m_ScriptScope.LookupFunction("DispatchOnPostSpawn");
|
||||
if (hFuncDisp)
|
||||
{
|
||||
variant_t variant;
|
||||
variant.SetString(MAKE_STRING("DispatchOnPostSpawn"));
|
||||
g_EventQueue.AddEvent(this, "CallScriptFunction", variant, 0, this, this);
|
||||
m_ScriptScope.ReleaseFunction(hFuncDisp);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HSCRIPT CBaseEntity::GetScriptOwnerEntity()
|
||||
{
|
||||
return ToHScript(GetOwnerEntity());
|
||||
}
|
||||
|
||||
void CBaseEntity::SetScriptOwnerEntity(HSCRIPT pOwner)
|
||||
{
|
||||
SetOwnerEntity(ToEnt(pOwner));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// VScript access to model's key values
|
||||
// for iteration and value access, use:
|
||||
// ScriptFindKey, ScriptGetFirstSubKey, ScriptGetString,
|
||||
// ScriptGetInt, ScriptGetFloat, ScriptGetNextKey
|
||||
//-----------------------------------------------------------------------------
|
||||
HSCRIPT CBaseEntity::ScriptGetModelKeyValues( void )
|
||||
{
|
||||
KeyValues *pModelKeyValues = new KeyValues("");
|
||||
HSCRIPT hScript = NULL;
|
||||
const char *pszModelName = modelinfo->GetModelName( GetModel() );
|
||||
const char *pBuffer = modelinfo->GetModelKeyValueText( GetModel() ) ;
|
||||
|
||||
if ( pModelKeyValues->LoadFromBuffer( pszModelName, pBuffer ) )
|
||||
{
|
||||
// UNDONE: how does destructor get called on this
|
||||
m_pScriptModelKeyValues = new CScriptKeyValues( pModelKeyValues );
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??? Does name need to be unique???
|
||||
|
||||
hScript = g_pScriptVM->RegisterInstance( m_pScriptModelKeyValues );
|
||||
|
||||
/*
|
||||
KeyValues *pParticleEffects = pModelKeyValues->FindKey("Particles");
|
||||
if ( pParticleEffects )
|
||||
{
|
||||
// Start grabbing the sounds and slotting them in
|
||||
for ( KeyValues *pSingleEffect = pParticleEffects->GetFirstSubKey(); pSingleEffect; pSingleEffect = pSingleEffect->GetNextKey() )
|
||||
{
|
||||
const char *pParticleEffectName = pSingleEffect->GetString( "name", "" );
|
||||
PrecacheParticleSystem( pParticleEffectName );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return hScript;
|
||||
}
|
||||
|
||||
void CBaseEntity::ScriptSetLocalAngularVelocity(float pitchVel, float yawVel, float rollVel)
|
||||
{
|
||||
QAngle qa;
|
||||
qa.Init(pitchVel, yawVel, rollVel);
|
||||
SetLocalAngularVelocity(qa);
|
||||
}
|
||||
|
||||
const Vector& CBaseEntity::ScriptGetLocalAngularVelocity(void)
|
||||
{
|
||||
QAngle qa = GetLocalAngularVelocity();
|
||||
static Vector v;
|
||||
v.x = qa.x;
|
||||
v.y = qa.y;
|
||||
v.z = qa.z;
|
||||
return v;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vscript: Gets the min collision bounds, centered on object
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vector& CBaseEntity::ScriptGetBoundingMins(void)
|
||||
{
|
||||
return m_Collision.OBBMins();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Vscript: Gets the max collision bounds, centered on object
|
||||
//-----------------------------------------------------------------------------
|
||||
const Vector& CBaseEntity::ScriptGetBoundingMaxs(void)
|
||||
{
|
||||
return m_Collision.OBBMaxs();
|
||||
}
|
||||
|
||||
|
||||
#ifdef MAPBASE
|
||||
extern int EntityFactory_AutoComplete( const char *cmdname, CUtlVector< CUtlString > &commands, CUtlRBTree< CUtlString > &symbols, char *substring, int checklen = 0 );
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include "shareddefs.h"
|
||||
#include "engine/ivmodelinfo.h"
|
||||
|
||||
#include "vscript/ivscript.h"
|
||||
#include "vscript_server.h"
|
||||
|
||||
class CDamageModifier;
|
||||
class CDmgAccumulator;
|
||||
|
||||
@ -311,11 +314,13 @@ a list of all CBaseEntitys is kept in gEntList
|
||||
CBaseEntity *CreateEntityByName( const char *className, int iForceEdictIndex = -1 );
|
||||
CBaseNetworkable *CreateNetworkableByName( const char *className );
|
||||
|
||||
CBaseEntity* ToEnt(HSCRIPT hScript);
|
||||
|
||||
// creates an entity and calls all the necessary spawn functions
|
||||
extern void SpawnEntityByName( const char *className, CEntityMapData *mapData = NULL );
|
||||
|
||||
// calls the spawn functions for an entity
|
||||
extern int DispatchSpawn( CBaseEntity *pEntity );
|
||||
extern int DispatchSpawn( CBaseEntity *pEntity, bool bRunVScripts = true);
|
||||
|
||||
inline CBaseEntity *GetContainingEntity( edict_t *pent );
|
||||
|
||||
@ -379,6 +384,8 @@ public:
|
||||
DECLARE_SERVERCLASS();
|
||||
// data description
|
||||
DECLARE_DATADESC();
|
||||
// script description
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
// memory handling
|
||||
void *operator new( size_t stAllocateBlock );
|
||||
@ -493,6 +500,8 @@ public:
|
||||
virtual void SetOwnerEntity( CBaseEntity* pOwner );
|
||||
void SetEffectEntity( CBaseEntity *pEffectEnt );
|
||||
CBaseEntity *GetEffectEntity() const;
|
||||
HSCRIPT GetScriptOwnerEntity();
|
||||
virtual void SetScriptOwnerEntity(HSCRIPT pOwner);
|
||||
|
||||
// Only CBaseEntity implements these. CheckTransmit calls the virtual ShouldTransmit to see if the
|
||||
// entity wants to be sent. If so, it calls SetTransmit, which will mark any dependents for transmission too.
|
||||
@ -563,9 +572,14 @@ public:
|
||||
virtual bool KeyValue( const char *szKeyName, float flValue );
|
||||
virtual bool KeyValue( const char *szKeyName, const Vector &vecValue );
|
||||
virtual bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen );
|
||||
bool KeyValueFromString( const char *szKeyName, const char *szValue ) { return KeyValue( szKeyName, szValue ); }
|
||||
bool KeyValueFromFloat( const char *szKeyName, float flValue ) { return KeyValue( szKeyName, flValue ); }
|
||||
bool KeyValueFromInt( const char *szKeyName, int nValue ) { return KeyValue( szKeyName, nValue ); }
|
||||
bool KeyValueFromVector( const char *szKeyName, const Vector &vecValue ) { return KeyValue( szKeyName, vecValue ); }
|
||||
|
||||
void ValidateEntityConnections();
|
||||
void FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay = 0.0f );
|
||||
CBaseEntityOutput *FindNamedOutput( const char *pszOutput );
|
||||
|
||||
// Activate - called for each entity after each load game and level load
|
||||
virtual void Activate( void );
|
||||
@ -588,6 +602,8 @@ public:
|
||||
int GetParentAttachment();
|
||||
|
||||
string_t GetEntityName();
|
||||
const char* GetEntityNameAsCStr(); // This method is temporary for VSCRIPT functionality until we figure out what to do with string_t (sjb)
|
||||
const char* GetPreTemplateName(); // Not threadsafe. Get the name stripped of template unique decoration
|
||||
|
||||
bool NameMatches( const char *pszNameOrWildcard );
|
||||
bool ClassMatches( const char *pszClassOrWildcard );
|
||||
@ -735,6 +751,14 @@ public:
|
||||
COutputEvent m_OnKilled;
|
||||
#endif
|
||||
|
||||
void InputRunScript(inputdata_t& inputdata);
|
||||
void InputRunScriptFile(inputdata_t& inputdata);
|
||||
void InputCallScriptFunction(inputdata_t& inputdata);
|
||||
|
||||
bool RunScriptFile(const char* pScriptFile, bool bUseRootScope = false);
|
||||
bool RunScript(const char* pScriptText, const char* pDebugFilename = "CBaseEntity::RunScript");
|
||||
|
||||
|
||||
// Returns the origin at which to play an inputted dispatcheffect
|
||||
virtual void GetInputDispatchEffectPosition( const char *sInputString, Vector &pOrigin, QAngle &pAngles );
|
||||
|
||||
@ -1715,7 +1739,7 @@ private:
|
||||
// was pev->flags
|
||||
CNetworkVarForDerived( int, m_fFlags );
|
||||
|
||||
string_t m_iName; // name used to identify this entity
|
||||
CNetworkVar( string_t, m_iName ); // name used to identify this entity
|
||||
|
||||
// Damage modifiers
|
||||
friend class CDamageModifier;
|
||||
@ -1920,6 +1944,59 @@ public:
|
||||
{
|
||||
return s_bAbsQueriesValid;
|
||||
}
|
||||
|
||||
|
||||
// VSCRIPT
|
||||
HSCRIPT GetScriptInstance();
|
||||
bool ValidateScriptScope();
|
||||
virtual void RunVScripts();
|
||||
bool CallScriptFunction(const char* pFunctionName, ScriptVariant_t* pFunctionReturn);
|
||||
void ConnectOutputToScript(const char* pszOutput, const char* pszScriptFunc);
|
||||
void DisconnectOutputFromScript(const char* pszOutput, const char* pszScriptFunc);
|
||||
void ScriptThink();
|
||||
const char* GetScriptId();
|
||||
HSCRIPT GetScriptScope();
|
||||
void RunPrecacheScripts(void);
|
||||
void RunOnPostSpawnScripts(void);
|
||||
|
||||
HSCRIPT ScriptGetMoveParent(void);
|
||||
HSCRIPT ScriptGetRootMoveParent();
|
||||
HSCRIPT ScriptFirstMoveChild(void);
|
||||
HSCRIPT ScriptNextMovePeer(void);
|
||||
|
||||
const Vector& ScriptEyePosition(void) { static Vector vec; vec = EyePosition(); return vec; }
|
||||
void ScriptSetAngles(float fPitch, float fYaw, float fRoll) { QAngle angles(fPitch, fYaw, fRoll); Teleport(NULL, &angles, NULL); }
|
||||
const Vector& ScriptGetAngles(void) { static Vector vec; QAngle qa = GetAbsAngles(); vec.x = qa.x; vec.y = qa.y; vec.z = qa.z; return vec; }
|
||||
|
||||
void ScriptSetSize(const Vector& mins, const Vector& maxs) { UTIL_SetSize(this, mins, maxs); }
|
||||
void ScriptUtilRemove(void) { UTIL_Remove(this); }
|
||||
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); }
|
||||
const Vector& ScriptGetForward(void) { static Vector vecForward; GetVectors(&vecForward, NULL, NULL); return vecForward; }
|
||||
const Vector& ScriptGetLeft(void) { static Vector vecLeft; GetVectors(NULL, &vecLeft, NULL); return vecLeft; }
|
||||
const Vector& ScriptGetUp(void) { static Vector vecUp; GetVectors(NULL, NULL, &vecUp); return vecUp; }
|
||||
|
||||
const char* ScriptGetModelName(void) const;
|
||||
HSCRIPT ScriptGetModelKeyValues(void);
|
||||
|
||||
void ScriptEmitSound(const char* soundname);
|
||||
float ScriptSoundDuration(const char* soundname, const char* actormodel);
|
||||
|
||||
void VScriptPrecacheScriptSound(const char* soundname);
|
||||
|
||||
const Vector& ScriptGetLocalAngularVelocity( void );
|
||||
void ScriptSetLocalAngularVelocity( float pitchVel, float yawVel, float rollVel );
|
||||
|
||||
const Vector& ScriptGetBoundingMins(void);
|
||||
const Vector& ScriptGetBoundingMaxs(void);
|
||||
|
||||
string_t m_iszVScripts;
|
||||
string_t m_iszScriptThinkFunction;
|
||||
CScriptScope m_ScriptScope;
|
||||
HSCRIPT m_hScriptInstance;
|
||||
string_t m_iszScriptId;
|
||||
CScriptKeyValues* m_pScriptModelKeyValues;
|
||||
};
|
||||
|
||||
// Send tables exposed in this module.
|
||||
@ -2048,6 +2125,21 @@ inline string_t CBaseEntity::GetEntityName()
|
||||
return m_iName;
|
||||
}
|
||||
|
||||
inline const char *CBaseEntity::GetEntityNameAsCStr()
|
||||
{
|
||||
return STRING(m_iName.Get());
|
||||
}
|
||||
|
||||
inline const char *CBaseEntity::GetPreTemplateName()
|
||||
{
|
||||
const char *pszDelimiter = V_strrchr( STRING(m_iName.Get()), '&' );
|
||||
if ( !pszDelimiter )
|
||||
return STRING( m_iName.Get() );
|
||||
static char szStrippedName[128];
|
||||
V_strncpy( szStrippedName, STRING( m_iName.Get() ), MIN( ARRAYSIZE(szStrippedName), pszDelimiter - STRING( m_iName.Get() ) + 1 ) );
|
||||
return szStrippedName;
|
||||
}
|
||||
|
||||
inline void CBaseEntity::SetName( string_t newName )
|
||||
{
|
||||
m_iName = newName;
|
||||
@ -2726,6 +2818,14 @@ inline void CBaseEntity::FireBullets( int cShots, const Vector &vecSrc,
|
||||
FireBullets( info );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// VScript
|
||||
//-----------------------------------------------------------------------------
|
||||
inline const char* CBaseEntity::ScriptGetModelName(void) const
|
||||
{
|
||||
return STRING(m_ModelName);
|
||||
}
|
||||
|
||||
// Ugly technique to override base member functions
|
||||
// Normally it's illegal to cast a pointer to a member function of a derived class to a pointer to a
|
||||
// member function of a base class. static_cast is a sleezy way around that problem.
|
||||
|
@ -95,6 +95,10 @@ BEGIN_DATADESC( CBaseFlex )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CBaseFlex, CBaseAnimating, "Animated characters who have vertex flex capability." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetOldestScene, "GetCurrentScene", "Returns the instance of the oldest active scene entity (if any)." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSceneByIndex, "GetSceneByIndex", "Returns the instance of the scene entity at the specified index." )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS( funCBaseFlex, CBaseFlex ); // meaningless independant class!!
|
||||
@ -421,7 +425,8 @@ void CBaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEn
|
||||
info.m_pEvent = event;
|
||||
info.m_pScene = scene;
|
||||
info.m_hTarget = pTarget;
|
||||
info.m_bStarted = false;
|
||||
info.m_bStarted = false;
|
||||
info.m_hSceneEntity = pSceneEnt;
|
||||
|
||||
#ifdef MAPBASE
|
||||
if (StartSceneEvent( &info, scene, event, actor, pTarget, pSceneEnt ))
|
||||
@ -2029,6 +2034,37 @@ float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname )
|
||||
#endif
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Returns the script instance of the scene entity associated with our oldest ("top level") scene event
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
HSCRIPT CBaseFlex::ScriptGetOldestScene( void )
|
||||
{
|
||||
if ( m_SceneEvents.Count() > 0 )
|
||||
{
|
||||
CSceneEventInfo curScene = m_SceneEvents.Head();
|
||||
return ToHScript( (CBaseEntity*)(curScene.m_hSceneEntity.Get()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Returns the script instance of the scene at the specified index, or null if index >= count
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
HSCRIPT CBaseFlex::ScriptGetSceneByIndex( int index )
|
||||
{
|
||||
if ( m_SceneEvents.IsValidIndex( index ) )
|
||||
{
|
||||
CSceneEventInfo curScene = m_SceneEvents.Element( index );
|
||||
return ToHScript( (CBaseEntity*)(curScene.m_hSceneEntity.Get()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FIXME: move to CBaseActor
|
||||
|
@ -46,6 +46,8 @@ public:
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_PREDICTABLE();
|
||||
// script description
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
// Construction
|
||||
CBaseFlex( void );
|
||||
@ -130,6 +132,10 @@ public:
|
||||
virtual float PlayAutoGeneratedSoundScene( const char *soundname );
|
||||
#endif
|
||||
|
||||
// Returns the script instance of the scene entity associated with our oldest ("top level") scene event
|
||||
virtual HSCRIPT ScriptGetOldestScene( void );
|
||||
virtual HSCRIPT ScriptGetSceneByIndex( int index );
|
||||
|
||||
virtual int GetSpecialDSP( void ) { return 0; }
|
||||
|
||||
protected:
|
||||
|
@ -396,6 +396,28 @@ void CBaseEntityOutput::AddEventAction( CEventAction *pEventAction )
|
||||
m_ActionList = pEventAction;
|
||||
}
|
||||
|
||||
void CBaseEntityOutput::RemoveEventAction( CEventAction *pEventAction )
|
||||
{
|
||||
CEventAction *pAction = GetActionList();
|
||||
CEventAction *pPrevAction = NULL;
|
||||
while ( pAction )
|
||||
{
|
||||
if ( pAction == pEventAction )
|
||||
{
|
||||
if ( !pPrevAction )
|
||||
{
|
||||
m_ActionList = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrevAction->m_pNext = pAction->m_pNext;
|
||||
}
|
||||
return;
|
||||
}
|
||||
pAction = pAction->m_pNext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// save data description for the event queue
|
||||
BEGIN_SIMPLE_DATADESC( CBaseEntityOutput )
|
||||
|
@ -26,6 +26,7 @@ class IDataCache;
|
||||
class IMDLCache;
|
||||
class IServerEngineTools;
|
||||
class IXboxSystem;
|
||||
class IScriptManager;
|
||||
class CSteamAPIContext;
|
||||
class CSteamGameServerAPIContext;
|
||||
|
||||
@ -43,6 +44,7 @@ extern IDataCache *datacache;
|
||||
extern IMDLCache *mdlcache;
|
||||
extern IServerEngineTools *serverenginetools;
|
||||
extern IXboxSystem *xboxsystem; // 360 only
|
||||
extern IScriptManager *scriptmanager;
|
||||
extern CSteamAPIContext *steamapicontext; // available on game clients
|
||||
extern CSteamGameServerAPIContext *steamgameserverapicontext; //available on game servers
|
||||
|
||||
|
@ -667,7 +667,7 @@ CBaseEntity *CGlobalEntityList::FindEntityByName( CBaseEntity *pStartEntity, con
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !ent->m_iName )
|
||||
if ( !ent->m_iName.Get() )
|
||||
continue;
|
||||
|
||||
if ( ent->NameMatches( szName ) )
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
|
||||
void ParseEventAction( const char *EventData );
|
||||
void AddEventAction( CEventAction *pEventAction );
|
||||
void RemoveEventAction( CEventAction *pEventAction );
|
||||
|
||||
int Save( ISave &save );
|
||||
int Restore( IRestore &restore, int elementCount );
|
||||
|
@ -30,6 +30,7 @@ class CEnvEntityMaker : public CPointEntity
|
||||
DECLARE_CLASS( CEnvEntityMaker, CPointEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
virtual void Spawn( void );
|
||||
virtual void Activate( void );
|
||||
@ -43,6 +44,10 @@ public:
|
||||
void InputForceSpawnAtPosition( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
void SpawnEntityFromScript();
|
||||
void SpawnEntityAtEntityOriginFromScript(HSCRIPT hEntity);
|
||||
void SpawnEntityAtNamedEntityOriginFromScript(const char* pszName);
|
||||
void SpawnEntityAtLocationFromScript(const Vector& vecAlternateOrigin, const Vector& vecAlternateAngles);
|
||||
private:
|
||||
|
||||
CPointTemplate *FindTemplate();
|
||||
@ -102,6 +107,13 @@ BEGIN_DATADESC( CEnvEntityMaker )
|
||||
DEFINE_THINKFUNC( CheckSpawnThink ),
|
||||
END_DATADESC()
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CEnvEntityMaker, CBaseEntity, "env_entity_maker" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityFromScript, "SpawnEntity", "Create an entity at the location of the maker" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityAtEntityOriginFromScript, "SpawnEntityAtEntityOrigin", "Create an entity at the location of a specified entity instance" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityAtNamedEntityOriginFromScript, "SpawnEntityAtNamedEntityOrigin", "Create an entity at the location of a named entity" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( SpawnEntityAtLocationFromScript, "SpawnEntityAtLocation", "Create an entity at a specified location and orientaton, orientation is Euler angle in degrees (pitch, yaw, roll)" )
|
||||
END_SCRIPTDESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_entity_maker, CEnvEntityMaker );
|
||||
|
||||
|
||||
@ -266,8 +278,50 @@ void CEnvEntityMaker::SpawnEntity( Vector vecAlternateOrigin, QAngle vecAlternat
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pTemplate->CreationComplete( hNewEntities );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityFromScript()
|
||||
{
|
||||
SpawnEntity();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityAtEntityOriginFromScript( HSCRIPT hEntity )
|
||||
{
|
||||
CBaseEntity *pTargetEntity = ToEnt( hEntity );
|
||||
if ( pTargetEntity )
|
||||
{
|
||||
SpawnEntity( pTargetEntity->GetAbsOrigin(), pTargetEntity->GetAbsAngles() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityAtNamedEntityOriginFromScript( const char *pszName )
|
||||
{
|
||||
CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, pszName, this, NULL, NULL );
|
||||
|
||||
if( pTargetEntity )
|
||||
{
|
||||
SpawnEntity( pTargetEntity->GetAbsOrigin(), pTargetEntity->GetAbsAngles() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn an instance of the entity
|
||||
//-----------------------------------------------------------------------------
|
||||
void CEnvEntityMaker::SpawnEntityAtLocationFromScript( const Vector &vecAlternateOrigin, const Vector &vecAlternateAngles )
|
||||
{
|
||||
SpawnEntity( vecAlternateOrigin, *((QAngle *)&vecAlternateAngles) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns whether or not the template entities can fit if spawned.
|
||||
|
@ -93,6 +93,9 @@
|
||||
#include "world.h"
|
||||
#endif
|
||||
|
||||
#include "vscript/ivscript.h"
|
||||
#include "vscript_server.h"
|
||||
|
||||
|
||||
#ifdef TF_DLL
|
||||
#include "gc_clientsystem.h"
|
||||
@ -185,6 +188,7 @@ IServerEngineTools *serverenginetools = NULL;
|
||||
ISceneFileCache *scenefilecache = NULL;
|
||||
IXboxSystem *xboxsystem = NULL; // Xbox 360 only
|
||||
IMatchmaking *matchmaking = NULL; // Xbox 360 only
|
||||
IScriptManager *scriptmanager = NULL;
|
||||
#if defined( REPLAY_ENABLED )
|
||||
IReplaySystem *g_pReplay = NULL;
|
||||
IServerReplayContext *g_pReplayServerContext = NULL;
|
||||
@ -627,6 +631,11 @@ bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory,
|
||||
if ( IsX360() && (matchmaking = (IMatchmaking *)appSystemFactory( VENGINE_MATCHMAKING_VERSION, NULL )) == NULL )
|
||||
return false;
|
||||
|
||||
if (!CommandLine()->CheckParm("-noscripting"))
|
||||
{
|
||||
scriptmanager = (IScriptManager*)appSystemFactory(VSCRIPT_INTERFACE_VERSION, NULL);
|
||||
}
|
||||
|
||||
// If not running dedicated, grab the engine vgui interface
|
||||
if ( !engine->IsDedicatedServer() )
|
||||
{
|
||||
@ -684,6 +693,7 @@ bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory,
|
||||
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetCommentarySaveRestoreBlockHandler() );
|
||||
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEventQueueSaveRestoreBlockHandler() );
|
||||
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetAchievementSaveRestoreBlockHandler() );
|
||||
g_pGameSaveRestoreBlockSet->AddBlockHandler( GetVScriptSaveRestoreBlockHandler() );
|
||||
|
||||
// The string system must init first + shutdown last
|
||||
IGameSystem::Add( GameStringSystem() );
|
||||
@ -762,6 +772,7 @@ void CServerGameDLL::DLLShutdown( void )
|
||||
// Due to dependencies, these are not autogamesystems
|
||||
ModelSoundsCacheShutdown();
|
||||
|
||||
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetVScriptSaveRestoreBlockHandler() );
|
||||
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetAchievementSaveRestoreBlockHandler() );
|
||||
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetCommentarySaveRestoreBlockHandler() );
|
||||
g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEventQueueSaveRestoreBlockHandler() );
|
||||
|
@ -27,6 +27,126 @@
|
||||
|
||||
extern CServerGameDLL g_ServerGameDLL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: An entity that acts as a container for game scripts.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define MAX_SCRIPT_GROUP 16
|
||||
|
||||
class CLogicScript : public CPointEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CLogicScript, CPointEntity );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void RunVScripts()
|
||||
{
|
||||
/*
|
||||
EntityGroup <- [];
|
||||
function __AppendToScriptGroup( name )
|
||||
{
|
||||
if ( name.len() == 0 )
|
||||
{
|
||||
EntityGroup.append( null );
|
||||
}
|
||||
else
|
||||
{
|
||||
local ent = Entities.FindByName( null, name );
|
||||
EntityGroup.append( ent );
|
||||
if ( ent != null )
|
||||
{
|
||||
ent.ValidateScriptScope();
|
||||
ent.GetScriptScope().EntityGroup <- EntityGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static const char szAddCode[] =
|
||||
{
|
||||
0x45,0x6e,0x74,0x69,0x74,0x79,0x47,0x72,0x6f,0x75,0x70,0x20,0x3c,0x2d,0x20,0x5b,0x5d,0x3b,0x0d,0x0a,
|
||||
0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x5f,0x5f,0x41,0x70,0x70,0x65,0x6e,0x64,0x54,0x6f,0x53,
|
||||
0x63,0x72,0x69,0x70,0x74,0x47,0x72,0x6f,0x75,0x70,0x28,0x20,0x6e,0x61,0x6d,0x65,0x20,0x29,0x20,0x0d,
|
||||
0x0a,0x7b,0x0d,0x0a,0x09,0x69,0x66,0x20,0x28,0x20,0x6e,0x61,0x6d,0x65,0x2e,0x6c,0x65,0x6e,0x28,0x29,
|
||||
0x20,0x3d,0x3d,0x20,0x30,0x20,0x29,0x20,0x0d,0x0a,0x09,0x7b,0x20,0x0d,0x0a,0x09,0x09,0x45,0x6e,0x74,
|
||||
0x69,0x74,0x79,0x47,0x72,0x6f,0x75,0x70,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x28,0x20,0x6e,0x75,0x6c,
|
||||
0x6c,0x20,0x29,0x3b,0x20,0x0d,0x0a,0x09,0x7d,0x20,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,
|
||||
0x7b,0x20,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x74,0x20,0x3d,0x20,0x45,0x6e,
|
||||
0x74,0x69,0x74,0x69,0x65,0x73,0x2e,0x46,0x69,0x6e,0x64,0x42,0x79,0x4e,0x61,0x6d,0x65,0x28,0x20,0x6e,
|
||||
0x75,0x6c,0x6c,0x2c,0x20,0x6e,0x61,0x6d,0x65,0x20,0x29,0x3b,0x0d,0x0a,0x09,0x09,0x45,0x6e,0x74,0x69,
|
||||
0x74,0x79,0x47,0x72,0x6f,0x75,0x70,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x28,0x20,0x65,0x6e,0x74,0x20,
|
||||
0x29,0x3b,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x28,0x20,0x65,0x6e,0x74,0x20,0x21,0x3d,0x20,0x6e,0x75,
|
||||
0x6c,0x6c,0x20,0x29,0x0d,0x0a,0x09,0x09,0x7b,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x74,0x2e,0x56,0x61,
|
||||
0x6c,0x69,0x64,0x61,0x74,0x65,0x53,0x63,0x72,0x69,0x70,0x74,0x53,0x63,0x6f,0x70,0x65,0x28,0x29,0x3b,
|
||||
0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x74,0x2e,0x47,0x65,0x74,0x53,0x63,0x72,0x69,0x70,0x74,0x53,0x63,
|
||||
0x6f,0x70,0x65,0x28,0x29,0x2e,0x45,0x6e,0x74,0x69,0x74,0x79,0x47,0x72,0x6f,0x75,0x70,0x20,0x3c,0x2d,
|
||||
0x20,0x45,0x6e,0x74,0x69,0x74,0x79,0x47,0x72,0x6f,0x75,0x70,0x3b,0x0d,0x0a,0x09,0x09,0x7d,0x0d,0x0a,
|
||||
0x09,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x00
|
||||
};
|
||||
|
||||
int iLastMember;
|
||||
for ( iLastMember = MAX_SCRIPT_GROUP - 1; iLastMember >= 0; iLastMember-- )
|
||||
{
|
||||
if ( m_iszGroupMembers[iLastMember] != NULL_STRING )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( iLastMember >= 0 )
|
||||
{
|
||||
HSCRIPT hAddScript = g_pScriptVM->CompileScript( szAddCode );
|
||||
if ( hAddScript )
|
||||
{
|
||||
ValidateScriptScope();
|
||||
m_ScriptScope.Run( hAddScript );
|
||||
HSCRIPT hAddFunc = m_ScriptScope.LookupFunction( "__AppendToScriptGroup" );
|
||||
if ( hAddFunc )
|
||||
{
|
||||
for ( int i = 0; i <= iLastMember; i++ )
|
||||
{
|
||||
m_ScriptScope.Call( hAddFunc, NULL, STRING(m_iszGroupMembers[i]) );
|
||||
}
|
||||
g_pScriptVM->ReleaseFunction( hAddFunc );
|
||||
m_ScriptScope.ClearValue( "__AppendToScriptGroup" );
|
||||
}
|
||||
|
||||
g_pScriptVM->ReleaseScript( hAddScript );
|
||||
}
|
||||
}
|
||||
BaseClass::RunVScripts();
|
||||
}
|
||||
|
||||
string_t m_iszGroupMembers[MAX_SCRIPT_GROUP];
|
||||
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( logic_script, CLogicScript );
|
||||
|
||||
BEGIN_DATADESC( CLogicScript )
|
||||
// Silence, Classcheck!
|
||||
// DEFINE_ARRAY( m_iszGroupMembers, FIELD_STRING, MAX_NUM_TEMPLATES ),
|
||||
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[0], FIELD_STRING, "Group00"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[1], FIELD_STRING, "Group01"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[2], FIELD_STRING, "Group02"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[3], FIELD_STRING, "Group03"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[4], FIELD_STRING, "Group04"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[5], FIELD_STRING, "Group05"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[6], FIELD_STRING, "Group06"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[7], FIELD_STRING, "Group07"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[8], FIELD_STRING, "Group08"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[9], FIELD_STRING, "Group09"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[10], FIELD_STRING, "Group10"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[11], FIELD_STRING, "Group11"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[12], FIELD_STRING, "Group12"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[13], FIELD_STRING, "Group13"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[14], FIELD_STRING, "Group14"),
|
||||
DEFINE_KEYFIELD( m_iszGroupMembers[15], FIELD_STRING, "Group16"),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Compares a set of integer inputs to the one main input
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "IEffects.h"
|
||||
#include "props.h"
|
||||
|
||||
#include "point_template.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
@ -114,6 +116,8 @@ END_DATADESC()
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseNPCMaker::Spawn( void )
|
||||
{
|
||||
ScriptInstallPreSpawnHook();
|
||||
|
||||
SetSolid( SOLID_NONE );
|
||||
m_nLiveChildren = 0;
|
||||
Precache();
|
||||
@ -830,6 +834,12 @@ void CTemplateNPCMaker::MakeNPC( void )
|
||||
pent->SetAbsAngles( angles );
|
||||
}
|
||||
|
||||
if ( !ScriptPreInstanceSpawn( &m_ScriptScope, pEntity, m_iszTemplateData ) )
|
||||
{
|
||||
UTIL_RemoveImmediate( pEntity );
|
||||
return;
|
||||
}
|
||||
|
||||
m_OnSpawnNPC.Set( pEntity, pEntity, this );
|
||||
|
||||
if ( m_spawnflags & SF_NPCMAKER_FADE )
|
||||
@ -867,6 +877,8 @@ void CTemplateNPCMaker::MakeNPC( void )
|
||||
SetUse( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
ScriptPostSpawn( &m_ScriptScope, &pEntity, 1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -478,6 +478,10 @@ BEGIN_DATADESC( CBasePlayer )
|
||||
// DEFINE_UTLVECTOR( m_vecPlayerSimInfo ),
|
||||
END_DATADESC()
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CBasePlayer, CBaseAnimating, "The player entity." )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptIsPlayerNoclipping, "IsNoclipping", "Returns true if the player is in noclip mode." )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
int giPrecacheGrunt = 0;
|
||||
|
||||
edict_t *CBasePlayer::s_PlayerEdict = NULL;
|
||||
@ -690,6 +694,11 @@ CBasePlayer::~CBasePlayer( )
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlayer::UpdateOnRemove( void )
|
||||
{
|
||||
if ( !g_pGameRules->IsMultiplayer() && g_pScriptVM )
|
||||
{
|
||||
g_pScriptVM->SetValue( "player", SCRIPT_VARIANT_NULL );
|
||||
}
|
||||
|
||||
VPhysicsDestroyObject();
|
||||
|
||||
// Remove him from his current team
|
||||
@ -5110,6 +5119,11 @@ void CBasePlayer::Spawn( void )
|
||||
UpdateLastKnownArea();
|
||||
|
||||
m_weaponFiredTimer.Invalidate();
|
||||
|
||||
if ( !g_pGameRules->IsMultiplayer() && g_pScriptVM )
|
||||
{
|
||||
g_pScriptVM->SetValue( "player", GetScriptInstance() );
|
||||
}
|
||||
}
|
||||
|
||||
void CBasePlayer::Activate( void )
|
||||
@ -5300,6 +5314,14 @@ void CBasePlayer::OnRestore( void )
|
||||
m_nVehicleViewSavedFrame = 0;
|
||||
|
||||
m_nBodyPitchPoseParam = LookupPoseParameter( "body_pitch" );
|
||||
|
||||
// HACK: (03/25/09) Then the player goes across a transition it doesn't spawn and register
|
||||
// it's instance. We're hacking around this for now, but this will go away when we get around to
|
||||
// having entities cross transitions and keep their script state.
|
||||
if ( !g_pGameRules->IsMultiplayer() && g_pScriptVM && (gpGlobals->eLoadType == MapLoad_Transition) )
|
||||
{
|
||||
g_pScriptVM->SetValue( "player", GetScriptInstance() );
|
||||
}
|
||||
}
|
||||
|
||||
/* void CBasePlayer::SetTeamName( const char *pTeamName )
|
||||
@ -6864,6 +6886,14 @@ void CBasePlayer::ShowCrosshair( bool bShow )
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Used by vscript to determine if the player is noclipping
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBasePlayer::ScriptIsPlayerNoclipping(void)
|
||||
{
|
||||
return (GetMoveType() == MOVETYPE_NOCLIP);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -244,6 +244,8 @@ protected:
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
DECLARE_SERVERCLASS();
|
||||
// script description
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
CBasePlayer();
|
||||
~CBasePlayer();
|
||||
@ -386,6 +388,8 @@ public:
|
||||
void ShowViewModel( bool bShow );
|
||||
void ShowCrosshair( bool bShow );
|
||||
|
||||
bool ScriptIsPlayerNoclipping(void);
|
||||
|
||||
// View model prediction setup
|
||||
void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov );
|
||||
|
||||
|
@ -53,24 +53,6 @@ END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( point_devshot_camera, CPointDevShotCamera );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Convenience function so we don't have to make this check all over
|
||||
//-----------------------------------------------------------------------------
|
||||
static CBasePlayer * UTIL_GetLocalPlayerOrListenServerHost( void )
|
||||
{
|
||||
if ( gpGlobals->maxClients > 1 )
|
||||
{
|
||||
if ( engine->IsDedicatedServer() )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return UTIL_GetListenServerHost();
|
||||
}
|
||||
|
||||
return UTIL_GetLocalPlayer();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -133,6 +133,8 @@ void PrecachePointTemplates()
|
||||
void CPointTemplate::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
ScriptInstallPreSpawnHook();
|
||||
ValidateScriptScope();
|
||||
}
|
||||
|
||||
void CPointTemplate::Precache()
|
||||
@ -381,7 +383,15 @@ bool CPointTemplate::CreateInstance( const Vector &vecOrigin, const QAngle &vecA
|
||||
pEntity->SetAbsOrigin( vecNewOrigin );
|
||||
pEntity->SetAbsAngles( vecNewAngles );
|
||||
|
||||
pSpawnList[i].m_pEntity = pEntity;
|
||||
if (ScriptPreInstanceSpawn(&m_ScriptScope, pEntity, Templates_FindByIndex(iTemplateIndex)))
|
||||
{
|
||||
pSpawnList[i].m_pEntity = pEntity;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSpawnList[i].m_pEntity = NULL;
|
||||
UTIL_RemoveImmediate(pEntity);
|
||||
}
|
||||
pSpawnList[i].m_nDepth = 0;
|
||||
pSpawnList[i].m_pDeferredParent = NULL;
|
||||
}
|
||||
@ -474,6 +484,17 @@ bool CPointTemplate::CreateSpecificInstance( int iTemplate, const Vector &vecOri
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
void CPointTemplate::CreationComplete( const CUtlVector<CBaseEntity*> &entities )
|
||||
{
|
||||
if ( !entities.Count() )
|
||||
return;
|
||||
|
||||
ScriptPostSpawn( &m_ScriptScope, (CBaseEntity **)entities.Base(), entities.Count() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &inputdata -
|
||||
@ -514,3 +535,72 @@ void CPointTemplate::InputForceSpawnRandomTemplate( inputdata_t &inputdata )
|
||||
m_pOutputOutEntity.Set(pEntity, pEntity, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
void ScriptInstallPreSpawnHook()
|
||||
{
|
||||
#ifdef IS_WINDOWS_PC
|
||||
if ( !g_pScriptVM->ValueExists( "__ExecutePreSpawn " ) )
|
||||
{
|
||||
//g_pScriptVM->Run( g_Script_spawn_helper );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: This function is called after a spawner creates its child entity
|
||||
// but before the keyvalues are injected. This gives us an
|
||||
// opportunity to change any keyvalues before the entity is
|
||||
// configured and spawned. In this case, we see if there is a VScript
|
||||
// that wants to change anything about this entity.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ScriptPreInstanceSpawn( CScriptScope *pScriptScope, CBaseEntity *pChild, string_t iszKeyValueData )
|
||||
{
|
||||
if ( !pScriptScope->IsInitialized() )
|
||||
return true;
|
||||
|
||||
ScriptVariant_t result;
|
||||
if ( pScriptScope->Call( "__ExecutePreSpawn", &result, ToHScript( pChild ) ) != SCRIPT_DONE )
|
||||
return true;
|
||||
|
||||
if ( ( result.m_type == FIELD_BOOLEAN && !result.m_bool ) || ( result.m_type == FIELD_INTEGER && !result.m_int ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void ScriptPostSpawn( CScriptScope *pScriptScope, CBaseEntity **ppEntities, int nEntities )
|
||||
{
|
||||
if ( !pScriptScope->IsInitialized() )
|
||||
return;
|
||||
|
||||
HSCRIPT hPostSpawnFunc = pScriptScope->LookupFunction( "PostSpawn" );
|
||||
|
||||
if ( !hPostSpawnFunc )
|
||||
return;
|
||||
|
||||
ScriptVariant_t varEntityMakerResultTable;
|
||||
if ( !g_pScriptVM->GetValue( *pScriptScope, "__EntityMakerResult", &varEntityMakerResultTable ) )
|
||||
return;
|
||||
|
||||
if ( varEntityMakerResultTable.m_type != FIELD_HSCRIPT )
|
||||
return;
|
||||
|
||||
HSCRIPT hEntityMakerResultTable = varEntityMakerResultTable.m_hScript;
|
||||
char szEntName[256];
|
||||
for ( int i = 0; i < nEntities; i++ )
|
||||
{
|
||||
V_strncpy( szEntName, ppEntities[i]->GetEntityNameAsCStr(), ARRAYSIZE(szEntName) );
|
||||
char *pAmpersand = V_strrchr( szEntName, '&' );
|
||||
if ( pAmpersand )
|
||||
*pAmpersand = 0;
|
||||
g_pScriptVM->SetValue( hEntityMakerResultTable, szEntName, ToHScript( ppEntities[i] ) );
|
||||
}
|
||||
pScriptScope->Call( hPostSpawnFunc, NULL, hEntityMakerResultTable );
|
||||
pScriptScope->Call( "__FinishSpawn" );
|
||||
g_pScriptVM->ReleaseValue( varEntityMakerResultTable );
|
||||
g_pScriptVM->ReleaseFunction( hPostSpawnFunc );
|
||||
}
|
||||
|
@ -20,6 +20,10 @@ struct template_t
|
||||
DECLARE_SIMPLE_DATADESC();
|
||||
};
|
||||
|
||||
void ScriptInstallPreSpawnHook();
|
||||
bool ScriptPreInstanceSpawn( CScriptScope *pScriptScope, CBaseEntity *pChild, string_t iszKeyValueData );
|
||||
void ScriptPostSpawn( CScriptScope *pScriptScope, CBaseEntity **ppEntities, int nEntities );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -52,6 +56,7 @@ public:
|
||||
#ifdef MAPBASE
|
||||
bool CreateSpecificInstance( int iTemplate, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity **pOutEntity );
|
||||
#endif
|
||||
void CreationComplete(const CUtlVector<CBaseEntity*>& entities);
|
||||
|
||||
// Inputs
|
||||
void InputForceSpawn( inputdata_t &inputdata );
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "SceneCache.h"
|
||||
#include "scripted.h"
|
||||
#include "env_debughistory.h"
|
||||
#include "team.h"
|
||||
#include "triggers.h"
|
||||
|
||||
#ifdef HL2_EPISODIC
|
||||
#include "npc_alyx_episodic.h"
|
||||
@ -323,6 +325,8 @@ public:
|
||||
|
||||
DECLARE_CLASS( CSceneEntity, CPointEntity );
|
||||
DECLARE_SERVERCLASS();
|
||||
// script description
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
CSceneEntity( void );
|
||||
~CSceneEntity( void );
|
||||
@ -470,6 +474,8 @@ public:
|
||||
|
||||
void InputScriptPlayerDeath( inputdata_t &inputdata );
|
||||
|
||||
void AddBroadcastTeamTarget( int nTeamIndex );
|
||||
void RemoveBroadcastTeamTarget( int nTeamIndex );
|
||||
// Data
|
||||
public:
|
||||
string_t m_iszSceneFile;
|
||||
@ -543,6 +549,9 @@ public:
|
||||
virtual CBaseEntity *FindNamedEntity( const char *name, CBaseEntity *pActor = NULL, bool bBaseFlexOnly = false, bool bUseClear = false );
|
||||
CBaseEntity *FindNamedTarget( string_t iszTarget, bool bBaseFlexOnly = false );
|
||||
virtual CBaseEntity *FindNamedEntityClosest( const char *name, CBaseEntity *pActor = NULL, bool bBaseFlexOnly = false, bool bUseClear = false, const char *pszSecondary = NULL );
|
||||
HSCRIPT ScriptFindNamedEntity( const char *name );
|
||||
bool ScriptLoadSceneFromString( const char * pszFilename, const char *pszData );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@ -764,6 +773,17 @@ BEGIN_DATADESC( CSceneEntity )
|
||||
DEFINE_OUTPUT( m_OnTrigger16, "OnTrigger16"),
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
BEGIN_ENT_SCRIPTDESC( CSceneEntity, CBaseEntity, "Choreographed scene which controls animation and/or dialog on one or more actors." )
|
||||
DEFINE_SCRIPTFUNC( EstimateLength, "Returns length of this scene in seconds." )
|
||||
DEFINE_SCRIPTFUNC( IsPlayingBack, "If this scene is currently playing." )
|
||||
DEFINE_SCRIPTFUNC( IsPaused, "If this scene is currently paused." )
|
||||
DEFINE_SCRIPTFUNC( AddBroadcastTeamTarget, "Adds a team (by index) to the broadcast list" )
|
||||
DEFINE_SCRIPTFUNC( RemoveBroadcastTeamTarget, "Removes a team (by index) from the broadcast list" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFindNamedEntity, "FindNamedEntity", "given an entity reference, such as !target, get actual entity from scene object" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptLoadSceneFromString, "LoadSceneFromString", "given a dummy scene name and a vcd string, load the scene" )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
const ConVar *CSceneEntity::m_pcvSndMixahead = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -3066,7 +3086,7 @@ void CSceneEntity::StartEvent( float currenttime, CChoreoScene *scene, CChoreoEv
|
||||
|
||||
CBaseFlex *pActor = NULL;
|
||||
CChoreoActor *actor = event->GetActor();
|
||||
if ( actor )
|
||||
if ( actor && (event->GetType() != CChoreoEvent::SCRIPT) && (event->GetType() != CChoreoEvent::CAMERA) )
|
||||
{
|
||||
pActor = FindNamedActor( actor );
|
||||
if (pActor == NULL)
|
||||
@ -3229,6 +3249,80 @@ void CSceneEntity::StartEvent( float currenttime, CChoreoScene *scene, CChoreoEv
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CChoreoEvent::CAMERA:
|
||||
{
|
||||
// begin the camera shot
|
||||
const char *pszShotType = event->GetParameters();
|
||||
|
||||
CBaseEntity *pActor1 = FindNamedEntity( event->GetParameters2( ), pActor );
|
||||
CBaseEntity *pActor2 = FindNamedEntity( event->GetParameters3( ), pActor );
|
||||
float duration = event->GetDuration();
|
||||
|
||||
// grab any camera we find in the map
|
||||
// TODO: find camera that is nearest this scene entity?
|
||||
CTriggerCamera *pCamera = (CTriggerCamera *)gEntList.FindEntityByClassname( NULL, "point_viewcontrol" );
|
||||
|
||||
if ( !pCamera )
|
||||
{
|
||||
Warning( "CSceneEntity %s unable to find a camera (point_viewcontrol) in this map!\n", STRING(GetEntityName()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pCamera->StartCameraShot( pszShotType, this, pActor1, pActor2, duration );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CChoreoEvent::SCRIPT:
|
||||
{
|
||||
// NOTE: this is only used by auto-generated vcds to embed script commands to map entities.
|
||||
|
||||
// vscript call - param1 is entity name, param2 is function name, param3 is function parameter string
|
||||
// calls a vscript function defined on the scope of the named CBaseEntity object/actor.
|
||||
// script call is of the format FunctionName(pActor, pThisSceneEntity, pszScriptParameters, duration)
|
||||
const char *pszActorName = event->GetParameters();
|
||||
const char *pszFunctionName = event->GetParameters2();
|
||||
const char *pszScriptParameters = event->GetParameters3();
|
||||
|
||||
float duration = event->GetDuration();
|
||||
|
||||
// TODO: should be new method CBaseEntity::CallScriptFunctionParams()
|
||||
CBaseEntity *pEntity = (CBaseEntity *)gEntList.FindEntityByName( NULL, pszActorName );
|
||||
|
||||
//START_VMPROFILE
|
||||
if ( !pEntity )
|
||||
{
|
||||
Warning( "CSceneEntity::SCRIPT event - unable to find entity named '%s' in this map!\n", pszActorName );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if( !pEntity->ValidateScriptScope() )
|
||||
{
|
||||
DevMsg("\n***\nCChoreoEvent::SCRIPT - FAILED to create private ScriptScope. ABORTING script call\n***\n");
|
||||
break;
|
||||
}
|
||||
|
||||
HSCRIPT hFunc = pEntity->m_ScriptScope.LookupFunction( pszFunctionName );
|
||||
|
||||
if( hFunc )
|
||||
{
|
||||
pEntity->m_ScriptScope.Call( hFunc, NULL, ToHScript(this), pszScriptParameters, duration );
|
||||
pEntity->m_ScriptScope.ReleaseFunction( hFunc );
|
||||
|
||||
//UPDATE_VMPROFILE
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning("CSceneEntity::SCRIPT event - '%s' entity has no script function '%s' defined!\n", pszActorName,pszFunctionName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case CChoreoEvent::FIRETRIGGER:
|
||||
{
|
||||
if ( IsMultiplayer() )
|
||||
@ -3437,6 +3531,19 @@ void CSceneEntity::EndEvent( float currenttime, CChoreoScene *scene, CChoreoEven
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CChoreoEvent::CAMERA:
|
||||
{
|
||||
// call the end of camera or call a dispatch function
|
||||
}
|
||||
break;
|
||||
|
||||
case CChoreoEvent::SCRIPT:
|
||||
{
|
||||
// call the end of script or call a dispatch function
|
||||
}
|
||||
break;
|
||||
|
||||
case CChoreoEvent::SEQUENCE:
|
||||
{
|
||||
if ( pActor )
|
||||
@ -4268,6 +4375,53 @@ CBaseEntity *CSceneEntity::FindNamedEntityClosest( const char *name, CBaseEntity
|
||||
}
|
||||
|
||||
|
||||
HSCRIPT CSceneEntity::ScriptFindNamedEntity(const char* name)
|
||||
{
|
||||
return ToHScript(FindNamedEntity(name, NULL, false, false));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: vscript - create a scene directly from a buffer containing
|
||||
// a vcd description, and load it into the scene entity.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSceneEntity::ScriptLoadSceneFromString(const char* pszFilename, const char* pszData)
|
||||
{
|
||||
CChoreoScene* pScene = new CChoreoScene(NULL);
|
||||
|
||||
// CSceneTokenProcessor SceneTokenProcessor;
|
||||
// SceneTokenProcessor.SetBuffer( pszData );
|
||||
g_TokenProcessor.SetBuffer((char*)pszData);
|
||||
|
||||
if (!pScene->ParseFromBuffer(pszFilename, &g_TokenProcessor)) //&SceneTokenProcessor ) )
|
||||
{
|
||||
Warning("CSceneEntity::LoadSceneFromString: Unable to parse scene data '%s'\n", pszFilename);
|
||||
delete pScene;
|
||||
pScene = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pScene->SetPrintFunc(LocalScene_Printf);
|
||||
pScene->SetEventCallbackInterface(this);
|
||||
|
||||
|
||||
// precache all sounds for the newly constructed scene
|
||||
PrecacheScene(pScene);
|
||||
}
|
||||
|
||||
if (pScene != NULL)
|
||||
{
|
||||
// release prior scene if present
|
||||
UnloadScene();
|
||||
m_pScene = pScene;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Remove all "scene" expressions from all actors in this scene
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -4691,6 +4845,44 @@ void CSceneEntity::SetRecipientFilter( IRecipientFilter *filter )
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Adds a player (by index) to the recipient filter
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::AddBroadcastTeamTarget(int nTeamIndex)
|
||||
{
|
||||
if (m_pRecipientFilter == NULL)
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
SetRecipientFilter(&filter);
|
||||
}
|
||||
|
||||
CTeam* pTeam = GetGlobalTeam(nTeamIndex);
|
||||
Assert(pTeam);
|
||||
if (pTeam == NULL)
|
||||
return;
|
||||
|
||||
m_pRecipientFilter->AddRecipientsByTeam(pTeam);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Removes a player (by index) from the recipient filter
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSceneEntity::RemoveBroadcastTeamTarget(int nTeamIndex)
|
||||
{
|
||||
if (m_pRecipientFilter == NULL)
|
||||
{
|
||||
CRecipientFilter filter;
|
||||
SetRecipientFilter(&filter);
|
||||
}
|
||||
|
||||
CTeam* pTeam = GetGlobalTeam(nTeamIndex);
|
||||
Assert(pTeam);
|
||||
if (pTeam == NULL)
|
||||
return;
|
||||
|
||||
m_pRecipientFilter->RemoveRecipientsByTeam(pTeam);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
@ -4986,6 +5178,26 @@ int GetSceneSpeechCount( char const *pszScene )
|
||||
return 0;
|
||||
}
|
||||
|
||||
HSCRIPT ScriptCreateSceneEntity( const char* pszScene )
|
||||
{
|
||||
if ( IsEntityCreationAllowedInScripts() == false )
|
||||
{
|
||||
Warning( "VScript error: A script attempted to create a scene entity mid-game. Entity creation from scripts is only allowed during map init.\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_pScriptVM->RegisterClass( GetScriptDescForClass( CSceneEntity ) );
|
||||
CSceneEntity *pScene = (CSceneEntity *)CBaseEntity::CreateNoSpawn( "logic_choreographed_scene", vec3_origin, vec3_angle );
|
||||
|
||||
if ( pScene )
|
||||
{
|
||||
pScene->m_iszSceneFile = AllocPooledString( pszScene );
|
||||
DispatchSpawn( pScene );
|
||||
}
|
||||
|
||||
return ToHScript( pScene );
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
CON_COMMAND(mapbase_scene_precache, "Just work")
|
||||
{
|
||||
|
@ -48,6 +48,7 @@ int GetSceneSpeechCount( char const *pszScene );
|
||||
bool IsInInterruptableScenes( CBaseFlex *pActor );
|
||||
|
||||
void PrecacheInstancedScene( char const *pszScene );
|
||||
HSCRIPT ScriptCreateSceneEntity( char const *pszScene );
|
||||
|
||||
char const *GetSceneFilename( CBaseEntity *ent );
|
||||
void ReloadSceneFromDisk( CBaseEntity *ent );
|
||||
|
@ -648,6 +648,11 @@ $Project
|
||||
$File "$SRCDIR\game\shared\voice_common.h"
|
||||
$File "$SRCDIR\game\shared\voice_gamemgr.cpp"
|
||||
$File "$SRCDIR\game\shared\voice_gamemgr.h"
|
||||
$File "vscript_server.cpp"
|
||||
$File "vscript_server.h"
|
||||
$File "vscript_server.nut"
|
||||
$File "$SRCDIR\game\shared\vscript_shared.cpp"
|
||||
$File "$SRCDIR\game\shared\vscript_shared.h"
|
||||
$File "waterbullet.cpp"
|
||||
$File "waterbullet.h"
|
||||
$File "WaterLODControl.cpp"
|
||||
|
@ -2978,94 +2978,6 @@ void CAI_ChangeHintGroup::InputActivate( inputdata_t &inputdata )
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTriggerCamera : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CTriggerCamera, CBaseEntity );
|
||||
|
||||
#ifdef MAPBASE
|
||||
CTriggerCamera();
|
||||
|
||||
void UpdateOnRemove();
|
||||
#endif
|
||||
|
||||
void Spawn( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
void Enable( void );
|
||||
void Disable( void );
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
void FollowTarget( void );
|
||||
#ifdef MAPBASE
|
||||
void MoveThink( void );
|
||||
#endif
|
||||
void Move(void);
|
||||
|
||||
// Always transmit to clients so they know where to move the view to
|
||||
virtual int UpdateTransmitState();
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
// Input handlers
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void InputSetFOV( inputdata_t &inputdata );
|
||||
void InputSetFOVRate( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
private:
|
||||
EHANDLE m_hPlayer;
|
||||
EHANDLE m_hTarget;
|
||||
|
||||
// used for moving the camera along a path (rail rides)
|
||||
CBaseEntity *m_pPath;
|
||||
string_t m_sPath;
|
||||
float m_flWait;
|
||||
float m_flReturnTime;
|
||||
float m_flStopTime;
|
||||
float m_moveDistance;
|
||||
float m_targetSpeed;
|
||||
float m_initialSpeed;
|
||||
float m_acceleration;
|
||||
float m_deceleration;
|
||||
int m_state;
|
||||
Vector m_vecMoveDir;
|
||||
|
||||
#ifdef MAPBASE
|
||||
float m_fov;
|
||||
float m_fovSpeed;
|
||||
|
||||
bool m_bDontSetPlayerView;
|
||||
#endif
|
||||
|
||||
string_t m_iszTargetAttachment;
|
||||
int m_iAttachmentIndex;
|
||||
bool m_bSnapToGoal;
|
||||
|
||||
#if HL2_EPISODIC
|
||||
bool m_bInterpolatePosition;
|
||||
|
||||
// these are interpolation vars used for interpolating the camera over time
|
||||
Vector m_vStartPos, m_vEndPos;
|
||||
float m_flInterpStartTime;
|
||||
|
||||
const static float kflPosInterpTime; // seconds
|
||||
#endif
|
||||
|
||||
int m_nPlayerButtons;
|
||||
int m_nOldTakeDamage;
|
||||
|
||||
private:
|
||||
COutputEvent m_OnEndFollow;
|
||||
#ifdef MAPBASE
|
||||
COutputEvent m_OnStartFollow;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if HL2_EPISODIC
|
||||
const float CTriggerCamera::kflPosInterpTime = 2.0f;
|
||||
#endif
|
||||
@ -3127,6 +3039,12 @@ BEGIN_DATADESC( CTriggerCamera )
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
// VScript: publish class and select members to script language
|
||||
BEGIN_ENT_SCRIPTDESC( CTriggerCamera, CBaseEntity, "Server-side camera entity" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFov, "GetFov", "get camera's current fov setting as integer" )
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptSetFov, "SetFov", "set camera's current fov in integer degrees and fov change rate as float" )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
#ifdef MAPBASE
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
@ -3641,6 +3559,59 @@ void CTriggerCamera::FollowTarget( )
|
||||
Move();
|
||||
}
|
||||
|
||||
void CTriggerCamera::StartCameraShot( const char *pszShotType, CBaseEntity *pSceneEntity, CBaseEntity *pActor1, CBaseEntity *pActor2, float duration )
|
||||
{
|
||||
// called from SceneEntity in response to a CChoreoEvent::CAMERA sent from a VCD.
|
||||
// talk to vscript, start a camera move
|
||||
|
||||
HSCRIPT hStartCameraShot = NULL;
|
||||
|
||||
// switch to this camera
|
||||
// Enable();
|
||||
|
||||
// get script module associated with this ent, lookup function in module
|
||||
if( m_iszVScripts != NULL_STRING )
|
||||
{
|
||||
hStartCameraShot = m_ScriptScope.LookupFunction( "ScriptStartCameraShot" );
|
||||
}
|
||||
|
||||
// call the script function to begin the camera move
|
||||
if ( hStartCameraShot )
|
||||
{
|
||||
g_pScriptVM->Call( hStartCameraShot, m_ScriptScope, true, NULL, pszShotType, ToHScript(pSceneEntity), ToHScript(pActor1), ToHScript(pActor2), duration );
|
||||
g_pScriptVM->ReleaseFunction( hStartCameraShot );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: vscript callback to get the player's fov
|
||||
//-----------------------------------------------------------------------------
|
||||
int CTriggerCamera::ScriptGetFov(void)
|
||||
{
|
||||
if (m_hPlayer)
|
||||
{
|
||||
CBasePlayer* pBasePlayer = (CBasePlayer*)m_hPlayer.Get();
|
||||
int iFOV = pBasePlayer->GetFOV();
|
||||
return iFOV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: vscript callback to slam the player's fov
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTriggerCamera::ScriptSetFov(int iFOV, float fovSpeed)
|
||||
{
|
||||
if (m_hPlayer)
|
||||
{
|
||||
m_fov = iFOV;
|
||||
m_fovSpeed = fovSpeed;
|
||||
|
||||
CBasePlayer* pBasePlayer = (CBasePlayer*)m_hPlayer.Get();
|
||||
pBasePlayer->SetFOV(this, iFOV, fovSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAPBASE
|
||||
void CTriggerCamera::MoveThink()
|
||||
{
|
||||
|
@ -244,4 +244,98 @@ public:
|
||||
CUtlVector<EHANDLE> m_hurtEntities;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
class CTriggerCamera : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CTriggerCamera, CBaseEntity );
|
||||
// script description
|
||||
DECLARE_ENT_SCRIPTDESC();
|
||||
|
||||
#ifdef MAPBASE
|
||||
CTriggerCamera();
|
||||
|
||||
void UpdateOnRemove();
|
||||
#endif
|
||||
|
||||
void Spawn( void );
|
||||
bool KeyValue( const char *szKeyName, const char *szValue );
|
||||
void Enable( void );
|
||||
void Disable( void );
|
||||
|
||||
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
|
||||
void FollowTarget( void );
|
||||
void StartCameraShot( const char *pszShotType, CBaseEntity *pSceneEntity, CBaseEntity *pActor1, CBaseEntity *pActor2, float duration );
|
||||
int ScriptGetFov(void);
|
||||
void ScriptSetFov(int iFOV, float rate);
|
||||
#ifdef MAPBASE
|
||||
void MoveThink( void );
|
||||
#endif
|
||||
void Move(void);
|
||||
|
||||
// Always transmit to clients so they know where to move the view to
|
||||
virtual int UpdateTransmitState();
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
||||
// Input handlers
|
||||
void InputEnable( inputdata_t &inputdata );
|
||||
void InputDisable( inputdata_t &inputdata );
|
||||
|
||||
#ifdef MAPBASE
|
||||
void InputSetFOV( inputdata_t &inputdata );
|
||||
void InputSetFOVRate( inputdata_t &inputdata );
|
||||
#endif
|
||||
|
||||
private:
|
||||
EHANDLE m_hPlayer;
|
||||
EHANDLE m_hTarget;
|
||||
|
||||
// used for moving the camera along a path (rail rides)
|
||||
CBaseEntity *m_pPath;
|
||||
string_t m_sPath;
|
||||
float m_flWait;
|
||||
float m_flReturnTime;
|
||||
float m_flStopTime;
|
||||
float m_moveDistance;
|
||||
float m_targetSpeed;
|
||||
float m_initialSpeed;
|
||||
float m_acceleration;
|
||||
float m_deceleration;
|
||||
int m_state;
|
||||
Vector m_vecMoveDir;
|
||||
|
||||
#ifdef MAPBASE
|
||||
float m_fov;
|
||||
float m_fovSpeed;
|
||||
|
||||
bool m_bDontSetPlayerView;
|
||||
#endif
|
||||
|
||||
string_t m_iszTargetAttachment;
|
||||
int m_iAttachmentIndex;
|
||||
bool m_bSnapToGoal;
|
||||
|
||||
#if HL2_EPISODIC
|
||||
bool m_bInterpolatePosition;
|
||||
|
||||
// these are interpolation vars used for interpolating the camera over time
|
||||
Vector m_vStartPos, m_vEndPos;
|
||||
float m_flInterpStartTime;
|
||||
|
||||
const static float kflPosInterpTime; // seconds
|
||||
#endif
|
||||
|
||||
int m_nPlayerButtons;
|
||||
int m_nOldTakeDamage;
|
||||
|
||||
private:
|
||||
COutputEvent m_OnEndFollow;
|
||||
#ifdef MAPBASE
|
||||
COutputEvent m_OnStartFollow;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // TRIGGERS_H
|
||||
|
@ -1959,7 +1959,7 @@ extern "C" void Sys_Error( char *error, ... )
|
||||
// *mapData - pointer a block of entity map data
|
||||
// Output : -1 if the entity was not successfully created; 0 on success
|
||||
//-----------------------------------------------------------------------------
|
||||
int DispatchSpawn( CBaseEntity *pEntity )
|
||||
int DispatchSpawn( CBaseEntity *pEntity, bool bRunVScripts )
|
||||
{
|
||||
if ( pEntity )
|
||||
{
|
||||
@ -1974,6 +1974,12 @@ int DispatchSpawn( CBaseEntity *pEntity )
|
||||
//pEntity->SetAbsMins( pEntity->GetOrigin() - Vector(1,1,1) );
|
||||
//pEntity->SetAbsMaxs( pEntity->GetOrigin() + Vector(1,1,1) );
|
||||
|
||||
if (bRunVScripts)
|
||||
{
|
||||
pEntity->RunVScripts();
|
||||
pEntity->RunPrecacheScripts();
|
||||
}
|
||||
|
||||
#if defined(TRACK_ENTITY_MEMORY) && defined(USE_MEM_DEBUG)
|
||||
const char *pszClassname = NULL;
|
||||
int iClassname = ((CEntityFactoryDictionary*)EntityFactoryDictionary())->m_Factories.Find( pEntity->GetClassname() );
|
||||
@ -2040,6 +2046,11 @@ int DispatchSpawn( CBaseEntity *pEntity )
|
||||
}
|
||||
|
||||
gEntList.NotifySpawn( pEntity );
|
||||
|
||||
if( bRunVScripts )
|
||||
{
|
||||
pEntity->RunOnPostSpawnScripts();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -237,6 +237,24 @@ CBasePlayer* UTIL_GetLocalPlayer( void );
|
||||
// get the local player on a listen server
|
||||
CBasePlayer *UTIL_GetListenServerHost( void );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Convenience function so we don't have to make this check all over
|
||||
//-----------------------------------------------------------------------------
|
||||
static CBasePlayer * UTIL_GetLocalPlayerOrListenServerHost( void )
|
||||
{
|
||||
if ( gpGlobals->maxClients > 1 )
|
||||
{
|
||||
if ( engine->IsDedicatedServer() )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return UTIL_GetListenServerHost();
|
||||
}
|
||||
|
||||
return UTIL_GetLocalPlayer();
|
||||
}
|
||||
|
||||
CBasePlayer* UTIL_PlayerByUserId( int userID );
|
||||
CBasePlayer* UTIL_PlayerByName( const char *name ); // not case sensitive
|
||||
|
||||
|
787
sp/src/game/server/vscript_server.cpp
Normal file
787
sp/src/game/server/vscript_server.cpp
Normal file
@ -0,0 +1,787 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "vscript_server.h"
|
||||
#include "icommandline.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/fmtstr.h"
|
||||
#include "filesystem.h"
|
||||
#include "eventqueue.h"
|
||||
#include "characterset.h"
|
||||
#include "sceneentity.h" // for exposing scene precache function
|
||||
#include "isaverestore.h"
|
||||
#include "gamerules.h"
|
||||
#ifdef _WIN32
|
||||
//#include "vscript_server_nut.h"
|
||||
#endif
|
||||
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
|
||||
#define VMPROF_START float debugStartTime = Plat_FloatTime();
|
||||
#define VMPROF_SHOW( funcname, funcdesc ) DevMsg("***VSCRIPT PROFILE***: %s %s: %6.4f milliseconds\n", (##funcname), (##funcdesc), (Plat_FloatTime() - debugStartTime)*1000.0 );
|
||||
|
||||
#else // !VMPROFILE
|
||||
|
||||
#define VMPROF_START
|
||||
#define VMPROF_SHOW
|
||||
|
||||
#endif // VMPROFILE
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CScriptEntityIterator
|
||||
{
|
||||
public:
|
||||
HSCRIPT First() { return Next(NULL); }
|
||||
|
||||
HSCRIPT Next( HSCRIPT hStartEntity )
|
||||
{
|
||||
return ToHScript( gEntList.NextEnt( ToEnt( hStartEntity ) ) );
|
||||
}
|
||||
|
||||
HSCRIPT CreateByClassname( const char *className )
|
||||
{
|
||||
return ToHScript( CreateEntityByName( className ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByClassname( HSCRIPT hStartEntity, const char *szName )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByClassname( ToEnt( hStartEntity ), szName ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByName( HSCRIPT hStartEntity, const char *szName )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByName( ToEnt( hStartEntity ), szName ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindInSphere( HSCRIPT hStartEntity, const Vector &vecCenter, float flRadius )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityInSphere( ToEnt( hStartEntity ), vecCenter, flRadius ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByTarget( HSCRIPT hStartEntity, const char *szName )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByTarget( ToEnt( hStartEntity ), szName ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByModel( HSCRIPT hStartEntity, const char *szModelName )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByModel( ToEnt( hStartEntity ), szModelName ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByNameNearest( const char *szName, const Vector &vecSrc, float flRadius )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByNameNearest( szName, vecSrc, flRadius ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByNameWithin( HSCRIPT hStartEntity, const char *szName, const Vector &vecSrc, float flRadius )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByNameWithin( ToEnt( hStartEntity ), szName, vecSrc, flRadius ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByClassnameNearest( szName, vecSrc, flRadius ) );
|
||||
}
|
||||
|
||||
HSCRIPT FindByClassnameWithin( HSCRIPT hStartEntity , const char *szName, const Vector &vecSrc, float flRadius )
|
||||
{
|
||||
return ToHScript( gEntList.FindEntityByClassnameWithin( ToEnt( hStartEntity ), szName, vecSrc, flRadius ) );
|
||||
}
|
||||
|
||||
private:
|
||||
} g_ScriptEntityIterator;
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT_NAMED( CScriptEntityIterator, "CEntities", SCRIPT_SINGLETON "The global list of entities" )
|
||||
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" )
|
||||
DEFINE_SCRIPTFUNC( FindByClassname, "Find entities by class name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
DEFINE_SCRIPTFUNC( FindByName, "Find entities by name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
DEFINE_SCRIPTFUNC( FindInSphere, "Find entities within a radius. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
DEFINE_SCRIPTFUNC( FindByTarget, "Find entities by targetname. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
DEFINE_SCRIPTFUNC( FindByModel, "Find entities by model name. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
DEFINE_SCRIPTFUNC( FindByNameNearest, "Find entities by name nearest to a point." )
|
||||
DEFINE_SCRIPTFUNC( FindByNameWithin, "Find entities by name within a radius. Pass 'null' to start an iteration, or reference to a previously found entity to continue a search" )
|
||||
DEFINE_SCRIPTFUNC( FindByClassnameNearest, "Find entities by class name nearest to a point." )
|
||||
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" )
|
||||
END_SCRIPTDESC();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// KeyValues access - CBaseEntity::ScriptGetKeyFromModel returns root KeyValues
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BEGIN_SCRIPTDESC_ROOT( CScriptKeyValues, "Wrapper class over KeyValues instance" )
|
||||
DEFINE_SCRIPT_CONSTRUCTOR()
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptFindKey, "FindKey", "Given a KeyValues object and a key name, find a KeyValues object associated with the key name" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetFirstSubKey, "GetFirstSubKey", "Given a KeyValues object, return the first sub key object" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetNextKey, "GetNextKey", "Given a KeyValues object, return the next key object in a sub key group" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueInt, "GetKeyInt", "Given a KeyValues object and a key name, return associated integer value" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueFloat, "GetKeyFloat", "Given a KeyValues object and a key name, return associated float value" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueBool, "GetKeyBool", "Given a KeyValues object and a key name, return associated bool value" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValueString, "GetKeyString", "Given a KeyValues object and a key name, return associated string value" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptIsKeyValueEmpty, "IsKeyEmpty", "Given a KeyValues object and a key name, return true if key name has no value" );
|
||||
DEFINE_SCRIPTFUNC_NAMED( ScriptReleaseKeyValues, "ReleaseKeyValues", "Given a root KeyValues object, release its contents" );
|
||||
END_SCRIPTDESC();
|
||||
|
||||
HSCRIPT CScriptKeyValues::ScriptFindKey( const char *pszName )
|
||||
{
|
||||
KeyValues *pKeyValues = m_pKeyValues->FindKey(pszName);
|
||||
if ( pKeyValues == NULL )
|
||||
return NULL;
|
||||
|
||||
CScriptKeyValues *pScriptKey = new CScriptKeyValues( pKeyValues );
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??
|
||||
HSCRIPT hScriptInstance = g_pScriptVM->RegisterInstance( pScriptKey );
|
||||
return hScriptInstance;
|
||||
}
|
||||
|
||||
HSCRIPT CScriptKeyValues::ScriptGetFirstSubKey( void )
|
||||
{
|
||||
KeyValues *pKeyValues = m_pKeyValues->GetFirstSubKey();
|
||||
if ( pKeyValues == NULL )
|
||||
return NULL;
|
||||
|
||||
CScriptKeyValues *pScriptKey = new CScriptKeyValues( pKeyValues );
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??
|
||||
HSCRIPT hScriptInstance = g_pScriptVM->RegisterInstance( pScriptKey );
|
||||
return hScriptInstance;
|
||||
}
|
||||
|
||||
HSCRIPT CScriptKeyValues::ScriptGetNextKey( void )
|
||||
{
|
||||
KeyValues *pKeyValues = m_pKeyValues->GetNextKey();
|
||||
if ( pKeyValues == NULL )
|
||||
return NULL;
|
||||
|
||||
CScriptKeyValues *pScriptKey = new CScriptKeyValues( pKeyValues );
|
||||
|
||||
// UNDONE: who calls ReleaseInstance on this??
|
||||
HSCRIPT hScriptInstance = g_pScriptVM->RegisterInstance( pScriptKey );
|
||||
return hScriptInstance;
|
||||
}
|
||||
|
||||
int CScriptKeyValues::ScriptGetKeyValueInt( const char *pszName )
|
||||
{
|
||||
int i = m_pKeyValues->GetInt( pszName );
|
||||
return i;
|
||||
}
|
||||
|
||||
float CScriptKeyValues::ScriptGetKeyValueFloat( const char *pszName )
|
||||
{
|
||||
float f = m_pKeyValues->GetFloat( pszName );
|
||||
return f;
|
||||
}
|
||||
|
||||
const char *CScriptKeyValues::ScriptGetKeyValueString( const char *pszName )
|
||||
{
|
||||
const char *psz = m_pKeyValues->GetString( pszName );
|
||||
return psz;
|
||||
}
|
||||
|
||||
bool CScriptKeyValues::ScriptIsKeyValueEmpty( const char *pszName )
|
||||
{
|
||||
bool b = m_pKeyValues->IsEmpty( pszName );
|
||||
return b;
|
||||
}
|
||||
|
||||
bool CScriptKeyValues::ScriptGetKeyValueBool( const char *pszName )
|
||||
{
|
||||
bool b = m_pKeyValues->GetBool( pszName );
|
||||
return b;
|
||||
}
|
||||
|
||||
void CScriptKeyValues::ScriptReleaseKeyValues( )
|
||||
{
|
||||
m_pKeyValues->deleteThis();
|
||||
m_pKeyValues = NULL;
|
||||
}
|
||||
|
||||
|
||||
// constructors
|
||||
CScriptKeyValues::CScriptKeyValues( KeyValues *pKeyValues = NULL )
|
||||
{
|
||||
m_pKeyValues = pKeyValues;
|
||||
}
|
||||
|
||||
// destructor
|
||||
CScriptKeyValues::~CScriptKeyValues( )
|
||||
{
|
||||
if (m_pKeyValues)
|
||||
{
|
||||
m_pKeyValues->deleteThis();
|
||||
}
|
||||
m_pKeyValues = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
static float Time()
|
||||
{
|
||||
return gpGlobals->curtime;
|
||||
}
|
||||
|
||||
static float FrameTime()
|
||||
{
|
||||
return gpGlobals->frametime;
|
||||
}
|
||||
|
||||
static void SendToConsole( const char *pszCommand )
|
||||
{
|
||||
CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost();
|
||||
if ( !pPlayer )
|
||||
{
|
||||
DevMsg ("Cannot execute \"%s\", no player\n", pszCommand );
|
||||
return;
|
||||
}
|
||||
|
||||
engine->ClientCommand( pPlayer->edict(), pszCommand );
|
||||
}
|
||||
|
||||
static const char *GetMapName()
|
||||
{
|
||||
return STRING( gpGlobals->mapname );
|
||||
}
|
||||
|
||||
static const char *DoUniqueString( const char *pszBase )
|
||||
{
|
||||
static char szBuf[512];
|
||||
g_pScriptVM->GenerateUniqueKey( pszBase, szBuf, ARRAYSIZE(szBuf) );
|
||||
return szBuf;
|
||||
}
|
||||
|
||||
static void DoEntFire( const char *pszTarget, const char *pszAction, const char *pszValue, float delay, HSCRIPT hActivator, HSCRIPT hCaller )
|
||||
{
|
||||
const char *target = "", *action = "Use";
|
||||
variant_t value;
|
||||
|
||||
target = STRING( AllocPooledString( pszTarget ) );
|
||||
|
||||
// Don't allow them to run anything on a point_servercommand unless they're the host player. Otherwise they can ent_fire
|
||||
// and run any command on the server. Admittedly, they can only do the ent_fire if sv_cheats is on, but
|
||||
// people complained about users resetting the rcon password if the server briefly turned on cheats like this:
|
||||
// give point_servercommand
|
||||
// ent_fire point_servercommand command "rcon_password mynewpassword"
|
||||
if ( gpGlobals->maxClients > 1 && V_stricmp( target, "point_servercommand" ) == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( *pszAction )
|
||||
{
|
||||
action = STRING( AllocPooledString( pszAction ) );
|
||||
}
|
||||
if ( *pszValue )
|
||||
{
|
||||
value.SetString( AllocPooledString( pszValue ) );
|
||||
}
|
||||
if ( delay < 0 )
|
||||
{
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
g_EventQueue.AddEvent( target, action, value, delay, ToEnt(hActivator), ToEnt(hCaller) );
|
||||
}
|
||||
|
||||
|
||||
bool DoIncludeScript( const char *pszScript, HSCRIPT hScope )
|
||||
{
|
||||
if ( !VScriptRunScript( pszScript, hScope, true ) )
|
||||
{
|
||||
g_pScriptVM->RaiseException( CFmtStr( "Failed to include script \"%s\"", ( pszScript ) ? pszScript : "unknown" ) );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HSCRIPT CreateProp( const char *pszEntityName, const Vector &vOrigin, const char *pszModelName, int iAnim )
|
||||
{
|
||||
CBaseAnimating *pBaseEntity = (CBaseAnimating *)CreateEntityByName( pszEntityName );
|
||||
pBaseEntity->SetAbsOrigin( vOrigin );
|
||||
pBaseEntity->SetModel( pszModelName );
|
||||
pBaseEntity->SetPlaybackRate( 1.0f );
|
||||
|
||||
int iSequence = pBaseEntity->SelectWeightedSequence( (Activity)iAnim );
|
||||
|
||||
if ( iSequence != -1 )
|
||||
{
|
||||
pBaseEntity->SetSequence( iSequence );
|
||||
}
|
||||
|
||||
return ToHScript( pBaseEntity );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// Use an entity's script instance to add an entity IO event (used for firing events on unnamed entities from vscript)
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
static void DoEntFireByInstanceHandle( HSCRIPT hTarget, const char *pszAction, const char *pszValue, float delay, HSCRIPT hActivator, HSCRIPT hCaller )
|
||||
{
|
||||
const char *action = "Use";
|
||||
variant_t value;
|
||||
|
||||
if ( *pszAction )
|
||||
{
|
||||
action = STRING( AllocPooledString( pszAction ) );
|
||||
}
|
||||
if ( *pszValue )
|
||||
{
|
||||
value.SetString( AllocPooledString( pszValue ) );
|
||||
}
|
||||
if ( delay < 0 )
|
||||
{
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
CBaseEntity* pTarget = ToEnt(hTarget);
|
||||
|
||||
if ( !pTarget )
|
||||
{
|
||||
Warning( "VScript error: DoEntFire was passed an invalid entity instance.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
g_EventQueue.AddEvent( pTarget, action, value, delay, ToEnt(hActivator), ToEnt(hCaller) );
|
||||
}
|
||||
|
||||
static float ScriptTraceLine( const Vector &vecStart, const Vector &vecEnd, HSCRIPT entIgnore )
|
||||
{
|
||||
// UTIL_TraceLine( vecAbsStart, vecAbsEnd, MASK_BLOCKLOS, pLooker, COLLISION_GROUP_NONE, ptr );
|
||||
trace_t tr;
|
||||
CBaseEntity *pLooker = ToEnt(entIgnore);
|
||||
UTIL_TraceLine( vecStart, vecEnd, MASK_NPCWORLDSTATIC, pLooker, COLLISION_GROUP_NONE, &tr);
|
||||
if (tr.fractionleftsolid && tr.startsolid)
|
||||
{
|
||||
return 1.0 - tr.fractionleftsolid;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tr.fraction;
|
||||
}
|
||||
}
|
||||
|
||||
bool VScriptServerInit()
|
||||
{
|
||||
VMPROF_START
|
||||
|
||||
if( scriptmanager != NULL )
|
||||
{
|
||||
ScriptLanguage_t scriptLanguage = SL_DEFAULT;
|
||||
|
||||
char const *pszScriptLanguage;
|
||||
if ( CommandLine()->CheckParm( "-scriptlang", &pszScriptLanguage ) )
|
||||
{
|
||||
if( !Q_stricmp(pszScriptLanguage, "gamemonkey") )
|
||||
{
|
||||
scriptLanguage = SL_GAMEMONKEY;
|
||||
}
|
||||
else if( !Q_stricmp(pszScriptLanguage, "squirrel") )
|
||||
{
|
||||
scriptLanguage = SL_SQUIRREL;
|
||||
}
|
||||
else if( !Q_stricmp(pszScriptLanguage, "python") )
|
||||
{
|
||||
scriptLanguage = SL_PYTHON;
|
||||
}
|
||||
else
|
||||
{
|
||||
DevWarning("-server_script does not recognize a language named '%s'. virtual machine did NOT start.\n", pszScriptLanguage );
|
||||
scriptLanguage = SL_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
if( scriptLanguage != SL_NONE )
|
||||
{
|
||||
if ( g_pScriptVM == NULL )
|
||||
g_pScriptVM = scriptmanager->CreateVM( scriptLanguage );
|
||||
|
||||
if( g_pScriptVM )
|
||||
{
|
||||
Log( "VSCRIPT: Started VScript virtual machine using script language '%s'\n", g_pScriptVM->GetLanguageName() );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, UTIL_ShowMessageAll, "ShowMessage", "Print a hud message on all clients" );
|
||||
|
||||
ScriptRegisterFunction( g_pScriptVM, SendToConsole, "Send a string to the console as a command" );
|
||||
ScriptRegisterFunction( g_pScriptVM, GetMapName, "Get the name of the map.");
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptTraceLine, "TraceLine", "given 2 points & ent to ignore, return fraction along line that hits world or models" );
|
||||
|
||||
ScriptRegisterFunction( g_pScriptVM, Time, "Get the current server time" );
|
||||
ScriptRegisterFunction( g_pScriptVM, FrameTime, "Get the time spent on the server in the last frame" );
|
||||
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." );
|
||||
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. Useful for adding data to tables when not sure what keys are already in use in that table." ) );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, ScriptCreateSceneEntity, "CreateSceneEntity", "Create a scene entity to play the specified scene." );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, NDebugOverlay::Box, "DebugDrawBox", "Draw a debug overlay box" );
|
||||
ScriptRegisterFunctionNamed( g_pScriptVM, NDebugOverlay::Line, "DebugDrawLine", "Draw a debug overlay box" );
|
||||
ScriptRegisterFunction( g_pScriptVM, DoIncludeScript, "Execute a script (internal)" );
|
||||
ScriptRegisterFunction( g_pScriptVM, CreateProp, "Create a physics prop" );
|
||||
|
||||
|
||||
if ( GameRules() )
|
||||
{
|
||||
GameRules()->RegisterScriptFunctions();
|
||||
}
|
||||
|
||||
g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
|
||||
|
||||
if ( scriptLanguage == SL_SQUIRREL )
|
||||
{
|
||||
//g_pScriptVM->Run( g_Script_vscript_server );
|
||||
}
|
||||
|
||||
VScriptRunScript( "mapspawn", false );
|
||||
|
||||
VMPROF_SHOW( pszScriptLanguage, "virtual machine startup" );
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DevWarning("VM Did not start!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log( "\nVSCRIPT: Scripting is disabled.\n" );
|
||||
}
|
||||
g_pScriptVM = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
void VScriptServerTerm()
|
||||
{
|
||||
if( g_pScriptVM != NULL )
|
||||
{
|
||||
if( g_pScriptVM )
|
||||
{
|
||||
scriptmanager->DestroyVM( g_pScriptVM );
|
||||
g_pScriptVM = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool VScriptServerReplaceClosures( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing )
|
||||
{
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HSCRIPT hReplaceClosuresFunc = g_pScriptVM->LookupFunction( "__ReplaceClosures" );
|
||||
if ( !hReplaceClosuresFunc )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
HSCRIPT hNewScript = VScriptCompileScript( pszScriptName, bWarnMissing );
|
||||
if ( !hNewScript )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pScriptVM->Call( hReplaceClosuresFunc, NULL, true, NULL, hNewScript, hScope );
|
||||
return true;
|
||||
}
|
||||
|
||||
CON_COMMAND( script_reload_code, "Execute a vscript file, replacing existing functions with the functions in the run script" )
|
||||
{
|
||||
if ( !*args[1] )
|
||||
{
|
||||
Warning( "No script specified\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
VScriptServerReplaceClosures( args[1], NULL, true );
|
||||
}
|
||||
|
||||
CON_COMMAND( script_reload_entity_code, "Execute all of this entity's VScripts, replacing existing functions with the functions in the run scripts" )
|
||||
{
|
||||
extern CBaseEntity *GetNextCommandEntity( CBasePlayer *pPlayer, const char *name, CBaseEntity *ent );
|
||||
|
||||
const char *pszTarget = "";
|
||||
if ( *args[1] )
|
||||
{
|
||||
pszTarget = args[1];
|
||||
}
|
||||
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_GetCommandClient();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
CBaseEntity *pEntity = NULL;
|
||||
while ( (pEntity = GetNextCommandEntity( pPlayer, pszTarget, pEntity )) != NULL )
|
||||
{
|
||||
if ( pEntity->m_ScriptScope.IsInitialized() && pEntity->m_iszVScripts != NULL_STRING )
|
||||
{
|
||||
char szScriptsList[255];
|
||||
Q_strcpy( szScriptsList, STRING(pEntity->m_iszVScripts) );
|
||||
CUtlStringList szScripts;
|
||||
V_SplitString( szScriptsList, " ", szScripts);
|
||||
|
||||
for( int i = 0 ; i < szScripts.Count() ; i++ )
|
||||
{
|
||||
VScriptServerReplaceClosures( szScripts[i], pEntity->m_ScriptScope, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CON_COMMAND( script_reload_think, "Execute an activation script, replacing existing functions with the functions in the run script" )
|
||||
{
|
||||
extern CBaseEntity *GetNextCommandEntity( CBasePlayer *pPlayer, const char *name, CBaseEntity *ent );
|
||||
|
||||
const char *pszTarget = "";
|
||||
if ( *args[1] )
|
||||
{
|
||||
pszTarget = args[1];
|
||||
}
|
||||
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CBasePlayer *pPlayer = UTIL_GetCommandClient();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
CBaseEntity *pEntity = NULL;
|
||||
while ( (pEntity = GetNextCommandEntity( pPlayer, pszTarget, pEntity )) != NULL )
|
||||
{
|
||||
if ( pEntity->m_ScriptScope.IsInitialized() && pEntity->m_iszScriptThinkFunction != NULL_STRING )
|
||||
{
|
||||
VScriptServerReplaceClosures( STRING(pEntity->m_iszScriptThinkFunction), pEntity->m_ScriptScope, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CVScriptGameSystem : public CAutoGameSystemPerFrame
|
||||
{
|
||||
public:
|
||||
// Inherited from IAutoServerSystem
|
||||
virtual void LevelInitPreEntity( void )
|
||||
{
|
||||
m_bAllowEntityCreationInScripts = true;
|
||||
VScriptServerInit();
|
||||
}
|
||||
|
||||
virtual void LevelInitPostEntity( void )
|
||||
{
|
||||
m_bAllowEntityCreationInScripts = false;
|
||||
}
|
||||
|
||||
virtual void LevelShutdownPostEntity( void )
|
||||
{
|
||||
VScriptServerTerm();
|
||||
}
|
||||
|
||||
virtual void FrameUpdatePostEntityThink()
|
||||
{
|
||||
if ( g_pScriptVM )
|
||||
g_pScriptVM->Frame( gpGlobals->frametime );
|
||||
}
|
||||
|
||||
bool m_bAllowEntityCreationInScripts;
|
||||
};
|
||||
|
||||
CVScriptGameSystem g_VScriptGameSystem;
|
||||
|
||||
bool IsEntityCreationAllowedInScripts( void )
|
||||
{
|
||||
return g_VScriptGameSystem.m_bAllowEntityCreationInScripts;
|
||||
}
|
||||
|
||||
static short VSCRIPT_SERVER_SAVE_RESTORE_VERSION = 2;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class CVScriptSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler
|
||||
{
|
||||
public:
|
||||
CVScriptSaveRestoreBlockHandler() :
|
||||
m_InstanceMap( DefLessFunc(const char *) )
|
||||
{
|
||||
}
|
||||
const char *GetBlockName()
|
||||
{
|
||||
return "VScriptServer";
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void Save( ISave *pSave )
|
||||
{
|
||||
pSave->StartBlock();
|
||||
|
||||
int temp = g_pScriptVM != NULL;
|
||||
pSave->WriteInt( &temp );
|
||||
if ( g_pScriptVM )
|
||||
{
|
||||
temp = g_pScriptVM->GetLanguage();
|
||||
pSave->WriteInt( &temp );
|
||||
CUtlBuffer buffer;
|
||||
g_pScriptVM->WriteState( &buffer );
|
||||
temp = buffer.TellPut();
|
||||
pSave->WriteInt( &temp );
|
||||
if ( temp > 0 )
|
||||
{
|
||||
pSave->WriteData( (const char *)buffer.Base(), temp );
|
||||
}
|
||||
}
|
||||
|
||||
pSave->EndBlock();
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void WriteSaveHeaders( ISave *pSave )
|
||||
{
|
||||
pSave->WriteShort( &VSCRIPT_SERVER_SAVE_RESTORE_VERSION );
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void ReadRestoreHeaders( IRestore *pRestore )
|
||||
{
|
||||
// No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so.
|
||||
short version;
|
||||
pRestore->ReadShort( &version );
|
||||
m_fDoLoad = ( version == VSCRIPT_SERVER_SAVE_RESTORE_VERSION );
|
||||
}
|
||||
|
||||
//---------------------------------
|
||||
|
||||
void Restore( IRestore *pRestore, bool createPlayers )
|
||||
{
|
||||
if ( !m_fDoLoad && g_pScriptVM )
|
||||
{
|
||||
return;
|
||||
}
|
||||
CBaseEntity *pEnt = gEntList.FirstEnt();
|
||||
while ( pEnt )
|
||||
{
|
||||
if ( pEnt->m_iszScriptId != NULL_STRING )
|
||||
{
|
||||
g_pScriptVM->RegisterClass( pEnt->GetScriptDesc() );
|
||||
m_InstanceMap.Insert( STRING( pEnt->m_iszScriptId ), pEnt );
|
||||
}
|
||||
pEnt = gEntList.NextEnt( pEnt );
|
||||
}
|
||||
|
||||
pRestore->StartBlock();
|
||||
if ( pRestore->ReadInt() && pRestore->ReadInt() == g_pScriptVM->GetLanguage() )
|
||||
{
|
||||
int nBytes = pRestore->ReadInt();
|
||||
if ( nBytes > 0 )
|
||||
{
|
||||
CUtlBuffer buffer;
|
||||
buffer.EnsureCapacity( nBytes );
|
||||
pRestore->ReadData( (char *)buffer.AccessForDirectRead( nBytes ), nBytes, 0 );
|
||||
g_pScriptVM->ReadState( &buffer );
|
||||
}
|
||||
}
|
||||
pRestore->EndBlock();
|
||||
}
|
||||
|
||||
void PostRestore( void )
|
||||
{
|
||||
for ( int i = m_InstanceMap.FirstInorder(); i != m_InstanceMap.InvalidIndex(); i = m_InstanceMap.NextInorder( i ) )
|
||||
{
|
||||
CBaseEntity *pEnt = m_InstanceMap[i];
|
||||
if ( pEnt->m_hScriptInstance )
|
||||
{
|
||||
ScriptVariant_t variant;
|
||||
if ( g_pScriptVM->GetValue( STRING(pEnt->m_iszScriptId), &variant ) && variant.m_type == FIELD_HSCRIPT )
|
||||
{
|
||||
pEnt->m_ScriptScope.Init( variant.m_hScript, false );
|
||||
pEnt->RunPrecacheScripts();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Script system probably has no internal references
|
||||
pEnt->m_iszScriptId = NULL_STRING;
|
||||
}
|
||||
}
|
||||
m_InstanceMap.Purge();
|
||||
}
|
||||
|
||||
|
||||
CUtlMap<const char *, CBaseEntity *> m_InstanceMap;
|
||||
|
||||
private:
|
||||
bool m_fDoLoad;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
CVScriptSaveRestoreBlockHandler g_VScriptSaveRestoreBlockHandler;
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
ISaveRestoreBlockHandler *GetVScriptSaveRestoreBlockHandler()
|
||||
{
|
||||
return &g_VScriptSaveRestoreBlockHandler;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool CBaseEntityScriptInstanceHelper::ToString( void *p, char *pBuf, int bufSize )
|
||||
{
|
||||
CBaseEntity *pEntity = (CBaseEntity *)p;
|
||||
if ( pEntity->GetEntityName() != NULL_STRING )
|
||||
{
|
||||
V_snprintf( pBuf, bufSize, "([%d] %s: %s)", pEntity->entindex(), STRING(pEntity->m_iClassname), STRING( pEntity->GetEntityName() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
V_snprintf( pBuf, bufSize, "([%d] %s)", pEntity->entindex(), STRING(pEntity->m_iClassname) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void *CBaseEntityScriptInstanceHelper::BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId )
|
||||
{
|
||||
int iEntity = g_VScriptSaveRestoreBlockHandler.m_InstanceMap.Find( pszId );
|
||||
if ( iEntity != g_VScriptSaveRestoreBlockHandler.m_InstanceMap.InvalidIndex() )
|
||||
{
|
||||
CBaseEntity *pEnt = g_VScriptSaveRestoreBlockHandler.m_InstanceMap[iEntity];
|
||||
pEnt->m_hScriptInstance = hInstance;
|
||||
return pEnt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
CBaseEntityScriptInstanceHelper g_BaseEntityScriptInstanceHelper;
|
||||
|
||||
|
57
sp/src/game/server/vscript_server.h
Normal file
57
sp/src/game/server/vscript_server.h
Normal file
@ -0,0 +1,57 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VSCRIPT_SERVER_H
|
||||
#define VSCRIPT_SERVER_H
|
||||
|
||||
#include "vscript/ivscript.h"
|
||||
#include "tier1/KeyValues.h"
|
||||
#include "vscript_shared.h"
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
class ISaveRestoreBlockHandler;
|
||||
|
||||
bool VScriptServerReplaceClosures( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing = false );
|
||||
ISaveRestoreBlockHandler *GetVScriptSaveRestoreBlockHandler();
|
||||
|
||||
|
||||
class CBaseEntityScriptInstanceHelper : public IScriptInstanceHelper
|
||||
{
|
||||
bool ToString( void *p, char *pBuf, int bufSize );
|
||||
void *BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId );
|
||||
};
|
||||
|
||||
extern CBaseEntityScriptInstanceHelper g_BaseEntityScriptInstanceHelper;
|
||||
|
||||
// Only allow scripts to create entities during map initialization
|
||||
bool IsEntityCreationAllowedInScripts( void );
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// KeyValues access
|
||||
// ----------------------------------------------------------------------------
|
||||
class CScriptKeyValues
|
||||
{
|
||||
public:
|
||||
CScriptKeyValues( KeyValues *pKeyValues );
|
||||
~CScriptKeyValues( );
|
||||
|
||||
HSCRIPT ScriptFindKey( const char *pszName );
|
||||
HSCRIPT ScriptGetFirstSubKey( void );
|
||||
HSCRIPT ScriptGetNextKey( void );
|
||||
int ScriptGetKeyValueInt( const char *pszName );
|
||||
float ScriptGetKeyValueFloat( const char *pszName );
|
||||
const char *ScriptGetKeyValueString( const char *pszName );
|
||||
bool ScriptIsKeyValueEmpty( const char *pszName );
|
||||
bool ScriptGetKeyValueBool( const char *pszName );
|
||||
void ScriptReleaseKeyValues( );
|
||||
|
||||
KeyValues *m_pKeyValues; // actual KeyValue entity
|
||||
};
|
||||
|
||||
#endif // VSCRIPT_SERVER_H
|
127
sp/src/game/server/vscript_server.nut
Normal file
127
sp/src/game/server/vscript_server.nut
Normal file
@ -0,0 +1,127 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
function UniqueString( string = "" )
|
||||
{
|
||||
return DoUniqueString( string.tostring() );
|
||||
}
|
||||
|
||||
function EntFire( target, action, value = null, delay = 0.0, activator = null )
|
||||
{
|
||||
if ( !value )
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
local caller = null;
|
||||
if ( "self" in this )
|
||||
{
|
||||
caller = self;
|
||||
if ( !activator )
|
||||
{
|
||||
activator = self;
|
||||
}
|
||||
}
|
||||
|
||||
DoEntFire( target.tostring(), action.tostring(), value.tostring(), delay, activator, caller );
|
||||
}
|
||||
|
||||
function __ReplaceClosures( script, scope )
|
||||
{
|
||||
if ( !scope )
|
||||
{
|
||||
scope = getroottable();
|
||||
}
|
||||
|
||||
local tempParent = { getroottable = function() { return null; } };
|
||||
local temp = { runscript = script };
|
||||
delegate tempParent : temp;
|
||||
|
||||
temp.runscript()
|
||||
foreach( key,val in temp )
|
||||
{
|
||||
if ( typeof(val) == "function" && key != "runscript" )
|
||||
{
|
||||
printl( " Replacing " + key );
|
||||
scope[key] <- val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__OutputsPattern <- regexp("^On.*Output$");
|
||||
|
||||
function ConnectOutputs( table )
|
||||
{
|
||||
const nCharsToStrip = 6;
|
||||
foreach( key, val in table )
|
||||
{
|
||||
if ( typeof( val ) == "function" && __OutputsPattern.match( key ) )
|
||||
{
|
||||
//printl(key.slice( 0, nCharsToStrip ) );
|
||||
table.self.ConnectOutput( key.slice( 0, key.len() - nCharsToStrip ), key );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function IncludeScript( name, scope = null )
|
||||
{
|
||||
if ( scope == null )
|
||||
{
|
||||
scope = this;
|
||||
}
|
||||
return ::DoIncludeScript( name, scope );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Text dump this scope's contents to the console.
|
||||
//---------------------------------------------------------
|
||||
function __DumpScope( depth, table )
|
||||
{
|
||||
local indent=function( count )
|
||||
{
|
||||
local i;
|
||||
for( i = 0 ; i < count ; i++ )
|
||||
{
|
||||
print(" ");
|
||||
}
|
||||
}
|
||||
|
||||
foreach(key, value in table)
|
||||
{
|
||||
indent(depth);
|
||||
print( key );
|
||||
switch (type(value))
|
||||
{
|
||||
case "table":
|
||||
print("(TABLE)\n");
|
||||
indent(depth);
|
||||
print("{\n");
|
||||
__DumpScope( depth + 1, value);
|
||||
indent(depth);
|
||||
print("}");
|
||||
break;
|
||||
case "array":
|
||||
print("(ARRAY)\n");
|
||||
indent(depth);
|
||||
print("[\n")
|
||||
__DumpScope( depth + 1, value);
|
||||
indent(depth);
|
||||
print("]");
|
||||
break;
|
||||
case "string":
|
||||
print(" = \"");
|
||||
print(value);
|
||||
print("\"");
|
||||
break;
|
||||
default:
|
||||
print(" = ");
|
||||
print(value);
|
||||
break;
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
|
@ -1217,6 +1217,19 @@ void CBaseEntity::EmitSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle,
|
||||
EmitSound( filter, entindex(), params, handle );
|
||||
}
|
||||
|
||||
#if !defined ( CLIENT_DLL )
|
||||
void CBaseEntity::ScriptEmitSound( const char *soundname )
|
||||
{
|
||||
EmitSound( soundname );
|
||||
}
|
||||
|
||||
float CBaseEntity::ScriptSoundDuration( const char *soundname, const char *actormodel )
|
||||
{
|
||||
float duration = CBaseEntity::GetSoundDuration( soundname, actormodel );
|
||||
return duration;
|
||||
}
|
||||
#endif // !CLIENT
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : filter -
|
||||
@ -1486,6 +1499,14 @@ HSOUNDSCRIPTHANDLE CBaseEntity::PrecacheScriptSound( const char *soundname )
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined ( CLIENT_DLL )
|
||||
// Same as server version of above, but signiture changed so it can be deduced by the macros
|
||||
void CBaseEntity::VScriptPrecacheScriptSound(const char* soundname)
|
||||
{
|
||||
g_SoundEmitterSystem.PrecacheScriptSound(soundname);
|
||||
}
|
||||
#endif // !CLIENT_DLL
|
||||
|
||||
void CBaseEntity::PrefetchScriptSound( const char *soundname )
|
||||
{
|
||||
g_SoundEmitterSystem.PrefetchScriptSound( soundname );
|
||||
|
@ -68,6 +68,9 @@ enum InvalidatePhysicsBits_t
|
||||
|
||||
#endif
|
||||
|
||||
#include "vscript/ivscript.h"
|
||||
#include "vscript_shared.h"
|
||||
|
||||
#if !defined( NO_ENTITY_PREDICTION )
|
||||
// CBaseEntity inlines
|
||||
inline bool CBaseEntity::IsPlayerSimulated( void ) const
|
||||
@ -247,6 +250,17 @@ inline bool CBaseEntity::IsEffectActive( int nEffects ) const
|
||||
return (m_fEffects & nEffects) != 0;
|
||||
}
|
||||
|
||||
inline HSCRIPT ToHScript(CBaseEntity* pEnt)
|
||||
{
|
||||
return (pEnt) ? pEnt->GetScriptInstance() : NULL;
|
||||
}
|
||||
|
||||
template <> ScriptClassDesc_t* GetScriptDesc<CBaseEntity>(CBaseEntity*);
|
||||
inline CBaseEntity* ToEnt(HSCRIPT hScript)
|
||||
{
|
||||
return (hScript) ? (CBaseEntity*)g_pScriptVM->GetInstanceValue(hScript, GetScriptDescForClass(CBaseEntity)) : NULL;
|
||||
}
|
||||
|
||||
// Shared EntityMessage between game and client .dlls
|
||||
#define BASEENTITY_MSG_REMOVE_DECALS 1
|
||||
|
||||
|
@ -2064,6 +2064,8 @@ static EventNameMap_t g_NameMap[] =
|
||||
{ CChoreoEvent::STOPPOINT, "stoppoint" },
|
||||
{ CChoreoEvent::PERMIT_RESPONSES, "permitresponses" },
|
||||
{ CChoreoEvent::GENERIC, "generic" },
|
||||
{ CChoreoEvent::CAMERA, "camera" },
|
||||
{ CChoreoEvent::SCRIPT, "script" },
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -307,6 +307,12 @@ public:
|
||||
// A string passed to the game code for interpretation
|
||||
GENERIC,
|
||||
|
||||
// Camera control
|
||||
CAMERA,
|
||||
|
||||
// Script function call
|
||||
SCRIPT,
|
||||
|
||||
// THIS MUST BE LAST!!!
|
||||
NUM_TYPES,
|
||||
} EVENTTYPE;
|
||||
|
@ -173,6 +173,8 @@ public:
|
||||
|
||||
virtual bool InRoundRestart( void ) { return false; }
|
||||
|
||||
virtual void RegisterScriptFunctions( void ){ };
|
||||
|
||||
//Allow thirdperson camera.
|
||||
virtual bool AllowThirdPersonCamera( void ) { return false; }
|
||||
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
m_pEvent( 0 ),
|
||||
m_pScene( 0 ),
|
||||
m_pActor( 0 ),
|
||||
m_hSceneEntity(0),
|
||||
m_bStarted( false ),
|
||||
m_iLayer( -1 ),
|
||||
m_iPriority( 0 ),
|
||||
@ -63,6 +64,8 @@ public:
|
||||
// Current actor
|
||||
CChoreoActor *m_pActor;
|
||||
|
||||
CHandle< CSceneEntity > m_hSceneEntity;
|
||||
|
||||
// Set after the first time the event has been configured ( allows
|
||||
// bumping markov index only at start of event playback, not every frame )
|
||||
bool m_bStarted;
|
||||
|
266
sp/src/game/shared/vscript_shared.cpp
Normal file
266
sp/src/game/shared/vscript_shared.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "vscript_shared.h"
|
||||
#include "icommandline.h"
|
||||
#include "tier1/utlbuffer.h"
|
||||
#include "tier1/fmtstr.h"
|
||||
#include "filesystem.h"
|
||||
#include "characterset.h"
|
||||
#include "isaverestore.h"
|
||||
#include "gamerules.h"
|
||||
|
||||
IScriptVM * g_pScriptVM;
|
||||
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
|
||||
|
||||
// #define VMPROFILE 1
|
||||
|
||||
#ifdef VMPROFILE
|
||||
|
||||
#define VMPROF_START float debugStartTime = Plat_FloatTime();
|
||||
#define VMPROF_SHOW( funcname, funcdesc ) DevMsg("***VSCRIPT PROFILE***: %s %s: %6.4f milliseconds\n", (##funcname), (##funcdesc), (Plat_FloatTime() - debugStartTime)*1000.0 );
|
||||
|
||||
#else // !VMPROFILE
|
||||
|
||||
#define VMPROF_START
|
||||
#define VMPROF_SHOW
|
||||
|
||||
#endif // VMPROFILE
|
||||
|
||||
|
||||
|
||||
HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing )
|
||||
{
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *pszExtensions[] =
|
||||
{
|
||||
"", // SL_NONE
|
||||
".gm", // SL_GAMEMONKEY
|
||||
".nut", // SL_SQUIRREL
|
||||
".lua", // SL_LUA
|
||||
".py", // SL_PYTHON
|
||||
};
|
||||
|
||||
const char *pszVMExtension = pszExtensions[g_pScriptVM->GetLanguage()];
|
||||
const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' );
|
||||
if ( pszIncomingExtension && V_strcmp( pszIncomingExtension, pszVMExtension ) != 0 )
|
||||
{
|
||||
Warning( "Script file type does not match VM type\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFmtStr scriptPath;
|
||||
if ( pszIncomingExtension )
|
||||
{
|
||||
scriptPath.sprintf( "scripts/vscripts/%s", pszScriptName );
|
||||
}
|
||||
else
|
||||
{
|
||||
scriptPath.sprintf( "scripts/vscripts/%s%s", pszScriptName, pszVMExtension );
|
||||
}
|
||||
|
||||
const char *pBase;
|
||||
CUtlBuffer bufferScript;
|
||||
|
||||
if ( g_pScriptVM->GetLanguage() == SL_PYTHON )
|
||||
{
|
||||
// python auto-loads raw or precompiled modules - don't load data here
|
||||
pBase = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bResult = filesystem->ReadFile( scriptPath, "GAME", bufferScript );
|
||||
|
||||
if( !bResult )
|
||||
{
|
||||
Warning( "Script not found (%s) \n", scriptPath.operator const char *() );
|
||||
Assert( "Error running script" );
|
||||
}
|
||||
|
||||
pBase = (const char *) bufferScript.Base();
|
||||
|
||||
if ( !pBase || !*pBase )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *pszFilename = V_strrchr( scriptPath, '/' );
|
||||
pszFilename++;
|
||||
HSCRIPT hScript = g_pScriptVM->CompileScript( pBase, pszFilename );
|
||||
if ( !hScript )
|
||||
{
|
||||
Warning( "FAILED to compile and execute script file named %s\n", scriptPath.operator const char *() );
|
||||
Assert( "Error running script" );
|
||||
}
|
||||
return hScript;
|
||||
}
|
||||
|
||||
static int g_ScriptServerRunScriptDepth;
|
||||
|
||||
bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing )
|
||||
{
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !pszScriptName || !*pszScriptName )
|
||||
{
|
||||
Warning( "Cannot run script: NULL script name\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prevent infinite recursion in VM
|
||||
if ( g_ScriptServerRunScriptDepth > 16 )
|
||||
{
|
||||
Warning( "IncludeScript stack overflow\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
g_ScriptServerRunScriptDepth++;
|
||||
HSCRIPT hScript = VScriptCompileScript( pszScriptName, bWarnMissing );
|
||||
bool bSuccess = false;
|
||||
if ( hScript )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
if ( gpGlobals->maxClients == 1 )
|
||||
{
|
||||
CBaseEntity *pPlayer = UTIL_GetLocalPlayer();
|
||||
if ( pPlayer )
|
||||
{
|
||||
g_pScriptVM->SetValue( "player", pPlayer->GetScriptInstance() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bSuccess = ( g_pScriptVM->Run( hScript, hScope ) != SCRIPT_ERROR );
|
||||
if ( !bSuccess )
|
||||
{
|
||||
Warning( "Error running script named %s\n", pszScriptName );
|
||||
Assert( "Error running script" );
|
||||
}
|
||||
}
|
||||
g_ScriptServerRunScriptDepth--;
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
CON_COMMAND( script_client, "Run the text as a script" )
|
||||
#else
|
||||
CON_COMMAND( script, "Run the text as a script" )
|
||||
#endif
|
||||
{
|
||||
if ( !*args[1] )
|
||||
{
|
||||
Warning( "No function name specified\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
const char *pszScript = args.GetCommandString();
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
pszScript += 13;
|
||||
#else
|
||||
pszScript += 6;
|
||||
#endif
|
||||
|
||||
while ( *pszScript == ' ' )
|
||||
{
|
||||
pszScript++;
|
||||
}
|
||||
|
||||
if ( !*pszScript )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( *pszScript != '\"' )
|
||||
{
|
||||
g_pScriptVM->Run( pszScript );
|
||||
}
|
||||
else
|
||||
{
|
||||
pszScript++;
|
||||
const char *pszEndQuote = pszScript;
|
||||
while ( *pszEndQuote != '\"' )
|
||||
{
|
||||
pszEndQuote++;
|
||||
}
|
||||
if ( !*pszEndQuote )
|
||||
{
|
||||
return;
|
||||
}
|
||||
*((char *)pszEndQuote) = 0;
|
||||
g_pScriptVM->Run( pszScript );
|
||||
*((char *)pszEndQuote) = '\"';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CON_COMMAND_SHARED( script_execute, "Run a vscript file" )
|
||||
{
|
||||
if ( !*args[1] )
|
||||
{
|
||||
Warning( "No script specified\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
VScriptRunScript( args[1], true );
|
||||
}
|
||||
|
||||
CON_COMMAND_SHARED( script_debug, "Connect the vscript VM to the script debugger" )
|
||||
{
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
g_pScriptVM->ConnectDebugger();
|
||||
}
|
||||
|
||||
CON_COMMAND_SHARED( script_help, "Output help for script functions, optionally with a search string" )
|
||||
{
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
const char *pszArg1 = "*";
|
||||
if ( *args[1] )
|
||||
{
|
||||
pszArg1 = args[1];
|
||||
}
|
||||
|
||||
g_pScriptVM->Run( CFmtStr( "PrintHelp( \"%s\" );", pszArg1 ) );
|
||||
}
|
||||
|
||||
CON_COMMAND_SHARED( script_dump_all, "Dump the state of the VM to the console" )
|
||||
{
|
||||
if ( !g_pScriptVM )
|
||||
{
|
||||
Warning( "Scripting disabled or no server running\n" );
|
||||
return;
|
||||
}
|
||||
g_pScriptVM->DumpState();
|
||||
}
|
34
sp/src/game/shared/vscript_shared.h
Normal file
34
sp/src/game/shared/vscript_shared.h
Normal file
@ -0,0 +1,34 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VSCRIPT_SHARED_H
|
||||
#define VSCRIPT_SHARED_H
|
||||
|
||||
#include "vscript/ivscript.h"
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
extern IScriptVM * g_pScriptVM;
|
||||
|
||||
HSCRIPT VScriptCompileScript( const char *pszScriptName, bool bWarnMissing = false );
|
||||
bool VScriptRunScript( const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing = false );
|
||||
inline bool VScriptRunScript( const char *pszScriptName, bool bWarnMissing = false ) { return VScriptRunScript( pszScriptName, NULL, bWarnMissing ); }
|
||||
|
||||
#define DECLARE_ENT_SCRIPTDESC() ALLOW_SCRIPT_ACCESS(); virtual ScriptClassDesc_t *GetScriptDesc()
|
||||
|
||||
#define BEGIN_ENT_SCRIPTDESC( className, baseClass, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC( className, baseClass, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT( className, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT( className, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description )
|
||||
#define BEGIN_ENT_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ); BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description )
|
||||
|
||||
#define _IMPLEMENT_ENT_SCRIPTDESC_ACCESSOR( className ) template <> ScriptClassDesc_t * GetScriptDesc<className>( className * ); ScriptClassDesc_t *className::GetScriptDesc() { return ::GetScriptDesc( this ); }
|
||||
|
||||
// Only allow scripts to create entities during map initialization
|
||||
bool IsEntityCreationAllowedInScripts( void );
|
||||
|
||||
#endif // VSCRIPT_SHARED_H
|
@ -632,6 +632,18 @@ private:
|
||||
static ConCommand name##_command( #name, name, description ); \
|
||||
static void name( const CCommand &args )
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#define CON_COMMAND_SHARED( name, description ) \
|
||||
static void name( const CCommand &args ); \
|
||||
static ConCommand name##_command_client( #name "_client", name, description ); \
|
||||
static void name( const CCommand &args )
|
||||
#else
|
||||
#define CON_COMMAND_SHARED( name, description ) \
|
||||
static void name( const CCommand &args ); \
|
||||
static ConCommand name##_command( #name, name, description ); \
|
||||
static void name( const CCommand &args )
|
||||
#endif
|
||||
|
||||
#define CON_COMMAND_F( name, description, flags ) \
|
||||
static void name( const CCommand &args ); \
|
||||
static ConCommand name##_command( #name, name, description, flags ); \
|
||||
|
@ -142,6 +142,9 @@ public:
|
||||
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Access for direct read into buffer
|
||||
void * AccessForDirectRead( int nBytes );
|
||||
|
||||
// Attaches the buffer to external memory....
|
||||
void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 );
|
||||
@ -1096,5 +1099,13 @@ inline void CUtlBuffer::CopyBuffer( const void *pubData, int cubData )
|
||||
}
|
||||
}
|
||||
|
||||
inline void *CUtlBuffer::AccessForDirectRead( int nBytes )
|
||||
{
|
||||
Assert( m_Get == 0 && m_Put == 0 && m_nMaxPut == 0 );
|
||||
EnsureCapacity( nBytes );
|
||||
m_nMaxPut = nBytes;
|
||||
return Base();
|
||||
}
|
||||
|
||||
#endif // UTLBUFFER_H
|
||||
|
||||
|
1412
sp/src/public/vscript/ivscript.h
Normal file
1412
sp/src/public/vscript/ivscript.h
Normal file
File diff suppressed because it is too large
Load Diff
414
sp/src/public/vscript/vscript_templates.h
Normal file
414
sp/src/public/vscript/vscript_templates.h
Normal file
@ -0,0 +1,414 @@
|
||||
//========== Copyright © 2008, Valve Corporation, All rights reserved. ========
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#ifndef VSCRIPT_TEMPLATES_H
|
||||
#define VSCRIPT_TEMPLATES_H
|
||||
|
||||
#include "tier0/basetypes.h"
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#define FUNC_APPEND_PARAMS_0
|
||||
#define FUNC_APPEND_PARAMS_1 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 1 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) );
|
||||
#define FUNC_APPEND_PARAMS_2 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 2 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) );
|
||||
#define FUNC_APPEND_PARAMS_3 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 3 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) );
|
||||
#define FUNC_APPEND_PARAMS_4 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 4 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) );
|
||||
#define FUNC_APPEND_PARAMS_5 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 5 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) );
|
||||
#define FUNC_APPEND_PARAMS_6 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 6 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) );
|
||||
#define FUNC_APPEND_PARAMS_7 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 7 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) );
|
||||
#define FUNC_APPEND_PARAMS_8 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 8 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) );
|
||||
#define FUNC_APPEND_PARAMS_9 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 9 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) );
|
||||
#define FUNC_APPEND_PARAMS_10 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 10 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) );
|
||||
#define FUNC_APPEND_PARAMS_11 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 11 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) );
|
||||
#define FUNC_APPEND_PARAMS_12 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 12 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) );
|
||||
#define FUNC_APPEND_PARAMS_13 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 13 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) );
|
||||
#define FUNC_APPEND_PARAMS_14 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 14 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_14 ) );
|
||||
|
||||
#define DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER(N) \
|
||||
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
|
||||
{ \
|
||||
pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \
|
||||
FUNC_APPEND_PARAMS_##N \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER );
|
||||
|
||||
#define DEFINE_MEMBER_FUNC_TYPE_DEDUCER(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
|
||||
{ \
|
||||
pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \
|
||||
FUNC_APPEND_PARAMS_##N \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_TYPE_DEDUCER );
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER(N) \
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \
|
||||
{ \
|
||||
pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \
|
||||
FUNC_APPEND_PARAMS_##N \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER );
|
||||
|
||||
#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); }
|
||||
|
||||
#define ScriptInitFuncDescriptorNamed( pDesc, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, &func ); }
|
||||
#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func )
|
||||
#define ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, scriptName ) ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName )
|
||||
#define ScriptInitMemberFuncDescriptor( pDesc, class, func ) ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, #func )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template <typename FUNCPTR_TYPE>
|
||||
inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc )
|
||||
{
|
||||
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) )
|
||||
{
|
||||
union FuncPtrConvert
|
||||
{
|
||||
void *p;
|
||||
FUNCPTR_TYPE pFunc;
|
||||
};
|
||||
|
||||
FuncPtrConvert convert;
|
||||
convert.pFunc = pFunc;
|
||||
return convert.p;
|
||||
}
|
||||
#if defined( _MSC_VER )
|
||||
else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) )
|
||||
{
|
||||
struct MicrosoftUnknownMFP
|
||||
{
|
||||
void *p;
|
||||
int m_delta;
|
||||
};
|
||||
|
||||
union FuncPtrConvertMI
|
||||
{
|
||||
MicrosoftUnknownMFP mfp;
|
||||
FUNCPTR_TYPE pFunc;
|
||||
};
|
||||
|
||||
FuncPtrConvertMI convert;
|
||||
convert.pFunc = pFunc;
|
||||
if ( convert.mfp.m_delta == 0 )
|
||||
{
|
||||
return convert.mfp.p;
|
||||
}
|
||||
AssertMsg( 0, "Function pointer must be from primary vtable" );
|
||||
}
|
||||
else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) )
|
||||
{
|
||||
struct MicrosoftUnknownMFP
|
||||
{
|
||||
void *p;
|
||||
int m_delta;
|
||||
int m_vtordisp;
|
||||
int m_vtable_index;
|
||||
};
|
||||
|
||||
union FuncPtrConvertMI
|
||||
{
|
||||
MicrosoftUnknownMFP mfp;
|
||||
FUNCPTR_TYPE pFunc;
|
||||
};
|
||||
|
||||
FuncPtrConvertMI convert;
|
||||
convert.pFunc = pFunc;
|
||||
if ( convert.mfp.m_delta == 0 )
|
||||
{
|
||||
return convert.mfp.p;
|
||||
}
|
||||
AssertMsg( 0, "Function pointer must be from primary vtable" );
|
||||
}
|
||||
#elif defined( GNUC )
|
||||
else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) )
|
||||
{
|
||||
AssertMsg( 0, "Note: This path has not been verified yet. See comments below in #else case." );
|
||||
|
||||
struct GnuMFP
|
||||
{
|
||||
union
|
||||
{
|
||||
void *funcadr; // If vtable_index_2 is even, then this is the function pointer.
|
||||
int vtable_index_2; // If vtable_index_2 is odd, then this = vindex*2+1.
|
||||
};
|
||||
int delta;
|
||||
};
|
||||
|
||||
GnuMFP *p = (GnuMFP*)&pFunc;
|
||||
if ( p->vtable_index_2 & 1 )
|
||||
{
|
||||
char **delta = (char**)p->delta;
|
||||
char *pCur = *delta + (p->vtable_index_2+1)/2;
|
||||
return (void*)( pCur + 4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return p->funcadr;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error "Need to implement code to crack non-offset member function pointer case"
|
||||
// For gcc, see: http://www.codeproject.com/KB/cpp/FastDelegate.aspx
|
||||
//
|
||||
// Current versions of the GNU compiler use a strange and tricky
|
||||
// optimization. It observes that, for virtual inheritance, you have to look
|
||||
// up the vtable in order to get the voffset required to calculate the this
|
||||
// pointer. While you're doing that, you might as well store the function
|
||||
// pointer in the vtable. By doing this, they combine the m_func_address and
|
||||
// m_vtable_index fields into one, and they distinguish between them by
|
||||
// ensuring that function pointers always point to even addresses but vtable
|
||||
// indices are always odd:
|
||||
//
|
||||
// // GNU g++ uses a tricky space optimisation, also adopted by IBM's VisualAge and XLC.
|
||||
// struct GnuMFP {
|
||||
// union {
|
||||
// CODEPTR funcadr; // always even
|
||||
// int vtable_index_2; // = vindex*2+1, always odd
|
||||
// };
|
||||
// int delta;
|
||||
// };
|
||||
// adjustedthis = this + delta
|
||||
// if (funcadr & 1) CALL (* ( *delta + (vindex+1)/2) + 4)
|
||||
// else CALL funcadr
|
||||
//
|
||||
// The G++ method is well documented, so it has been adopted by many other
|
||||
// vendors, including IBM's VisualAge and XLC compilers, recent versions of
|
||||
// Open64, Pathscale EKO, and Metrowerks' 64-bit compilers. A simpler scheme
|
||||
// used by earlier versions of GCC is also very common. SGI's now
|
||||
// discontinued MIPSPro and Pro64 compilers, and Apple's ancient MrCpp
|
||||
// compiler used this method. (Note that the Pro64 compiler has become the
|
||||
// open source Open64 compiler).
|
||||
|
||||
#endif
|
||||
else
|
||||
AssertMsg( 0, "Member function pointer not supported. Why on earth are you using virtual inheritance!?" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename FUNCPTR_TYPE>
|
||||
inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p )
|
||||
{
|
||||
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) )
|
||||
{
|
||||
union FuncPtrConvert
|
||||
{
|
||||
void *p;
|
||||
FUNCPTR_TYPE pFunc;
|
||||
};
|
||||
|
||||
FuncPtrConvert convert;
|
||||
convert.p = p;
|
||||
return convert.pFunc;
|
||||
}
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) )
|
||||
{
|
||||
struct MicrosoftUnknownMFP
|
||||
{
|
||||
void *p;
|
||||
int m_delta;
|
||||
};
|
||||
|
||||
union FuncPtrConvertMI
|
||||
{
|
||||
MicrosoftUnknownMFP mfp;
|
||||
FUNCPTR_TYPE pFunc;
|
||||
};
|
||||
|
||||
FuncPtrConvertMI convert;
|
||||
convert.mfp.p = p;
|
||||
convert.mfp.m_delta = 0;
|
||||
return convert.pFunc;
|
||||
}
|
||||
if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) )
|
||||
{
|
||||
struct MicrosoftUnknownMFP
|
||||
{
|
||||
void *p;
|
||||
int m_delta;
|
||||
int m_vtordisp;
|
||||
int m_vtable_index;
|
||||
};
|
||||
|
||||
union FuncPtrConvertMI
|
||||
{
|
||||
MicrosoftUnknownMFP mfp;
|
||||
FUNCPTR_TYPE pFunc;
|
||||
};
|
||||
|
||||
FuncPtrConvertMI convert;
|
||||
convert.mfp.p = p;
|
||||
convert.mfp.m_delta = 0;
|
||||
return convert.pFunc;
|
||||
}
|
||||
#elif defined( POSIX )
|
||||
AssertMsg( 0, "Note: This path has not been implemented yet." );
|
||||
#else
|
||||
#error "Need to implement code to crack non-offset member function pointer case"
|
||||
#endif
|
||||
Assert( 0 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_0
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_1 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_1
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_2 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_2
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_3 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_3
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_4 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_4
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_5 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_5
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_6 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_6
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_7 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_7
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_8 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_8
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_9 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_9
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_10 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_10
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_11 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_11
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_12 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_12
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_13 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_13
|
||||
#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_14 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_14
|
||||
|
||||
#define SCRIPT_BINDING_ARGS_0
|
||||
#define SCRIPT_BINDING_ARGS_1 pArguments[0]
|
||||
#define SCRIPT_BINDING_ARGS_2 pArguments[0], pArguments[1]
|
||||
#define SCRIPT_BINDING_ARGS_3 pArguments[0], pArguments[1], pArguments[2]
|
||||
#define SCRIPT_BINDING_ARGS_4 pArguments[0], pArguments[1], pArguments[2], pArguments[3]
|
||||
#define SCRIPT_BINDING_ARGS_5 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4]
|
||||
#define SCRIPT_BINDING_ARGS_6 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5]
|
||||
#define SCRIPT_BINDING_ARGS_7 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6]
|
||||
#define SCRIPT_BINDING_ARGS_8 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7]
|
||||
#define SCRIPT_BINDING_ARGS_9 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8]
|
||||
#define SCRIPT_BINDING_ARGS_10 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9]
|
||||
#define SCRIPT_BINDING_ARGS_11 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10]
|
||||
#define SCRIPT_BINDING_ARGS_12 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11]
|
||||
#define SCRIPT_BINDING_ARGS_13 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12]
|
||||
#define SCRIPT_BINDING_ARGS_14 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12], pArguments[13]
|
||||
|
||||
|
||||
#define DEFINE_SCRIPT_BINDINGS(N) \
|
||||
template <typename FUNC_TYPE, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CNonMemberScriptBinding##N \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( !pContext ); \
|
||||
\
|
||||
if ( nArguments != N || !pReturn || pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
*pReturn = ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \
|
||||
if ( pReturn->m_type == FIELD_VECTOR ) \
|
||||
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CNonMemberScriptBinding##N<FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( !pReturn ); \
|
||||
Assert( !pContext ); \
|
||||
\
|
||||
if ( nArguments != N || pReturn || pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CMemberScriptBinding##N \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( pReturn ); \
|
||||
Assert( pContext ); \
|
||||
\
|
||||
if ( nArguments != N || !pReturn || !pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
*pReturn = (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
|
||||
if ( pReturn->m_type == FIELD_VECTOR ) \
|
||||
pReturn->m_pVector = new Vector(*pReturn->m_pVector); \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class OBJECT_TYPE_PTR, typename FUNC_TYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
class CMemberScriptBinding##N<OBJECT_TYPE_PTR, FUNC_TYPE, void FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N> \
|
||||
{ \
|
||||
public: \
|
||||
static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \
|
||||
{ \
|
||||
Assert( nArguments == N ); \
|
||||
Assert( !pReturn ); \
|
||||
Assert( pContext ); \
|
||||
\
|
||||
if ( nArguments != N || pReturn || !pContext ) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
(((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid<FUNC_TYPE>(pFunction))( SCRIPT_BINDING_ARGS_##N ); \
|
||||
return true; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
inline ScriptBindingFunc_t ScriptCreateBinding(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
|
||||
{ \
|
||||
typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
|
||||
return &CNonMemberScriptBinding##N<Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
|
||||
} \
|
||||
\
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \
|
||||
{ \
|
||||
typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
|
||||
return &CMemberScriptBinding##N<OBJECT_TYPE_PTR, Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
|
||||
} \
|
||||
\
|
||||
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N> \
|
||||
inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \
|
||||
{ \
|
||||
typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \
|
||||
return &CMemberScriptBinding##N<OBJECT_TYPE_PTR, Func_t, FUNCTION_RETTYPE FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_##N>::Call; \
|
||||
}
|
||||
|
||||
FUNC_GENERATE_ALL( DEFINE_SCRIPT_BINDINGS );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // VSCRIPT_TEMPLATES_H
|
Loading…
x
Reference in New Issue
Block a user