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

📄 volumebrush.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : VolumeBrush.cpp
//
// PURPOSE : VolumeBrush implementation
//
// CREATED : 1/29/98
//
// ----------------------------------------------------------------------- //

#include "VolumeBrush.h"
#include "cpp_server_de.h"
#include "ObjectUtilities.h"
#include "PolyGrid.h"
#include "BaseCharacter.h"
#include <stdio.h>
#include "ClientServerShared.h"
#include "SFXMsgIds.h"


void BPrint(char*);

#define UPDATE_DELTA			0.1f
#define DAMAGE_UPDATE_DELTA		0.1f
#define LIQUID_GRAVITY			-200.0f
#define TRIGGER_MSG_ON			"ON"
#define TRIGGER_MSG_OFF			"OFF"
#define TRIGGER_MSG_TOGGLE		"TOGGLE"


BEGIN_CLASS(VolumeBrush)
	ADD_VISIBLE_FLAG(0, 0)
	ADD_REALPROP(Viscosity, 0.0f)
	ADD_BOOLPROP(Hidden, DFALSE)
	ADD_BOOLPROP(ShowSurface, DTRUE)
    ADD_STRINGPROP(SpriteSurfaceName, "")   
	ADD_BOOLPROP(FogEnable, DFALSE)
    ADD_REALPROP(FogFarZ, 300.0f)   
    ADD_REALPROP(FogNearZ,-100.0f)   
    ADD_COLORPROP(FogColor, 0.0f, 0.0f, 0.0f)   
    ADD_REALPROP(XScaleMin, 15.0f)   
    ADD_REALPROP(XScaleMax, 25.0f)   
    ADD_REALPROP(YScaleMin, 15.0f)   
    ADD_REALPROP(YScaleMax, 25.0f)   
    ADD_REALPROP(XScaleDuration, 60.0f)   
    ADD_REALPROP(YScaleDuration, 60.0f)   
	ADD_REALPROP(SurfaceHeight, 2.0f)
    ADD_COLORPROP(SurfaceColor1, 255.0f, 255.0f, 255.0f)   
    ADD_COLORPROP(SurfaceColor2, 255.0f, 255.0f, 255.0f)   
	ADD_REALPROP(SurfaceAlpha, 0.7f)
	ADD_LONGINTPROP(Code, CC_NOTHING)
	ADD_VECTORPROP_VAL(Current, 0.0f, 0.0f, 0.0f)
	ADD_REALPROP(Damage, 0.0f)
	ADD_LONGINTPROP(DamageType, DAMAGE_TYPE_NORMAL)
	ADD_LONGINTPROP(NumSurfacePolies, 160)
	ADD_BOOLPROP(Locked, DFALSE)
	ADD_BOOLPROP(UnlockKeyRemove, DFALSE)
	ADD_STRINGPROP(UnlockKeyName, "")
END_CLASS_DEFAULT(VolumeBrush, B2BaseClass, NULL, NULL)

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

VolumeBrush::VolumeBrush() : B2BaseClass(OT_CONTAINER)
{
	m_hPlayerClass		= DNULL;
	m_dwSaveFlags		= 0;
	m_eContainerCode	= CC_NOTHING;
	m_fDamage			= 0.0f;
	m_nDamageType		= DAMAGE_TYPE_NORMAL;
	m_bShowSurface		= DTRUE;
	m_fSurfaceHeight	= 2.0f;
	m_fSurfaceAlpha		= 0.7f;
	m_fViscosity		= 0.0f;
	m_hSurfaceObj		= DNULL;
	m_bHidden			= DFALSE;
	m_fGravity			= LIQUID_GRAVITY;
	m_fLastDamageTime	= 0.0f;

	VEC_INIT(m_vLastPos);
	VEC_INIT(m_vCurrent);

	m_bFogEnable	= DFALSE;
	m_fFogFarZ		= 300.0f;
	m_fFogNearZ		= -100.0f;
	VEC_INIT(m_vFogColor);

	// Surface related stuff...

	m_fXScaleMin = 15.0f;
	m_fXScaleMax = 25.0f;
	m_fYScaleMin = 15.0f;
	m_fYScaleMax = 25.0f;
	m_fXScaleDuration = 10.0f;
	m_fYScaleDuration = 10.0f;
	m_hstrSurfaceSprite = DNULL;

	m_dwNumSurfacePolies = 160;

	VEC_SET(m_vSurfaceColor1, 255.0f, 255.0f, 255.0f);
	VEC_SET(m_vSurfaceColor2, 255.0f, 255.0f, 255.0f);

	m_dwFlags = FLAG_TOUCH_NOTIFY | FLAG_FULLPOSITIONRES | FLAG_GOTHRUWORLD | FLAG_FORCECLIENTUPDATE;
	m_bLocked = DFALSE;
	m_bUnlockKeyRemove = DFALSE;
	m_hstrKeyName = DNULL;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	VolumeBrush::~VolumeBrush
//
//	PURPOSE:	Deallocate
//
// ----------------------------------------------------------------------- //

VolumeBrush::~VolumeBrush()
{ 
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	if (m_hstrSurfaceSprite)
	{
		pServerDE->FreeString(m_hstrSurfaceSprite);
	}
	if (m_hstrKeyName)
	{
		pServerDE->FreeString(m_hstrKeyName);
	}
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	VolumeBrush::EngineMessageFn
//
//	PURPOSE:	Handle engine messages
//
// ----------------------------------------------------------------------- //

DDWORD VolumeBrush::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
	switch(messageID)
	{
		case MID_UPDATE:
		{
			Update();
			break;
		}

		case MID_AFFECTPHYSICS:
		{
			UpdatePhysics((ContainerPhysics*)pData);
			break;
		}

		case MID_PRECREATE:
		{
			// Need to call base class to have the object name read in before
			// we call PostPropRead()

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

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

			ObjectCreateStruct* pStruct = (ObjectCreateStruct*)pData;
			
			if (pStruct)
			{
				pStruct->m_Flags |= m_dwFlags;
				pStruct->m_ObjectType = OT_CONTAINER;
				_mbscpy((unsigned char*)pStruct->m_Filename, (const unsigned char*)pStruct->m_Name);
				pStruct->m_SkinName[0] = '\0';
				pStruct->m_ContainerCode = (D_WORD)m_eContainerCode;
			}
			return dwRet;
		}
		break;

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

			CacheFiles();
			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:	VolumeBrush::ObjectMessageFn()
//
//	PURPOSE:	Handler for server object messages.
//
// --------------------------------------------------------------------------- //

DDWORD VolumeBrush::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
{
	CServerDE* pServerDE = GetServerDE();
	switch (messageID)
	{
		case MID_TRIGGER:
		{
			HSTRING hMsg = pServerDE->ReadFromMessageHString(hRead);
			HandleTrigger(hSender, hMsg);
			pServerDE->FreeString(hMsg);
			break;
		}

		case MID_KEYQUERYRESPONSE:
		{
			HSTRING hItemName = pServerDE->ReadFromMessageHString(hRead);
			DBOOL	bHaveItem = (DBOOL)pServerDE->ReadFromMessageByte(hRead);

			// Check the key & locked status
			if (m_bLocked && bHaveItem && pServerDE->CompareStringsUpper(hItemName, m_hstrKeyName))
			{
				m_bLocked = DFALSE;

				// Key is no longer needed, tell the sender to remove it
//				if (m_bUnlockKeyRemove)
//				{
//					HMESSAGEWRITE hMessage = pServerDE->StartMessageToObject((LPBASECLASS)this, hSender, MID_KEYREMOVE);
//					pServerDE->WriteToMessageHString(hMessage, m_hstrKeyName);
//					pServerDE->EndMessage(hMessage);
// 				}
			}
			pServerDE->FreeString(hItemName);
			break;
		}
		break;
	}
	
	return B2BaseClass::ObjectMessageFn(hSender, messageID, hRead);
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	VolumeBrush::TriggerMsg()
//
//	PURPOSE:	Handler for volume brush trigger messages.
//
// --------------------------------------------------------------------------- //

void VolumeBrush::HandleTrigger(HOBJECT hSender, HSTRING hMsg)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	char* pMsg = pServerDE->GetStringData(hMsg);
	if (!pMsg || !pMsg[0]) return;

	DBOOL bToggle = DFALSE;

	if (_mbsicmp((const unsigned char*)pMsg, (const unsigned char*)TRIGGER_MSG_TOGGLE) == 0)
	{
		bToggle = DTRUE;
	}

	if ((bToggle && m_bHidden) || _mbsicmp((const unsigned char*)pMsg, (const unsigned char*)TRIGGER_MSG_ON) == 0)
	{
		DDWORD dwFlags;
		pServerDE->SetObjectFlags(m_hObject, m_dwSaveFlags);

		dwFlags = pServerDE->GetObjectUserFlags(m_hObject);
		pServerDE->SetObjectUserFlags(m_hObject, dwFlags | USRFLG_VISIBLE);

		if (m_hSurfaceObj)
		{
			dwFlags = pServerDE->GetObjectUserFlags(m_hSurfaceObj);
			pServerDE->SetObjectUserFlags(m_hSurfaceObj, dwFlags | USRFLG_VISIBLE);
		}

		m_bHidden = DFALSE;
	}
	else if ((bToggle && !m_bHidden) || _mbsicmp((const unsigned char*)pMsg, (const unsigned char*)TRIGGER_MSG_OFF) == 0)
	{
		DDWORD dwFlags;
		pServerDE->SetObjectFlags(m_hObject, m_dwSaveFlags & ~FLAG_VISIBLE);

		dwFlags = pServerDE->GetObjectUserFlags(m_hObject);
		pServerDE->SetObjectUserFlags(m_hObject, dwFlags & ~USRFLG_VISIBLE);

		if (m_hSurfaceObj)
		{
			dwFlags = pServerDE->GetObjectUserFlags(m_hSurfaceObj);
			pServerDE->SetObjectUserFlags(m_hSurfaceObj, dwFlags & ~USRFLG_VISIBLE);
		}

		m_bHidden = DTRUE;
	}
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	VolumeBrush::ReadProp
//
//	PURPOSE:	Set property value
//
// ----------------------------------------------------------------------- //

void VolumeBrush::ReadProp(ObjectCreateStruct *pStruct)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !pStruct) return;

	long nLongVal;
	char buf[MAX_CS_FILENAME_LEN];

	pServerDE->GetPropBool("Hidden", &m_bHidden);
	pServerDE->GetPropBool("ShowSurface", &m_bShowSurface);

	buf[0] = '\0';
	pServerDE->GetPropString("SpriteSurfaceName", buf, MAX_CS_FILENAME_LEN);
	if (buf[0]) m_hstrSurfaceSprite = pServerDE->CreateString(buf);

	pServerDE->GetPropBool( "FogEnable", &m_bFogEnable );
	pServerDE->GetPropReal( "FogFarZ", &m_fFogFarZ );
	pServerDE->GetPropReal( "FogNearZ", &m_fFogNearZ );
	pServerDE->GetPropVector( "FogColor", &m_vFogColor );

	pServerDE->GetPropReal("XScaleMin", &m_fXScaleMin);
	pServerDE->GetPropReal("XScaleMax", &m_fXScaleMax);
	pServerDE->GetPropReal("YScaleMin", &m_fYScaleMin);
	pServerDE->GetPropReal("YScaleMax", &m_fYScaleMax);
	pServerDE->GetPropReal("XScaleDuration", &m_fXScaleDuration);
	pServerDE->GetPropReal("YScaleDuration", &m_fYScaleDuration);
	pServerDE->GetPropReal("SurfaceHeight", &m_fSurfaceHeight);
	pServerDE->GetPropVector("SurfaceColor1", &m_vSurfaceColor1);
	pServerDE->GetPropVector("SurfaceColor2", &m_vSurfaceColor2);
	pServerDE->GetPropReal("Viscosity", &m_fViscosity);
	pServerDE->GetPropReal( "SurfaceAlpha", &m_fSurfaceAlpha);

	if (pServerDE->GetPropLongInt("Code", &nLongVal) == DE_OK)
		m_eContainerCode = (ContainerCode)nLongVal;
	pServerDE->GetPropVector("Current", &m_vCurrent);
	pServerDE->GetPropReal("Damage", &m_fDamage);
	if (pServerDE->GetPropLongInt("DamageType", &nLongVal) == DE_OK)
		m_nDamageType = (DBYTE)nLongVal;

	pServerDE->GetPropBool("Locked", &m_bLocked);
	pServerDE->GetPropBool("UnlockKeyRemove", &m_bUnlockKeyRemove);

	buf[0] = '\0';
	pServerDE->GetPropString("UnlockKeyName", buf, MAX_CS_FILENAME_LEN);
	if (buf[0]) m_hstrKeyName = pServerDE->CreateString(buf);

	if (pServerDE->GetPropLongInt("NumSurfacePolies", &nLongVal) == DE_OK)
	{
		m_dwNumSurfacePolies = (DDWORD)nLongVal;
	}
}


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

void VolumeBrush::InitialUpdate(int nData)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	// For save game restores, just recreate the surface
	if (nData == INITIALUPDATE_SAVEGAME)
		return;

	if (m_bShowSurface) 
	{
		CreateSurface();
	}

	m_hPlayerClass = pServerDE->GetClass("CPlayerObj");

	DDWORD dwUserFlags = m_bHidden ? 0 : USRFLG_VISIBLE;
	dwUserFlags |= USRFLG_SAVEABLE;

	pServerDE->SetObjectUserFlags(m_hObject, dwUserFlags);

	if (m_hSurfaceObj) 
	{
		pServerDE->SetObjectUserFlags(m_hSurfaceObj, dwUserFlags);
	}

	// Tell the client about any special fx (fog)...
	HMESSAGEWRITE hMessage = pServerDE->StartSpecialEffectMessage(this);
	pServerDE->WriteToMessageByte(hMessage, SFX_VOLUMEBRUSH_ID);
//pServerDE->WriteToMessageByte(hMessage, DTRUE);
	pServerDE->WriteToMessageByte(hMessage, (DBYTE)m_bFogEnable);
	pServerDE->WriteToMessageFloat(hMessage, m_fFogFarZ);
	pServerDE->WriteToMessageFloat(hMessage, m_fFogNearZ);
	pServerDE->WriteToMessageVector(hMessage, &m_vFogColor);
	pServerDE->EndMessage(hMessage);

	pServerDE->SetNextUpdate(m_hObject, 0.001f);


	// Save volume brush's initial flags...

	m_dwSaveFlags = pServerDE->GetObjectFlags(m_hObject);


	// Normalize viscosity (1 = no movement, 0 = full movement)...

	if (m_fViscosity < 0.0) m_fViscosity = 0.0f;
	else if (m_fViscosity > 1.0) m_fViscosity = 1.0f;

	// Okay, internally we really want it the opposite way (i.e., 1 = full
	// movement, 0 = no movement)...

⌨️ 快捷键说明

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