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

📄 tchernotronic.cpp

📁 Blood 2全套源码
💻 CPP
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : Tchernotronic.cpp
//
// PURPOSE : Tchernotronic - Implementation
//
// CREATED : 5/11/98
//
// ----------------------------------------------------------------------- //

#include "Tchernotronic.h"
#include "ClientServerShared.h"
#include "Trigger.h"
#include "ObjectUtilities.h"
#include "PhysicalAttributes.h"
#include "SFXMsgIds.h"
#include "SoundTypes.h"

#define INVALID_ANI		((DDWORD)-1)

#define TIME_REMOVE		0.5f		// Remove 2 seconds after trigger

// Static global variables..
static char *g_szTriggerOn = "TRIGGER"; 


BEGIN_CLASS(Tchernotronic)
	ADD_STRINGPROP_FLAG(Filename, "Models\\WorldObjects\\Technoberg.abc", PF_HIDDEN)
	ADD_STRINGPROP_FLAG(Skin, "Skins\\WorldObjects\\Technoberg.dtx", PF_HIDDEN)
	ADD_STRINGPROP(DestroyTriggerTarget, "") 
	ADD_STRINGPROP(DestroyTriggerMessage, "")
END_CLASS_DEFAULT(Tchernotronic, B2BaseClass, NULL, NULL)


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	Tchernotronic::Tchernotronic
//
//	PURPOSE:	Initialize
//
// ----------------------------------------------------------------------- //

Tchernotronic::Tchernotronic() : B2BaseClass(OT_MODEL)
{ 
	m_hstrTriggerTarget = DNULL;
	m_hstrTriggerMessage = DNULL;

	m_nRestAnim		= INVALID_ANI;
	m_nMovingAnim	= INVALID_ANI;

	m_bTimer		= DFALSE;
	m_fRemoveTime	= 0.0f;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	Tchernotronic::~Tchernotronic()
//
//	PURPOSE:	Deallocate object
//
// ----------------------------------------------------------------------- //

Tchernotronic::~Tchernotronic()
{
	CServerDE* pServerDE = GetServerDE();

	if (m_hstrTriggerTarget)
	{
		pServerDE->FreeString(m_hstrTriggerTarget);
		m_hstrTriggerTarget = DNULL;
	}

	if (m_hstrTriggerMessage)
	{
		pServerDE->FreeString(m_hstrTriggerMessage);
		m_hstrTriggerMessage = DNULL;
	}
}

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

DDWORD Tchernotronic::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
	switch(messageID)
	{
		case MID_UPDATE:
		{
			if (!Update((DVector *)pData))
            {
            	CServerDE* pServerDE = GetServerDE();
            	if (!pServerDE) break;

            	pServerDE->RemoveObject(m_hObject);		
            }
			break;
		}

		case MID_PRECREATE:
		{
			ReadProp((ObjectCreateStruct *)pData);
			break;
		}

		case MID_INITIALUPDATE:
		{
			if (( DDWORD )fData != INITIALUPDATE_SAVEGAME)
			{
				InitialUpdate((DVector *)pData);
			}
			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:	Tchernotronic::ObjectMessageFn()
//
//	PURPOSE:	Handler for server object messages.
//
// --------------------------------------------------------------------------- //

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


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

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

	char buf[MAX_CS_FILENAME_LEN];
	buf[0] = '\0';
	pServerDE->GetPropString("DestroyTriggerTarget", buf, MAX_CS_FILENAME_LEN);
	if (buf[0]) m_hstrTriggerTarget = pServerDE->CreateString(buf);

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

	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	Tchernotronic::InitialUpdate
//
//	PURPOSE:	Handle initial Update
//
// ----------------------------------------------------------------------- //

void Tchernotronic::InitialUpdate(DVector *pMovement)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return;

	// Mark this object as savable
	DDWORD dwUsrFlags = pServerDE->GetObjectUserFlags(m_hObject);
	dwUsrFlags |= USRFLG_SAVEABLE;
	pServerDE->SetObjectUserFlags(m_hObject, dwUsrFlags);

	DDWORD dwFlags = (FLAG_VISIBLE | FLAG_SOLID);

	pServerDE->SetObjectFlags(m_hObject, dwFlags);

	// Get model animations
	m_nRestAnim			= pServerDE->GetAnimIndex(m_hObject, "static_model");
	m_nMovingAnim		= pServerDE->GetAnimIndex(m_hObject, "animate");

	pServerDE->SetModelLooping(m_hObject, DFALSE);

	DVector vDims;
	pServerDE->GetModelAnimUserDims(m_hObject, &vDims, m_nRestAnim);
	pServerDE->SetObjectDims(m_hObject, &vDims);

	pServerDE->SetBlockingPriority(m_hObject, BLOCKPRIORITY_NONPUSHABLE);

	// Wait to be triggered
	pServerDE->SetNextUpdate(m_hObject, 0.0f);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	Tchernotronic::Update
//
//	PURPOSE:	Handle Update
//
// ----------------------------------------------------------------------- //

DBOOL Tchernotronic::Update(DVector *pMovement)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE) return DFALSE;

	DFLOAT fTime = pServerDE->GetTime();
	// See if the current anim is finished.. If so, blow up!
	if (m_bTimer)
	{
		if (fTime >= m_fRemoveTime)
		{
			// Send any trigger messages
			if (m_hstrTriggerTarget && m_hstrTriggerMessage)
				SendTriggerMsgToObjects(this, m_hstrTriggerTarget, m_hstrTriggerMessage);

			return DFALSE;
		}
	}
	else
	{
		DDWORD dwState	= pServerDE->GetModelPlaybackState(m_hObject);
		if (dwState & MS_PLAYDONE)
		{
			DVector vPos;
			pServerDE->GetObjectPos(m_hObject, &vPos);
			AddExplosion(vPos);
			m_fRemoveTime = fTime + TIME_REMOVE;
			m_bTimer = DTRUE;

		}
	}

	pServerDE->SetNextUpdate(m_hObject, 0.05f);

	return DTRUE;
}


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	Tchernotronic::TriggerMsg()
//
//	PURPOSE:	Handler for Tchernotronic trigger messages.
//
// --------------------------------------------------------------------------- //

void Tchernotronic::TriggerMsg(HOBJECT hSender, HSTRING hMsg)
{
	CServerDE* pServerDE = GetServerDE();
	HSTRING hstr;

	// See if he's been triggered to start moving
	if (IsPlayer(hSender)) return;

	hstr = pServerDE->CreateString(g_szTriggerOn);
	if (pServerDE->CompareStringsUpper(hMsg, hstr))
	{
		PlayAnimation(m_nMovingAnim);
		pServerDE->SetNextUpdate(m_hObject, 0.1f);
	}
	pServerDE->FreeString(hstr);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	Tchernotronic::PlayAnimation()
//
//	PURPOSE:	Set model to new animation
//
// ----------------------------------------------------------------------- //

DBOOL Tchernotronic::PlayAnimation(DDWORD dwNewAni)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE || dwNewAni == INVALID_ANI) return DFALSE;

	DDWORD dwAni	= pServerDE->GetModelAnimation(m_hObject);
	DDWORD dwState	= pServerDE->GetModelPlaybackState(m_hObject);

	if (dwAni == dwNewAni && (dwState & MS_PLAYDONE))
	{
		return DFALSE;
	}
	else if (dwAni != dwNewAni)
	{
		pServerDE->SetModelAnimation(m_hObject, dwNewAni);
	}

	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	Tchernotronic::AddExplosion()
//
//	PURPOSE:	Add an explosion
//
// ----------------------------------------------------------------------- //
/*
void Tchernotronic::AddExplosion(DVector &vPos)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return;

	Explosion* pExplosion = DNULL;

	ObjectCreateStruct theStruct;
	INIT_OBJECTCREATESTRUCT(theStruct);

	HCLASS hClass = pServerDE->GetClass("Explosion");

	if (hClass)
	{

		DRotation rRot;
		pServerDE->GetObjectRotation(m_hObject, &rRot);
		ROT_COPY(theStruct.m_Rotation, rRot);

		for (int i=0; i<4; i++)
		{
			VEC_COPY(theStruct.m_Pos, vPos);
			// Vary the position of the explosions
			switch (i)
			{
			case 0:
				theStruct.m_Pos.y -= 40.0f;
				theStruct.m_Pos.x += 10.0f;
				break;
			case 1:
				theStruct.m_Pos.z -= 15.0f;
				break;
			case 2:
				theStruct.m_Pos.y += 50.0f;
				theStruct.m_Pos.x += 10.0f;
				break;
			case 3:
				theStruct.m_Pos.y -= 20.0f;
				theStruct.m_Pos.x += 5.0f;
				theStruct.m_Pos.z -= 5.0f;
				break;
			};
	
			pExplosion = (Explosion*)pServerDE->CreateObject(hClass, &theStruct);
			if (pExplosion)
			{
				pExplosion->Setup("Sounds\\exp_tnt.wav", 2000, 0.75f,
								  NULL, 150.0f, 100.0f, 1.0f,
								  20.0f, DTRUE, DFALSE, DFALSE);

				// Set up the impact light...
				DVector vLightColor;
				VEC_SET(vLightColor, 1.0f, 0.5f, 0.0f);

				pExplosion->SetupLight(DTRUE, vLightColor, 20.0f, 300.0f);

				pExplosion->Explode(i*0.25f);
			}
		}
	}
}
*/

void Tchernotronic::AddExplosion(DVector &vPos)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return;

	DDWORD		nType = EXP_GRENADE;
	DVector		vUp;
	VEC_SET(vUp, 0.0f, 1.0f, 0.0f);

	HMESSAGEWRITE hMessage = pServerDE->StartInstantSpecialEffectMessage(&vPos);
	pServerDE->WriteToMessageByte(hMessage, SFX_EXPLOSIONFX_ID);

	pServerDE->WriteToMessageVector(hMessage, &vPos);
	pServerDE->WriteToMessageVector(hMessage, &vUp);
	pServerDE->WriteToMessageDWord(hMessage, nType);

	pServerDE->EndMessage(hMessage);

	PlaySoundFromPos(&vPos, "Sounds\\Weapons\\c4\\explosion_1.wav", 1000.0f, SOUNDPRIORITY_MISC_MEDIUM);

	// Do some damage
	DamageObjectsInRadius(m_hObject, pServerDE->HandleToObject(m_hObject), vPos, 200.0f, 100.0f, DAMAGE_TYPE_EXPLODE);
}


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

void Tchernotronic::Save(HMESSAGEWRITE hWrite, DDWORD dwSaveGame)
{
	DFLOAT fTime;

	fTime = g_pServerDE->GetTime( );

	g_pServerDE->WriteToMessageHString( hWrite, m_hstrTriggerTarget );
	g_pServerDE->WriteToMessageHString( hWrite, m_hstrTriggerMessage );
	g_pServerDE->WriteToMessageDWord( hWrite, m_nRestAnim );
	g_pServerDE->WriteToMessageDWord( hWrite, m_nMovingAnim );
	g_pServerDE->WriteToMessageByte( hWrite, m_bTimer );
	g_pServerDE->WriteToMessageFloat( hWrite, m_fRemoveTime - fTime );
}


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

void Tchernotronic::Load(HMESSAGEREAD hRead, DDWORD dwLoadGame)
{
	DFLOAT fTime;

	fTime = g_pServerDE->GetTime( );

	if( m_hstrTriggerTarget )
	{
		g_pServerDE->FreeString( m_hstrTriggerTarget );
	}
	m_hstrTriggerTarget = g_pServerDE->ReadFromMessageHString( hRead );

	if( m_hstrTriggerMessage )
	{
		g_pServerDE->FreeString( m_hstrTriggerMessage );
	}
	m_hstrTriggerMessage = g_pServerDE->ReadFromMessageHString( hRead );

	m_nRestAnim = g_pServerDE->ReadFromMessageDWord( hRead );
	m_nMovingAnim = g_pServerDE->ReadFromMessageDWord( hRead );
	m_bTimer = g_pServerDE->ReadFromMessageByte( hRead );
	m_fRemoveTime = g_pServerDE->ReadFromMessageFloat( hRead ) + fTime;

}



⌨️ 快捷键说明

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