📄 corpse.cpp
字号:
#include <stdio.h>
#include "corpse.h"
#include "ObjectUtilities.h"
#include "weapon.h"
#include "SFXMsgIds.h"
#include "ClientServerShared.h"
#include "ClientGibFX.h"
#include "ClientSplatFX.h"
#include "sparam.h"
#include "PlayerObj.h"
#include "VoiceMgrDefs.h"
#include "BloodServerShell.h"
BEGIN_CLASS(CCorpse)
END_CLASS_DEFAULT_FLAGS(CCorpse, B2BaseClass, NULL, NULL, CF_HIDDEN)
extern CPlayerObj* g_pPlayerObj;
#define CORPSE_REMOVETIME 30.0f
// --------------------------------------------------------------------------- //
//
// ROUTINE: CCorpse::Setup()
//
// PURPOSE: Setup
//
// --------------------------------------------------------------------------- //
void CCorpse::Setup(HOBJECT hFireObj, DBOOL bLimbLoss)
{
CServerDE* g_pServerDE = GetServerDE();
if (!g_pServerDE) return;
if(hFireObj)
{
m_hFireSource = hFireObj;
DVector offset;
VEC_SET(offset, 0.0f, 0.0f, 0.0f);
HMESSAGEWRITE hMessage = g_pServerDE->StartInstantSpecialEffectMessage(&offset);
g_pServerDE->WriteToMessageByte(hMessage, SFX_OBJECTFX_ID);
g_pServerDE->WriteToMessageObject(hMessage, m_hFireSource);
g_pServerDE->WriteToMessageVector(hMessage, &offset);
g_pServerDE->WriteToMessageFloat(hMessage, 3.0f);
g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_SCALENUMPARTICLES);
g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_FLAMING_2);
g_pServerDE->WriteToMessageDWord(hMessage, 0);
g_pServerDE->EndMessage(hMessage);
DRotation rRot;
ROT_INIT(rRot);
g_pServerDE->CreateAttachment(m_hObject, m_hFireSource, "torso", &offset, &rRot, &m_hAttach);
m_fBurnStart = g_pServerDE->GetTime();
//play ambient looping sound
PlaySoundInfo playSoundInfo;
PLAYSOUNDINFO_INIT( playSoundInfo );
playSoundInfo.m_dwFlags = PLAYSOUND_3D | PLAYSOUND_ATTACHED | PLAYSOUND_GETHANDLE | PLAYSOUND_REVERB;
playSoundInfo.m_dwFlags |= PLAYSOUND_LOOP | PLAYSOUND_CTRL_VOL;
_mbsncpy((unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)"sounds\\weapons\\fireloop.wav", _MAX_PATH );
playSoundInfo.m_hObject = m_hObject;
playSoundInfo.m_nPriority = SOUNDPRIORITY_AI_MEDIUM;
playSoundInfo.m_fOuterRadius = 1000;
playSoundInfo.m_fInnerRadius = 1000 * 0.2f;
playSoundInfo.m_nVolume = 60;
g_pServerDE->PlaySound( &playSoundInfo );
m_hLoopSound = playSoundInfo.m_hSound;
//create the smoke object
ObjectCreateStruct ocStruct;
INIT_OBJECTCREATESTRUCT(ocStruct);
ocStruct.m_ObjectType = OT_NORMAL;
ocStruct.m_NextUpdate = 0.01f;
g_pServerDE->GetModelNodeTransform(m_hObject, "torso",&ocStruct.m_Pos,&ocStruct.m_Rotation);
ocStruct.m_Flags = FLAG_FORCECLIENTUPDATE;
HCLASS hClass = g_pServerDE->GetClass("BaseClass");
BaseClass* pObj = g_pServerDE->CreateObject(hClass, &ocStruct);
if(pObj)
{
m_hSmokeSource = pObj->m_hObject;
}
}
m_bLimbLoss = bLimbLoss;
return;
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CCorpse::EngineMessageFn()
//
// PURPOSE: Handler for engine messages
//
// --------------------------------------------------------------------------- //
DDWORD CCorpse::EngineMessageFn(DDWORD messageID, void *pData, float fData)
{
switch(messageID)
{
case MID_UPDATE:
{
if (!Update())
g_pServerDE->RemoveObject( m_hObject );
break;
}
case MID_PRECREATE:
{
DDWORD dwRet = B2BaseClass::EngineMessageFn(messageID, pData, fData);
if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
{
ReadProp((ObjectCreateStruct*)pData);
}
PostPropRead((ObjectCreateStruct*)pData);
return dwRet;
}
case MID_INITIALUPDATE:
{
if (fData != INITIALUPDATE_SAVEGAME)
{
InitialUpdate((DVector *)pData);
}
if (fData == INITIALUPDATE_WORLDFILE)
{
MoveObjectToGround(m_hObject);
}
break;
}
case MID_SAVEOBJECT:
{
Save((HMESSAGEWRITE)pData, (DDWORD)fData);
break;
}
case MID_LOADOBJECT:
{
Load((HMESSAGEREAD)pData, (DDWORD)fData);
break;
}
case MID_MODELSTRINGKEY:
{
OnStringKey((ArgList*)pData);
break;
}
}
return B2BaseClass::EngineMessageFn(messageID, pData, fData);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CCorpse::ObjectMessageFn
//
// PURPOSE: Handle object-to-object messages
//
// ----------------------------------------------------------------------- //
DDWORD CCorpse::ObjectMessageFn( HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead )
{
CServerDE* g_pServerDE = GetServerDE();
if (!g_pServerDE) return 0;
switch(messageID)
{
case MID_DAMAGE:
{
B2BaseClass::ObjectMessageFn(hSender, messageID, hRead);
DVector vDir,vPos;
DFLOAT fDamage;
DBYTE nType;
g_pServerDE->ReadFromMessageVector(hRead, &vDir);
fDamage = g_pServerDE->ReadFromMessageFloat(hRead);
nType = g_pServerDE->ReadFromMessageByte(hRead);
HOBJECT hObj = g_pServerDE->ReadFromMessageObject(hRead);
g_pServerDE->ReadFromMessageVector(hRead, &vPos);
VEC_MULSCALAR(vDir,vDir,-1.0f);
if (!m_bDead)
return HandleDamage(vDir, fDamage, nType, vPos);
else
return 0;
}
default : break;
}
return B2BaseClass::ObjectMessageFn(hSender, messageID, hRead);
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CCorpse::ReadProp()
//
// PURPOSE: Reads properties
//
// --------------------------------------------------------------------------- //
DBOOL CCorpse::ReadProp(ObjectCreateStruct *pStruct)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE || !pStruct) return DFALSE;
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: PostPropRead()
//
// PURPOSE: Update properties
//
// ----------------------------------------------------------------------- //
void CCorpse::PostPropRead(ObjectCreateStruct *pStruct)
{
if (!pStruct) return;
pStruct->m_Flags = FLAG_VISIBLE | FLAG_RAYHIT | FLAG_GRAVITY | FLAG_MODELKEYS | FLAG_REMOVEIFOUTSIDE;
if(pStruct->m_UserData)
_mbscpy((unsigned char*)m_szSoundDir, (const unsigned char*)pStruct->m_UserData);
return;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CCorpse::InitialUpdate()
//
// PURPOSE: Handle initial update
//
// ----------------------------------------------------------------------- //
void CCorpse::InitialUpdate(DVector *pMovement)
{
if (!g_pServerDE) return;
m_damage.Init( m_hObject );
// Setup damage stats...
m_damage.SetMass( m_fMass );
m_damage.SetHitPoints( m_fHitPoints );
m_damage.SetMaxHitPoints( m_fHitPoints );
m_damage.SetArmorPoints( 0.0f );
m_damage.SetMaxArmorPoints( 0.0f );
m_damage.SetApplyDamagePhysics(DFALSE);
GenerateHitSpheres();
DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
dwFlags |= (SURFTYPE_FLESH << 24);
dwFlags |= USRFLG_SAVEABLE | USRFLG_SINGULARITY_ATTRACT;
g_pServerDE->SetObjectUserFlags(m_hObject, dwFlags);
g_pServerDE->SetNextUpdate( m_hObject, 0.01f );
return;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CCorpse::Update
//
// PURPOSE: Update until the death anim is done..
//
// ----------------------------------------------------------------------- //
DBOOL CCorpse::Update()
{
if (m_bDead || !g_pServerDE) return DFALSE;
DDWORD dwState = g_pServerDE->GetModelPlaybackState(m_hObject);
DFLOAT fTime = g_pServerDE->GetTime();
if(m_fRemoveTime && m_fRemoveTime <= fTime) return DFALSE;
if(m_fSmokeStart == 0.0f && m_hFireSource && fTime - m_fBurnStart > 5.0f)
{
g_pServerDE->RemoveAttachment(m_hAttach);
g_pServerDE->RemoveObject(m_hFireSource);
m_hFireSource = DNULL;
if(m_hLoopSound)
{
g_pServerDE->KillSound(m_hLoopSound);
m_hLoopSound = DNULL;
}
//create the smoke
DVector offset;
VEC_SET(offset, 0.0f, 0.0f, 0.0f);
HMESSAGEWRITE hMessage = g_pServerDE->StartInstantSpecialEffectMessage(&offset);
g_pServerDE->WriteToMessageByte(hMessage, SFX_OBJECTFX_ID);
g_pServerDE->WriteToMessageObject(hMessage, m_hSmokeSource);
g_pServerDE->WriteToMessageVector(hMessage, &offset);
g_pServerDE->WriteToMessageFloat(hMessage, 3.0f);
g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_SCALENUMPARTICLES);
g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_SMOKING_2);
g_pServerDE->WriteToMessageDWord(hMessage, 0);
g_pServerDE->EndMessage(hMessage);
DRotation rRot;
ROT_INIT(rRot);
g_pServerDE->CreateAttachment(m_hObject, m_hSmokeSource, "torso", &offset, &rRot, &m_hAttach);
m_fSmokeStart = fTime;
g_pServerDE->DebugOut("SmokeStart: %f\r\n", m_fSmokeStart);
}
else if(m_hFireSource == DNULL && m_hSmokeSource && fTime - m_fSmokeStart > 5.0f)
{
g_pServerDE->DebugOut("SmokeEnd: %f\r\n", fTime);
g_pServerDE->RemoveAttachment(m_hAttach);
g_pServerDE->RemoveObject(m_hSmokeSource);
m_hSmokeSource = DNULL;
m_hAttach = DNULL;
}
// Done with any death animation
if (dwState & MS_PLAYDONE)
{
CreateBloodPool();
if (g_pBloodServerShell->IsMultiplayerGame())
m_fRemoveTime = fTime + CORPSE_REMOVETIME - 0.1f;
if(m_hAttach == DNULL)
{
if (g_pBloodServerShell->IsMultiplayerGame())
g_pServerDE->SetNextUpdate(m_hObject, CORPSE_REMOVETIME);
else
g_pServerDE->SetNextUpdate(m_hObject, 0.0f);
}
else
g_pServerDE->SetNextUpdate(m_hObject, 0.1f);
}
else
{
g_pServerDE->SetNextUpdate(m_hObject, 0.1f);
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CCorpse::HandleDamage
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
DBOOL CCorpse::HandleDamage(DVector vDir, DFLOAT fDamage, int nType, DVector vPos)
{
// int nNodeHit = SetProperNode(CalculateHitLimb(vDir,vPos));
if (!m_hObject) return DFALSE;
int nNodeHit = -1;
if(m_bLimbLoss)
{
nNodeHit = SetProperNode(CalculateHitLimb(vDir,vPos));
//sanity check
if(nNodeHit == -1 && !(nType & DAMAGE_TYPE_EXPLODE))
return DFALSE;
}
if (m_damage.IsDead())
{
m_bDead = DTRUE;
CreateGibs(vDir, ((int)m_damage.GetMass())>>5, nType, fDamage);
// Set update to remove on next frame.
g_pServerDE->SetNextUpdate(m_hObject, 0.1f);
if(m_hAttach)
g_pServerDE->RemoveAttachment(m_hAttach);
if(m_hFireSource)
{
g_pServerDE->RemoveObject(m_hFireSource);
m_hFireSource = DNULL;
}
if(m_hLoopSound)
{
g_pServerDE->KillSound(m_hLoopSound);
m_hLoopSound = DNULL;
}
if (IsRandomChance(7))
{
g_pPlayerObj->PlayVoiceGroupEventOnClient(VME_BIGGIB, DTRUE); // [blg]
}
}
else if (nNodeHit >= 0 && nNodeHit < NUM_ALL_NODES && m_bLimbLoss)
{
if(IsRandomChance(50) && AIShared.HideLimb(m_hObject,nNodeHit))
{
AIShared.CreateLimb(m_hObject, nNodeHit, vDir);
// AIShared.CreateLimb(vDir);
//Create an arterial blood spurt
// CreateBloodSpurt(nNodeHit);
}
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE : CCorpse::CalculateHitLimb
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -