📄 volumebrush.cpp
字号:
// ----------------------------------------------------------------------- //
//
// 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 + -