📄 gib.cpp
字号:
if (hClass)
{
pTrail = (CClientSmokeTrail*)pServerDE->CreateObject(hClass, &theStruct);
}
if (pTrail)
{
DVector vVel;
pServerDE->GetVelocity(m_hObject, &vVel);
pTrail->Setup(vVel, DFALSE);
m_hSmokeTrail = pTrail->m_hObject;
}
}
/*
if (m_bAddBloodTrail)
{
ObjectCreateStruct theStruct;
INIT_OBJECTCREATESTRUCT(theStruct);
pServerDE->GetObjectPos(m_hObject, &theStruct.m_Pos);
HCLASS hClass = pServerDE->GetClass("CClientBloodTrail");
CClientBloodTrail* pTrail = DNULL;
if (hClass)
{
pTrail = (CClientBloodTrail*)pServerDE->CreateObject(hClass, &theStruct);
}
if (pTrail)
{
DVector vVel,vColor;
VEC_SET(vColor,200.0f,0.0f,0.0f);
pServerDE->GetVelocity(m_hObject, &vVel);
pTrail->Setup(vVel, vColor);
m_hBloodTrail = pTrail->m_hObject;
}
}
*/
if (m_dwSurfType)
{
DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
dwFlags |= (m_dwSurfType << 24);
g_pServerDE->SetObjectUserFlags(m_hObject,dwFlags);
}
if(m_dwGibType & GIB_CORPSE) //so the corpse does not initially make a noise
m_bPlaySplat = DTRUE;
if (g_pBloodServerShell->IsMultiplayerGame())
{
m_fRemoveTime = g_pServerDE->GetTime() + GIB_REMOVETIME - 0.1f;
}
//scale the object down if small
pServerDE->SetNextUpdate( m_hObject, 0.1f );
pServerDE->SetDeactivationTime( m_hObject, 1.0f );
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CGib::Update
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
DBOOL CGib::Update()
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return DFALSE;
DVector vVel;
DRotation rRot;
DFLOAT fTime = pServerDE->GetTime();
if (m_fRemoveTime && m_fRemoveTime < fTime) return DFALSE;
if (m_bFirstUpdate)
{
// If any dim are significantly smaller than the others, set alignment so it'll come to
// rest aligned correctly.
DVector vDims;
pServerDE->GetObjectDims(m_hObject, &vDims);
if (vDims.y < vDims.x * 0.7f)
m_nAxisAlign = 2;
if (vDims.x < vDims.y * 0.7f)
m_nAxisAlign = 1;
if (vDims.z < vDims.y * 0.7f)
m_nAxisAlign = 3;
m_bFirstUpdate = DFALSE;
}
pServerDE->GetObjectPos(m_hObject, &m_vLastPos);
pServerDE->GetObjectRotation( m_hObject, &rRot );
pServerDE->GetVelocity( m_hObject ,&vVel );
if (m_bAddBloodSpurt && m_dwSurfType == SURFTYPE_FLESH)
{
DVector vSpurtVel;
VEC_MULSCALAR(vSpurtVel, vVel, 0.1f);
HMESSAGEWRITE hMessage = g_pServerDE->StartInstantSpecialEffectMessage(&m_vLastPos);
g_pServerDE->WriteToMessageByte(hMessage, SFX_PARTICLEEXPLOSION_ID);
g_pServerDE->WriteToMessageVector(hMessage, &m_vLastPos);
g_pServerDE->WriteToMessageCompVector(hMessage, &vSpurtVel);
g_pServerDE->EndMessage(hMessage);
m_bAddBloodSpurt = DFALSE;
}
if(m_hSmokeTrail)
pServerDE->SetObjectPos(m_hSmokeTrail, &m_vLastPos);
if(m_hBloodTrail)
pServerDE->SetObjectPos(m_hBloodTrail, &m_vLastPos);
m_fRotateTime -= pServerDE->GetFrameTime();
// If velocity slows enough, stop moving
if (VEC_MAGSQR(vVel) <= 50.0 || m_fRotateTime <= 0.0f)
{
if(m_hSmokeTrail)
{
pServerDE->RemoveObject(m_hSmokeTrail);
m_hSmokeTrail = DNULL;
}
if(m_hBloodTrail)
{
pServerDE->RemoveObject(m_hBloodTrail);
m_hBloodTrail = DNULL;
}
m_fPitchVel = 0;
m_fYawVel = 0;
m_fRollVel = 0;
// Align so that y axis is either straight up or down
switch(m_nAxisAlign)
{
case 1: // Yaw
{
m_fYaw = (m_fYaw > MATH_HALFPI && m_fYaw < MATH_HALFPI + MATH_PI) ? MATH_PI : 0;
}
break;
case 2: // Pitch
{
m_fPitch = (m_fPitch > MATH_HALFPI && m_fPitch < MATH_HALFPI + MATH_PI) ? MATH_PI : 0;
}
break;
case 3: // Roll
{
m_fRoll = (m_fRoll > MATH_HALFPI && m_fRoll < MATH_HALFPI + MATH_PI) ? MATH_PI : 0;
}
break;
}
pServerDE->SetupEuler(&rRot, m_fPitch, m_fYaw, m_fRoll);
pServerDE->SetObjectRotation(m_hObject, &rRot);
if (g_pBloodServerShell->IsMultiplayerGame())
pServerDE->SetNextUpdate( m_hObject, 0.01f );
else
pServerDE->SetNextUpdate( m_hObject, 0.0f );
}
else
{
if (m_fPitchVel != 0 || m_fYawVel != 0 || m_fRollVel != 0)
{
DFLOAT fDeltaTime = pServerDE->GetFrameTime();
m_fPitch += m_fPitchVel * fDeltaTime;
if (m_fPitch > MATH_CIRCLE) m_fPitch -= MATH_CIRCLE;
m_fYaw += m_fYawVel * fDeltaTime;
if (m_fYaw > MATH_CIRCLE) m_fYaw -= MATH_CIRCLE;
m_fRoll += m_fRollVel * fDeltaTime;
if (m_fRoll > MATH_CIRCLE) m_fRoll -= MATH_CIRCLE;
pServerDE->SetupEuler(&rRot, m_fPitch, m_fYaw, m_fRoll);
pServerDE->SetObjectRotation(m_hObject, &rRot);
}
pServerDE->SetNextUpdate( m_hObject, 0.01f );
}
pServerDE->SetDeactivationTime( m_hObject, 1.0f );
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CGib::HandleTouch
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
void CGib::HandleTouch(HOBJECT hObj, DFLOAT fData)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
if (!pServerDE) return;
DVector vPos;
pServerDE->GetObjectPos(m_hObject, &vPos);
// See if it should kick high..
if (m_bKickable && IsBaseCharacter(hObj))
{
DVector vVel;
pServerDE->GetVelocity(hObj, &vVel);
if (VEC_MAGSQR(vVel) > 25.0f)
{
vVel.y += 300.0f;
VEC_MULSCALAR(vVel, vVel, 2.0f);
pServerDE->SetVelocity(m_hObject, &vVel);
m_nBounceCount = 2;
m_fPitchVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE) / 3.0f;
m_fYawVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE) / 3.0f;
m_fRollVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE) / 3.0f;
PlayBounceSound();
if (m_dwSurfType == SURFTYPE_FLESH)
{
VEC_MULSCALAR(vVel, vVel, 0.02f);
HMESSAGEWRITE hMessage = g_pServerDE->StartInstantSpecialEffectMessage(&vPos);
g_pServerDE->WriteToMessageByte(hMessage, SFX_PARTICLEEXPLOSION_ID);
g_pServerDE->WriteToMessageVector(hMessage, &vPos);
g_pServerDE->WriteToMessageCompVector(hMessage, &vVel);
g_pServerDE->EndMessage(hMessage);
}
m_fRotateTime = 1.0f;
pServerDE->SetNextUpdate( m_hObject, 0.01f );
return;
}
}
// return if it hit a non solid object
if (hObj != pServerDE->GetWorldObject() && !(pServerDE->GetObjectFlags(hObj) & FLAG_SOLID)) // Ignore non-solid objects
return;
// Cast a ray from our last known position to see what we hit
IntersectQuery iq;
IntersectInfo ii;
DVector vVel;
pServerDE->GetVelocity(m_hObject, &vVel);
// If velocity is small then do not Cast segment...
if ( ((int)vVel.x+(int)vVel.z) == 0 || ((int)vVel.x+(int)vVel.z) == -0 || --m_nBounceCount < 0)
{
return;
}
VEC_COPY(iq.m_From, m_vLastPos); // Get start point at the last known position.
VEC_MULSCALAR(iq.m_To, vVel, 1.1f);
VEC_ADD(iq.m_To, iq.m_To, iq.m_From); // Get destination point slightly past where we should be
iq.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
iq.m_FilterFn = NULL;
iq.m_pUserData = NULL;
// Hit something!
if (pServerDE->IntersectSegment(&iq, &ii))
{
// Compute new velocity reflected off of the surface.
DVector vNormal;
VEC_COPY(vNormal, ii.m_Plane.m_Normal);
DFLOAT r = VEC_DOT(vVel, vNormal);
r *= 0.3f;
if (r > -100.0f)
r = 0;
else
{
PlayBounceSound();
VEC_MULSCALAR(vNormal, vNormal, r);
VEC_SUB(vVel, vVel, vNormal);
// Adjust the bouncing..
m_fPitchVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE) / 3.0f;
m_fYawVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE) / 3.0f;
m_fRollVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE) / 3.0f;
}
VEC_MULSCALAR(vVel, vVel, 0.5f); // Lose some energy in the bounce.
pServerDE->SetVelocity(m_hObject, &vVel);
m_fRotateTime = 1.0f;
m_bAddBloodSpurt = DTRUE;
pServerDE->SetNextUpdate( m_hObject, 0.01f );
}
return;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CGib::PlayBounceSound()
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
void CGib::PlayBounceSound()
{
// Play a bounce sound...
char szSound[MAX_CS_FILENAME_LEN+1];
switch(m_dwSurfType)
{
case SURFTYPE_FLESH:
{
int index = GetRandom(1, NRES(5));
sprintf(szSound, "sounds\\gibs\\flesh\\gib_impact%d.wav", index);
break;
}
case SURFTYPE_PLASTIC:
{
sprintf(szSound, "sounds\\bounce\\pylon.wav");
break;
}
}
PlaySoundFromObject(m_hObject, szSound, 1000, SOUNDPRIORITY_MISC_LOW);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CGib::Damage()
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
void CGib::Damage(DVector vDir)
{
//if the gib is destroyed, create more possible
if(m_damage.IsDead())
{
if(!m_bGibbed && !(m_dwGibType & GIB_SMALL) && !(m_dwGibType & GIB_FLESH))
{
if(m_dwGibType & GIB_CORPSE)
{
m_dwGibType = m_dwGibType ^ GIB_CORPSE;
m_dwGibType |= GIB_FLESH;
}
else
m_dwGibType |= GIB_SMALL;
CreateGibs(m_hObject,m_dwGibType,m_damage.GetLastDamageType(),vDir, (int)m_fMass);
m_bGibbed = DTRUE;
}
g_pServerDE->RemoveObject( m_hObject );
}
return;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CGib::CreateGibs()
//
// PURPOSE: Create more gibs
//
// ----------------------------------------------------------------------- //
void CGib::CreateGibs(HOBJECT hObject, DDWORD dwGibType, DBYTE dmgType, DVector vDmgDir, int nNumDebris)
{
CServerDE* g_pServerDE = GetServerDE();
int nItem;
HCLASS hClass;
DVector vPos, vVel, vParentDims;
DRotation rRot;
hClass = g_pServerDE->GetClass( "CGib" );
if( !hClass )
return;
g_pServerDE->GetObjectPos( hObject, &vPos );
g_pServerDE->GetObjectRotation( hObject, &rRot );
// Get dims of this prop...
g_pServerDE->GetObjectDims( hObject, &vParentDims );
// Make the debris...
for( nItem = 0; nItem < nNumDebris; nItem++ )
{
ObjectCreateStruct theStruct;
INIT_OBJECTCREATESTRUCT(theStruct);
theStruct.m_Flags = FLAG_VISIBLE | FLAG_RAYHIT | FLAG_GRAVITY | FLAG_TOUCH_NOTIFY;
theStruct.m_UserData = dwGibType;
if (dmgType == DAMAGE_TYPE_EXPLODE)
theStruct.m_UserData |= GIB_SMOKETRAIL;
if(dwGibType & GIB_FLESH)
theStruct.m_UserData |= GIB_BLOODTRAIL;
VEC_SET( theStruct.m_Pos, GetServerDE()->Random( -vParentDims.x, vParentDims.x ), GetServerDE()->Random( 0.1f, vParentDims.y ),
GetServerDE()->Random( -vParentDims.z, vParentDims.z ));
VEC_ADD( theStruct.m_Pos, theStruct.m_Pos, vPos );
// Make sure the velocity is somewhat upward...
vVel.x = vDmgDir.x * g_pServerDE->Random(0.0f, 300.0f);
vVel.y = g_pServerDE->Random(0.0f, 400.0f);
vVel.z = vDmgDir.z * g_pServerDE->Random(0.0f, 300.0f);
//Copy the rotation vector
ROT_COPY(theStruct.m_Rotation,rRot);
// Allocate an object...
BaseClass* pObj = g_pServerDE->CreateObject( hClass, &theStruct );
if( !pObj )
break;
// Randomly scale
DVector vScale;
vScale.x = (DFLOAT)g_pServerDE->Random(0.8f,1.2f);
vScale.y = (DFLOAT)g_pServerDE->Random(0.8f,1.2f);
vScale.z = (DFLOAT)g_pServerDE->Random(0.8f,1.2f);
if(dwGibType & GIB_SMALL)
{
VEC_MULSCALAR(vScale,vScale,0.4f);
}
else
{
VEC_MULSCALAR(vScale,vScale,1.0f);
}
g_pServerDE->ScaleObject(pObj->m_hObject, &vScale);
g_pServerDE->SetVelocity( pObj->m_hObject, &vVel );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -