📄 destructablemodel.cpp
字号:
// ----------------------------------------------------------------------- //
//
// MODULE : DestructableModel.cpp
//
// PURPOSE : A Model object that replaces it's model with a new model when
// it is damaged and finally destroyed.
//
// CREATED : 10/25/97
//
// ----------------------------------------------------------------------- //
#include "DestructableModel.h"
#include "ObjectUtilities.h"
#include "ClientServerShared.h"
#include "PhysicalAttributes.h"
#include <mbstring.h>
#include "SoundTypes.h"
#include "SFXMsgIds.h"
BEGIN_CLASS(CDestructableModel)
ADD_DESTRUCTABLE_AGGREGATE()
ADD_VISIBLE_FLAG( 1, 0 )
ADD_SOLID_FLAG( 1, 0 )
ADD_GRAVITY_FLAG( 1, 0 )
ADD_SHADOW_FLAG( 1, 0 )
ADD_STRINGPROP_FLAG(InitFilename, "", PF_DIMS | PF_LOCALDIMS)
ADD_STRINGPROP(InitSkin, "")
ADD_VECTORPROP(InitDims)
ADD_STRINGPROP(DamageFilename, "")
ADD_STRINGPROP(DamageSkin, "")
ADD_VECTORPROP(DamageDims) //SCHLEGZ: added damaged state dims
ADD_STRINGPROP(DestroyFilename, "")
ADD_STRINGPROP(DestroySkin, "")
ADD_VECTORPROP(DestroyDims)
ADD_BOOLPROP( DestroyVisible, DTRUE)
ADD_BOOLPROP( DestroySolid, DTRUE)
ADD_BOOLPROP( DestroyGravity, DTRUE)
ADD_REALPROP(HitPoints, 100.0f)
ADD_REALPROP(DamageHitPoints, 50.0f)
ADD_REALPROP(ObjectMass, 100.0f)
ADD_REALPROP(Alpha, 1.0f)
ADD_BOOLPROP(Destructable, DTRUE)
ADD_BOOLPROP(Pushable, DFALSE)
ADD_LONGINTPROP(SurfaceType, SURFTYPE_UNKNOWN)
ADD_REALPROP( ModelScale, 1.0f )
ADD_COLORPROP(TintColor, 0.0f, 0.0f, 0.0f)
ADD_BOOLPROP(Chrome, 0)
ADD_STRINGPROP(SlidingSound, "")
ADD_DEBRIS_AGGREGATE()
END_CLASS_DEFAULT(CDestructableModel, B2BaseClass, NULL, NULL)
#define PUSHSOUNDEXTRATIME 0.1f
#define STANDINGONCHECKTIME 0.1f
// --------------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::CDestructableModel
//
// PURPOSE: constructor
//
// --------------------------------------------------------------------------- //
CDestructableModel::CDestructableModel() : B2BaseClass(OT_MODEL)
{
AddAggregate(&m_damage);
AddAggregate(&m_Debris);
m_fInitHitPoints = 100;
m_fDamagedHitPoints = 50;
m_fMass = 100;
m_fAlpha = 1.0f;
m_fTargetAlpha = 1.0f;
m_bDeadState = DFALSE;
VEC_INIT(m_InitDims);
VEC_INIT(m_DamageDims); //SCHLEGZ: added damaged state dims
VEC_INIT(m_DestroyDims);
m_dwDestroyFlags = 0;
m_hstrDamagedFilename = DNULL;
m_hstrDestroyFilename = DNULL;
m_hstrDamagedSkinName = DNULL;
m_hstrDestroySkinName = DNULL;
m_bDestroyVisible = DTRUE;
m_bDestroySolid = DTRUE;
m_bDestroyGravity = DTRUE;
m_bDestructable = DTRUE;
m_bPushable = DFALSE;
m_dwSurfType = SURFTYPE_UNKNOWN;
m_bChrome = DFALSE;
m_fScale = 1.0f;
VEC_SET(m_vTintColor, 0.0f, 0.0f, 0.0f);
m_fAlphaFadeRate = 0.0f;
m_fLastTime = 0.0f;
m_bSliding = DFALSE;
m_hstrSlidingSound = DNULL;
m_hSlidingSound = DNULL;
VEC_INIT( m_vLastPos );
m_nSlidingFrameCounter = 0;
m_bStandingOn = DFALSE;
m_nStandingOnFrameCounter = 0;
m_fYaw = 0;
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::~CDestructableModel
//
// PURPOSE: destructor
//
// --------------------------------------------------------------------------- //
CDestructableModel::~CDestructableModel()
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return;
if (m_hstrDamagedFilename)
pServerDE->FreeString(m_hstrDamagedFilename);
if (m_hstrDamagedSkinName)
pServerDE->FreeString(m_hstrDamagedSkinName);
if (m_hstrDestroyFilename)
pServerDE->FreeString(m_hstrDestroyFilename);
if (m_hstrDestroySkinName)
pServerDE->FreeString(m_hstrDestroySkinName);
if (m_hstrSlidingSound)
pServerDE->FreeString(m_hstrSlidingSound);
if( m_hSlidingSound )
g_pServerDE->KillSound( m_hSlidingSound );
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::ReadProp()
//
// PURPOSE: Reads properties
//
// --------------------------------------------------------------------------- //
DBOOL CDestructableModel::ReadProp(ObjectCreateStruct *pStruct)
{
if (!g_pServerDE || !pStruct) return DFALSE;
GenericProp genProp;
// Read in the destroyed object props.
if (g_pServerDE->GetPropGeneric("InitFilename", &genProp) == DE_OK)
{
if (genProp.m_String[0]) _mbscpy((unsigned char*)pStruct->m_Filename, (const unsigned char*)genProp.m_String);
}
if (g_pServerDE->GetPropGeneric("InitSkin", &genProp) == DE_OK)
{
if (genProp.m_String[0]) _mbscpy((unsigned char*)pStruct->m_SkinName, (const unsigned char*)genProp.m_String);
}
if (g_pServerDE->GetPropGeneric("InitDims", &genProp) == DE_OK)
{
VEC_COPY(m_InitDims, genProp.m_Vec);
}
// Read in the damaged object props.
if (g_pServerDE->GetPropGeneric("DamageFilename", &genProp) == DE_OK)
{
if (genProp.m_String[0]) m_hstrDamagedFilename = g_pServerDE->CreateString(genProp.m_String);
}
if (g_pServerDE->GetPropGeneric("DamageSkin", &genProp) == DE_OK)
{
if (genProp.m_String[0]) m_hstrDamagedSkinName = g_pServerDE->CreateString(genProp.m_String);
}
if (g_pServerDE->GetPropGeneric("DamageDims", &genProp) == DE_OK)
{
VEC_COPY(m_DamageDims, genProp.m_Vec);
}
// Read in the destroyed object props.
if (g_pServerDE->GetPropGeneric("DestroyFilename", &genProp) == DE_OK)
{
if (genProp.m_String[0]) m_hstrDestroyFilename = g_pServerDE->CreateString(genProp.m_String);
}
if (g_pServerDE->GetPropGeneric("DestroySkin", &genProp) == DE_OK)
{
if (genProp.m_String[0]) m_hstrDestroySkinName = g_pServerDE->CreateString(genProp.m_String);
}
if (g_pServerDE->GetPropGeneric("DestroyDims", &genProp) == DE_OK)
{
VEC_COPY(m_DestroyDims, genProp.m_Vec);
}
if (g_pServerDE->GetPropGeneric("DestroyVisible", &genProp) == DE_OK)
{
m_bDestroyVisible = genProp.m_Bool;
}
if (g_pServerDE->GetPropGeneric("DestroySolid", &genProp) == DE_OK)
{
m_bDestroySolid = genProp.m_Bool;
}
if (g_pServerDE->GetPropGeneric("DestroyGravity", &genProp) == DE_OK)
{
m_bDestroyGravity = genProp.m_Bool;
}
m_dwDestroyFlags = (m_bDestroyVisible ? FLAG_VISIBLE : 0) |
(m_bDestroySolid ? FLAG_SOLID : 0) |
(m_bDestroyGravity ? FLAG_GRAVITY : 0);
if (g_pServerDE->GetPropGeneric("HitPoints", &genProp) == DE_OK)
{
m_fInitHitPoints = genProp.m_Float;
}
if (g_pServerDE->GetPropGeneric("DamageHitPoints", &genProp) == DE_OK)
{
m_fDamagedHitPoints = genProp.m_Float;
}
if (g_pServerDE->GetPropGeneric("ObjectMass", &genProp) == DE_OK)
{
m_fMass = genProp.m_Float;
}
if (g_pServerDE->GetPropGeneric("Alpha", &genProp) == DE_OK)
{
m_fAlpha = m_fTargetAlpha = genProp.m_Float;
}
if (g_pServerDE->GetPropGeneric("Pushable", &genProp) == DE_OK)
{
m_bPushable = genProp.m_Bool;
}
if (g_pServerDE->GetPropGeneric("SurfaceType", &genProp) == DE_OK)
{
m_dwSurfType = (DDWORD)genProp.m_Long;
}
if (g_pServerDE->GetPropGeneric("Destructable", &genProp) == DE_OK)
{
m_bDestructable = genProp.m_Bool;
}
if (g_pServerDE->GetPropGeneric( "Chrome", &genProp ) == DE_OK)
m_bChrome = genProp.m_Bool;
if (g_pServerDE->GetPropGeneric("ModelScale", &genProp) == DE_OK)
{
m_fScale = genProp.m_Float;
}
if (g_pServerDE->GetPropGeneric("TintColor", &genProp) == DE_OK)
{
VEC_COPY(m_vTintColor, genProp.m_Vec);
}
if (g_pServerDE->GetPropGeneric("SlidingSound", &genProp) == DE_OK)
{
if (genProp.m_String[0]) m_hstrSlidingSound = g_pServerDE->CreateString(genProp.m_String);
}
/* if (g_pServerDE->GetPropGeneric("Rotation", &genProp) == DE_OK)
{
m_fYaw = genProp.m_Vec.y;
}
*/
return DTRUE;
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::EngineMessageFn()
//
// PURPOSE: Handles engine messages.
//
// --------------------------------------------------------------------------- //
DDWORD CDestructableModel::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
DDWORD dwRet;
CServerDE* pServerDE = GetServerDE();
switch(messageID)
{
case MID_UPDATE:
{
Update( );
}
break;
case MID_PRECREATE:
{
dwRet = B2BaseClass::EngineMessageFn(messageID, pData, fData);
ObjectCreateStruct* pStruct = (ObjectCreateStruct*)pData;
if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
ReadProp(pStruct);
if (m_bChrome)
{
pStruct->m_Flags |= FLAG_ENVIRONMENTMAP;
}
if (m_bPushable)
{
pStruct->m_Flags |= FLAG_TOUCH_NOTIFY | FLAG_GRAVITY;
}
if (fData == PRECREATE_STRINGPROP)
{
pStruct->m_Flags |= FLAG_GRAVITY | FLAG_SOLID | FLAG_SHADOW | FLAG_VISIBLE | FLAG_TOUCH_NOTIFY | FLAG_MODELGOURAUDSHADE;
}
return dwRet;
}
break;
case MID_INITIALUPDATE:
{
dwRet = B2BaseClass::EngineMessageFn(messageID, pData, fData);
InitialUpdate(( DDWORD )fData );
return dwRet;
}
break;
case MID_TOUCHNOTIFY:
{
TouchNotify(( HOBJECT )pData, fData );
}
break;
case MID_SAVEOBJECT:
{
Save((HMESSAGEWRITE)pData, (DDWORD)fData);
}
break;
case MID_LOADOBJECT:
{
Load((HMESSAGEREAD)pData, (DDWORD)fData);
}
break;
default : break;
}
return B2BaseClass::EngineMessageFn(messageID, pData, fData);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::InitialUpdate
//
// PURPOSE: Initial update.
//
// ----------------------------------------------------------------------- //
void CDestructableModel::InitialUpdate( DDWORD nData )
{
DRotation rRot;
if (nData != INITIALUPDATE_SAVEGAME)
{
// Set object translucency...
DVector vTintColor;
VEC_DIVSCALAR(vTintColor, m_vTintColor, 255.0f);
g_pServerDE->SetObjectColor(m_hObject, vTintColor.x, vTintColor.y,
vTintColor.z, m_fAlpha);
m_damage.Init(m_hObject);
m_damage.SetMaxHitPoints( m_fInitHitPoints );
m_damage.SetHitPoints(m_fInitHitPoints);
m_damage.SetMass(m_fMass);
m_Debris.Init(m_hObject);
// If no damage models, don't allow damage hitpoints
if (!m_hstrDamagedFilename || !m_hstrDamagedSkinName)
{
m_fDamagedHitPoints = 0.0f;
}
m_damage.SetApplyDamagePhysics(m_bPushable);
if (m_bPushable)
{
g_pServerDE->SetBlockingPriority(m_hObject, BLOCKPRIORITY_PUSHABLE);
// Mark this object as moveable
DDWORD dwUsrFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
dwUsrFlags |= USRFLG_MOVEABLE;
g_pServerDE->SetObjectUserFlags(m_hObject, dwUsrFlags);
// Need to be told about all collisions...
g_pServerDE->SetForceIgnoreLimit( m_hObject, 0.0f );
}
else
{
g_pServerDE->SetBlockingPriority(m_hObject, BLOCKPRIORITY_NONPUSHABLE);
}
// Scale the model. If the dims property wasn't set, then scale the dims too...
DVector vScale;
VEC_SET( vScale, m_fScale, m_fScale, m_fScale );
g_pServerDE->ScaleObject( m_hObject, &vScale );
// Try to determine dims based on rotation if InitDims isn't set
if( VEC_MAGSQR( m_InitDims ) == 0.0f )
{
g_pServerDE->GetModelAnimUserDims(m_hObject, &m_InitDims, 0);
g_pServerDE->GetObjectRotation( m_hObject, &rRot );
if( VEC_MAGSQR( rRot.m_Vec ) > 0.0f )
{
RotateDims( &rRot, &m_InitDims);
}
VEC_MULSCALAR( m_InitDims, m_InitDims, m_fScale );
}
g_pServerDE->SetObjectDims(m_hObject, &m_InitDims);
// If the object is less than 10x10x10, then turn off shadows, because the
// shadows will be visible through model...
if( VEC_MAGSQR( m_InitDims ) < 1000.0f )
{
DDWORD dwFlags;
dwFlags = g_pServerDE->GetObjectFlags( m_hObject );
dwFlags &= ~FLAG_SHADOW;
g_pServerDE->SetObjectFlags( m_hObject, dwFlags );
}
// Mark this object as savable
DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
dwFlags |= USRFLG_SAVEABLE;
if (m_bPushable)
{
dwFlags |= USRFLG_SINGULARITY_ATTRACT;
}
dwFlags |= (m_dwSurfType << 24);
g_pServerDE->SetObjectUserFlags(m_hObject, dwFlags);
g_pServerDE->SetDeactivationTime( m_hObject, 1.0f );
if( !m_hstrSlidingSound )
m_hstrSlidingSound = g_pServerDE->CreateString( GetSlidingSound( ));
// Set damage delay for cascading items
if (m_Debris.IsExploding())
{
m_damage.SetDeathDelay(0.25f);
}
HMESSAGEWRITE hMessage = g_pServerDE->StartSpecialEffectMessage(this);
g_pServerDE->WriteToMessageByte( hMessage, SFX_DESTRUCTABLEMODEL );
g_pServerDE->WriteToMessageCompVector( hMessage, &m_InitDims );
g_pServerDE->EndMessage(hMessage);
}
if (nData == INITIALUPDATE_WORLDFILE)
{
DDWORD dwFlags = g_pServerDE->GetObjectFlags(m_hObject);
if (dwFlags & FLAG_GRAVITY)
MoveObjectToGround(m_hObject);
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::Update
//
// PURPOSE: Initial update.
//
// ----------------------------------------------------------------------- //
void CDestructableModel::Update( )
{
DFLOAT fTime, fDeltaTime, fAlphaAdjust;
DVector vPos;
CollisionInfo colInfo;
char *pszSlidingSound;
DBOOL bSlid, bUpdateAgain;
fTime = g_pServerDE->GetTime( );
bUpdateAgain = DFALSE;
// Waiting for death..
if (m_damage.GetHitPoints() <= 0)
{
if (m_damage.IsDead())
HandleDestruction();
else
g_pServerDE->SetNextUpdate(m_hObject, 0.001f);
}
// Update the frame counters...
if( m_nSlidingFrameCounter > 0 )
m_nSlidingFrameCounter--;
if( m_nStandingOnFrameCounter > 0 )
m_nStandingOnFrameCounter--;
// Check if sound is playing because object is sliding...
if( m_bSliding )
{
g_pServerDE->GetObjectPos( m_hObject, &vPos );
// Check if still moving...
bSlid = DFALSE;
if( VEC_DISTSQR( vPos, m_vLastPos ) > 0.1f )
{
VEC_COPY( m_vLastPos, vPos );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -