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

📄 rotatingdoor.cpp

📁 Blood 2全套源码
💻 CPP
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : RotatingDoor.CPP
//
// PURPOSE : A RotatingDoor object
//
// CREATED : 12/3/97
//
// ----------------------------------------------------------------------- //

// Includes...

#include "RotatingDoor.h"
#include "ObjectUtilities.h"
#include "SoundTypes.h"

BEGIN_CLASS(RotatingDoor)
	ADD_REALPROP_FLAG(MoveDist, 0.0f, PF_HIDDEN)	//  hide some of our
	ADD_VECTORPROP_FLAG(MoveDir, PF_HIDDEN)			//  parent's properties
	ADD_VECTORPROP_FLAG(RotationPoint, 0)			//  point to rotate around
	ADD_VECTORPROP_FLAG(RotationAngles, 0)			//  where to rotate to
	ADD_BOOLPROP(BoxPhysics, DFALSE)				// Door does NOT use "box physics"
	ADD_BOOLPROP(PushPlayerBack, DTRUE)		
END_CLASS_DEFAULT(RotatingDoor, Door, NULL, NULL)

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::RotatingDoor()
//
//	PURPOSE:	Initialize object
//
// ----------------------------------------------------------------------- //

RotatingDoor::RotatingDoor() : Door()
{
	VEC_INIT(m_vRotationPoint);
	VEC_INIT(m_vRotationAngles);
	VEC_INIT(m_vOpenAngles);
	VEC_INIT(m_vClosedAngles);
	VEC_INIT(m_vOriginalPos);

	m_nOpenDirX = 0;
	m_nOpenDirY = 0;
	m_nOpenDirZ = 0;

	m_fPitch = 0.0f;
	m_fYaw	 = 0.0f;
	m_fRoll	 = 0.0f;
	m_bPushPlayerBack = DTRUE;
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::EngineMessageFn()
//
//	PURPOSE:	Handler for engine messages
//
// --------------------------------------------------------------------------- //

DDWORD RotatingDoor::EngineMessageFn(DDWORD messageID, void *pData, float fData)
{
	switch (messageID)
	{
		case MID_PRECREATE:
		{
			// Need to call base class to have the object name read in before
			// we call PostPropRead()

			DDWORD dwRet = Door::EngineMessageFn(messageID, pData, fData);

			if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
			{
				ReadProp((ObjectCreateStruct*)pData);
			}

			// Convert speeds from degrees to radians
			m_fSpeed		= MATH_DEGREES_TO_RADIANS(m_fSpeed);
			m_fClosingSpeed	= MATH_DEGREES_TO_RADIANS(m_fClosingSpeed);

			return dwRet;
		}

		case MID_INITIALUPDATE:
		{
			if (fData != INITIALUPDATE_SAVEGAME)
				InitialUpdate();
			break;
		}

		case MID_SAVEOBJECT:
			Save((HMESSAGEWRITE)pData, (DDWORD)fData);
			break;

		case MID_LOADOBJECT:
			Load((HMESSAGEREAD)pData, (DDWORD)fData);
			break;

		default : break;
	}

	return Door::EngineMessageFn(messageID, pData, fData);
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::ReadProp()
//
//	PURPOSE:	Reads RotatingDoor properties
//
// --------------------------------------------------------------------------- //

DBOOL RotatingDoor::ReadProp(ObjectCreateStruct *)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return DFALSE;

	GenericProp genProp;

	if (g_pServerDE->GetPropGeneric("RotationAngles", &genProp) == DE_OK)
	{
		VEC_COPY(m_vRotationAngles, genProp.m_Vec);
	}

	if (g_pServerDE->GetPropGeneric("RotationPoint", &genProp) == DE_OK)
	{
		VEC_COPY(m_vRotationPoint, genProp.m_Vec);
	}

	DVector vTemp;
	pServerDE->GetPropRotationEuler("Rotation", &vTemp);

	m_fPitch = vTemp.x;
	m_fYaw	 = vTemp.y;
	m_fRoll	 = vTemp.z;


	if (g_pServerDE->GetPropGeneric("PushPlayerBack", &genProp) == DE_OK)
	{
		m_bPushPlayerBack = genProp.m_Bool;
	}


	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::InitialUpdate()
//
//	PURPOSE:	First update
//
// ----------------------------------------------------------------------- //

void RotatingDoor::InitialUpdate()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	// Set open/closed angle...

	VEC_SET(m_vClosedAngles, m_fPitch, m_fYaw, m_fRoll);
	m_vOpenAngles.x = DEG2RAD(m_vRotationAngles.x) + m_fPitch;
	m_vOpenAngles.y = DEG2RAD(m_vRotationAngles.y) + m_fYaw;
	m_vOpenAngles.z = DEG2RAD(m_vRotationAngles.z) + m_fRoll;

	
	// Save the object's original position...

	pServerDE->GetObjectPos(m_hObject, &m_vOriginalPos);


	// The door must rotate at least 1 degree...
	
	const DFLOAT c_fMinDelta = DEG2RAD(1.0f);


	// Determine direction to open door in X...

	DFLOAT fOffset = m_vClosedAngles.x - m_vOpenAngles.x;

	if (fOffset > c_fMinDelta)
	{
		m_nOpenDirX = -1;
	}
	else if (fOffset < c_fMinDelta)
	{
		m_nOpenDirX = 1;
	}


	// Determine direction to open door in Y...

	fOffset = m_vClosedAngles.y - m_vOpenAngles.y;

	if (fOffset > c_fMinDelta)
	{
		m_nOpenDirY = -1;
	}
	else if (fOffset < c_fMinDelta)
	{
		m_nOpenDirY = 1;
	}


	// Determine direction to open door in Z...

	fOffset = m_vClosedAngles.z - m_vOpenAngles.z;

	if (fOffset > c_fMinDelta)
	{
		m_nOpenDirZ = -1;
	}
	else if (fOffset < c_fMinDelta)
	{
		m_nOpenDirZ = 1;
	}

	if (m_bPushPlayerBack)
		pServerDE->SetForceIgnoreLimit(m_hObject, 0.0f);
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::Opening()
//
//	PURPOSE:	Handles the RotatingDoor opening state
//
// --------------------------------------------------------------------------- //

void RotatingDoor::Opening()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	if (!m_bStartedMoving)
	{
		m_bStartedMoving = DTRUE;
		StartSound(m_hstrOpenBusySound, DTRUE);
		SetPortalState(DTRUE);
	}

	DBOOL bDoneInX = DFALSE;
	DBOOL bDoneInY = DFALSE;
	DBOOL bDoneInZ = DFALSE;

	// Keep track of current rotation and position in case the door is blocked
	DRotation rCurRot;
	DVector vCurPos;
	pServerDE->GetObjectRotation(m_hObject, &rCurRot);
	pServerDE->GetObjectPos(m_hObject, &vCurPos);
	DFLOAT fLastPitch	= m_fPitch;
	DFLOAT fLastYaw		= m_fYaw;
	DFLOAT fLastRoll	= m_fRoll;


	// Calculate new pitch, yaw, and roll...
	bDoneInX = CalcAngle(m_fPitch, m_vClosedAngles.x, m_vOpenAngles.x, m_nOpenDirX, m_fSpeed);
	bDoneInY = CalcAngle(m_fYaw,   m_vClosedAngles.y, m_vOpenAngles.y, m_nOpenDirY, m_fSpeed);
	bDoneInZ = CalcAngle(m_fRoll,  m_vClosedAngles.z, m_vOpenAngles.z, m_nOpenDirZ, m_fSpeed);

	
	// Rotate the object...
	DoRotation();

	if (m_bDoorBlocked)
	{
		pServerDE->SetObjectRotation(m_hObject, &rCurRot);	
		pServerDE->MoveObject(m_hObject, &vCurPos);
		m_fPitch	= fLastPitch;
		m_fYaw		= fLastYaw;
		m_fRoll		= fLastRoll;
	}
	else if (bDoneInX && bDoneInY && bDoneInZ)
	{
		if (m_hstrOpenStopSound)
        {
			PlaySoundFromObject(m_hObject, pServerDE->GetStringData(m_hstrOpenStopSound), 1000, SOUNDPRIORITY_MISC_MEDIUM);
        }    
		SetOpen();
	}
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::Closing()
//
//	PURPOSE:	Handles the RotatingDoor closing state
//
// --------------------------------------------------------------------------- //

void RotatingDoor::Closing()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	DBOOL bDoneInX = DFALSE;
	DBOOL bDoneInY = DFALSE;
	DBOOL bDoneInZ = DFALSE;

	// Keep track of current rotation and position in case the door is blocked
	DRotation rCurRot;
	DVector vCurPos;
	pServerDE->GetObjectRotation(m_hObject, &rCurRot);
	pServerDE->GetObjectPos(m_hObject, &vCurPos);
	DFLOAT fLastPitch	= m_fPitch;
	DFLOAT fLastYaw		= m_fYaw;
	DFLOAT fLastRoll	= m_fRoll;

	// Calculate new pitch, yaw, and roll...
	bDoneInX = CalcAngle(m_fPitch, m_vOpenAngles.x, m_vClosedAngles.x, -m_nOpenDirX, m_fClosingSpeed);
	bDoneInY = CalcAngle(m_fYaw,   m_vOpenAngles.y, m_vClosedAngles.y, -m_nOpenDirY, m_fClosingSpeed);
	bDoneInZ = CalcAngle(m_fRoll,  m_vOpenAngles.z, m_vClosedAngles.z, -m_nOpenDirZ, m_fClosingSpeed);

	
	// Rotate the object...
	DoRotation();

	if (m_bDoorBlocked)
	{
		pServerDE->SetObjectRotation(m_hObject, &rCurRot);	
		pServerDE->MoveObject(m_hObject, &vCurPos);
		m_fPitch	= fLastPitch;
		m_fYaw		= fLastYaw;
		m_fRoll		= fLastRoll;
	}
	else if (bDoneInX && bDoneInY && bDoneInZ)
	{
		if (m_hstrCloseStopSound)
        {
			PlaySoundFromObject(m_hObject, pServerDE->GetStringData(m_hstrCloseStopSound), 1000, SOUNDPRIORITY_MISC_MEDIUM);
        
        }            
		SetClosed();
	}
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::DoRotation()
//
//	PURPOSE:	Do the rotation calculation based on the current values of
//				m_fPitch, m_fYaw, and m_fRoll
//
// --------------------------------------------------------------------------- //

void RotatingDoor::DoRotation()
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	DVector vDes, vPoint, vPos;
	pServerDE->GetObjectPos(m_hObject, &vPos);

	DRotation rRot;
	pServerDE->SetupEuler(&rRot, m_fPitch, m_fYaw, m_fRoll);

	VEC_SUB(vPoint, m_vOriginalPos, m_vRotationPoint);

	DMatrix mat;
	pServerDE->SetupRotationMatrix(&mat, &rRot);

	MatVMul_H(&vDes, &mat, &vPoint);

	DVector vOriginTranslation;
	VEC_SUB(vOriginTranslation, vDes, vPoint);
	VEC_ADD(vPos, m_vOriginalPos, vOriginTranslation);

	// Set the object's new rotation and position...

	pServerDE->RotateObject(m_hObject, &rRot);	
	pServerDE->MoveObject(m_hObject, &vPos);
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::CalcAngle()
//
//	PURPOSE:	Calculate the new value of fAngle
//
// --------------------------------------------------------------------------- //

DBOOL RotatingDoor::CalcAngle(DFLOAT & fAngle, DFLOAT fInitial, DFLOAT fTarget, int nDir, DFLOAT fSpeed)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return DFALSE;

	DBOOL bRet = DFALSE; // Are we at the target angle?

	DFLOAT fPercent = 1.0f - (fTarget - fAngle) / (fTarget - fInitial);
	DFLOAT fAmount = GetWaveValue(fSpeed, fPercent, m_dwWaveform) * pServerDE->GetFrameTime();

	// Calculate percentage moved so far
	if (nDir != 0)
	{
		if (nDir > 0)
		{
			if (fAngle < fTarget)
			{
				fAngle += fAmount;
			}
			else
			{
				fAngle = fTarget;
				bRet   = DTRUE;
			}
		}
		else
		{
			if (fAngle > fTarget)
			{
				fAngle -= fAmount;
			}
			else
			{
				fAngle = fTarget;
				bRet   = DTRUE;
			}
		}
	}

	if (nDir != 0)
	{
		if (nDir > 0)
		{
			if (fAngle < fTarget)
			{
				fAngle += fAmount;
			}
			else
			{
				fAngle = fTarget;
				bRet   = DTRUE;
			}
		}
		else
		{
			if (fAngle > fTarget)
			{
				fAngle -= fAmount;
			}
			else
			{
				fAngle = fTarget;
				bRet   = DTRUE;
			}
		}
	}
	else
	{
		bRet = DTRUE;
	}

	return bRet;
}



// ----------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::Save
//
//	PURPOSE:	Save the object
//
// ----------------------------------------------------------------------- //

void RotatingDoor::Save(HMESSAGEWRITE hWrite, DDWORD dwSaveFlags)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !hWrite) return;

	pServerDE->WriteToMessageVector(hWrite, &m_vRotationAngles);	
	pServerDE->WriteToMessageVector(hWrite, &m_vRotationPoint);
	pServerDE->WriteToMessageVector(hWrite, &m_vOpenAngles);	
	pServerDE->WriteToMessageVector(hWrite, &m_vClosedAngles);	
	pServerDE->WriteToMessageVector(hWrite, &m_vOriginalPos);	

	pServerDE->WriteToMessageDWord(hWrite, m_nOpenDirX);
	pServerDE->WriteToMessageDWord(hWrite, m_nOpenDirY);
	pServerDE->WriteToMessageDWord(hWrite, m_nOpenDirZ);

	pServerDE->WriteToMessageFloat(hWrite, m_fPitch);
	pServerDE->WriteToMessageFloat(hWrite, m_fYaw);
	pServerDE->WriteToMessageFloat(hWrite, m_fRoll);

	pServerDE->WriteToMessageByte(hWrite, m_bPushPlayerBack);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	RotatingDoor::Load
//
//	PURPOSE:	Load the object
//
// ----------------------------------------------------------------------- //

void RotatingDoor::Load(HMESSAGEREAD hRead, DDWORD dwLoadFlags)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !hRead) return;

	pServerDE->ReadFromMessageVector(hRead, &m_vRotationAngles);	
	pServerDE->ReadFromMessageVector(hRead, &m_vRotationPoint);
	pServerDE->ReadFromMessageVector(hRead, &m_vOpenAngles);	
	pServerDE->ReadFromMessageVector(hRead, &m_vClosedAngles);	
	pServerDE->ReadFromMessageVector(hRead, &m_vOriginalPos);	

	m_nOpenDirX = (short)pServerDE->ReadFromMessageDWord(hRead);
	m_nOpenDirY = (short)pServerDE->ReadFromMessageDWord(hRead);
	m_nOpenDirZ = (short)pServerDE->ReadFromMessageDWord(hRead);

	m_fPitch	= pServerDE->ReadFromMessageFloat(hRead);
	m_fYaw		= pServerDE->ReadFromMessageFloat(hRead);
	m_fRoll		= pServerDE->ReadFromMessageFloat(hRead);

	m_bPushPlayerBack = pServerDE->ReadFromMessageByte(hRead);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -