📄 destructablemodel.cpp
字号:
// Check if still on something...
if( m_bStandingOn )
{
// Start a sound, if it's not going already...
if( !m_hSlidingSound )
{
pszSlidingSound = g_pServerDE->GetStringData( m_hstrSlidingSound );
if( pszSlidingSound )
{
m_hSlidingSound = PlaySoundFromObject( m_hObject, pszSlidingSound, 1000.0f, SOUNDPRIORITY_MISC_LOW, DTRUE, DTRUE );
}
}
bSlid = DTRUE;
// Don't stop the sliding sound for at least a little
// time after this...
m_nSlidingFrameCounter = 2;
bUpdateAgain = DTRUE;
}
}
// Not sliding any more...
if( !bSlid && m_nSlidingFrameCounter == 0 )
{
m_bSliding = DFALSE;
if( m_hSlidingSound )
{
g_pServerDE->KillSound( m_hSlidingSound );
m_hSlidingSound = DNULL;
}
}
else
{
bUpdateAgain = DTRUE;
}
}
// Check if still standing on something...
if( m_bStandingOn )
{
// Check if standing on something...
g_pServerDE->GetStandingOn( m_hObject, &colInfo );
if( !colInfo.m_hObject && m_nStandingOnFrameCounter == 0 )
{
m_bStandingOn = DFALSE;
}
}
// Adjust the alpha...
if( fabs( m_fAlpha - m_fTargetAlpha ) > 0.0001f )
{
fDeltaTime = fTime - m_fLastTime;
m_fLastTime = fTime;
fAlphaAdjust = m_fAlphaFadeRate * fDeltaTime;
// Don't pass the target up...
if( fabs( fAlphaAdjust ) >= fabs( m_fTargetAlpha - m_fAlpha ))
{
m_fAlpha = m_fTargetAlpha;
}
else
{
m_fAlpha += fAlphaAdjust;
bUpdateAgain = DTRUE;
}
// 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);
}
// Schedule next update...
if( bUpdateAgain )
{
g_pServerDE->SetNextUpdate( m_hObject, 0.001f );
g_pServerDE->SetDeactivationTime( m_hObject, 1.0f );
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::TouchNotify
//
// PURPOSE: Handles getting touched by something.
//
// ----------------------------------------------------------------------- //
void CDestructableModel::TouchNotify( HOBJECT hObj, DFLOAT fForce )
{
CollisionInfo colInfo;
DBOOL bDoUpdate;
bDoUpdate = DFALSE;
// If a ai or player is pushing us, and we are on the ground, then
// start playing a sliding sound...
if( !m_bSliding && IsBaseCharacter( hObj ))
{
m_bSliding = DTRUE;
m_nSlidingFrameCounter = 2;
bDoUpdate = DTRUE;
}
// Check if standing on something. If not, then we'll catch that in the update..
g_pServerDE->GetStandingOn( m_hObject, &colInfo );
if( fabs( fForce ) > 0.0f && colInfo.m_hObject )
{
m_bStandingOn = DTRUE;
m_nStandingOnFrameCounter = 2;
bDoUpdate = DTRUE;
}
// Schedule next update...
if( bDoUpdate )
{
g_pServerDE->SetNextUpdate( m_hObject, 0.001f );
g_pServerDE->SetDeactivationTime( m_hObject, 1.0f );
}
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::ObjectMessageFn()
//
// PURPOSE: Processes a message from a server object.
//
// --------------------------------------------------------------------------- //
DDWORD CDestructableModel::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
{
CServerDE* pServerDE = GetServerDE();
switch(messageID)
{
case MID_DAMAGE:
{
DDWORD dwRet = B2BaseClass::ObjectMessageFn(hSender, messageID, hRead);
HandleDamage();
return dwRet;
// Set an update so we can check for damage.
//pServerDE->SetNextUpdate(m_hObject, 0.001f);
break;
}
case MID_TRIGGER:
{
HSTRING hMsg = g_pServerDE->ReadFromMessageHString(hRead);
char *pMsg = g_pServerDE->GetStringData(hMsg);
HandleTriggerMessage( pMsg );
pServerDE->FreeString(hMsg);
break;
}
}
return B2BaseClass::ObjectMessageFn(hSender, messageID, hRead);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::GetSlidingSound
//
// PURPOSE: Choose the sliding sound based on the debris type.
//
// ----------------------------------------------------------------------- //
char *CDestructableModel::GetSlidingSound( )
{
char *pszSlidingSound;
pszSlidingSound = DNULL;
switch( m_Debris.GetType( ))
{
case SURFTYPE_STONE:
pszSlidingSound = "sounds\\events\\pushstone.wav";
break;
case SURFTYPE_METAL:
pszSlidingSound = "sounds\\events\\pushmetal.wav";
break;
case SURFTYPE_WOOD:
pszSlidingSound = "sounds\\events\\pushwood.wav";
break;
case SURFTYPE_TERRAIN:
pszSlidingSound = "sounds\\events\\pushterrain.wav";
break;
case SURFTYPE_PLASTIC:
pszSlidingSound = "sounds\\events\\pushplastic.wav";
break;
case SURFTYPE_GLASS:
pszSlidingSound = "sounds\\events\\pushglass.wav";
break;
case SURFTYPE_FLESH:
pszSlidingSound = "sounds\\events\\pushflesh.wav";
break;
case SURFTYPE_LIQUID:
pszSlidingSound = "sounds\\events\\pushliquid.wav";
break;
case SURFTYPE_ENERGY:
pszSlidingSound = "sounds\\events\\pushenergy.wav";
break;
default:
pszSlidingSound = "sounds\\events\\pushwood.wav";
break;
}
return pszSlidingSound;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::Save
//
// PURPOSE: Save the object
//
// ----------------------------------------------------------------------- //
void CDestructableModel::HandleTriggerMessage( char *pMsg )
{
int nArgs;
char tokenSpace[64*20];
char *pTokens[64];
char *pCommand, *pCommandPos;
DFLOAT fFadeTime;
DBOOL bMore;
pCommand = pMsg;
bMore = DTRUE;
while( bMore )
{
bMore = g_pServerDE->Parse( pMsg, &pCommandPos, tokenSpace, pTokens, &nArgs );
// Handle the alpha change command...
if( _mbsicmp((const unsigned char*) pTokens[0], (const unsigned char*)"Alpha" ) == 0 && nArgs > 1 )
{
// Get the new alpha value...
m_fTargetAlpha = ( DFLOAT )atof( pTokens[1] );
// Get the optional alpha fade time...
if( nArgs == 3 )
fFadeTime = ( DFLOAT )atof( pTokens[2] );
else
fFadeTime = 0.0f;
if( fFadeTime > 0.0f )
m_fAlphaFadeRate = ( m_fTargetAlpha - m_fAlpha ) / fFadeTime;
else
m_fAlphaFadeRate = 1.0e10;
m_fLastTime = g_pServerDE->GetTime( );
g_pServerDE->SetNextUpdate( m_hObject, 0.01f );
g_pServerDE->SetDeactivationTime( m_hObject, 1.0f );
}
pCommand = pCommandPos;
}
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::HandleDamage()
//
// PURPOSE: Processes a damage message...
//
// --------------------------------------------------------------------------- //
void CDestructableModel::HandleDamage()
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return;
if (!m_bDeadState && m_bDestructable)
{
if (m_damage.GetHitPoints() <= 0) // m_damage.IsDead())
{
// Set next update so we can wait for the cascade delay.
pServerDE->SetNextUpdate(m_hObject, 0.001f);
// HandleDestruction();
}
else if (m_fDamagedHitPoints > 0 && m_damage.GetHitPoints() <= m_fDamagedHitPoints)
{
if (m_hstrDamagedFilename || m_hstrDamagedSkinName)
pServerDE->SetModelFilenames(m_hObject,
pServerDE->GetStringData(m_hstrDamagedFilename),
pServerDE->GetStringData(m_hstrDamagedSkinName));
DVector vScale;
VEC_SET( vScale, m_fScale, m_fScale, m_fScale );
pServerDE->ScaleObject( m_hObject, &vScale );
if( VEC_MAG( m_DamageDims ) == 0.0f )
{
pServerDE->GetModelAnimUserDims(m_hObject, &m_DamageDims, 0);
VEC_MULSCALAR( m_DamageDims, m_DamageDims, m_fScale );
}
pServerDE->SetObjectDims(m_hObject,&m_DamageDims); //SCHLEGZ: added damaged dims
// If the object is less than 20x20x20, then turn off shadows, because the
// shadows will be visible through model...
if( VEC_MAGSQR( m_DamageDims ) < 8000.0f )
{
DDWORD dwFlags;
dwFlags = g_pServerDE->GetObjectFlags( m_hObject );
dwFlags &= ~FLAG_SHADOW;
g_pServerDE->SetObjectFlags( m_hObject, dwFlags );
}
m_fDamagedHitPoints = 0;
HMESSAGEWRITE hMessage = pServerDE->StartSpecialEffectMessage(this);
pServerDE->WriteToMessageByte( hMessage, SFX_DESTRUCTABLEMODEL );
pServerDE->WriteToMessageCompVector( hMessage, &m_DamageDims );
pServerDE->EndMessage(hMessage);
}
}
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::HandleDestruction()
//
// PURPOSE: Handles the object's destruction
//
// --------------------------------------------------------------------------- //
void CDestructableModel::HandleDestruction()
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return;
m_bDeadState = DTRUE;
// No destroyed filenames, so remove
if (!m_hstrDestroyFilename && !m_hstrDestroySkinName)
{
pServerDE->RemoveObject(m_hObject);
}
else
{
pServerDE->SetModelFilenames(m_hObject,
pServerDE->GetStringData(m_hstrDestroyFilename),
pServerDE->GetStringData(m_hstrDestroySkinName));
DVector vScale;
VEC_SET( vScale, m_fScale, m_fScale, m_fScale );
pServerDE->ScaleObject( m_hObject, &vScale );
pServerDE->SetObjectFlags(m_hObject, m_dwDestroyFlags);
if (VEC_MAG(m_DestroyDims) == 0.0f)
{
pServerDE->GetModelAnimUserDims(m_hObject, &m_DestroyDims, 0);
VEC_MULSCALAR( m_DestroyDims, m_DestroyDims, m_fScale );
}
pServerDE->SetObjectDims(m_hObject, &m_DestroyDims);
// If the object is less than 20x20x20, then turn off shadows, because the
// shadows will be visible through model...
if( VEC_MAGSQR( m_DestroyDims ) < 8000.0f )
{
DDWORD dwFlags;
dwFlags = g_pServerDE->GetObjectFlags( m_hObject );
dwFlags &= ~FLAG_SHADOW;
g_pServerDE->SetObjectFlags( m_hObject, dwFlags );
}
HMESSAGEWRITE hMessage = pServerDE->StartSpecialEffectMessage(this);
pServerDE->WriteToMessageByte( hMessage, SFX_DESTRUCTABLEMODEL );
pServerDE->WriteToMessageCompVector( hMessage, &m_DestroyDims );
pServerDE->EndMessage(hMessage);
}
// Create the debris
DVector vDir;
m_damage.GetLastDamageDirection(&vDir);
m_Debris.Create(vDir, m_damage.GetLastDamageAmount());
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::RotateDims
//
// PURPOSE: Try to adjust the dims based on the rotation in m_fYaw
//
// ----------------------------------------------------------------------- //
void CDestructableModel::RotateDims( DRotation *prRot, DVector *pvDims )
{
DVector vPt[8], vDims;
DMatrix mMat;
int i;
float fVal;
g_pServerDE->SetupRotationMatrix( &mMat, prRot );
VEC_SET( vPt[0], pvDims->x, pvDims->y, pvDims->z );
VEC_SET( vPt[1], pvDims->x, pvDims->y, -pvDims->z );
VEC_SET( vPt[2], pvDims->x, -pvDims->y, pvDims->z );
VEC_SET( vPt[3], pvDims->x, -pvDims->y, -pvDims->z );
VEC_SET( vPt[4], -pvDims->x, pvDims->y, pvDims->z );
VEC_SET( vPt[5], -pvDims->x, pvDims->y, -pvDims->z );
VEC_SET( vPt[6], -pvDims->x, -pvDims->y, pvDims->z );
VEC_SET( vPt[7], -pvDims->x, -pvDims->y, -pvDims->z );
VEC_INIT( vDims );
for( i = 0; i < 8; i++ )
{
MatVMul_InPlace( &mMat, &vPt[i] );
fVal = ( float )fabs( vPt[i].x );
if( vDims.x < fVal )
vDims.x = fVal;
fVal = ( float )fabs( vPt[i].y );
if( vDims.y < fVal )
vDims.y = fVal;
fVal = ( float )fabs( vPt[i].z );
if( vDims.z < fVal )
vDims.z = fVal;
}
VEC_COPY( *pvDims, vDims );
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::Save
//
// PURPOSE: Save the object
//
// ----------------------------------------------------------------------- //
void CDestructableModel::Save(HMESSAGEWRITE hWrite, DDWORD dwSaveGame)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE || !hWrite) return;
pServerDE->WriteToMessageHString(hWrite, m_hstrDamagedFilename);
pServerDE->WriteToMessageHString(hWrite, m_hstrDamagedSkinName);
pServerDE->WriteToMessageHString(hWrite, m_hstrDestroyFilename);
pServerDE->WriteToMessageHString(hWrite, m_hstrDestroySkinName);
pServerDE->WriteToMessageVector(hWrite, &m_InitDims);
pServerDE->WriteToMessageVector(hWrite, &m_DamageDims);
pServerDE->WriteToMessageVector(hWrite, &m_DestroyDims);
pServerDE->WriteToMessageDWord(hWrite, m_dwDestroyFlags);
pServerDE->WriteToMessageByte(hWrite, m_bDeadState);
pServerDE->WriteToMessageFloat(hWrite, m_fInitHitPoints);
pServerDE->WriteToMessageFloat(hWrite, m_fDamagedHitPoints);
pServerDE->WriteToMessageFloat(hWrite, m_fMass);
pServerDE->WriteToMessageFloat(hWrite, m_fAlpha);
pServerDE->WriteToMessageFloat(hWrite, m_fYaw);
pServerDE->WriteToMessageByte(hWrite, m_bDestroyVisible);
pServerDE->WriteToMessageByte(hWrite, m_bDestroySolid);
pServerDE->WriteToMessageByte(hWrite, m_bDestroyGravity);
pServerDE->WriteToMessageByte(hWrite, m_bDestructable);
pServerDE->WriteToMessageByte(hWrite, m_bPushable);
pServerDE->WriteToMessageDWord(hWrite, m_dwSurfType);
pServerDE->WriteToMessageByte(hWrite, m_bChrome);
pServerDE->WriteToMessageFloat( hWrite, m_fScale );
pServerDE->WriteToMessageVector(hWrite, &m_vTintColor);
pServerDE->WriteToMessageFloat(hWrite, m_fTargetAlpha);
pServerDE->WriteToMessageFloat(hWrite, m_fAlphaFadeRate);
pServerDE->WriteToMessageFloat(hWrite, m_fLastTime);
pServerDE->WriteToMessageHString(hWrite, m_hstrSlidingSound);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CDestructableModel::Load
//
// PURPOSE: Load the object
//
// ----------------------------------------------------------------------- //
void CDestructableModel::Load(HMESSAGEREAD hRead, DDWORD dwLoadGame)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE || !hRead) return;
m_hstrDamagedFilename = pServerDE->ReadFromMessageHString(hRead);
m_hstrDamagedSkinName = pServerDE->ReadFromMessageHString(hRead);
m_hstrDestroyFilename = pServerDE->ReadFromMessageHString(hRead);
m_hstrDestroySkinName = pServerDE->ReadFromMessageHString(hRead);
pServerDE->ReadFromMessageVector(hRead, &m_InitDims);
pServerDE->ReadFromMessageVector(hRead, &m_DamageDims);
pServerDE->ReadFromMessageVector(hRead, &m_DestroyDims);
m_dwDestroyFlags = pServerDE->ReadFromMessageDWord(hRead);
m_bDeadState = pServerDE->ReadFromMessageByte(hRead);
m_fInitHitPoints = pServerDE->ReadFromMessageFloat(hRead);
m_fDamagedHitPoints = pServerDE->ReadFromMessageFloat(hRead);
m_fMass = pServerDE->ReadFromMessageFloat(hRead);
m_fAlpha = pServerDE->ReadFromMessageFloat(hRead);
m_fYaw = pServerDE->ReadFromMessageFloat(hRead);
m_bDestroyVisible = pServerDE->ReadFromMessageByte(hRead);
m_bDestroySolid = pServerDE->ReadFromMessageByte(hRead);
m_bDestroyGravity = pServerDE->ReadFromMessageByte(hRead);
m_bDestructable = pServerDE->ReadFromMessageByte(hRead);
m_bPushable = pServerDE->ReadFromMessageByte(hRead);
m_dwSurfType = pServerDE->ReadFromMessageDWord(hRead);
m_bChrome = pServerDE->ReadFromMessageByte(hRead);
m_fScale = pServerDE->ReadFromMessageFloat( hRead );
pServerDE->ReadFromMessageVector(hRead, &m_vTintColor);
m_fTargetAlpha = pServerDE->ReadFromMessageFloat(hRead);
m_fAlphaFadeRate = pServerDE->ReadFromMessageFloat(hRead);
m_fLastTime = pServerDE->ReadFromMessageFloat(hRead);
m_hstrSlidingSound = pServerDE->ReadFromMessageHString(hRead);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -