📄 bloodtrailsegmentfx.cpp
字号:
/****************************************************************************
;
; MODULE: BloodTrailSegmentFX.cpp
;
; PURPOSE: Blood trail effect
;
; HISTORY: Created by SCHLEGZ on 5/20/98 8:06:29 PM
;
; COMMENT: Copyright (c) 1997, Monolith Productions Inc.
;
****************************************************************************/
#include "bloodtrailsegmentfx.h"
#include "cpp_client_de.h"
#include "ClientUtilities.h"
#include "ContainerCodes.h"
#include "sfxmgr.h"
#include "bloodclientshell.h"
#include "bloodsplatfx.h"
#include "sfxmsgids.h"
// ----------------------------------------------------------------------- //
// ROUTINE : CBloodTrailSegmentFX::Init
// DESCRIPTION :
// RETURN TYPE : DBOOL
// PARAMS : SFXCREATESTRUCT* psfxCreateStruct
// ----------------------------------------------------------------------- //
DBOOL CBloodTrailSegmentFX::Init(SFXCREATESTRUCT* psfxCreateStruct)
{
if (!CBaseParticleSystemFX::Init(psfxCreateStruct)) return DFALSE;
BTSCREATESTRUCT* pBTS = (BTSCREATESTRUCT*)psfxCreateStruct;
VEC_COPY(m_vColor1, pBTS->vColor1);
m_fLifeTime = pBTS->fLifeTime;
m_fOffsetTime = pBTS->fOffsetTime;
m_fRadius = pBTS->fRadius;
m_nNumPerPuff = pBTS->nNumPerPuff;
m_fGravity /= 3.0f;
return DTRUE;
}
// ----------------------------------------------------------------------- //
// ROUTINE : CBloodTrailSegmentFX::CreateObject
// DESCRIPTION :
// RETURN TYPE : DBOOL
// PARAMS : CClientDE *pClientDE
// ----------------------------------------------------------------------- //
DBOOL CBloodTrailSegmentFX::CreateObject(CClientDE *pClientDE)
{
if (!pClientDE || !m_hServerObject) return DFALSE;
switch(GetRandom(1,15))
{
case 1: m_pTextureName = "spritetextures\\blood32_1.dtx"; break;
case 2: m_pTextureName = "spritetextures\\blood32_2.dtx"; break;
case 3: m_pTextureName = "spritetextures\\blood32_3.dtx"; break;
case 4: m_pTextureName = "spritetextures\\blood32_4.dtx"; break;
case 5: m_pTextureName = "spritetextures\\blood32_5.dtx"; break;
case 6: m_pTextureName = "spritetextures\\blood32_6.dtx"; break;
case 7: m_pTextureName = "spritetextures\\blood32_7.dtx"; break;
case 8: m_pTextureName = "spritetextures\\blood32_8.dtx"; break;
case 9: m_pTextureName = "spritetextures\\blood32_9.dtx"; break;
case 10: m_pTextureName = "spritetextures\\blood32_10.dtx"; break;
case 11: m_pTextureName = "spritetextures\\blood64_1.dtx"; break;
case 12: m_pTextureName = "spritetextures\\blood64_2.dtx"; break;
case 13: m_pTextureName = "spritetextures\\blood64_3.dtx"; break;
case 14: m_pTextureName = "spritetextures\\blood64_4.dtx"; break;
case 15: m_pTextureName = "spritetextures\\blood64_5.dtx"; break;
}
// Determine if we are in a liquid...
DVector vPos;
pClientDE->GetObjectPos(m_hServerObject, &vPos);
HLOCALOBJ objList[1];
DDWORD dwNum = pClientDE->GetPointContainers(&vPos, objList, 1);
if (dwNum > 0 && objList[0])
{
D_WORD dwCode;
if (pClientDE->GetContainerCode(objList[0], &dwCode))
{
if (IsLiquid((ContainerCode)dwCode))
{
m_fRadius *= 0.25f;
m_fGravity /= 3.0f;
m_nNumPerPuff *= 3;
}
}
}
return CBaseParticleSystemFX::CreateObject(pClientDE);
}
// ----------------------------------------------------------------------- //
// ROUTINE : CBloodTrailSegmentFX::Update
// DESCRIPTION :
// RETURN TYPE : DBOOL
// ----------------------------------------------------------------------- //
DBOOL CBloodTrailSegmentFX::Update()
{
if (!m_hObject || !m_pClientDE) return DFALSE;
DFLOAT fTime = m_pClientDE->GetTime();
if (m_bFirstUpdate)
{
if (!m_hServerObject) return DFALSE;
m_bFirstUpdate = DFALSE;
m_fStartTime = fTime;
m_fLastTime = fTime;
// Where is the server (moving) object...
DVector vPos, vTemp;
m_pClientDE->GetObjectPos(m_hServerObject, &vPos);
// Current position is relative to the particle system's postion (i.e.,
// each puff of blood is some distance away from the particle system's
/// position)...
m_pClientDE->GetObjectPos(m_hObject, &vTemp);
VEC_SUB(vPos, vPos, vTemp);
VEC_COPY(m_vLastPos, vPos);
}
// Check to see if we should just wait for last blood puff to go away...
if (m_bWantRemove)
{
if (fTime > m_fLastTime + m_fLifeTime)
{
return DFALSE;
}
return DTRUE;
}
//time to see if we splashed against ground
DVector vU, vR, vF,vPos;
DEParticle *pHead,*pTail;
m_pClientDE->GetParticles(m_hObject,&pHead,&pTail);
m_pClientDE->GetObjectPos(m_hObject,&vPos);
// m_pClientDE->GetObjectRotation(m_hObject, &rRot);
m_pClientDE->GetRotationVectors(&m_rRot, &vU, &vR, &vF);
ClientIntersectQuery iq;
ClientIntersectInfo ii;
iq.m_Flags = INTERSECT_HPOLY;
m_pClientDE->GetParticlePos(m_hObject,pHead,&iq.m_From);
VEC_ADD(iq.m_From,iq.m_From,vPos);
VEC_MULSCALAR(iq.m_To, vU, -1.0f);
VEC_ADD(iq.m_To, iq.m_To, iq.m_From); // Get destination point slightly past where we should be
if(m_pClientDE->IntersectSegment(&iq, &ii))
{
CBloodClientShell *pShell = (CBloodClientShell*)m_pClientDE->GetClientShell();
if (!pShell) return DFALSE;
CSFXMgr* psfxMgr = pShell->GetSFXMgr();
if (!psfxMgr) return DFALSE;
VEC_MULSCALAR(vU,vU,0.5f);
VEC_ADD(ii.m_Point,ii.m_Point,vU);
m_pClientDE->SetObjectPos(m_hObject,&ii.m_Point);
char* pSplatSprite = DNULL;
switch(GetRandom(1,3))
{
case 1: pSplatSprite = "sprites\\blood1.spr"; break;
case 2: pSplatSprite = "sprites\\blood2.spr"; break;
case 3: pSplatSprite = "sprites\\blood3.spr"; break;
default: pSplatSprite = "sprites\\blood1.spr"; break;
}
BSCREATESTRUCT splat;
splat.hServerObj = m_hObject;
VEC_COPY(splat.m_Pos, ii.m_Point);
m_pClientDE->AlignRotation( &splat.m_Rotation, &ii.m_Plane.m_Normal, &ii.m_Plane.m_Normal);
splat.m_fScale = 0.1f + GetRandom(-0.05f,0.05f);
splat.m_hstrSprite = m_pClientDE->CreateString(pSplatSprite);
splat.m_fGrowScale = 0.01f;
psfxMgr->CreateSFX(SFX_BLOODSPLAT_ID, &splat, DFALSE, this);
g_pClientDE->FreeString( splat.m_hstrSprite );
}
// See if it is time to create a new blood puff...
if ((fTime > m_fLastTime + m_fOffsetTime) && m_hServerObject)
{
DVector vCurPos, vPos, vDelta, vTemp, vDriftVel;
// Calculate blood puff position...
// Where is the server (moving) object...
m_pClientDE->GetObjectPos(m_hServerObject, &vCurPos);
// Current position is relative to the particle system's postion (i.e.,
// each puff of blood is some distance away from the particle system's
/// position)...
m_pClientDE->GetObjectPos(m_hObject, &vTemp);
VEC_SUB(vCurPos, vCurPos, vTemp);
// How long has it been since the last blood puff?
DFLOAT fTimeOffset = fTime - m_fLastTime;
// Fill the distance between the last projectile position, and it's
// current position with blood puffs...
int nNumSteps = (m_fLastTime > 0) ? 10 : 1;
VEC_SUB(vTemp, vCurPos, m_vLastPos);
VEC_MULSCALAR(vDelta, vTemp, 1.0f/float(nNumSteps));
VEC_COPY(vPos, m_vLastPos);
DFLOAT fLifeTimeOffset = fTimeOffset / float(nNumSteps);
DFLOAT fOffset = 3.0f;
DVector vDriftOffset;
VEC_SET(vDriftOffset, 4.0f, 5.5f, 0.5f);
VEC_SET(vDriftOffset, 5.0f, 5.0f, 5.0f);
for (int i=0; i < nNumSteps; i++)
{
// Build the individual blood puffs...
for (int j=0; j < m_nNumPerPuff; j++)
{
VEC_COPY(vTemp, vPos);
VEC_SET(vDriftVel, GetRandom(-vDriftOffset.x*2.0f, -vDriftOffset.x),
GetRandom(5.0f, 6.0f),
GetRandom(-vDriftOffset.z, vDriftOffset.z));
vTemp.x += GetRandom(-fOffset, fOffset);
vTemp.y += GetRandom(-fOffset, fOffset);
vTemp.z += GetRandom(-fOffset, fOffset);
m_pClientDE->AddParticle(m_hObject, &vTemp, &vDriftVel, &m_vColor1, m_fLifeTime);
}
VEC_ADD(vPos, vPos, vDelta);
}
m_fLastTime = fTime;
VEC_COPY(m_vLastPos, vCurPos);
}
return DTRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -