Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

vscript additions and fixes #59

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions sp/src/game/server/baseanimating.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
DEFINE_SCRIPTFUNC( GetSequence, "Gets the current sequence" )
DEFINE_SCRIPTFUNC( SetSequence, "Sets the current sequence" )
DEFINE_SCRIPTFUNC( SequenceLoops, "Loops the current sequence" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSequenceDuration, "SequenceDuration", "Get the specified sequence duration" )
DEFINE_SCRIPTFUNC( LookupSequence, "Gets the index of the specified sequence name" )
DEFINE_SCRIPTFUNC( LookupActivity, "Gets the ID of the specified activity name" )
DEFINE_SCRIPTFUNC_NAMED( HasMovement, "SequenceHasMovement", "Checks if the specified sequence has movement" )
Expand All @@ -312,6 +313,10 @@ BEGIN_ENT_SCRIPTDESC( CBaseAnimating, CBaseEntity, "Animating models" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectWeightedSequence, "SelectWeightedSequence", "Selects a sequence for the specified activity ID" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSelectHeaviestSequence, "SelectHeaviestSequence", "Selects the sequence with the heaviest weight for the specified activity ID" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetSequenceKeyValues, "GetSequenceKeyValues", "Get a KeyValue class instance on the specified sequence. WARNING: This uses the same KeyValue pointer as GetModelKeyValues!" )
DEFINE_SCRIPTFUNC( GetPlaybackRate, "" )
DEFINE_SCRIPTFUNC( SetPlaybackRate, "" )
DEFINE_SCRIPTFUNC( GetCycle, "" )
DEFINE_SCRIPTFUNC( SetCycle, "" )
DEFINE_SCRIPTFUNC( GetSkin, "Gets the model's skin" )
DEFINE_SCRIPTFUNC( SetSkin, "Sets the model's skin" )
#endif
Expand Down
3 changes: 3 additions & 0 deletions sp/src/game/server/baseanimating.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ class CBaseAnimating : public CBaseEntity
inline float SequenceDuration( void ) { return SequenceDuration( m_nSequence ); }
float SequenceDuration( CStudioHdr *pStudioHdr, int iSequence );
inline float SequenceDuration( int iSequence ) { return SequenceDuration(GetModelPtr(), iSequence); }
#ifdef MAPBASE_VSCRIPT
inline float ScriptSequenceDuration( int iSequence ) { return SequenceDuration(GetModelPtr(), iSequence); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would assume this was split into its own function so the inline function could continue to be inlined in its existing uses, but this new function uses inline anyway. Is that a mistake or am I misunderstanding the purpose?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It exists for the scriptfunc definition, as it does not accept overloaded functions. Inlining is only for consistency, I don't think it matters at all for scriptfuncs.

#endif
float GetSequenceCycleRate( CStudioHdr *pStudioHdr, int iSequence );
inline float GetSequenceCycleRate( int iSequence ) { return GetSequenceCycleRate(GetModelPtr(),iSequence); }
float GetLastVisibleCycle( CStudioHdr *pStudioHdr, int iSequence );
Expand Down
136 changes: 109 additions & 27 deletions sp/src/game/server/baseentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1329,6 +1329,31 @@ void CBaseEntity::FireNamedOutput( const char *pszOutput, variant_t variant, CBa
}
}

#ifdef MAPBASE_VSCRIPT
void CBaseEntity::ScriptFireOutput( const char *pszOutput, HSCRIPT hActivator, HSCRIPT hCaller, const char *szValue, float flDelay )
{
variant_t value;
value.SetString( MAKE_STRING(szValue) );

FireNamedOutput( pszOutput, value, ToEnt(hActivator), ToEnt(hCaller), flDelay );
}

float CBaseEntity::GetMaxOutputDelay( const char *pszOutput )
{
CBaseEntityOutput *pOutput = FindNamedOutput( pszOutput );
if ( pOutput )
{
return pOutput->GetMaxDelay();
}
return 0;
}

void CBaseEntity::CancelEventsByInput( const char *szInput )
{
g_EventQueue.CancelEventsByInput( this, szInput );
}
#endif // MAPBASE_VSCRIPT

CBaseEntityOutput *CBaseEntity::FindNamedOutput( const char *pszOutput )
{
if ( pszOutput == NULL )
Expand Down Expand Up @@ -2271,6 +2296,11 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"

DEFINE_SCRIPTFUNC_NAMED( ScriptClassify, "Classify", "Get Class_T class ID" )

DEFINE_SCRIPTFUNC_NAMED( ScriptAcceptInput, "AcceptInput", "" )
DEFINE_SCRIPTFUNC_NAMED( ScriptFireOutput, "FireOutput", "Fire an entity output" )
DEFINE_SCRIPTFUNC( GetMaxOutputDelay, "Get the longest delay for all events attached to an output" )
DEFINE_SCRIPTFUNC( CancelEventsByInput, "Cancel all I/O events for this entity, match input" )

DEFINE_SCRIPTFUNC_NAMED( ScriptAddOutput, "AddOutput", "Add an output" )
DEFINE_SCRIPTFUNC_NAMED( ScriptGetKeyValue, "GetKeyValue", "Get a keyvalue" )

Expand Down Expand Up @@ -2321,6 +2351,9 @@ BEGIN_ENT_SCRIPTDESC_ROOT( CBaseEntity, "Root class of all server-side entities"
DEFINE_SCRIPTFUNC( AddEFlags, "Add Eflags" )
DEFINE_SCRIPTFUNC( RemoveEFlags, "Remove Eflags" )

DEFINE_SCRIPTFUNC( GetTransmitState, "" )
DEFINE_SCRIPTFUNC( SetTransmitState, "" )

DEFINE_SCRIPTFUNC_NAMED( ScriptGetMoveType, "GetMoveType", "Get the move type" )
DEFINE_SCRIPTFUNC_NAMED( ScriptSetMoveType, "SetMoveType", "Set the move type" )

Expand Down Expand Up @@ -2474,9 +2507,18 @@ void CBaseEntity::UpdateOnRemove( void )
{
CallScriptFunctionHandle( hFunc, NULL );
}
#endif
#endif // MAPBASE_VSCRIPT

g_pScriptVM->RemoveInstance( m_hScriptInstance );
m_hScriptInstance = NULL;

#ifdef MAPBASE_VSCRIPT
if ( m_hfnThink )
{
g_pScriptVM->ReleaseScript( m_hfnThink );
m_hfnThink = NULL;
}
#endif // MAPBASE_VSCRIPT
}
}

Expand Down Expand Up @@ -4411,7 +4453,11 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator,
// found a match

// mapper debug message
#ifdef MAPBASE
ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iName.Get()) : "<NULL>", GetDebugName(), szInputName, Value.String() );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've occasionally received requests/suggestions to color console messages in a similar way to later branches of Source/Source 2. I didn't think it was important enough to do it with the desired consistency, but I hadn't thought about this particular case before. I've had difficulty distinguishing these I/O messages from others in the past, so this might motivate me to finally begin expanding colored console messages to other areas.

I also might change this later to use static Color instances instead of storing the values in preprocessors.

#else
DevMsg( 2, "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iName.Get()) : "<NULL>", GetDebugName(), szInputName, Value.String() );
#endif
ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer );

if (m_debugOverlays & OVERLAY_MESSAGE_BIT)
Expand Down Expand Up @@ -4544,10 +4590,25 @@ bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator,
}
}

#ifdef MAPBASE
ConColorMsg( 2, Color(CON_COLOR_DEV_VERBOSE), "unhandled input: (%s) -> (%s,%s)\n", szInputName, STRING(m_iClassname), GetDebugName() );
#else
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())*/ );
#endif
return false;
}

#ifdef MAPBASE_VSCRIPT
bool CBaseEntity::ScriptAcceptInput( const char *szInputName, const char *szValue, HSCRIPT hActivator, HSCRIPT hCaller )
{
variant_t value;
value.SetString( MAKE_STRING(szValue) );

return AcceptInput( szInputName, ToEnt(hActivator), ToEnt(hCaller), value, 0 );
}
#endif


//-----------------------------------------------------------------------------
// Purpose: Input handler for the entity alpha.
// Input : nAlpha - Alpha value (0 - 255).
Expand Down Expand Up @@ -4587,6 +4648,17 @@ void CBaseEntity::InputColor( inputdata_t &inputdata )
void CBaseEntity::InputUse( inputdata_t &inputdata )
{
Use( inputdata.pActivator, inputdata.pCaller, (USE_TYPE)inputdata.nOutputID, 0 );

#ifdef MAPBASE
IGameEvent *event = gameeventmanager->CreateEvent( "player_use" );
if ( event )
{
event->SetInt( "userid", inputdata.pActivator && inputdata.pActivator->IsPlayer() ?
((CBasePlayer*)inputdata.pActivator)->GetUserID() : 0 );
event->SetInt( "entity", entindex() );
gameeventmanager->FireEvent( event );
}
#endif // MAPBASE
}


Expand Down Expand Up @@ -4702,7 +4774,19 @@ void CBaseEntity::InputKill( inputdata_t &inputdata )
m_OnKilled.FireOutput( inputdata.pActivator, this );
#endif

#ifdef MAPBASE
// Kick players
if ( IsPlayer() )
{
engine->ServerCommand( UTIL_VarArgs( "kickid %d CBaseEntity::InputKill()\n", engine->GetPlayerUserId(edict()) ) );
}
else
{
UTIL_Remove( this );
}
#else
UTIL_Remove( this );
#endif
}

void CBaseEntity::InputKillHierarchy( inputdata_t &inputdata )
Expand All @@ -4724,6 +4808,9 @@ void CBaseEntity::InputKillHierarchy( inputdata_t &inputdata )

#ifdef MAPBASE
m_OnKilled.FireOutput( inputdata.pActivator, this );

// Kicking players in InputKillHierarchy does not exist in future Valve games
// if ( IsPlayer() )
#endif

UTIL_Remove( this );
Expand Down Expand Up @@ -8410,7 +8497,7 @@ void CBaseEntity::ScriptThink(void)
#ifdef MAPBASE_VSCRIPT
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptSetThinkFunction(const char *szFunc, float time)
void CBaseEntity::ScriptSetThinkFunction( const char *szFunc, float flTime )
{
// Empty string stops thinking
if (!szFunc || szFunc[0] == '\0')
Expand All @@ -8420,7 +8507,8 @@ void CBaseEntity::ScriptSetThinkFunction(const char *szFunc, float time)
else
{
m_iszScriptThinkFunction = AllocPooledString(szFunc);
SetContextThink( &CBaseEntity::ScriptThink, gpGlobals->curtime + time, "ScriptThink" );
flTime = max( 0, flTime );
SetContextThink( &CBaseEntity::ScriptThink, gpGlobals->curtime + flTime, "ScriptThink" );
}
}

Expand All @@ -8434,37 +8522,30 @@ void CBaseEntity::ScriptStopThinkFunction()
//-----------------------------------------------------------------------------
void CBaseEntity::ScriptThinkH()
{
if (m_hfnThink)
ScriptVariant_t varThinkRetVal;
if ( g_pScriptVM->ExecuteFunction(m_hfnThink, NULL, 0, &varThinkRetVal, NULL, true) == SCRIPT_ERROR )
{
ScriptVariant_t varThinkRetVal;
if (g_pScriptVM->ExecuteFunction(m_hfnThink, NULL, 0, &varThinkRetVal, NULL, true) == SCRIPT_ERROR)
{
DevWarning("%s FAILED to call script think function (invalid closure)!\n", GetDebugName());
ScriptStopThink();
return;
}

float flThinkFrequency = 0.f;
if (!varThinkRetVal.AssignTo(&flThinkFrequency))
{
// no return value stops thinking
ScriptStopThink();
return;
}

SetNextThink(gpGlobals->curtime + flThinkFrequency, "ScriptThinkH");
DevWarning("%s FAILED to call script think function (invalid closure)!\n", GetDebugName());
ScriptStopThink();
return;
}
else

float flThinkFrequency = 0.f;
if ( !varThinkRetVal.AssignTo(&flThinkFrequency) )
{
DevWarning("%s FAILED to call script think function (invalid closure)!\n", GetDebugName());
// no return value stops thinking
ScriptStopThink();
return;
}

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

void CBaseEntity::ScriptSetThink(HSCRIPT hFunc, float time)
void CBaseEntity::ScriptSetThink( HSCRIPT hFunc, float flTime )
{
if (hFunc)
if ( hFunc )
{
if (m_hfnThink)
if ( m_hfnThink )
{
// release old func
ScriptStopThink();
Expand All @@ -8473,7 +8554,8 @@ void CBaseEntity::ScriptSetThink(HSCRIPT hFunc, float time)
// no type check here, print error on call instead
m_hfnThink = hFunc;

SetContextThink( &CBaseEntity::ScriptThinkH, gpGlobals->curtime + time, "ScriptThinkH" );
flTime = max( 0, flTime );
SetContextThink( &CBaseEntity::ScriptThinkH, gpGlobals->curtime + flTime, "ScriptThinkH" );
}
else
{
Expand Down
9 changes: 9 additions & 0 deletions sp/src/game/server/baseentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,12 @@ class CBaseEntity : public IServerEntity
void ValidateEntityConnections();
void FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay = 0.0f );
CBaseEntityOutput *FindNamedOutput( const char *pszOutput );
#ifdef MAPBASE_VSCRIPT
void ScriptFireOutput( const char *pszOutput, HSCRIPT hActivator, HSCRIPT hCaller, const char *szValue, float flDelay );
float GetMaxOutputDelay( const char *pszOutput );
void CancelEventsByInput( const char *szInput );
#endif


// Activate - called for each entity after each load game and level load
virtual void Activate( void );
Expand Down Expand Up @@ -656,6 +662,9 @@ class CBaseEntity : public IServerEntity
// handles an input (usually caused by outputs)
// returns true if the the value in the pass in should be set, false if the input is to be ignored
virtual bool AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID );
#ifdef MAPBASE_VSCRIPT
bool ScriptAcceptInput(const char *szInputName, const char *szValue, HSCRIPT hActivator, HSCRIPT hCaller);
#endif

//
// Input handlers.
Expand Down
Loading