⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 destructablemodel.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ----------------------------------------------------------------------- //
//
// 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 + -