mirror of
https://github.com/ENSL/NS.git
synced 2024-11-14 17:01:29 +00:00
518 lines
15 KiB
C++
518 lines
15 KiB
C++
//======== (C) Copyright 2002 Charles G. Cleveland All rights reserved. =========
|
|
//
|
|
// The copyright to the contents herein is the property of Charles G. Cleveland.
|
|
// The contents may be used and/or copied only with the written permission of
|
|
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
|
|
// the agreement/contract under which the contents have been supplied.
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $Workfile: AvHParticleSystemEntity.cpp $
|
|
// $Date: 2002/11/22 21:28:16 $
|
|
//
|
|
//-------------------------------------------------------------------------------
|
|
// $Log: AvHParticleSystemEntity.cpp,v $
|
|
// Revision 1.13 2002/11/22 21:28:16 Flayra
|
|
// - mp_consistency changes
|
|
//
|
|
// Revision 1.12 2002/05/23 02:33:20 Flayra
|
|
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
|
|
//
|
|
//===============================================================================
|
|
#include "util/nowarnings.h"
|
|
#include "AvHParticleSystemEntity.h"
|
|
#include "AvHParticleTemplateServer.h"
|
|
#include "AvHParticleSystemManager.h"
|
|
#include "AvHConstants.h"
|
|
#include "AvHMarineEquipmentConstants.h"
|
|
#include "AvHSpecials.h"
|
|
#include "AvHParticleTemplate.h"
|
|
#include "AvHParticleConstants.h"
|
|
|
|
extern AvHParticleTemplateListServer gParticleTemplateList;
|
|
|
|
uint32 AvHParticleSystemEntity::sCurrentHandle = 1;
|
|
const float kDefaultParticleSystemThinkRate = 0.05f;
|
|
|
|
LINK_ENTITY_TO_CLASS( keParticles, AvHParticleSystemEntity );
|
|
LINK_ENTITY_TO_CLASS( keParticlesCustom, AvHCustomParticleSystemEntity );
|
|
|
|
AvHParticleSystemEntity::AvHParticleSystemEntity()
|
|
{
|
|
this->mTemplateIndex = -1;
|
|
this->mIsOn = false;
|
|
//this->mClientIsOn = false;
|
|
this->mUseState = false;
|
|
this->mHandle = 0;
|
|
this->mCreatedTemplate = false;
|
|
this->mTimeParticlesCreated = 0;
|
|
this->mCustomData = 0;
|
|
}
|
|
|
|
void AvHParticleSystemEntity::SetTemplateIndex(int inTemplateIndex)
|
|
{
|
|
this->mTemplateIndex = inTemplateIndex;
|
|
}
|
|
|
|
uint16 AvHParticleSystemEntity::GetCustomData() const
|
|
{
|
|
return this->mCustomData;
|
|
}
|
|
|
|
void AvHParticleSystemEntity::SetCustomData(uint16 inCustomData)
|
|
{
|
|
this->mCustomData = inCustomData;
|
|
this->pev->weaponmodel = this->mCustomData;
|
|
}
|
|
|
|
|
|
// Fetch template if we have a valid template index, create a new custom template if we don't
|
|
AvHParticleTemplate*
|
|
AvHParticleSystemEntity::GetCustomTemplate()
|
|
{
|
|
AvHParticleTemplate* theTemplate = NULL;
|
|
|
|
if(!this->mCreatedTemplate)
|
|
{
|
|
if(this->mTemplateIndex == -1)
|
|
{
|
|
// Create a new template, none was specified in the name field
|
|
ASSERT(!this->mCreatedTemplate);
|
|
this->mTemplateIndex = gParticleTemplateList.CreateTemplateFromIndex();
|
|
}
|
|
//else
|
|
//{
|
|
// // Create a template from our existing base template
|
|
// this->mTemplateIndex = gParticleTemplateList.CreateTemplateFromIndex(this->mTemplateIndex);
|
|
//}
|
|
|
|
// Set the name of our new custom particle system
|
|
theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
|
|
ASSERT(theTemplate);
|
|
string theName = STRING(this->pev->targetname);
|
|
theTemplate->SetName(theName);
|
|
|
|
this->mCreatedTemplate = true;
|
|
}
|
|
|
|
ASSERT(this->mTemplateIndex != -1);
|
|
if(!theTemplate)
|
|
theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
|
|
|
|
return theTemplate;
|
|
}
|
|
|
|
void
|
|
AvHParticleSystemEntity::KeyValue( KeyValueData* inPkvd )
|
|
{
|
|
if(FStrEq(inPkvd->szKeyName, kpscSystemName))
|
|
{
|
|
uint32 theIndex;
|
|
if(gParticleTemplateList.GetTemplateIndexWithName(inPkvd->szValue, theIndex))
|
|
{
|
|
this->mTemplateIndex = theIndex;
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Call down to base class
|
|
CBaseEntity::KeyValue(inPkvd);
|
|
}
|
|
}
|
|
|
|
void
|
|
AvHParticleSystemEntity::ParticleThink()
|
|
{
|
|
this->UpdateClientData();
|
|
|
|
// Look up particle system
|
|
AvHParticleSystem* theParticleSystem = AvHParticleSystemManager::Instance()->GetParticleSystem(this->mHandle);
|
|
if(theParticleSystem)
|
|
{
|
|
// Call UpdatePhysics()
|
|
theParticleSystem->UpdatePhysics(this->pev);
|
|
|
|
// The actual entity's position is the regular position of the entity, unless it's using a generaton entity, then use it instead
|
|
//theParticleSystem->GetEffectiveOrigin(this->pev->origin);
|
|
////UTIL_SetOrigin(this->pev, theGenerationEntityOrigin);
|
|
}
|
|
|
|
this->pev->nextthink = gpGlobals->time + kDefaultParticleSystemThinkRate;
|
|
}
|
|
|
|
void
|
|
AvHParticleSystemEntity::ParticleTouch( CBaseEntity* /*pOther*/ )
|
|
{
|
|
//EMIT_SOUND(ENT(pev), CHAN_VOICE, "buttons/spark1.wav", 1.0f, ATTN_NORM);
|
|
}
|
|
|
|
void
|
|
AvHParticleSystemEntity::ParticleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
|
{
|
|
switch(useType)
|
|
{
|
|
case USE_OFF:
|
|
this->mUseState = false;
|
|
break;
|
|
|
|
case USE_ON:
|
|
this->mUseState = true;
|
|
break;
|
|
|
|
case USE_SET:
|
|
// Handle this?
|
|
break;
|
|
|
|
case USE_TOGGLE:
|
|
this->mUseState = !this->mUseState;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
AvHParticleSystemEntity::Precache(void)
|
|
{
|
|
CBaseEntity::Precache();
|
|
PRECACHE_UNMODIFIED_MODEL(kNullModel);
|
|
}
|
|
|
|
void AvHParticleSystemEntity::SetUseState(USE_TYPE inUseType)
|
|
{
|
|
this->ParticleUse(NULL, NULL, inUseType, 0.0f);
|
|
}
|
|
|
|
void
|
|
AvHParticleSystemEntity::Spawn( void )
|
|
{
|
|
// Just in case our class derives off of something else in the future
|
|
CBaseEntity::Spawn();
|
|
|
|
this->Precache();
|
|
|
|
this->pev->classname = MAKE_STRING(kesParticlesCustom);
|
|
this->pev->solid = SOLID_NOT;
|
|
this->pev->movetype = MOVETYPE_NONE;
|
|
//this->pev->movetype = MOVETYPE_PUSH;
|
|
//this->pev->effects = EF_BRIGHTLIGHT;
|
|
|
|
this->SetTouch(&AvHParticleSystemEntity::ParticleTouch);
|
|
this->SetUse(&AvHParticleSystemEntity::ParticleUse);
|
|
|
|
SET_MODEL(ENT(this->pev), kNullModel);
|
|
UTIL_SetOrigin(this->pev, this->pev->origin);
|
|
|
|
// Set the other flags
|
|
AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
|
|
//ASSERT(theTemplate);
|
|
if(theTemplate)
|
|
{
|
|
//theTemplate->SetFlags(theSpawnFlags);
|
|
|
|
string theTargetName = STRING(this->pev->targetname);
|
|
if(!FStrEq(theTargetName.c_str(), ""))
|
|
{
|
|
theTemplate->SetName(theTargetName);
|
|
}
|
|
|
|
this->SetThink(&AvHParticleSystemEntity::ParticleThink);
|
|
pev->nextthink = gpGlobals->time + kDefaultParticleSystemThinkRate;
|
|
|
|
// The spawn flags field is the only one that doesn't get set through KeyValue(), so
|
|
// we set it in the template this way
|
|
int theSpawnFlags = this->pev->spawnflags;
|
|
if(!theSpawnFlags)
|
|
{
|
|
theSpawnFlags = theTemplate->GetFlags();
|
|
}
|
|
|
|
// Did they check the "start on" flag?
|
|
if(theSpawnFlags & 1)
|
|
{
|
|
this->mUseState = true;
|
|
}
|
|
|
|
theTemplate->SetFlags(theSpawnFlags);
|
|
}
|
|
else
|
|
{
|
|
ALERT(at_logged, "Couldn't find particle system template: %d\n", this->mTemplateIndex);
|
|
UTIL_Remove(this);
|
|
}
|
|
}
|
|
|
|
void
|
|
AvHParticleSystemEntity::UpdateClientData()
|
|
{
|
|
// Turn the system on or off
|
|
if(this->mIsOn != this->mUseState)
|
|
{
|
|
this->mIsOn = this->mUseState;
|
|
|
|
// set up entity so it's propagated correctly
|
|
if(this->mIsOn)
|
|
{
|
|
// TODO: Reset sCurrentHandle to 1 every time a new game starts?
|
|
this->mHandle = sCurrentHandle++;
|
|
|
|
// Create server side system for collision only
|
|
int theEntIndex = this->entindex();
|
|
AvHParticleSystemManager::Instance()->CreateParticleSystemIfNotCreated(theEntIndex, this->mTemplateIndex, this->mHandle);
|
|
|
|
// Replicate action to everyone
|
|
this->pev->iuser3 = AVH_USER3_PARTICLE_ON;
|
|
const AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
|
|
ASSERT(theTemplate);
|
|
|
|
int theGenEntityIndex = theTemplate->GetGenerationEntityIndex();
|
|
if(theGenEntityIndex == -1)
|
|
{
|
|
theGenEntityIndex = 0;
|
|
}
|
|
|
|
//this->pev->fuser1 = /*this->mTemplateIndex;*/ (theGenEntityIndex << 16) | this->mTemplateIndex;
|
|
|
|
ASSERT(this->mTemplateIndex < 256);
|
|
this->pev->fuser1 = (theGenEntityIndex << 16) | ((this->mTemplateIndex & 0xFF) << 8);
|
|
this->pev->fuser2 = this->mHandle;
|
|
|
|
// Store our custom data
|
|
this->SetCustomData(this->mCustomData);
|
|
|
|
this->mTimeParticlesCreated = gpGlobals->time;
|
|
}
|
|
else
|
|
{
|
|
// Destroy server side particle system
|
|
//AvHParticleSystemManager::Instance()->DestroyParticleSystemIfNotDestroyed(this->entindex(), this->mHandle);
|
|
AvHParticleSystemManager::Instance()->MarkParticleSystemForDeletion(this->entindex(), this->mHandle);
|
|
|
|
// Replicate action to everyone
|
|
this->pev->iuser3 = AVH_USER3_PARTICLE_OFF;
|
|
this->pev->fuser1 = this->mHandle;
|
|
}
|
|
}
|
|
|
|
if(this->mIsOn)
|
|
{
|
|
AvHParticleTemplate* theTemplate = gParticleTemplateList.GetTemplateAtIndex(this->mTemplateIndex);
|
|
ASSERT(theTemplate);
|
|
|
|
// If particle system was set to expire, make sure to realize when it turns off
|
|
int theParticleSystemLifetime = theTemplate->GetParticleSystemLifetime();
|
|
if(theParticleSystemLifetime != -1)
|
|
{
|
|
if(gpGlobals->time - this->mTimeParticlesCreated >= theParticleSystemLifetime)
|
|
{
|
|
//this->mIsOn = false;
|
|
this->mUseState = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a custom particle system. Create a new template instead of reading
|
|
// one off disk.
|
|
void
|
|
AvHCustomParticleSystemEntity::KeyValue( KeyValueData* inPkvd )
|
|
{
|
|
// Read tag with ps name and create a new template using it
|
|
if(FStrEq(inPkvd->szKeyName, kpscSystemName))
|
|
{
|
|
// Custom particle systems shouldn't be specifying a system in the .ps to use
|
|
ASSERT(false);
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscGenSource) || FStrEq(inPkvd->szKeyName, "particleGenerationSource"))
|
|
{
|
|
char* theEntityName = inPkvd->szValue;
|
|
this->GetCustomTemplate()->SetGenerationEntityName(theEntityName);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscGenShape) || FStrEq(inPkvd->szKeyName, "particleGenerationShape"))
|
|
{
|
|
int theGenerationShape = 0;
|
|
if(sscanf(inPkvd->szValue, "%d", &theGenerationShape))
|
|
{
|
|
ShapeType theShape = PS_Point;
|
|
switch(theGenerationShape)
|
|
{
|
|
case 4:
|
|
theShape = PS_Box;
|
|
break;
|
|
case 5:
|
|
theShape = PS_Sphere;
|
|
break;
|
|
case 8:
|
|
theShape = PS_Blob;
|
|
break;
|
|
}
|
|
this->GetCustomTemplate()->SetGenerationShape(theShape);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscSprite) || FStrEq(inPkvd->szKeyName, "particleSprite"))
|
|
{
|
|
// relative path to sprite
|
|
string theSpriteName(inPkvd->szValue);
|
|
this->GetCustomTemplate()->SetSprite(theSpriteName);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscSpriteNumFrames) || FStrEq(inPkvd->szKeyName, "particleSpriteNumFrames"))
|
|
{
|
|
// int number of frames
|
|
int theNumFrames = 0;
|
|
if(sscanf(inPkvd->szValue, "%d", &theNumFrames) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetNumSpriteFrames(theNumFrames);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscGenShapeParams) || FStrEq(inPkvd->szKeyName, "particleGenerationShapeParams"))
|
|
{
|
|
float theParameter = 0;
|
|
if(sscanf(inPkvd->szValue, "%f", &theParameter) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetGenerationEntityParameter(theParameter);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscNumParticles) || FStrEq(inPkvd->szKeyName, "particleNumParticles"))
|
|
{
|
|
// max particles, or density
|
|
int theNumParticles = 0;
|
|
if(sscanf(inPkvd->szValue, "%d", &theNumParticles) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetMaxParticles(theNumParticles);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscGenRate) || FStrEq(inPkvd->szKeyName, "particleGenerationRate"))
|
|
{
|
|
// num particles per second
|
|
int theNumParticles = 0;
|
|
if(sscanf(inPkvd->szValue, "%d", &theNumParticles) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetGenerationRate(theNumParticles);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscSize) || FStrEq(inPkvd->szKeyName, "particleSize"))
|
|
{
|
|
// float particle size
|
|
float theParticleSize = 0;
|
|
if(sscanf(inPkvd->szValue, "%f", &theParticleSize) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetParticleSize(theParticleSize);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscSystemLifetime) || FStrEq(inPkvd->szKeyName, "particleSystemLifetime"))
|
|
{
|
|
// string system lifetime
|
|
float theLifetime = -1;
|
|
if(sscanf(inPkvd->szValue, "%f", &theLifetime) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetParticleSystemLifetime(theLifetime);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscAnimationSpeed) || FStrEq(inPkvd->szKeyName, "particleAnimationSpeed"))
|
|
{
|
|
// Sprite animation speed
|
|
float theAnimSpeed = 1.0f;
|
|
if(sscanf(inPkvd->szValue, "%f", &theAnimSpeed) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetAnimationSpeed(theAnimSpeed);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscParticleLifetime) || FStrEq(inPkvd->szKeyName, "particleLifetime"))
|
|
{
|
|
// string particle lifetime
|
|
float theLifetime = -1;
|
|
if(sscanf(inPkvd->szValue, "%f", &theLifetime) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetParticleLifetime(theLifetime);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscVelocityShape) || FStrEq(inPkvd->szKeyName, "particleStartingVelocityShape"))
|
|
{
|
|
int theVelocityShape = 0;
|
|
if(sscanf(inPkvd->szValue, "%d", &theVelocityShape))
|
|
{
|
|
ShapeType theShape = PS_Point;
|
|
switch(theVelocityShape)
|
|
{
|
|
case 1:
|
|
theShape = PS_Point;
|
|
break;
|
|
case 2:
|
|
theShape = PS_Box;
|
|
break;
|
|
case 3:
|
|
theShape = PS_Sphere;
|
|
break;
|
|
case 4:
|
|
theShape = PS_Blob;
|
|
break;
|
|
}
|
|
this->GetCustomTemplate()->SetStartingVelocityShape(theShape);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscVelocityParams) || FStrEq(inPkvd->szKeyName, "particleStartingVelParams"))
|
|
{
|
|
// string, 8 comma-delimited parms
|
|
ParticleParams theVelParms;
|
|
if(sscanf(inPkvd->szValue, "%d,%d,%d,%d,%d,%d,%d,%d", theVelParms + 0, theVelParms + 1, theVelParms + 2, theVelParms + 3, theVelParms + 4, theVelParms + 5, theVelParms + 6, theVelParms + 7) == 8)
|
|
{
|
|
this->GetCustomTemplate()->SetStartingVelocityParams(theVelParms);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscScale) || FStrEq(inPkvd->szKeyName, "particleScaling"))
|
|
{
|
|
// float/string particle scaling
|
|
float theScaling = 1.0f;
|
|
if(sscanf(inPkvd->szValue, "%f", &theScaling) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetParticleScaling(theScaling);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscRendermode) || FStrEq(inPkvd->szKeyName, "particleRenderMode"))
|
|
{
|
|
// 0-5 render mode
|
|
int theRenderMode = 0;
|
|
if(sscanf(inPkvd->szValue, "%d", &theRenderMode) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetRenderMode(theRenderMode);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscMaxAlpha) || FStrEq(inPkvd->szKeyName, "particleMaxAlpha"))
|
|
{
|
|
float theMaxAlpha = 1.0f;
|
|
if(sscanf(inPkvd->szValue, "%f", &theMaxAlpha) == 1)
|
|
{
|
|
this->GetCustomTemplate()->SetMaxAlpha(theMaxAlpha);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
}
|
|
else if(FStrEq(inPkvd->szKeyName, kpscSystemToGen) || FStrEq(inPkvd->szKeyName, "particleSystemToGenerate"))
|
|
{
|
|
string theSystemToGenerate = inPkvd->szValue;
|
|
this->GetCustomTemplate()->SetParticleSystemToGenerate(theSystemToGenerate);
|
|
inPkvd->fHandled = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Call down to base class
|
|
AvHParticleSystemEntity::KeyValue(inPkvd);
|
|
}
|
|
}
|
|
|