📄 objectfx.cpp
字号:
// ----------------------------------------------------------------------- //
//
// MODULE : ObjectFX.cpp
//
// PURPOSE : General object special FX - Implementation
//
// CREATED : 8/25/98
//
// ----------------------------------------------------------------------- //
#include "ObjectFX.h"
#include "SFXMsgIds.h"
#include "cpp_client_de.h"
#include "ClientUtilities.h"
#include "BloodClientShell.h"
// ----------------------------------------------------------------------- //
//
// ROUTINE: CObjectParticleFX::Init
//
// PURPOSE: Init the system
//
// ----------------------------------------------------------------------- //
DBOOL CObjectParticleFX::Init(SFXCREATESTRUCT* psfxCreateStruct)
{
if (!psfxCreateStruct) return DFALSE;
CBaseParticleSystemFX::Init(psfxCreateStruct);
OBJECTPARTICLEFXCS* pPS = (OBJECTPARTICLEFXCS*)psfxCreateStruct;
m_hObj = pPS->hObj;
VEC_COPY(m_vOffset, pPS->vOffset);
m_fRampUpTime = pPS->fRampUpTime;
m_fRampDownTime = pPS->fRampDownTime;
m_fDuration = pPS->fDuration;
m_fAddDelay = pPS->fAddDelay;
m_fRadius = pPS->fRadius;
m_fGravity = pPS->fGravity;
VEC_COPY(m_vRotations, pPS->vRotations);
m_fPosRadius = pPS->fPosRadius;
m_nEmitType = pPS->nEmitType;
m_nNumParticles = pPS->nNumParticles;
m_fDensity = pPS->fDensity;
m_fAlpha = pPS->fAlpha;
VEC_COPY(m_vColor1, pPS->vMinColor);
VEC_COPY(m_vColor2, pPS->vMaxColor);
m_fMinVelocity = pPS->fMinVelocity;
m_fMaxVelocity = pPS->fMaxVelocity;
m_fMinLifetime = pPS->fMinLifetime;
m_fMaxLifetime = pPS->fMaxLifetime;
m_nRampUpType = pPS->nRampUpType;
m_nRampDownType = pPS->nRampDownType;
m_nFXFlags = pPS->nFXFlags;
m_szParticle = pPS->szParticle;
VEC_INIT(m_vPos);
m_bMove = DTRUE;
m_bFirstStop = DTRUE;
m_fStopTime = 0.0f;
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CObjectParticleFX::CreateObject
//
// PURPOSE: Create object associated the particle system.
//
// ----------------------------------------------------------------------- //
DBOOL CObjectParticleFX::CreateObject(CClientDE *pClientDE)
{
if(!pClientDE || !m_hObj) return DFALSE;
if(m_szParticle) m_pTextureName = pClientDE->GetStringData(m_szParticle);
else m_pTextureName = "SpriteTextures\\smoke64_2.dtx";
DBOOL bRet = CBaseParticleSystemFX::CreateObject(pClientDE);
// pClientDE->SetObjectClientFlags(m_hObj, pClientDE->GetObjectClientFlags(m_hObj)|CF_NOTIFYREMOVE);
// Setup the initial position variables for the object
m_pClientDE->GetObjectPos(m_hObj, &m_vPos);
m_pClientDE->SetObjectPos(m_hObject, &m_vPos);
// m_pClientDE->GetObjectRotation(m_hObj, &m_rLastRot);
VEC_COPY(m_vLastPos, m_vPos);
VEC_COPY(m_vLastObjPos, m_vPos);
VEC_COPY(m_vOrigin, m_vPos);
m_fStartTime = m_pClientDE->GetTime();
return bRet;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CObjectParticleFX::Update
//
// PURPOSE: Update the particles
//
// ----------------------------------------------------------------------- //
DBOOL CObjectParticleFX::Update()
{
if(!m_hObject || !m_pClientDE || !m_hObj || !m_hServerObject)
return DFALSE;
DFLOAT fTime = m_pClientDE->GetTime() - m_fStartTime;
DVector vU, vR, vF;
DRotation rRot;
// Initialize some data during the first update...
if(m_bFirstUpdate)
{
m_fLastAddTime = 0.0f;
m_bFirstUpdate = 0;
return DTRUE;
}
// See if we should delete the FX
if(m_fDuration)
{
if(m_fDuration < fTime)
return DFALSE;
}
else
{
if(!g_pBloodClientShell->IsMultiplayerGame())
{
DVector vPos;
m_pClientDE->GetObjectPos(m_hObj, &vPos);
if(m_nFXFlags & OBJPSFX_REMOVESTOPPED)
{
DVector vVel;
VEC_SUB(vVel, vPos, m_vLastObjPos);
if((vVel.x == 0.0f) && (vVel.y == 0.0f) && (vVel.z == 0.0f))
{
m_bMove = DFALSE;
if(m_nFXFlags & OBJPSFX_RAMPDOWNSTOPPED)
m_fDuration = fTime + m_fRampDownTime + m_fMaxLifetime;
else
return DFALSE;
}
}
VEC_COPY(m_vLastObjPos, vPos);
}
else
{
DVector vPos;
m_pClientDE->GetObjectPos(m_hObj, &vPos);
if(m_nFXFlags & OBJPSFX_REMOVESTOPPED)
{
DVector vVel;
VEC_SUB(vVel, vPos, m_vLastObjPos);
if((vVel.x == 0.0f) && (vVel.y == 0.0f) && (vVel.z == 0.0f))
{
m_bMove = DFALSE;
if(m_bFirstStop)
{
m_fStopTime = m_pClientDE->GetTime();
m_bFirstStop = DFALSE;
}
if(m_pClientDE->GetTime() > m_fStopTime + 1.0f)
{
if(m_nFXFlags & OBJPSFX_RAMPDOWNSTOPPED)
m_fDuration = fTime + m_fRampDownTime + m_fMaxLifetime;
else
return DFALSE;
}
}
else
{
m_bFirstStop = DTRUE;
m_bMove = DTRUE;
}
}
VEC_COPY(m_vLastObjPos, vPos);
}
}
//*********************************************************************
// Set the ramp state and ratio
//*********************************************************************
if(m_nRampUpType && m_fDuration && (fTime <= m_fRampUpTime))
{
m_fRampRatio = fTime / m_fRampUpTime;
m_bRampState = OBJPSFX_RAMPUP;
if(m_fRampRatio > 1.0f) m_fRampRatio = 1.0f;
}
else if(m_nRampDownType && m_fDuration && (fTime >= m_fDuration - m_fRampDownTime))
{
m_fRampRatio = (m_fDuration - fTime) / m_fRampDownTime;
m_bRampState = OBJPSFX_RAMPDOWN;
if(m_fRampRatio < 0.0f) m_fRampRatio = 0.0f;
}
else
{
m_fRampRatio = 1.0f;
m_bRampState = 0;
}
//*********************************************************************
// Handle the location and rotation of the system
//*********************************************************************
if(m_bMove)
{
m_pClientDE->GetObjectPos(m_hObj, &m_vPos);
m_pClientDE->GetObjectRotation(m_hObj, &rRot);
m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);
VEC_MULSCALAR(vU, vU, m_vOffset.x);
VEC_MULSCALAR(vR, vR, m_vOffset.y);
VEC_MULSCALAR(vF, vF, m_vOffset.z);
VEC_ADD(m_vPos, m_vPos, vU);
VEC_ADD(m_vPos, m_vPos, vR);
VEC_ADD(m_vPos, m_vPos, vF);
}
// Update the position of the object if we should
if(!(m_nFXFlags & OBJPSFX_MOVINGSOURCE))
m_pClientDE->SetObjectPos(m_hObject, &m_vPos);
// Update the rotation of the system with the object
if(m_nFXFlags & OBJPSFX_ALIGNROTATION)
{
m_pClientDE->GetObjectRotation(m_hObj, &m_rRot);
m_pClientDE->GetRotationVectors(&m_rRot, &vU, &vR, &vF);
m_pClientDE->GetObjectRotation(m_hObject, &m_rRot);
m_pClientDE->AlignRotation(&m_rRot, &vF, &vU);
}
else
m_pClientDE->GetObjectRotation(m_hObject, &m_rRot);
// Rotate the object if it has rotation values
DVector vRotate;
VEC_COPY(vRotate, m_vRotations);
if(((m_bRampState == OBJPSFX_RAMPUP) && (m_nRampUpType & OBJPSFX_RAMPROTATION)) ||
((m_bRampState == OBJPSFX_RAMPDOWN) && (m_nRampDownType & OBJPSFX_RAMPROTATION)))
VEC_MULSCALAR(vRotate, vRotate, m_fRampRatio);
if(m_vRotations.x || m_vRotations.y || m_vRotations.z)
{
if(m_vRotations.x) m_pClientDE->EulerRotateX(&m_rRot, vRotate.x * MATH_PI);
if(m_vRotations.y) m_pClientDE->EulerRotateY(&m_rRot, vRotate.y * MATH_PI);
if(m_vRotations.z) m_pClientDE->EulerRotateZ(&m_rRot, vRotate.z * MATH_PI);
}
if(!(m_nFXFlags & OBJPSFX_ROTATINGSOURCE))
m_pClientDE->SetObjectRotation(m_hObject, &m_rRot);
//*********************************************************************
// Handle the alpha ramp values and add more particles
//*********************************************************************
if(((m_bRampState == OBJPSFX_RAMPUP) && (m_nRampUpType & OBJPSFX_RAMPALPHA)) ||
((m_bRampState == OBJPSFX_RAMPDOWN) && (m_nRampDownType & OBJPSFX_RAMPALPHA)))
{
// Fade in the particles
DFLOAT r, g, b, a;
m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a);
a = m_fAlpha * m_fRampRatio;
m_pClientDE->SetObjectColor(m_hObject, r, g, b, a);
}
// Add more particles if it's time to
if(m_pClientDE->GetTime() - m_fLastAddTime >= m_fAddDelay)
{
m_fLastAddTime = m_pClientDE->GetTime();
AddParticles();
VEC_COPY(m_vLastPos, m_vPos);
ROT_COPY(m_rLastRot, m_rRot);
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CObjectParticleFX::AddParticles
//
// PURPOSE: Add a new batch of particles
//
// ----------------------------------------------------------------------- //
void CObjectParticleFX::AddParticles()
{
if(!m_pClientDE) return;
// Add the particles to the system
DDWORD i, j = (DDWORD)m_fDensity;
DFLOAT life;
DVector start, vel, color, vUp, vU, vR, vF;
DRotation rRot;
VEC_SET(vUp, 0.0f, 1.0f, 0.0f);
ROT_COPY(rRot, m_rRot);
switch(m_nEmitType)
{
case OBJPSFX_EMITLOCATION:
{
m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);
VEC_SET(start, 0.0f, 0.0f, 0.0f);
VEC_NORM(vF);
if(m_nFXFlags & OBJPSFX_MOVINGSOURCE)
{
VEC_SUB(color, m_vPos, m_vOrigin);
VEC_ADD(start, start, color);
}
if(m_nFXFlags & OBJPSFX_MOVINGSTREAM)
{
DVector dif;
DFLOAT mag;
DDWORD count, num;
VEC_SUB(dif, m_vLastPos, m_vPos);
mag = VEC_MAG(dif);
num = (DDWORD)(mag / (m_fDensity * m_fRadius / 1000.0f));
VEC_DIVSCALAR(dif, dif, (DFLOAT)num);
for(count = 0; count < num; count++)
{
VEC_MULSCALAR(vel, vF, GetRandom(m_fMinVelocity, m_fMaxVelocity));
GetRandomColor(color);
life = GetRandom(m_fMinLifetime, m_fMaxLifetime);
m_pClientDE->AddParticle(m_hObject, &start, &vel, &color, life);
VEC_ADD(start, start, dif);
}
}
else
{
VEC_MULSCALAR(vel, vF, GetRandom(m_fMinVelocity, m_fMaxVelocity));
GetRandomColor(color);
life = GetRandom(m_fMinLifetime, m_fMaxLifetime);
m_pClientDE->AddParticle(m_hObject, &start, &vel, &color, life);
}
break;
}
case OBJPSFX_EMITRING:
case OBJPSFX_EMITFILLEDRING:
case OBJPSFX_EMITSPHERE:
case OBJPSFX_EMITFILLEDSPHERE:
{
DVector dif, offset;
DFLOAT mag;
DDWORD count, num = 1;
VEC_SET(offset, 0.0f, 0.0f, 0.0f);
if(m_nFXFlags & OBJPSFX_MOVINGSTREAM)
{
VEC_SUB(dif, m_vLastPos, m_vPos);
mag = VEC_MAG(dif);
num = (DDWORD)(mag / (m_fDensity * m_fRadius / 1000.0f));
VEC_DIVSCALAR(dif, dif, (DFLOAT)num);
}
for(count = 0; count < num; count++)
{
for(i = 0; i < m_nNumParticles; i++)
{
m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);
if((m_nEmitType == OBJPSFX_EMITSPHERE) || (m_nEmitType == OBJPSFX_EMITFILLEDSPHERE))
{
m_pClientDE->RotateAroundAxis(&rRot, &vF, GetRandom(-MATH_PI, MATH_PI));
m_pClientDE->RotateAroundAxis(&rRot, &vR, GetRandom(-MATH_PI, MATH_PI));
}
else
m_pClientDE->RotateAroundAxis(&rRot, &vF, GetRandom(-MATH_PI, MATH_PI));
VEC_NORM(vR);
VEC_COPY(start, vR);
VEC_COPY(vel, vR);
VEC_MULSCALAR(vel, vel, GetRandom(m_fMinVelocity, m_fMaxVelocity));
if((m_nEmitType == OBJPSFX_EMITFILLEDRING) || (m_nEmitType == OBJPSFX_EMITFILLEDSPHERE))
{ VEC_MULSCALAR(start, start, GetRandom(0.0f, m_fPosRadius)); }
else
{ VEC_MULSCALAR(start, start, m_fPosRadius); }
if(m_nFXFlags & OBJPSFX_MOVINGSOURCE)
{
VEC_SUB(color, m_vPos, m_vOrigin);
VEC_ADD(start, start, color);
}
if(m_nFXFlags & OBJPSFX_MOVINGSTREAM)
{
VEC_ADD(start, start, offset);
}
GetRandomColor(color);
life = GetRandom(m_fMinLifetime, m_fMaxLifetime);
m_pClientDE->AddParticle(m_hObject, &start, &vel, &color, life);
}
VEC_ADD(offset, offset, dif);
}
break;
}
case OBJPSFX_EMITCYLINDER:
case OBJPSFX_EMITFILLEDCYLINDER:
{
DVector dif, offset, up;
DRotation tempRot;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -