Skip to content

Commit

Permalink
Merge pull request #193 from arbabf/develop
Browse files Browse the repository at this point in the history
New entity: info_particle_system_coordinate, plus infinite cooldown functionality for prop_interactable
  • Loading branch information
Blixibon committed Oct 22, 2022
2 parents 3f5807f + 0c9883f commit 924f211
Show file tree
Hide file tree
Showing 4 changed files with 313 additions and 263 deletions.
210 changes: 114 additions & 96 deletions sp/src/game/client/c_particle_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,8 +40,9 @@ class C_ParticleSystem : public C_BaseEntity

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];

Expand All @@ -50,23 +51,24 @@ class C_ParticleSystem : public C_BaseEntity

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();

//-----------------------------------------------------------------------------
Expand All @@ -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
Expand All @@ -123,8 +125,8 @@ void C_ParticleSystem::PostDataUpdate( DataUpdateType_t updateType )
}
#else
{
ParticleProp()->StopEmission();
}
ParticleProp()->StopEmission();
}
#endif
}
}
Expand All @@ -133,53 +135,69 @@ 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]);
}
}
}

// NOTE: What we really want here is to compare our lifetime and that of our children and see if this delta is
// 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);
}
}
}
Expand All @@ -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<CNewParticleEffect> 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);


//======================================================================================================================
Expand All @@ -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);
Loading

0 comments on commit 924f211

Please sign in to comment.