From 697b92ea35a9355c50439b5681833949cbd0864a Mon Sep 17 00:00:00 2001 From: Arbab Ahmed Date: Mon, 25 Jul 2022 13:07:43 +1000 Subject: [PATCH 1/6] add info_particle_system_coordinate, plus infinite cooldown functionality for prop_interactable similar to that of func_button --- sp/src/game/client/c_particle_system.cpp | 210 +++++++++-------- sp/src/game/server/particle_system.cpp | 274 ++++++++++++----------- sp/src/game/server/particle_system.h | 51 +++-- sp/src/game/server/props.cpp | 34 +-- 4 files changed, 312 insertions(+), 257 deletions(-) diff --git a/sp/src/game/client/c_particle_system.cpp b/sp/src/game/client/c_particle_system.cpp index 27bafe0e..4986bccd 100644 --- a/sp/src/game/client/c_particle_system.cpp +++ b/sp/src/game/client/c_particle_system.cpp @@ -19,15 +19,15 @@ //----------------------------------------------------------------------------- class C_ParticleSystem : public C_BaseEntity { - DECLARE_CLASS( C_ParticleSystem, C_BaseEntity ); + DECLARE_CLASS(C_ParticleSystem, C_BaseEntity); public: DECLARE_CLIENTCLASS(); C_ParticleSystem(); - void PreDataUpdate( DataUpdateType_t updateType ); - void PostDataUpdate( DataUpdateType_t updateType ); - void ClientThink( void ); + void PreDataUpdate(DataUpdateType_t updateType); + void PostDataUpdate(DataUpdateType_t updateType); + void ClientThink(void); protected: int m_iEffectIndex; @@ -40,8 +40,9 @@ protected: enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me - + EHANDLE m_hControlPointEnts[kMAXCONTROLPOINTS]; + Vector m_vControlPointVecs[kMAXCONTROLPOINTS]; // SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ), unsigned char m_iControlPointParents[kMAXCONTROLPOINTS]; @@ -50,23 +51,24 @@ protected: IMPLEMENT_CLIENTCLASS(C_ParticleSystem, DT_ParticleSystem, CParticleSystem); -BEGIN_RECV_TABLE_NOBASE( C_ParticleSystem, DT_ParticleSystem ) - RecvPropVector( RECVINFO_NAME( m_vecNetworkOrigin, m_vecOrigin ) ), - RecvPropEHandle( RECVINFO(m_hOwnerEntity) ), - RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ), - RecvPropInt( RECVINFO( m_iParentAttachment ) ), - RecvPropQAngles( RECVINFO_NAME( m_angNetworkAngles, m_angRotation ) ), +BEGIN_RECV_TABLE_NOBASE(C_ParticleSystem, DT_ParticleSystem) +RecvPropVector(RECVINFO_NAME(m_vecNetworkOrigin, m_vecOrigin)), +RecvPropEHandle(RECVINFO(m_hOwnerEntity)), +RecvPropInt(RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent), +RecvPropInt(RECVINFO(m_iParentAttachment)), +RecvPropQAngles(RECVINFO_NAME(m_angNetworkAngles, m_angRotation)), - RecvPropInt( RECVINFO( m_iEffectIndex ) ), - RecvPropBool( RECVINFO( m_bActive ) ), +RecvPropInt(RECVINFO(m_iEffectIndex)), +RecvPropBool(RECVINFO(m_bActive)), #ifdef MAPBASE - RecvPropBool( RECVINFO( m_bDestroyImmediately ) ), +RecvPropBool(RECVINFO(m_bDestroyImmediately)), #endif - RecvPropFloat( RECVINFO( m_flStartTime ) ), +RecvPropFloat(RECVINFO(m_flStartTime)), - RecvPropArray3( RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle( RECVINFO( m_hControlPointEnts[0] ) ) ), - RecvPropArray3( RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt( RECVINFO(m_iControlPointParents[0]))), - RecvPropBool( RECVINFO( m_bWeatherEffect ) ), +RecvPropArray3(RECVINFO_ARRAY(m_hControlPointEnts), RecvPropEHandle(RECVINFO(m_hControlPointEnts[0]))), +RecvPropArray3(RECVINFO_ARRAY(m_vControlPointVecs), RecvPropVector(RECVINFO(m_vControlPointVecs[0]))), +RecvPropArray3(RECVINFO_ARRAY(m_iControlPointParents), RecvPropInt(RECVINFO(m_iControlPointParents[0]))), +RecvPropBool(RECVINFO(m_bWeatherEffect)), END_RECV_TABLE(); //----------------------------------------------------------------------------- @@ -80,38 +82,38 @@ C_ParticleSystem::C_ParticleSystem() //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::PreDataUpdate( DataUpdateType_t updateType ) +void C_ParticleSystem::PreDataUpdate(DataUpdateType_t updateType) { m_bOldActive = m_bActive; - BaseClass::PreDataUpdate( updateType ); + BaseClass::PreDataUpdate(updateType); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType ) +void C_ParticleSystem::PostDataUpdate(DataUpdateType_t updateType) { - BaseClass::PostDataUpdate( updateType ); + BaseClass::PostDataUpdate(updateType); // Always restart if just created and updated // FIXME: Does this play fairly with PVS? - if ( updateType == DATA_UPDATE_CREATED ) + if (updateType == DATA_UPDATE_CREATED) { - if ( m_bActive ) + if (m_bActive) { // Delayed here so that we don't get invalid abs queries on level init with active particle systems - SetNextClientThink( gpGlobals->curtime ); + SetNextClientThink(gpGlobals->curtime); } } else { - if ( m_bOldActive != m_bActive ) + if (m_bOldActive != m_bActive) { - if ( m_bActive ) + if (m_bActive) { // Delayed here so that we don't get invalid abs queries on level init with active particle systems - SetNextClientThink( gpGlobals->curtime ); + SetNextClientThink(gpGlobals->curtime); } else #ifdef MAPBASE @@ -123,8 +125,8 @@ void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType ) } #else { - ParticleProp()->StopEmission(); - } + ParticleProp()->StopEmission(); + } #endif } } @@ -133,38 +135,54 @@ void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void C_ParticleSystem::ClientThink( void ) +void C_ParticleSystem::ClientThink(void) { - if ( m_bActive ) + if (m_bActive) { - const char *pszName = GetParticleSystemNameFromIndex( m_iEffectIndex ); - if ( pszName && pszName[0] ) + const char *pszName = GetParticleSystemNameFromIndex(m_iEffectIndex); + if (pszName && pszName[0]) { - if ( !GameRules()->AllowMapParticleEffect( pszName ) ) + if (!GameRules()->AllowMapParticleEffect(pszName)) return; - if ( m_bWeatherEffect && !GameRules()->AllowWeatherParticles() ) + if (m_bWeatherEffect && !GameRules()->AllowWeatherParticles()) return; - CNewParticleEffect *pEffect = ParticleProp()->Create( pszName, PATTACH_ABSORIGIN_FOLLOW ); - AssertMsg1( pEffect, "Particle system couldn't make %s", pszName ); + CNewParticleEffect *pEffect = ParticleProp()->Create(pszName, PATTACH_ABSORIGIN_FOLLOW); + AssertMsg1(pEffect, "Particle system couldn't make %s", pszName); if (pEffect) { - for ( int i = 0 ; i < kMAXCONTROLPOINTS ; ++i ) - { - CBaseEntity *pOnEntity = m_hControlPointEnts[i].Get(); - if ( pOnEntity ) + if (m_vControlPointVecs[0] != GetAbsOrigin() && m_hControlPointEnts[0] == NULL){ + // we are using info_particle_system_coordinate + for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { - ParticleProp()->AddControlPoint( pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW ); + ParticleProp()->AddControlPoint(pEffect, i + 1, this, PATTACH_WORLDORIGIN, 0, m_vControlPointVecs[i] - GetAbsOrigin()); + AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS, + "Particle system specified bogus control point parent (%d) for point %d.", + m_iControlPointParents[i], i); + + if (m_iControlPointParents[i] != 0) + { + pEffect->SetControlPointParent(i + 1, m_iControlPointParents[i]); + } } - - AssertMsg2( m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS , - "Particle system specified bogus control point parent (%d) for point %d.", - m_iControlPointParents[i], i ); - - if (m_iControlPointParents[i] != 0) + } + else{ + for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { - pEffect->SetControlPointParent(i+1, m_iControlPointParents[i]); + CBaseEntity* pOnEntity = m_hControlPointEnts[i].Get(); + if (pOnEntity) + { + ParticleProp()->AddControlPoint(pEffect, i + 1, pOnEntity, PATTACH_ABSORIGIN_FOLLOW); + } + AssertMsg2(m_iControlPointParents[i] >= 0 && m_iControlPointParents[i] <= kMAXCONTROLPOINTS, + "Particle system specified bogus control point parent (%d) for point %d.", + m_iControlPointParents[i], i); + + if (m_iControlPointParents[i] != 0) + { + pEffect->SetControlPointParent(i + 1, m_iControlPointParents[i]); + } } } @@ -172,14 +190,14 @@ void C_ParticleSystem::ClientThink( void ) // already past the end of it, denoting that we're finished. In that case, just destroy us and be done. -- jdw // TODO: This can go when the SkipToTime code below goes - ParticleProp()->OnParticleSystemUpdated( pEffect, 0.0f ); + ParticleProp()->OnParticleSystemUpdated(pEffect, 0.0f); // Skip the effect ahead if we're restarting it float flTimeDelta = gpGlobals->curtime - m_flStartTime; - if ( flTimeDelta > 0.01f ) + if (flTimeDelta > 0.01f) { - VPROF_BUDGET( "C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation" ); - pEffect->SkipToTime( flTimeDelta ); + VPROF_BUDGET("C_ParticleSystem::ClientThink SkipToTime", "Particle Simulation"); + pEffect->SkipToTime(flTimeDelta); } } } @@ -193,79 +211,79 @@ void C_ParticleSystem::ClientThink( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void ParticleEffectCallback( const CEffectData &data ) +void ParticleEffectCallback(const CEffectData &data) { - if ( SuppressingParticleEffects() ) + if (SuppressingParticleEffects()) return; // this needs to be before using data.m_nHitBox, since that may be a serialized value that's past the end of the current particle system string table - const char *pszName = GetParticleSystemNameFromIndex( data.m_nHitBox ); + const char *pszName = GetParticleSystemNameFromIndex(data.m_nHitBox); CSmartPtr pEffect = NULL; - if ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY ) + if (data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY) { - if ( data.m_hEntity.Get() ) + if (data.m_hEntity.Get()) { - C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); - if ( pEnt && !pEnt->IsDormant() ) + C_BaseEntity *pEnt = C_BaseEntity::Instance(data.m_hEntity); + if (pEnt && !pEnt->IsDormant()) { - if ( data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES ) + if (data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES) { pEnt->ParticleProp()->StopEmission(); } - pEffect = pEnt->ParticleProp()->Create( pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex ); - AssertMsg2( pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", - C_BaseEntity::Instance( data.m_hEntity )->GetDebugName(), pszName ); - if ( pEffect.IsValid() && pEffect->IsValid() ) + pEffect = pEnt->ParticleProp()->Create(pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex); + AssertMsg2(pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", + C_BaseEntity::Instance(data.m_hEntity)->GetDebugName(), pszName); + if (pEffect.IsValid() && pEffect->IsValid()) { - if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN ) + if ((ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN) { - pEffect->SetSortOrigin( data.m_vOrigin ); - pEffect->SetControlPoint( 0, data.m_vOrigin ); - pEffect->SetControlPoint( 1, data.m_vStart ); + pEffect->SetSortOrigin(data.m_vOrigin); + pEffect->SetControlPoint(0, data.m_vOrigin); + pEffect->SetControlPoint(1, data.m_vStart); Vector vecForward, vecRight, vecUp; - AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); - pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); + AngleVectors(data.m_vAngles, &vecForward, &vecRight, &vecUp); + pEffect->SetControlPointOrientation(0, vecForward, vecRight, vecUp); } } } } - } + } else { - if ( GameRules() ) + if (GameRules()) { - pszName = GameRules()->TranslateEffectForVisionFilter( "particles", pszName ); + pszName = GameRules()->TranslateEffectForVisionFilter("particles", pszName); } - pEffect = CNewParticleEffect::Create( NULL, pszName ); - if ( pEffect->IsValid() ) + pEffect = CNewParticleEffect::Create(NULL, pszName); + if (pEffect->IsValid()) { - pEffect->SetSortOrigin( data.m_vOrigin ); - pEffect->SetControlPoint( 0, data.m_vOrigin ); - pEffect->SetControlPoint( 1, data.m_vStart ); + pEffect->SetSortOrigin(data.m_vOrigin); + pEffect->SetControlPoint(0, data.m_vOrigin); + pEffect->SetControlPoint(1, data.m_vStart); Vector vecForward, vecRight, vecUp; - AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); - pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); + AngleVectors(data.m_vAngles, &vecForward, &vecRight, &vecUp); + pEffect->SetControlPointOrientation(0, vecForward, vecRight, vecUp); } } - if ( pEffect.IsValid() && pEffect->IsValid() ) + if (pEffect.IsValid() && pEffect->IsValid()) { - if ( data.m_bCustomColors ) + if (data.m_bCustomColors) { - pEffect->SetControlPoint( CUSTOM_COLOR_CP1, data.m_CustomColors.m_vecColor1 ); - pEffect->SetControlPoint( CUSTOM_COLOR_CP2, data.m_CustomColors.m_vecColor2 ); + pEffect->SetControlPoint(CUSTOM_COLOR_CP1, data.m_CustomColors.m_vecColor1); + pEffect->SetControlPoint(CUSTOM_COLOR_CP2, data.m_CustomColors.m_vecColor2); } - if ( data.m_bControlPoint1 ) + if (data.m_bControlPoint1) { - pEffect->SetControlPoint( 1, data.m_ControlPoint1.m_vecOffset ); + pEffect->SetControlPoint(1, data.m_ControlPoint1.m_vecOffset); } } } -DECLARE_CLIENT_EFFECT( "ParticleEffect", ParticleEffectCallback ); +DECLARE_CLIENT_EFFECT("ParticleEffect", ParticleEffectCallback); //====================================================================================================================== @@ -274,16 +292,16 @@ DECLARE_CLIENT_EFFECT( "ParticleEffect", ParticleEffectCallback ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void ParticleEffectStopCallback( const CEffectData &data ) +void ParticleEffectStopCallback(const CEffectData &data) { - if ( data.m_hEntity.Get() ) + if (data.m_hEntity.Get()) { - C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); - if ( pEnt ) + C_BaseEntity *pEnt = C_BaseEntity::Instance(data.m_hEntity); + if (pEnt) { - pEnt->ParticleProp()->StopEmission(); - } + pEnt->ParticleProp()->StopEmission(); } } +} -DECLARE_CLIENT_EFFECT( "ParticleEffectStop", ParticleEffectStopCallback ); +DECLARE_CLIENT_EFFECT("ParticleEffectStop", ParticleEffectStopCallback); diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index 6ec0cb96..ca1caf4f 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -12,125 +12,128 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +extern void SendProxy_Origin(const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); +extern void SendProxy_Angles(const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); // Stripped down CBaseEntity send table IMPLEMENT_SERVERCLASS_ST_NOBASE(CParticleSystem, DT_ParticleSystem) - SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), - SendPropEHandle (SENDINFO(m_hOwnerEntity)), - SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), - SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), - SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ), +SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD | SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin), +SendPropEHandle(SENDINFO(m_hOwnerEntity)), +SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent)), +SendPropInt(SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), +SendPropQAngles(SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles), - SendPropInt( SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED ), - SendPropBool( SENDINFO(m_bActive) ), +SendPropInt(SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED), +SendPropBool(SENDINFO(m_bActive)), #ifdef MAPBASE - SendPropBool( SENDINFO(m_bDestroyImmediately) ), +SendPropBool(SENDINFO(m_bDestroyImmediately)), #endif - SendPropFloat( SENDINFO(m_flStartTime) ), +SendPropFloat(SENDINFO(m_flStartTime)), - SendPropArray3( SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle( SENDINFO_ARRAY(m_hControlPointEnts) ) ), - SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ), - SendPropBool( SENDINFO(m_bWeatherEffect) ), +SendPropArray3(SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle(SENDINFO_ARRAY(m_hControlPointEnts))), +SendPropArray3(SENDINFO_ARRAY3(m_vControlPointVecs), SendPropVector(SENDINFO_ARRAY(m_vControlPointVecs))), +SendPropArray3(SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt(SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED)), +SendPropBool(SENDINFO(m_bWeatherEffect)), END_SEND_TABLE() -BEGIN_DATADESC( CParticleSystem ) - DEFINE_KEYFIELD( m_bStartActive, FIELD_BOOLEAN, "start_active" ), - DEFINE_KEYFIELD( m_bWeatherEffect, FIELD_BOOLEAN, "flag_as_weather" ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), +BEGIN_DATADESC(CParticleSystem) +DEFINE_KEYFIELD(m_bStartActive, FIELD_BOOLEAN, "start_active"), +DEFINE_KEYFIELD(m_bWeatherEffect, FIELD_BOOLEAN, "flag_as_weather"), +DEFINE_FIELD(m_bActive, FIELD_BOOLEAN), #ifdef MAPBASE - DEFINE_FIELD( m_bDestroyImmediately, FIELD_BOOLEAN ), +DEFINE_FIELD(m_bDestroyImmediately, FIELD_BOOLEAN), #endif - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_iszEffectName, FIELD_STRING, "effect_name" ), - //DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. +DEFINE_FIELD(m_flStartTime, FIELD_TIME), +DEFINE_KEYFIELD(m_iszEffectName, FIELD_STRING, "effect_name"), +//DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. - DEFINE_KEYFIELD( m_iszControlPointNames[0], FIELD_STRING, "cpoint1" ), - DEFINE_KEYFIELD( m_iszControlPointNames[1], FIELD_STRING, "cpoint2" ), - DEFINE_KEYFIELD( m_iszControlPointNames[2], FIELD_STRING, "cpoint3" ), - DEFINE_KEYFIELD( m_iszControlPointNames[3], FIELD_STRING, "cpoint4" ), - DEFINE_KEYFIELD( m_iszControlPointNames[4], FIELD_STRING, "cpoint5" ), - DEFINE_KEYFIELD( m_iszControlPointNames[5], FIELD_STRING, "cpoint6" ), - DEFINE_KEYFIELD( m_iszControlPointNames[6], FIELD_STRING, "cpoint7" ), - DEFINE_KEYFIELD( m_iszControlPointNames[7], FIELD_STRING, "cpoint8" ), - DEFINE_KEYFIELD( m_iszControlPointNames[8], FIELD_STRING, "cpoint9" ), - DEFINE_KEYFIELD( m_iszControlPointNames[9], FIELD_STRING, "cpoint10" ), - DEFINE_KEYFIELD( m_iszControlPointNames[10], FIELD_STRING, "cpoint11" ), - DEFINE_KEYFIELD( m_iszControlPointNames[11], FIELD_STRING, "cpoint12" ), - DEFINE_KEYFIELD( m_iszControlPointNames[12], FIELD_STRING, "cpoint13" ), - DEFINE_KEYFIELD( m_iszControlPointNames[13], FIELD_STRING, "cpoint14" ), - DEFINE_KEYFIELD( m_iszControlPointNames[14], FIELD_STRING, "cpoint15" ), - DEFINE_KEYFIELD( m_iszControlPointNames[15], FIELD_STRING, "cpoint16" ), - DEFINE_KEYFIELD( m_iszControlPointNames[16], FIELD_STRING, "cpoint17" ), - DEFINE_KEYFIELD( m_iszControlPointNames[17], FIELD_STRING, "cpoint18" ), - DEFINE_KEYFIELD( m_iszControlPointNames[18], FIELD_STRING, "cpoint19" ), - DEFINE_KEYFIELD( m_iszControlPointNames[19], FIELD_STRING, "cpoint20" ), - DEFINE_KEYFIELD( m_iszControlPointNames[20], FIELD_STRING, "cpoint21" ), - DEFINE_KEYFIELD( m_iszControlPointNames[21], FIELD_STRING, "cpoint22" ), - DEFINE_KEYFIELD( m_iszControlPointNames[22], FIELD_STRING, "cpoint23" ), - DEFINE_KEYFIELD( m_iszControlPointNames[23], FIELD_STRING, "cpoint24" ), - DEFINE_KEYFIELD( m_iszControlPointNames[24], FIELD_STRING, "cpoint25" ), - DEFINE_KEYFIELD( m_iszControlPointNames[25], FIELD_STRING, "cpoint26" ), - DEFINE_KEYFIELD( m_iszControlPointNames[26], FIELD_STRING, "cpoint27" ), - DEFINE_KEYFIELD( m_iszControlPointNames[27], FIELD_STRING, "cpoint28" ), - DEFINE_KEYFIELD( m_iszControlPointNames[28], FIELD_STRING, "cpoint29" ), - DEFINE_KEYFIELD( m_iszControlPointNames[29], FIELD_STRING, "cpoint30" ), - DEFINE_KEYFIELD( m_iszControlPointNames[30], FIELD_STRING, "cpoint31" ), - DEFINE_KEYFIELD( m_iszControlPointNames[31], FIELD_STRING, "cpoint32" ), - DEFINE_KEYFIELD( m_iszControlPointNames[32], FIELD_STRING, "cpoint33" ), - DEFINE_KEYFIELD( m_iszControlPointNames[33], FIELD_STRING, "cpoint34" ), - DEFINE_KEYFIELD( m_iszControlPointNames[34], FIELD_STRING, "cpoint35" ), - DEFINE_KEYFIELD( m_iszControlPointNames[35], FIELD_STRING, "cpoint36" ), - DEFINE_KEYFIELD( m_iszControlPointNames[36], FIELD_STRING, "cpoint37" ), - DEFINE_KEYFIELD( m_iszControlPointNames[37], FIELD_STRING, "cpoint38" ), - DEFINE_KEYFIELD( m_iszControlPointNames[38], FIELD_STRING, "cpoint39" ), - DEFINE_KEYFIELD( m_iszControlPointNames[39], FIELD_STRING, "cpoint40" ), - DEFINE_KEYFIELD( m_iszControlPointNames[40], FIELD_STRING, "cpoint41" ), - DEFINE_KEYFIELD( m_iszControlPointNames[41], FIELD_STRING, "cpoint42" ), - DEFINE_KEYFIELD( m_iszControlPointNames[42], FIELD_STRING, "cpoint43" ), - DEFINE_KEYFIELD( m_iszControlPointNames[43], FIELD_STRING, "cpoint44" ), - DEFINE_KEYFIELD( m_iszControlPointNames[44], FIELD_STRING, "cpoint45" ), - DEFINE_KEYFIELD( m_iszControlPointNames[45], FIELD_STRING, "cpoint46" ), - DEFINE_KEYFIELD( m_iszControlPointNames[46], FIELD_STRING, "cpoint47" ), - DEFINE_KEYFIELD( m_iszControlPointNames[47], FIELD_STRING, "cpoint48" ), - DEFINE_KEYFIELD( m_iszControlPointNames[48], FIELD_STRING, "cpoint49" ), - DEFINE_KEYFIELD( m_iszControlPointNames[49], FIELD_STRING, "cpoint50" ), - DEFINE_KEYFIELD( m_iszControlPointNames[50], FIELD_STRING, "cpoint51" ), - DEFINE_KEYFIELD( m_iszControlPointNames[51], FIELD_STRING, "cpoint52" ), - DEFINE_KEYFIELD( m_iszControlPointNames[52], FIELD_STRING, "cpoint53" ), - DEFINE_KEYFIELD( m_iszControlPointNames[53], FIELD_STRING, "cpoint54" ), - DEFINE_KEYFIELD( m_iszControlPointNames[54], FIELD_STRING, "cpoint55" ), - DEFINE_KEYFIELD( m_iszControlPointNames[55], FIELD_STRING, "cpoint56" ), - DEFINE_KEYFIELD( m_iszControlPointNames[56], FIELD_STRING, "cpoint57" ), - DEFINE_KEYFIELD( m_iszControlPointNames[57], FIELD_STRING, "cpoint58" ), - DEFINE_KEYFIELD( m_iszControlPointNames[58], FIELD_STRING, "cpoint59" ), - DEFINE_KEYFIELD( m_iszControlPointNames[59], FIELD_STRING, "cpoint60" ), - DEFINE_KEYFIELD( m_iszControlPointNames[60], FIELD_STRING, "cpoint61" ), - DEFINE_KEYFIELD( m_iszControlPointNames[61], FIELD_STRING, "cpoint62" ), - DEFINE_KEYFIELD( m_iszControlPointNames[62], FIELD_STRING, "cpoint63" ), +DEFINE_KEYFIELD(m_iszControlPointNames[0], FIELD_STRING, "cpoint1"), +DEFINE_KEYFIELD(m_iszControlPointNames[1], FIELD_STRING, "cpoint2"), +DEFINE_KEYFIELD(m_iszControlPointNames[2], FIELD_STRING, "cpoint3"), +DEFINE_KEYFIELD(m_iszControlPointNames[3], FIELD_STRING, "cpoint4"), +DEFINE_KEYFIELD(m_iszControlPointNames[4], FIELD_STRING, "cpoint5"), +DEFINE_KEYFIELD(m_iszControlPointNames[5], FIELD_STRING, "cpoint6"), +DEFINE_KEYFIELD(m_iszControlPointNames[6], FIELD_STRING, "cpoint7"), +DEFINE_KEYFIELD(m_iszControlPointNames[7], FIELD_STRING, "cpoint8"), +DEFINE_KEYFIELD(m_iszControlPointNames[8], FIELD_STRING, "cpoint9"), +DEFINE_KEYFIELD(m_iszControlPointNames[9], FIELD_STRING, "cpoint10"), +DEFINE_KEYFIELD(m_iszControlPointNames[10], FIELD_STRING, "cpoint11"), +DEFINE_KEYFIELD(m_iszControlPointNames[11], FIELD_STRING, "cpoint12"), +DEFINE_KEYFIELD(m_iszControlPointNames[12], FIELD_STRING, "cpoint13"), +DEFINE_KEYFIELD(m_iszControlPointNames[13], FIELD_STRING, "cpoint14"), +DEFINE_KEYFIELD(m_iszControlPointNames[14], FIELD_STRING, "cpoint15"), +DEFINE_KEYFIELD(m_iszControlPointNames[15], FIELD_STRING, "cpoint16"), +DEFINE_KEYFIELD(m_iszControlPointNames[16], FIELD_STRING, "cpoint17"), +DEFINE_KEYFIELD(m_iszControlPointNames[17], FIELD_STRING, "cpoint18"), +DEFINE_KEYFIELD(m_iszControlPointNames[18], FIELD_STRING, "cpoint19"), +DEFINE_KEYFIELD(m_iszControlPointNames[19], FIELD_STRING, "cpoint20"), +DEFINE_KEYFIELD(m_iszControlPointNames[20], FIELD_STRING, "cpoint21"), +DEFINE_KEYFIELD(m_iszControlPointNames[21], FIELD_STRING, "cpoint22"), +DEFINE_KEYFIELD(m_iszControlPointNames[22], FIELD_STRING, "cpoint23"), +DEFINE_KEYFIELD(m_iszControlPointNames[23], FIELD_STRING, "cpoint24"), +DEFINE_KEYFIELD(m_iszControlPointNames[24], FIELD_STRING, "cpoint25"), +DEFINE_KEYFIELD(m_iszControlPointNames[25], FIELD_STRING, "cpoint26"), +DEFINE_KEYFIELD(m_iszControlPointNames[26], FIELD_STRING, "cpoint27"), +DEFINE_KEYFIELD(m_iszControlPointNames[27], FIELD_STRING, "cpoint28"), +DEFINE_KEYFIELD(m_iszControlPointNames[28], FIELD_STRING, "cpoint29"), +DEFINE_KEYFIELD(m_iszControlPointNames[29], FIELD_STRING, "cpoint30"), +DEFINE_KEYFIELD(m_iszControlPointNames[30], FIELD_STRING, "cpoint31"), +DEFINE_KEYFIELD(m_iszControlPointNames[31], FIELD_STRING, "cpoint32"), +DEFINE_KEYFIELD(m_iszControlPointNames[32], FIELD_STRING, "cpoint33"), +DEFINE_KEYFIELD(m_iszControlPointNames[33], FIELD_STRING, "cpoint34"), +DEFINE_KEYFIELD(m_iszControlPointNames[34], FIELD_STRING, "cpoint35"), +DEFINE_KEYFIELD(m_iszControlPointNames[35], FIELD_STRING, "cpoint36"), +DEFINE_KEYFIELD(m_iszControlPointNames[36], FIELD_STRING, "cpoint37"), +DEFINE_KEYFIELD(m_iszControlPointNames[37], FIELD_STRING, "cpoint38"), +DEFINE_KEYFIELD(m_iszControlPointNames[38], FIELD_STRING, "cpoint39"), +DEFINE_KEYFIELD(m_iszControlPointNames[39], FIELD_STRING, "cpoint40"), +DEFINE_KEYFIELD(m_iszControlPointNames[40], FIELD_STRING, "cpoint41"), +DEFINE_KEYFIELD(m_iszControlPointNames[41], FIELD_STRING, "cpoint42"), +DEFINE_KEYFIELD(m_iszControlPointNames[42], FIELD_STRING, "cpoint43"), +DEFINE_KEYFIELD(m_iszControlPointNames[43], FIELD_STRING, "cpoint44"), +DEFINE_KEYFIELD(m_iszControlPointNames[44], FIELD_STRING, "cpoint45"), +DEFINE_KEYFIELD(m_iszControlPointNames[45], FIELD_STRING, "cpoint46"), +DEFINE_KEYFIELD(m_iszControlPointNames[46], FIELD_STRING, "cpoint47"), +DEFINE_KEYFIELD(m_iszControlPointNames[47], FIELD_STRING, "cpoint48"), +DEFINE_KEYFIELD(m_iszControlPointNames[48], FIELD_STRING, "cpoint49"), +DEFINE_KEYFIELD(m_iszControlPointNames[49], FIELD_STRING, "cpoint50"), +DEFINE_KEYFIELD(m_iszControlPointNames[50], FIELD_STRING, "cpoint51"), +DEFINE_KEYFIELD(m_iszControlPointNames[51], FIELD_STRING, "cpoint52"), +DEFINE_KEYFIELD(m_iszControlPointNames[52], FIELD_STRING, "cpoint53"), +DEFINE_KEYFIELD(m_iszControlPointNames[53], FIELD_STRING, "cpoint54"), +DEFINE_KEYFIELD(m_iszControlPointNames[54], FIELD_STRING, "cpoint55"), +DEFINE_KEYFIELD(m_iszControlPointNames[55], FIELD_STRING, "cpoint56"), +DEFINE_KEYFIELD(m_iszControlPointNames[56], FIELD_STRING, "cpoint57"), +DEFINE_KEYFIELD(m_iszControlPointNames[57], FIELD_STRING, "cpoint58"), +DEFINE_KEYFIELD(m_iszControlPointNames[58], FIELD_STRING, "cpoint59"), +DEFINE_KEYFIELD(m_iszControlPointNames[59], FIELD_STRING, "cpoint60"), +DEFINE_KEYFIELD(m_iszControlPointNames[60], FIELD_STRING, "cpoint61"), +DEFINE_KEYFIELD(m_iszControlPointNames[61], FIELD_STRING, "cpoint62"), +DEFINE_KEYFIELD(m_iszControlPointNames[62], FIELD_STRING, "cpoint63"), - DEFINE_KEYFIELD( m_iControlPointParents[0], FIELD_CHARACTER, "cpoint1_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent" ), - - DEFINE_AUTO_ARRAY( m_hControlPointEnts, FIELD_EHANDLE ), +DEFINE_KEYFIELD(m_iControlPointParents[0], FIELD_CHARACTER, "cpoint1_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent"), +DEFINE_KEYFIELD(m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent"), - DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), +DEFINE_AUTO_ARRAY(m_hControlPointEnts, FIELD_EHANDLE), +DEFINE_AUTO_ARRAY(m_vControlPointVecs, FIELD_VECTOR), + +DEFINE_INPUTFUNC(FIELD_VOID, "Start", InputStart), +DEFINE_INPUTFUNC(FIELD_VOID, "Stop", InputStop), #ifdef MAPBASE - DEFINE_INPUTFUNC( FIELD_VOID, "DestroyImmediately", InputDestroyImmediately ), +DEFINE_INPUTFUNC(FIELD_VOID, "DestroyImmediately", InputDestroyImmediately), #endif - DEFINE_THINKFUNC( StartParticleSystemThink ), +DEFINE_THINKFUNC(StartParticleSystemThink), END_DATADESC() -LINK_ENTITY_TO_CLASS( info_particle_system, CParticleSystem ); +LINK_ENTITY_TO_CLASS(info_particle_system, CParticleSystem); +LINK_ENTITY_TO_CLASS(info_particle_system_coordinate, CParticleSystemCoordinate); //----------------------------------------------------------------------------- // Purpose: @@ -143,22 +146,22 @@ CParticleSystem::CParticleSystem() //----------------------------------------------------------------------------- // Precache //----------------------------------------------------------------------------- -void CParticleSystem::Precache( void ) +void CParticleSystem::Precache(void) { - const char *pParticleSystemName = STRING( m_iszEffectName ); - if ( pParticleSystemName == NULL || pParticleSystemName[0] == '\0' ) + const char *pParticleSystemName = STRING(m_iszEffectName); + if (pParticleSystemName == NULL || pParticleSystemName[0] == '\0') { - Warning( "info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr() ); + Warning("info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr()); } - PrecacheParticleSystem( pParticleSystemName ); + PrecacheParticleSystem(pParticleSystemName); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::Spawn( void ) +void CParticleSystem::Spawn(void) { BaseClass::Spawn(); @@ -169,14 +172,14 @@ void CParticleSystem::Spawn( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::Activate( void ) +void CParticleSystem::Activate(void) { BaseClass::Activate(); // Find our particle effect index - m_iEffectIndex = GetParticleSystemIndex( STRING(m_iszEffectName) ); + m_iEffectIndex = GetParticleSystemIndex(STRING(m_iszEffectName)); - if ( m_bStartActive ) + if (m_bStartActive) { m_bStartActive = false; StartParticleSystem(); @@ -186,7 +189,7 @@ void CParticleSystem::Activate( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystemThink( void ) +void CParticleSystem::StartParticleSystemThink(void) { StartParticleSystem(); } @@ -196,22 +199,22 @@ void CParticleSystem::StartParticleSystemThink( void ) //----------------------------------------------------------------------------- int CParticleSystem::UpdateTransmitState() { - return SetTransmitState( FL_EDICT_ALWAYS ); + return SetTransmitState(FL_EDICT_ALWAYS); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystem( void ) +void CParticleSystem::StartParticleSystem(void) { - if ( m_bActive == false ) + if (m_bActive == false) { m_flStartTime = gpGlobals->curtime; m_bActive = true; #ifdef MAPBASE m_bDestroyImmediately = false; #endif - + // Setup our control points at this time (in case our targets weren't around at spawn time) ReadControlPointEnts(); } @@ -220,7 +223,7 @@ void CParticleSystem::StartParticleSystem( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::StopParticleSystem( void ) +void CParticleSystem::StopParticleSystem(void) { m_bActive = false; } @@ -228,7 +231,7 @@ void CParticleSystem::StopParticleSystem( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputStart( inputdata_t &inputdata ) +void CParticleSystem::InputStart(inputdata_t &inputdata) { StartParticleSystem(); } @@ -236,7 +239,7 @@ void CParticleSystem::InputStart( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputStop( inputdata_t &inputdata ) +void CParticleSystem::InputStop(inputdata_t &inputdata) { StopParticleSystem(); } @@ -245,7 +248,7 @@ void CParticleSystem::InputStop( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CParticleSystem::InputDestroyImmediately( inputdata_t &inputdata ) +void CParticleSystem::InputDestroyImmediately(inputdata_t &inputdata) { m_bDestroyImmediately = true; StopParticleSystem(); @@ -254,23 +257,36 @@ void CParticleSystem::InputDestroyImmediately( inputdata_t &inputdata ) //----------------------------------------------------------------------------- // Purpose: Find each entity referred to by m_iszControlPointNames and -// resolve it into the corresponding slot in m_hControlPointEnts +// resolve it into the corresponding slot in m_vControlPointVecs //----------------------------------------------------------------------------- -void CParticleSystem::ReadControlPointEnts( void ) +void CParticleSystem::ReadControlPointEnts(void) { - for ( int i = 0 ; i < kMAXCONTROLPOINTS; ++i ) + for (int i = 0; i < kMAXCONTROLPOINTS; ++i) { - if ( m_iszControlPointNames[i] == NULL_STRING ) - continue; + if (UsesCoordinates()) { + float vecCoords[3]; + if (m_iszControlPointNames[i] == NULL_STRING) + m_vControlPointVecs.Set(i, GetAbsOrigin()); // use self as default position + else{ + // cast str to vector, add vector to array + const char* pszVector = STRING(m_iszControlPointNames[i]); + UTIL_StringToVector(vecCoords, pszVector); + m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); + } - CBaseEntity *pPointEnt = gEntList.FindEntityGeneric( NULL, STRING( m_iszControlPointNames[i] ), this ); - Assert( pPointEnt != NULL ); - if ( pPointEnt == NULL ) - { - Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr() ); - continue; } + else{ + if (m_iszControlPointNames[i] == NULL_STRING) + continue; + CBaseEntity *pPointEnt = gEntList.FindEntityGeneric(NULL, STRING(m_iszControlPointNames[i]), this); + Assert(pPointEnt != NULL); + if (pPointEnt == NULL) + { + Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr()); + continue; + } - m_hControlPointEnts.Set( i, pPointEnt ); + m_hControlPointEnts.Set(i, pPointEnt); + } } } diff --git a/sp/src/game/server/particle_system.h b/sp/src/game/server/particle_system.h index 6ce9a9c9..d9ed3fe6 100644 --- a/sp/src/game/server/particle_system.h +++ b/sp/src/game/server/particle_system.h @@ -17,49 +17,62 @@ //----------------------------------------------------------------------------- class CParticleSystem : public CBaseEntity { - DECLARE_CLASS( CParticleSystem, CBaseEntity ); + DECLARE_CLASS(CParticleSystem, CBaseEntity); public: DECLARE_SERVERCLASS(); DECLARE_DATADESC(); CParticleSystem(); - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); + virtual void Precache(void); + virtual void Spawn(void); + virtual void Activate(void); virtual int UpdateTransmitState(void); - void StartParticleSystem( void ); - void StopParticleSystem( void ); + void StartParticleSystem(void); + void StopParticleSystem(void); - void InputStart( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); + void InputStart(inputdata_t &inputdata); + void InputStop(inputdata_t &inputdata); #ifdef MAPBASE - void InputDestroyImmediately( inputdata_t &inputdata ); + void InputDestroyImmediately(inputdata_t &inputdata); #endif - void StartParticleSystemThink( void ); + void StartParticleSystemThink(void); enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me + virtual bool UsesCoordinates(void) { return false; } + protected: /// Load up and resolve the entities that are supposed to be the control points - void ReadControlPointEnts( void ); + virtual void ReadControlPointEnts(void); bool m_bStartActive; string_t m_iszEffectName; - - CNetworkVar( bool, m_bActive ); + + CNetworkVar(bool, m_bActive); #ifdef MAPBASE - CNetworkVar( bool, m_bDestroyImmediately ); + CNetworkVar(bool, m_bDestroyImmediately); #endif - CNetworkVar( int, m_iEffectIndex ) - CNetworkVar( float, m_flStartTime ); // Time at which this effect was started. This is used after restoring an active effect. + CNetworkVar(int, m_iEffectIndex) + CNetworkVar(float, m_flStartTime); // Time at which this effect was started. This is used after restoring an active effect. string_t m_iszControlPointNames[kMAXCONTROLPOINTS]; - CNetworkArray( EHANDLE, m_hControlPointEnts, kMAXCONTROLPOINTS ); - CNetworkArray( unsigned char, m_iControlPointParents, kMAXCONTROLPOINTS ); - CNetworkVar( bool, m_bWeatherEffect ); + CNetworkArray(EHANDLE, m_hControlPointEnts, kMAXCONTROLPOINTS); + CNetworkArray(Vector, m_vControlPointVecs, kMAXCONTROLPOINTS); + CNetworkArray(unsigned char, m_iControlPointParents, kMAXCONTROLPOINTS); + CNetworkVar(bool, m_bWeatherEffect); +}; + +//----------------------------------------------------------------------------- +// Purpose: An entity that spawns and controls a particle system using coordinates. +//----------------------------------------------------------------------------- +class CParticleSystemCoordinate : public CParticleSystem +{ + DECLARE_CLASS(CParticleSystemCoordinate, CParticleSystem); +public: + virtual bool UsesCoordinates(void) { return true; } }; #endif // PARTICLE_SYSTEM_H diff --git a/sp/src/game/server/props.cpp b/sp/src/game/server/props.cpp index c643dd68..e53582d5 100644 --- a/sp/src/game/server/props.cpp +++ b/sp/src/game/server/props.cpp @@ -2800,7 +2800,7 @@ void CInteractableProp::Precache( void ) // useType - // value - //----------------------------------------------------------------------------- -void CInteractableProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +void CInteractableProp::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { if (m_flCooldownTime > gpGlobals->curtime) return; @@ -2808,18 +2808,18 @@ void CInteractableProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_ // If we're using +USE mins/maxs, make sure this is being +USE'd from the right place if (m_vecUseMins.LengthSqr() != 0.0f && m_vecUseMaxs.LengthSqr() != 0.0f) { - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); + CBasePlayer *pPlayer = ToBasePlayer(pActivator); if (pPlayer) { Vector forward; - pPlayer->EyeVectors( &forward, NULL, NULL ); + pPlayer->EyeVectors(&forward, NULL, NULL); // This might be a little convoluted and/or seem needlessly expensive, but I couldn't figure out any better way to do this. // TOOD: Can we calculate a box in local space instead of world space? Vector vecWorldMins, vecWorldMaxs; - RotateAABB( EntityToWorldTransform(), m_vecUseMins, m_vecUseMaxs, vecWorldMins, vecWorldMaxs ); - TransformAABB( EntityToWorldTransform(), vecWorldMins, vecWorldMaxs, vecWorldMins, vecWorldMaxs ); - if (!IsBoxIntersectingRay( vecWorldMins, vecWorldMaxs, pPlayer->EyePosition(), forward * 1024 )) + RotateAABB(EntityToWorldTransform(), m_vecUseMins, m_vecUseMaxs, vecWorldMins, vecWorldMaxs); + TransformAABB(EntityToWorldTransform(), vecWorldMins, vecWorldMaxs, vecWorldMins, vecWorldMaxs); + if (!IsBoxIntersectingRay(vecWorldMins, vecWorldMaxs, pPlayer->EyePosition(), forward * 1024)) { // Reject this +USE if it's not in our box DevMsg("Outside of +USE box\n"); @@ -2832,28 +2832,36 @@ void CInteractableProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_ if (m_bLocked) { - m_OnLockedUse.FireOutput( pActivator, this ); + m_OnLockedUse.FireOutput(pActivator, this); EmitSound(STRING(m_iszLockedSound)); - nSequence = LookupSequence( STRING( m_iszLockedSequence ) ); + nSequence = LookupSequence(STRING(m_iszLockedSequence)); m_iCurSequence = INTERACTSEQ_LOCKED; } else { - m_OnPressed.FireOutput( pActivator, this ); + m_OnPressed.FireOutput(pActivator, this); EmitSound(STRING(m_iszPressedSound)); - nSequence = LookupSequence( STRING( m_iszInSequence ) ); + nSequence = LookupSequence(STRING(m_iszInSequence)); m_iCurSequence = INTERACTSEQ_IN; } - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) + if (nSequence > ACTIVITY_NOT_AVAILABLE) { SetPushSequence(nSequence); // We still fire our inherited animation outputs - m_pOutputAnimBegun.FireOutput( pActivator, this ); + m_pOutputAnimBegun.FireOutput(pActivator, this); } - m_flCooldownTime = gpGlobals->curtime + m_flCooldown; + if (m_flCooldown == -1 && !m_bLocked){ + m_flCooldownTime = 1e+30; // yeah we're not going to hit this any time soon + } + else if (m_flCooldown == -1){ + m_flCooldownTime = gpGlobals->curtime + 1.0f; // 1s cooldown if locked + } + else{ + m_flCooldownTime = gpGlobals->curtime + m_flCooldown; + } } //----------------------------------------------------------------------------- From fa3d686067a8829c3abe528fcbbb47a92c5392d9 Mon Sep 17 00:00:00 2001 From: Arbab Ahmed Date: Mon, 25 Jul 2022 23:43:58 +1000 Subject: [PATCH 2/6] remove setabsorigin() code in serverside particle system --- sp/src/game/server/particle_system.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index ca1caf4f..85ce3c10 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -265,13 +265,13 @@ void CParticleSystem::ReadControlPointEnts(void) { if (UsesCoordinates()) { float vecCoords[3]; - if (m_iszControlPointNames[i] == NULL_STRING) - m_vControlPointVecs.Set(i, GetAbsOrigin()); // use self as default position - else{ + if (UsesCoordinates()) { + float vecCoords[3]; // cast str to vector, add vector to array const char* pszVector = STRING(m_iszControlPointNames[i]); UTIL_StringToVector(vecCoords, pszVector); m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); + } } From a5770191bba498b220fe3bf5d9e8b03b3ae2bea8 Mon Sep 17 00:00:00 2001 From: Arbab Ahmed Date: Sat, 30 Jul 2022 15:56:50 +1000 Subject: [PATCH 3/6] use FLT_MAX instead of 1e+30, remove a busted two lines of code --- sp/src/game/server/particle_system.cpp | 13 ++++--------- sp/src/game/server/props.cpp | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/sp/src/game/server/particle_system.cpp b/sp/src/game/server/particle_system.cpp index 85ce3c10..a8f576a7 100644 --- a/sp/src/game/server/particle_system.cpp +++ b/sp/src/game/server/particle_system.cpp @@ -265,15 +265,10 @@ void CParticleSystem::ReadControlPointEnts(void) { if (UsesCoordinates()) { float vecCoords[3]; - if (UsesCoordinates()) { - float vecCoords[3]; - // cast str to vector, add vector to array - const char* pszVector = STRING(m_iszControlPointNames[i]); - UTIL_StringToVector(vecCoords, pszVector); - m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); - - } - + // cast str to vector, add vector to array + const char* pszVector = STRING(m_iszControlPointNames[i]); + UTIL_StringToVector(vecCoords, pszVector); + m_vControlPointVecs.Set(i, Vector(vecCoords[0], vecCoords[1], vecCoords[2])); } else{ if (m_iszControlPointNames[i] == NULL_STRING) diff --git a/sp/src/game/server/props.cpp b/sp/src/game/server/props.cpp index e53582d5..ad5cc84f 100644 --- a/sp/src/game/server/props.cpp +++ b/sp/src/game/server/props.cpp @@ -2854,7 +2854,7 @@ void CInteractableProp::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_T } if (m_flCooldown == -1 && !m_bLocked){ - m_flCooldownTime = 1e+30; // yeah we're not going to hit this any time soon + m_flCooldownTime = FLT_MAX; // yeah we're not going to hit this any time soon } else if (m_flCooldown == -1){ m_flCooldownTime = gpGlobals->curtime + 1.0f; // 1s cooldown if locked From 9bf1fb4ceaa62d1a18c4b2df2a303249d370a935 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Fri, 14 Oct 2022 18:23:33 +0300 Subject: [PATCH 4/6] Fix CScriptNetMsgHelper::WriteEntity() --- sp/src/game/shared/mapbase/vscript_singletons.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 8f821e6c..14949c60 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -1749,8 +1749,8 @@ void CNetMsgScriptHelper::WriteEntity( HSCRIPT hEnt ) { SCRIPT_NETMSG_WRITE_FUNC CBaseEntity *p = ToEnt(hEnt); - int i = p ? p->entindex() : -1; - m_MsgOut.WriteSBitLong( i, MAX_EDICT_BITS ); + int i = p ? p->entindex() : 0; + m_MsgOut.WriteUBitLong( i, MAX_EDICT_BITS ); } void CNetMsgScriptHelper::WriteEHandle( HSCRIPT hEnt ) @@ -1861,7 +1861,11 @@ bool CNetMsgScriptHelper::ReadBool() HSCRIPT CNetMsgScriptHelper::ReadEntity() { - int index = m_MsgIn_()ReadSBitLong( MAX_EDICT_BITS ); + int index = m_MsgIn_()ReadUBitLong( MAX_EDICT_BITS ); + + if ( !index ) + return NULL; + #ifdef GAME_DLL edict_t *e = INDEXENT(index); if ( e && !e->IsFree() ) From 7849b1440f875f7286f6902813727360622cf523 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Fri, 14 Oct 2022 18:25:46 +0300 Subject: [PATCH 5/6] Clarify comment --- sp/src/game/shared/mapbase/vscript_singletons.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sp/src/game/shared/mapbase/vscript_singletons.cpp b/sp/src/game/shared/mapbase/vscript_singletons.cpp index 14949c60..67af8015 100644 --- a/sp/src/game/shared/mapbase/vscript_singletons.cpp +++ b/sp/src/game/shared/mapbase/vscript_singletons.cpp @@ -740,7 +740,11 @@ void CScriptGameEventListener::StopListeningForEvent() #ifdef _DEBUG // Event listeners are iterated forwards in the game event manager, // removing while iterating will cause it to skip one listener. - // This could be prevented by writing a custom game event manager. + // + // Fix this in engine without altering any behaviour by + // changing event exeuction order to tail->head, + // changing listener removal to tail->head, + // changing listener addition to head if ( m_nEventTick == gpGlobals->tickcount ) { Warning("CScriptGameEventListener stopped in the same frame it was fired. This will break other event listeners!\n"); From a2cf90e3ace85881ea61ec1c2720cff318fe75b9 Mon Sep 17 00:00:00 2001 From: samisalreadytaken <46823719+samisalreadytaken@users.noreply.github.com> Date: Mon, 17 Oct 2022 23:10:10 +0300 Subject: [PATCH 6/6] Remove redundant SquirrelSafeCheck instance --- sp/src/vscript/vscript_squirrel.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/sp/src/vscript/vscript_squirrel.cpp b/sp/src/vscript/vscript_squirrel.cpp index 3b1e87ab..ddb8069e 100644 --- a/sp/src/vscript/vscript_squirrel.cpp +++ b/sp/src/vscript/vscript_squirrel.cpp @@ -2779,7 +2779,6 @@ bool SquirrelVM::GenerateUniqueKey(const char* pszRoot, char* pBuf, int nBufSize static int keyIdx = 0; // This gets used for script scope, still confused why it needs to be inside IScriptVM // is it just to be a compatible name for CreateScope? - SquirrelSafeCheck safeCheck(vm_); V_snprintf(pBuf, nBufSize, "%08X_%s", ++keyIdx, pszRoot); return true; }