📄 weaponfx.cpp
字号:
// ----------------------------------------------------------------------- //
//
// MODULE : WeaponFX.cpp
//
// PURPOSE : Weapon special effects - adapted from Riot
//
// CREATED : 4/30/98
//
// ----------------------------------------------------------------------- //
#include "WeaponFX.h"
#include "cpp_client_de.h"
#include "ClientUtilities.h"
#include "BloodClientShell.h"
#include "MarkSFX.h"
#include "SparksFX.h"
#include "ClientServerShared.h"
#include "SFXMsgIds.h"
#include "SmokeFX.h"
#include "SmokeImpactFX.h"
#include "SurfaceFragmentFX.h"
#include "bloodsplatfx.h"
#include "ParticleExplosionFX.h"
#include "ShellCasingFX.h"
#include "ExplosionFX.h"
#include "SplashFX.h"
#include "RippleFX.h"
#include "SoundTypes.h"
extern CBloodClientShell* g_pBloodClientShell;
char* szSmokeParticles[6] = {"SpriteTextures\\smoke64_1.dtx",
"SpriteTextures\\smoke64_2.dtx",
"SpriteTextures\\smoke64_3.dtx",
"SpriteTextures\\smoke64_4.dtx",
"SpriteTextures\\smoke64_5.dtx",
"SpriteTextures\\smoke64_6.dtx",};
char* szSmokeSprites[6] = {"Sprites\\smokepuff1.spr",
"Sprites\\smokepuff2.spr",
"Sprites\\smokepuff3.spr",
"Sprites\\smokepuff4.spr",
"Sprites\\smokepuff5.spr",
"Sprites\\smokepuff6.spr",};
#define DEFAULT_WATER_IMPACT_SOUND_RADIUS 2000.0f
#define DEFAULT_IMPACT_SOUND_RADIUS 500.0f
// ----------------------------------------------------------------------- //
//
// ROUTINE: CWeaponFX::Init
//
// PURPOSE: Init the weapon fx
//
// ----------------------------------------------------------------------- //
DBOOL CWeaponFX::Init(SFXCREATESTRUCT* psfxCreateStruct)
{
if (!CSpecialFX::Init(psfxCreateStruct)) return DFALSE;
WFXCREATESTRUCT* pCS = (WFXCREATESTRUCT*)psfxCreateStruct;
VEC_COPY(m_vSourcePos, pCS->vSourcePos);
VEC_COPY(m_vDestPos, pCS->vDestPos);
VEC_COPY(m_vForward, pCS->vForward);
VEC_COPY(m_vNormal, pCS->vNormal);
m_nFXFlags = pCS->nFXFlags;
m_nExtraData = pCS->nExtraData;
m_nAmmoType = pCS->nAmmoType;
m_eSurfaceType = (SurfaceType)pCS->nSurfaceType;
m_nExplosionType = pCS->nExplosionType;
m_fDamage = pCS->fDamage;
m_fDensity = pCS->fDensity;
VEC_COPY(m_vColor1, pCS->vColor1);
VEC_COPY(m_vColor2, pCS->vColor2);
VEC_COPY(m_vLightColor1, pCS->vLightColor1);
VEC_COPY(m_vLightColor2, pCS->vLightColor2);
m_eSourceCode = CC_NOTHING;
m_eDestCode = CC_NOTHING;
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CWeaponFX::CreateObject
//
// PURPOSE: Create the various fx
//
// ----------------------------------------------------------------------- //
DBOOL CWeaponFX::CreateObject(CClientDE* pClientDE)
{
CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
if (!CSpecialFX::CreateObject(pClientDE) || !pShell) return DFALSE;
// Calculate the direction vector
VEC_SUB(m_vDir, m_vDestPos, m_vSourcePos);
VEC_NORM(m_vDir);
VEC_NORM(m_vForward);
VEC_NORM(m_vNormal);
// Get the rotation
m_pClientDE->AlignRotation(&m_rRotation, &m_vNormal, DNULL);
// Determine what container the source location is in...
HLOCALOBJ objList[1];
DDWORD dwNum = m_pClientDE->GetPointContainers(&m_vSourcePos, objList, 1);
if(dwNum > 0 && objList[0])
{
DDWORD dwUserFlags;
m_pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags);
if(dwUserFlags & USRFLG_VISIBLE)
{
D_WORD dwCode;
if (m_pClientDE->GetContainerCode(objList[0], &dwCode))
m_eSourceCode = (ContainerCode)dwCode;
}
}
// Determine what container the destination location is in...
dwNum = m_pClientDE->GetPointContainers(&m_vDestPos, objList, 1);
if (dwNum > 0 && objList[0])
{
DDWORD dwUserFlags;
m_pClientDE->GetObjectUserFlags(objList[0], &dwUserFlags);
if (dwUserFlags & USRFLG_VISIBLE)
{
D_WORD dwCode;
if (m_pClientDE->GetContainerCode(objList[0], &dwCode))
m_eDestCode = (ContainerCode)dwCode;
}
}
// Create the FX from the muzzle to the destination
if(m_nFXFlags & WFX_MUZZLESMOKE) CreateMuzzleSmoke();
if(m_nFXFlags & WFX_MUZZLELIGHT) CreateMuzzleLight();
if(m_nFXFlags & WFX_EJECTSHELL)
{ CreateShellCasing(); if(m_nAmmoType == AMMO_SHELL) CreateShellCasing(); }
if(m_nFXFlags & WFX_TRACER) CreateTracer();
if(m_nFXFlags & WFX_PARTICLETRAIL) CreateParticleTrail();
// Create the FX at the destination
if(m_nFXFlags & WFX_MARK) CreateMark();
if(m_nFXFlags & WFX_FLASH) CreateFlash();
if(m_nFXFlags & WFX_SPARKS) CreateSparks();
if(m_nFXFlags & WFX_SPLASH) CreateSplash();
if(m_nFXFlags & WFX_SMOKE) CreateSmoke();
if(m_nFXFlags & WFX_SOUND) PlayImpactSound();
if(m_nFXFlags & WFX_BLOODSPLAT) CreateBloodSplat();
if(m_nFXFlags & WFX_BLOODSPURT) CreateBloodSpurt();
if(m_nFXFlags & WFX_EXPLOSION) CreateExplosion();
if(m_nFXFlags & WFX_FRAGMENTS) CreateFragments();
if(m_nFXFlags & WFX_IMPACTLIGHT) CreateImpactLight();
if(m_nFXFlags & WFX_SCREENSHAKE) CreateShakeNFlash();
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CWeaponFX::Update
//
// PURPOSE: Update the weapon fx
//
// ----------------------------------------------------------------------- //
DBOOL CWeaponFX::Update()
{
return DFALSE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CWeaponFX::CreateMark
//
// PURPOSE: Create a mark fx
//
// ----------------------------------------------------------------------- //
void CWeaponFX::CreateMark()
{
CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
if (!pShell) return;
CSFXMgr* psfxMgr = pShell->GetSFXMgr();
if (!psfxMgr) return;
char* pMarkSprite = GetMarkSprite(m_eSurfaceType);
if (!pMarkSprite) return;
MARKCREATESTRUCT mark;
mark.hServerObj = DNULL;
VEC_COPY(mark.m_Pos, m_vDestPos);
ROT_COPY(mark.m_Rotation, m_rRotation);
mark.m_fScale = (m_nAmmoType == AMMO_BULLET) ? 0.05f : 0.035f;
mark.m_hstrSprite = m_pClientDE->CreateString(pMarkSprite);
mark.m_bServerObj = DFALSE;
psfxMgr->CreateSFX(SFX_MARK_ID, &mark, DFALSE, this);
g_pClientDE->FreeString( mark.m_hstrSprite );
}
// ----------------------------------------------------------------------- //
// ROUTINE : CWeaponFX::CreateBloodSplat
// DESCRIPTION : Create a blood splat on surface
// RETURN TYPE : void
// ----------------------------------------------------------------------- //
void CWeaponFX::CreateBloodSplat()
{
CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
if (!pShell) return;
CSFXMgr* psfxMgr = pShell->GetSFXMgr();
if (!psfxMgr) return;
char* pSplatSprite = DNULL;
switch(GetRandom(1,3))
{
case 1: pSplatSprite = "sprites\\bloodsplat1.spr"; break;
case 2: pSplatSprite = "sprites\\bloodsplat2.spr"; break;
case 3: pSplatSprite = "sprites\\bloodsplat3.spr"; break;
default: pSplatSprite = "sprites\\bloodsplat1.spr"; break;
}
BSCREATESTRUCT splat;
splat.hServerObj = DNULL;
VEC_COPY(splat.m_Pos, m_vDestPos);
ROT_COPY(splat.m_Rotation, m_rRotation);
splat.m_fScale = 0.1f + GetRandom(-0.05f,0.05f);
splat.m_hstrSprite = m_pClientDE->CreateString(pSplatSprite);
splat.m_fGrowScale = 0;
psfxMgr->CreateSFX(SFX_BLOODSPLAT_ID, &splat, DFALSE, this);
g_pClientDE->FreeString( splat.m_hstrSprite );
}
// ----------------------------------------------------------------------- //
// ROUTINE : CWeaponFX::CreateBloodSpurt
// DESCRIPTION : Create a blood splat on surface
// RETURN TYPE : void
// ----------------------------------------------------------------------- //
void CWeaponFX::CreateBloodSpurt()
{
CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
if (!pShell) return;
CSFXMgr* psfxMgr = pShell->GetSFXMgr();
if (!psfxMgr) return;
char* szBlood[4] = { "spritetextures\\particles\\blooddrop_1.dtx",
"spritetextures\\particles\\blooddrop_2.dtx",
"spritetextures\\particles\\blooddrop_3.dtx",
"spritetextures\\particles\\blooddrop_4.dtx"};
PESCREATESTRUCT pe;
// VEC_SET(pe.vVelMin, -50.0f, 0.0f, -50.0f)
// VEC_SET(pe.vVelMax, 50.0f, 50.0f, 50.0f)
VEC_MULSCALAR(pe.vMinVel, m_vNormal, 30.0f);
VEC_MULSCALAR(pe.vMaxVel, m_vNormal, 50.0f);
pe.vMinVel.y = 40.0f;
pe.vMaxVel.y = 50.0f;
pe.vMinVel.x -= 20.0f;
pe.vMinVel.z -= 20.0f;
pe.vMaxVel.x += 20.0f;
pe.vMaxVel.z += 20.0f;
VEC_COPY(pe.vPos, m_vDestPos);
ROT_COPY(pe.rSurfaceRot, m_rRotation);
// VEC_SET(pe.vColor1, 255.0f, 255.0f, 255.0f);
// VEC_SET(pe.vColor2, 255.0f, 255.0f, 255.0f);
VEC_SET(pe.vColor1, 128.0f, 128.0f, 128.0f);
VEC_SET(pe.vColor2, 128.0f, 128.0f, 128.0f);
// VEC_COPY(pe.vMinVel, vVelMin);
// VEC_COPY(pe.vMaxVel, vVelMax);
VEC_SET(pe.vMinDriftOffset, 0.0f, -10.0f, 0.0f);
VEC_SET(pe.vMaxDriftOffset, 0.0f, -5.0f, 0.0f);
pe.bSmall = DFALSE;
pe.fLifeTime = 1.0f;
pe.fFadeTime = 0.5f;
pe.fOffsetTime = 0.0f;
pe.fRadius = 200.0f;
pe.fGravity = -100.0f;
pe.nNumPerPuff = 2;
pe.nNumEmitters = 1; //GetRandom(1,4);
pe.nEmitterFlags = MO_HALFGRAVITY;
pe.bIgnoreWind = DTRUE;
int nMaxSZBlood = NRES(4) - 1;
pe.pFilename = szBlood[GetRandom(0,nMaxSZBlood)];
pe.nSurfaceType = SURFTYPE_FLESH;
pe.nNumSteps = 6;
pe.bBounce = DFALSE;
CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_PARTICLEEXPLOSION_ID, &pe, DFALSE, this);
if (pFX)
{
CBaseParticleSystemFX* pBasePS = (CBaseParticleSystemFX*)pFX;
pBasePS->m_bSetSoftwareColor = DFALSE;
pFX->Update();
m_pClientDE->SetSoftwarePSColor(pFX->GetObject(), 1.0f, 0.0f, 0.0f);
}
// Create a pass-through spurt scaled by damage
VEC_MULSCALAR(pe.vMinVel, m_vNormal, -2.5f * m_fDamage);
VEC_MULSCALAR(pe.vMaxVel, m_vNormal, -3.0f * m_fDamage);
pe.vMinVel.y += 30.0f;
pe.vMaxVel.y += 40.0f;
pe.vMinVel.x -= 20.0f;
pe.vMinVel.z -= 20.0f;
pe.vMaxVel.x += 20.0f;
pe.vMaxVel.z += 20.0f;
pe.fLifeTime = 1.2f;
pe.fFadeTime = 0.8f;
pFX = psfxMgr->CreateSFX(SFX_PARTICLEEXPLOSION_ID, &pe, DFALSE, this);
if (pFX) pFX->Update();
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CWeaponFX::CreateSparks
//
// PURPOSE: Create sparks fx
//
// ----------------------------------------------------------------------- //
void CWeaponFX::CreateSparks()
{
CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
if (!pShell) return;
CSFXMgr* psfxMgr = pShell->GetSFXMgr();
if (!psfxMgr) return;
SCREATESTRUCT sp;
DBOOL big = DFALSE;
char str[128];
// General variables for the sparks
sp.hServerObj = DNULL;
VEC_COPY(sp.vPos, m_vDestPos);
sp.bFadeColors = DFALSE;
switch(m_eSurfaceType)
{
// Specific variable values just for metal surfaces
case SURFTYPE_METAL:
big = GetRandom(0,19) ? DFALSE : DTRUE;
VEC_MULSCALAR(sp.vDir, m_vNormal, 75.0f);
VEC_SET(sp.vColor1, 255.0f, 255.0f, 0.0f);
VEC_SET(sp.vColor2, 255.0f, 255.0f, 255.0f);
sp.hstrTexture = m_pClientDE->CreateString("spriteTextures\\particles\\particle2.dtx");
sp.fEmissionRadius = 0.3f;
sp.fRadius = 175.0f;
sp.fGravity = -150;
if(big)
{
sp.nSparks = (m_fDamage < 50.0f) ? (DBYTE)(m_fDamage * 5.0f): 250;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -