From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/game/server/env_effectsscript.cpp | 542 +++++++++++++++++++++++++++++++ 1 file changed, 542 insertions(+) create mode 100644 mp/src/game/server/env_effectsscript.cpp (limited to 'mp/src/game/server/env_effectsscript.cpp') diff --git a/mp/src/game/server/env_effectsscript.cpp b/mp/src/game/server/env_effectsscript.cpp new file mode 100644 index 00000000..a1d8621e --- /dev/null +++ b/mp/src/game/server/env_effectsscript.cpp @@ -0,0 +1,542 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "baseanimating.h" +#include "Sprite.h" +#include "SpriteTrail.h" +#include +#include "animation.h" +#include "eventlist.h" +#include "npcevent.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +enum EffectType +{ + EFFECT_TYPE_TRAIL = 1, + EFFECT_TYPE_SPRITE +}; + + +bool g_bUnget = false; +unsigned char *buffer; +char name[ 256 ]; +const char *currenttoken; +int tokencount; +char token[ 1204 ]; + +class CEffectScriptElement +{ +public: + + CEffectScriptElement(); + + char m_szEffectName[128]; + CHandle m_pTrail; + CHandle m_pSprite; + int m_iType; + int m_iRenderType; + + int m_iR; + int m_iG; + int m_iB; + int m_iA; + + char m_szAttachment[128]; + char m_szMaterial[128]; + + float m_flScale; + float m_flFadeTime; + float m_flTextureRes; + + bool m_bStopFollowOnKill; + + bool IsActive( void ) { return m_bActive; } + void Activate( void ) { m_bActive = true; } + void Deactivate( void ) { m_bActive = false; } +private: + + bool m_bActive; +}; + +CEffectScriptElement::CEffectScriptElement() +{ + m_pTrail = NULL; + m_pSprite = NULL; + m_iType = 0; + + Deactivate(); + m_iRenderType = kRenderTransAdd; + + m_iR = 255; + m_iG = 0; + m_iB = 0; + m_iA = 255; + + m_flScale = 1.0f; + m_flFadeTime = 1.0f; + m_flTextureRes = -1.0f; + m_bStopFollowOnKill = false; +} + + +//----------------------------------------------------------------------------- +// An entity which emits other entities at points +//----------------------------------------------------------------------------- +class CEnvEffectsScript : public CBaseAnimating +{ +public: + DECLARE_CLASS( CEnvEffectsScript, CBaseAnimating ); + DECLARE_DATADESC(); + + virtual void Precache(); + virtual void Spawn(); + virtual int UpdateTransmitState(); + + void InputSetSequence( inputdata_t &inputdata ); + void ParseScriptFile( void ); + void LoadFromBuffer( const char *scriptfile, const char *buffer ); + + virtual void Think( void ); + + void ParseNewEffect( void ); + + const char *GetScriptFile( void ) + { + return STRING( m_iszScriptName ); + } + + void HandleAnimEvent ( animevent_t *pEvent ); + void TrailEffectEvent( CEffectScriptElement *pEffect ); + void SpriteEffectEvent( CEffectScriptElement *pEffect ); + + CEffectScriptElement *GetScriptElementByName( const char *pName ); + +private: + + string_t m_iszScriptName; + + CUtlVector< CEffectScriptElement > m_ScriptElements; + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- + bool IsRootCommand( void ) + { + if ( !Q_stricmp( token, "effect" ) ) + return true; + + return false; + } +}; + +inline bool ParseToken( void ) +{ + if ( g_bUnget ) + { + g_bUnget = false; + return true; + } + + currenttoken = engine->ParseFile( currenttoken, token, sizeof( token ) ); + tokencount++; + return currenttoken != NULL ? true : false; +} + +inline void Unget() +{ + g_bUnget = true; +} + +inline bool TokenWaiting( void ) +{ + + const char *p = currenttoken; + while ( *p && *p!='\n') + { + // Special handler for // comment blocks + if ( *p == '/' && *(p+1) == '/' ) + return false; + + if ( !V_isspace( *p ) || V_isalnum( *p ) ) + return true; + + p++; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// Save/load +//----------------------------------------------------------------------------- +BEGIN_DATADESC( CEnvEffectsScript ) + // Inputs + DEFINE_INPUTFUNC( FIELD_STRING, "SetSequence", InputSetSequence ), + DEFINE_KEYFIELD( m_iszScriptName, FIELD_STRING, "scriptfile" ), + // DEFINE_FIELD( m_ScriptElements, CUtlVector < CEffectScriptElement > ), + + DEFINE_FUNCTION( Think ), + +END_DATADESC() + +LINK_ENTITY_TO_CLASS( env_effectscript, CEnvEffectsScript ); + +//----------------------------------------------------------------------------- +// Should we transmit it to the client? +//----------------------------------------------------------------------------- +int CEnvEffectsScript::UpdateTransmitState() +{ + return SetTransmitState( FL_EDICT_ALWAYS ); +} + +//----------------------------------------------------------------------------- +// Precache +//----------------------------------------------------------------------------- +void CEnvEffectsScript::Precache() +{ + BaseClass::Precache(); + PrecacheModel( STRING( GetModelName() ) ); + + if ( m_iszScriptName != NULL_STRING ) + ParseScriptFile(); + else + Warning( "CEnvEffectsScript with no script!\n" ); +} + +//----------------------------------------------------------------------------- +// Spawn +//----------------------------------------------------------------------------- +void CEnvEffectsScript::Spawn() +{ + Precache(); + BaseClass::Spawn(); + + // We need a model for its animation sequences even though we don't render it + SetModel( STRING( GetModelName() ) ); + + AddEffects( EF_NODRAW ); + + SetThink( &CEnvEffectsScript::Think ); + SetNextThink( gpGlobals->curtime + 0.1f ); +} + +void CEnvEffectsScript::Think( void ) +{ + StudioFrameAdvance(); + DispatchAnimEvents( this ); + + SetNextThink( gpGlobals->curtime + 0.1f ); +} + +void CEnvEffectsScript::TrailEffectEvent( CEffectScriptElement *pEffect ) +{ + if ( pEffect->IsActive() == false ) + { + //Only one type of this effect active at a time. + if ( pEffect->m_pTrail == NULL ) + { + pEffect->m_pTrail = CSpriteTrail::SpriteTrailCreate( pEffect->m_szMaterial, GetAbsOrigin(), true ); + pEffect->m_pTrail->FollowEntity( this ); + pEffect->m_pTrail->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone ); + pEffect->m_pTrail->SetStartWidth( pEffect->m_flScale ); + if ( pEffect->m_flTextureRes < 0.0f ) + { + pEffect->m_pTrail->SetTextureResolution( 1.0f / ( 16.0f * pEffect->m_flScale ) ); + } + else + { + pEffect->m_pTrail->SetTextureResolution( pEffect->m_flTextureRes ); + } + pEffect->m_pTrail->SetLifeTime( pEffect->m_flFadeTime ); + pEffect->m_pTrail->TurnOn(); + pEffect->m_pTrail->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) ); + + pEffect->Activate(); + } + } +} + +void CEnvEffectsScript::SpriteEffectEvent( CEffectScriptElement *pEffect ) +{ + if ( pEffect->IsActive() == false ) + { + //Only one type of this effect active at a time. + if ( pEffect->m_pSprite == NULL ) + { + pEffect->m_pSprite = CSprite::SpriteCreate( pEffect->m_szMaterial, GetAbsOrigin(), true ); + pEffect->m_pSprite->FollowEntity( this ); + pEffect->m_pSprite->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone ); + pEffect->m_pSprite->SetScale( pEffect->m_flScale ); + pEffect->m_pSprite->TurnOn(); + pEffect->m_pSprite->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) ); + + pEffect->Activate(); + } + } +} + +void CEnvEffectsScript::HandleAnimEvent ( animevent_t *pEvent ) +{ + if ( pEvent->event == AE_START_SCRIPTED_EFFECT ) + { + CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options ); + + if ( pCurrent ) + { + if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL ) + TrailEffectEvent( pCurrent ); + else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE ) + SpriteEffectEvent( pCurrent ); + } + + return; + } + + if ( pEvent->event == AE_STOP_SCRIPTED_EFFECT ) + { + CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options ); + + if ( pCurrent && pCurrent->IsActive() ) + { + pCurrent->Deactivate(); + + if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL ) + { + if ( pCurrent->m_bStopFollowOnKill == true ) + { + Vector vOrigin; + GetAttachment( pCurrent->m_pTrail->m_nAttachment, vOrigin ); + + pCurrent->m_pTrail->StopFollowingEntity(); + + pCurrent->m_pTrail->m_hAttachedToEntity = NULL; + pCurrent->m_pTrail->m_nAttachment = 0; + + pCurrent->m_pTrail->SetAbsOrigin( vOrigin); + } + + pCurrent->m_pTrail->FadeAndDie( pCurrent->m_flFadeTime ); + pCurrent->m_pTrail = NULL; + } + + else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE ) + { + if ( pCurrent->m_bStopFollowOnKill == true ) + { + Vector vOrigin; + GetAttachment( pCurrent->m_pSprite->m_nAttachment, vOrigin ); + + pCurrent->m_pSprite->StopFollowingEntity(); + + pCurrent->m_pSprite->m_hAttachedToEntity = NULL; + pCurrent->m_pSprite->m_nAttachment = 0; + + pCurrent->m_pSprite->SetAbsOrigin( vOrigin); + } + + pCurrent->m_pSprite->FadeAndDie( pCurrent->m_flFadeTime ); + pCurrent->m_pSprite = NULL; + } + } + return; + } + + BaseClass::HandleAnimEvent( pEvent ); +} +//----------------------------------------------------------------------------- +// Purpose: Input that sets the sequence of the entity +//----------------------------------------------------------------------------- +void CEnvEffectsScript::InputSetSequence( inputdata_t &inputdata ) +{ + if ( inputdata.value.StringID() != NULL_STRING ) + { + int nSequence = LookupSequence( STRING( inputdata.value.StringID() ) ); + if ( nSequence != ACT_INVALID ) + { + SetSequence( nSequence ); + ResetSequenceInfo(); + SetCycle( 0.0f ); + m_flPlaybackRate = 1.0f; + } + } +} + +void CEnvEffectsScript::ParseScriptFile( void ) +{ + int length = 0; + m_ScriptElements.RemoveAll(); + const char *pScriptName = GetScriptFile(); + + //Reset everything. + g_bUnget = false; + currenttoken = NULL; + tokencount = 0; + memset( token, 0, 1204 ); + memset( name, 0, 256 ); + + + unsigned char *buffer = (unsigned char *)UTIL_LoadFileForMe( pScriptName, &length ); + if ( length <= 0 || !buffer ) + { + DevMsg( 1, "CEnvEffectsScript: failed to load %s\n", pScriptName ); + return; + } + + currenttoken = (const char *)buffer; + LoadFromBuffer( pScriptName, (const char *)buffer ); + + UTIL_FreeFile( buffer ); +} + +void CEnvEffectsScript::LoadFromBuffer( const char *scriptfile, const char *buffer ) +{ + while ( 1 ) + { + ParseToken(); + + if ( !token[0] ) + { + break; + } + + if ( !Q_stricmp( token, "effect" ) ) + { + ParseNewEffect(); + } + else + { + Warning( "CEnvEffectsScript: Unknown entry type '%s'\n", token ); + break; + } + } +} + +void CEnvEffectsScript::ParseNewEffect( void ) +{ + //Add a new effect to the list. + CEffectScriptElement NewElement; + + // Effect Group Name + ParseToken(); + Q_strncpy( NewElement.m_szEffectName, token, sizeof( NewElement.m_szEffectName ) ); + + while ( 1 ) + { + ParseToken(); + + // Oops, part of next definition + if( IsRootCommand() ) + { + Unget(); + break; + } + + if ( !Q_stricmp( token, "{" ) ) + { + while ( 1 ) + { + ParseToken(); + if ( !Q_stricmp( token, "}" ) ) + break; + + if ( !Q_stricmp( token, "type" ) ) + { + ParseToken(); + + if ( !Q_stricmp( token, "trail" ) ) + NewElement.m_iType = EFFECT_TYPE_TRAIL; + else if ( !Q_stricmp( token, "sprite" ) ) + NewElement.m_iType = EFFECT_TYPE_SPRITE; + + continue; + } + + if ( !Q_stricmp( token, "material" ) ) + { + ParseToken(); + Q_strncpy( NewElement.m_szMaterial, token, sizeof( NewElement.m_szMaterial ) ); + PrecacheModel( NewElement.m_szMaterial ); + + continue; + } + + if ( !Q_stricmp( token, "attachment" ) ) + { + ParseToken(); + Q_strncpy( NewElement.m_szAttachment, token, sizeof( NewElement.m_szAttachment ) ); + + continue; + } + + if ( !Q_stricmp( token, "color" ) ) + { + ParseToken(); + sscanf( token, "%i %i %i %i", &NewElement.m_iR, &NewElement.m_iG, &NewElement.m_iB, &NewElement.m_iA ); + + continue; + } + + if ( !Q_stricmp( token, "scale" ) ) + { + ParseToken(); + + NewElement.m_flScale = atof( token ); + continue; + } + + if ( !Q_stricmp( token, "texturescale" ) ) + { + ParseToken(); + + float flTextureScale = atof( token ); + NewElement.m_flTextureRes = (flTextureScale > 0.0f) ? 1.0f / flTextureScale : 0.0f; + continue; + } + + if ( !Q_stricmp( token, "fadetime" ) ) + { + ParseToken(); + + NewElement.m_flFadeTime = atof( token ); + continue; + } + + if ( !Q_stricmp( token, "stopfollowonkill" ) ) + { + ParseToken(); + + NewElement.m_bStopFollowOnKill = !!atoi( token ); + continue; + } + + } + break; + } + } + + m_ScriptElements.AddToTail( NewElement ); +} + +CEffectScriptElement *CEnvEffectsScript::GetScriptElementByName( const char *pName ) +{ + for ( int i = 0; i < m_ScriptElements.Count(); i++ ) + { + CEffectScriptElement *pCurrent = &m_ScriptElements.Element( i ); + + if ( pCurrent && !Q_stricmp( pCurrent->m_szEffectName, pName ) ) + { + return pCurrent; + } + } + + return NULL; +} -- cgit v1.2.3