📄 seeingeye.cpp
字号:
// ----------------------------------------------------------------------- //
//
// MODULE : SeeingEye.cpp
//
// PURPOSE : DefenseGlobe AI
//
// CREATED : 12/01/97
//
// ----------------------------------------------------------------------- //
// 9.4.5 The all-seeing Eye!
// The all-seeing eye looks like a normal human eye (dislodged from someone's head, of course).
// The player can drop it anywhere, or throw it by holding down on it's hot key. Once the eye is
// in place the player can look through it and see what it sees by pressing it's hot key a second
// time. The eye is easily destroyed, and if they player is looking through it when this happens
// they are blinded for several seconds. Once the eye is destroyed it will automatically return
// to the player's inventory.
// Need a Eye model
// Reposition the Camera to eye models location
// Mlook only
// Change Screen border?
//
#include "SeeingEye.h"
#include "cpp_server_de.h"
#include "SharedDefs.h"
#include "PlayerObj.h"
#include "ClientServerShared.h"
//BEGIN_CLASS(CPlayerObj)
//END_CLASS_DEFAULT(CPlayerObj, CBaseCharacter, NULL, NULL)
BEGIN_CLASS(SeeingEye)
ADD_DESTRUCTABLE_AGGREGATE()
END_CLASS_DEFAULT_FLAGS(SeeingEye, BaseClass, NULL, NULL, CF_HIDDEN)
#define PINGPERIOD 1.0f
// ----------------------------------------------------------------------- //
//
// ROUTINE:
//
// PURPOSE: Constructor
//
// ----------------------------------------------------------------------- //
SeeingEye::SeeingEye() : BaseClass(OT_MODEL)
{
AddAggregate(&m_damage);
m_hOwner = DNULL;
m_hClient = DNULL;
m_bDropped = DFALSE;
m_hStuckObject = DNULL;
m_fNextPingTime = 0;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE:
//
// PURPOSE: Destructor
//
// ----------------------------------------------------------------------- //
SeeingEye::~SeeingEye()
{
Remove( DTRUE );
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: SeeingEye::Init()
//
// PURPOSE: Initializes the SeeingEye
//
// ----------------------------------------------------------------------- //
void SeeingEye::Init(HOBJECT hOwner, HCLIENT hClient)
{
CServerDE* pServerDE = BaseClass::GetServerDE();
m_hOwner = hOwner;
if( m_hOwner )
{
g_pServerDE->CreateInterObjectLink( m_hObject, m_hOwner );
}
m_hClient = hClient;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: EngineMessageFn
//
// PURPOSE: Handle engine messages
//
// ----------------------------------------------------------------------- //
DDWORD SeeingEye::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
switch(messageID)
{
case MID_PRECREATE:
{
DDWORD dwRet = BaseClass::EngineMessageFn(messageID, pData, fData);
if( fData != INITIALUPDATE_SAVEGAME )
PostPropRead((ObjectCreateStruct*)pData);
return dwRet;
}
case MID_INITIALUPDATE:
{
if( fData != INITIALUPDATE_SAVEGAME )
InitialUpdate((DVector *)pData);
break;
}
case MID_UPDATE:
{
Update();
break;
}
case MID_TOUCHNOTIFY:
{
ObjectTouch((HOBJECT)pData);
}
break;
case MID_LINKBROKEN:
{
if( m_hStuckObject == (HOBJECT)pData )
{
Pickup( );
}
else if( m_hOwner == (HOBJECT)pData )
{
Remove( DTRUE );
}
}
break;
case MID_SAVEOBJECT:
Save((HMESSAGEWRITE)pData, (DDWORD)fData);
break;
case MID_LOADOBJECT:
Load((HMESSAGEREAD)pData, (DDWORD)fData);
break;
default : break;
}
return BaseClass::EngineMessageFn(messageID, pData, fData);
}
// --------------------------------------------------------------------------- //
//
// ROUTINE: SeeingEye::ObjectMessageFn()
//
// PURPOSE: Processes a message from a server object.
//
// --------------------------------------------------------------------------- //
DDWORD SeeingEye::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
{
DDWORD dwRet;
switch(messageID)
{
case MID_UNATTACH:
{
if( hSender == m_hStuckObject )
{
Pickup( );
}
}
break;
case MID_DAMAGE:
{
dwRet = BaseClass::ObjectMessageFn(hSender, messageID, hRead);
if(m_damage.IsDead() )
{
Remove( DTRUE );
}
return dwRet;
}
break;
}
return BaseClass::ObjectMessageFn(hSender, messageID, hRead);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: PostPropRead()
//
// PURPOSE: Update properties
//
// ----------------------------------------------------------------------- //
void SeeingEye::PostPropRead(ObjectCreateStruct *pStruct)
{
if (!pStruct) return;
char* pFilename = "Models\\Powerups\\theeye_pu.abc";
char* pSkin = "Skins\\Powerups\\theeye_pu.dtx";
_mbscpy((unsigned char*)pStruct->m_Filename, (const unsigned char*)pFilename);
_mbscpy((unsigned char*)pStruct->m_SkinName, (const unsigned char*)pSkin);
pStruct->m_Flags = FLAG_VISIBLE | FLAG_GRAVITY | FLAG_SOLID | FLAG_TOUCH_NOTIFY | FLAG_NOSLIDING | FLAG_REMOVEIFOUTSIDE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: ObjectTouch
//
// PURPOSE: Handle object touch
//
// ----------------------------------------------------------------------- //
void SeeingEye::ObjectTouch (HOBJECT hObj)
{
DDWORD dwFlags;
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return;
// return if it hit a non solid object, but not if it hit a world object
HOBJECT hWorld = pServerDE->GetWorldObject();
if (hObj != hWorld && !(pServerDE->GetObjectFlags(hObj) & FLAG_SOLID)) // Ignore non-solid objects
return;
if (!m_bDropped)
{
if (hObj == m_hOwner)
return; // Let it get out of our bounding box...
m_bDropped = DTRUE;
DVector vVel;
VEC_SET(vVel, 0, 0, 0)
// Stop moving
pServerDE->SetVelocity(m_hObject, &vVel);
pServerDE->SetAcceleration(m_hObject, &vVel);
dwFlags = pServerDE->GetObjectFlags( m_hObject );
if (hObj != hWorld)
{
m_hStuckObject = hObj;
Attach( );
// Not solid anymore, and no gravity.
dwFlags &= ~( FLAG_SOLID | FLAG_GRAVITY );
}
pServerDE->SetObjectFlags(m_hObject, dwFlags );
}
else
{
// Pickup the eye
if (hObj == m_hOwner)
{
Pickup( );
}
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Attach()
//
// PURPOSE: Attaches eye to object
//
// ----------------------------------------------------------------------- //
void SeeingEye::Attach( )
{
HMESSAGEWRITE hMsg;
g_pServerDE->CreateInterObjectLink( m_hObject, m_hStuckObject );
hMsg = g_pServerDE->StartMessageToObject( this, m_hStuckObject, MID_ATTACH );
g_pServerDE->WriteToMessageObject( hMsg, m_hObject );
g_pServerDE->EndMessage( hMsg );
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: Pickup()
//
// PURPOSE: Pickup the eye
//
// ----------------------------------------------------------------------- //
void SeeingEye::Pickup( )
{
DVector vPos;
// Make sure it's a player
if( IsPlayer( m_hOwner ))
{
CPlayerObj *pOwner = (CPlayerObj*)g_pServerDE->HandleToObject(m_hOwner);
if( pOwner )
{
// Deactivate the Eye (in InventoryMgr)
CInvItem *pInvItem = pOwner->m_InventoryMgr.GetItem(INV_THEEYE);
if( pInvItem )
{
pInvItem->PickItUp();
g_pServerDE->GetObjectPos( m_hObject, &vPos );
PlaySoundFromPos( &vPos, "sounds\\powerups\\inventory1.wav", 300.0f, SOUNDPRIORITY_MISC_HIGH);
}
}
}
Remove( DFALSE );
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: InitialUpdate()
//
// PURPOSE: Handle initial update
//
// ----------------------------------------------------------------------- //
DBOOL SeeingEye::InitialUpdate(DVector *pMovement)
{
CServerDE* pServerDE = GetServerDE();
if (!pServerDE) return DFALSE;
m_damage.Init(m_hObject);
m_damage.SetHitPoints(10.0f);
m_damage.SetMaxHitPoints(10.0f);
m_damage.SetArmorPoints(0.0f);
m_damage.SetMaxArmorPoints(0.0f);
m_damage.SetMass(30.0f);
// Set the dims...
DVector vDims;
VEC_SET(vDims, 7, 7, 7);
pServerDE->SetObjectDims(m_hObject, &vDims);
// Toss the Eye up
DRotation rRot;
DVector vU, vR, vF;
pServerDE->GetObjectRotation(m_hObject, &rRot);
pServerDE->GetRotationVectors(&rRot, &vU, &vR, &vF);
DVector vVel;
DFLOAT fForward = pServerDE->Random(150.0f, 250.0f);
VEC_MULSCALAR(vF, vF, fForward);
DFLOAT fUpVel = pServerDE->Random(100.0f, 150.0f);
VEC_MULSCALAR(vU, vU, fUpVel);
VEC_ADD(vVel, vU, vF);
pServerDE->SetVelocity(m_hObject, &vVel);
pServerDE->SetForceIgnoreLimit(m_hObject, 0.0f);
pServerDE->SetFrictionCoefficient(m_hObject, 18.0);
pServerDE->SetNextUpdate(m_hObject, (DFLOAT)0.001);
pServerDE->SetObjectUserFlags( m_hObject, USRFLG_SAVEABLE );
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: SeeingEye::Update
//
// PURPOSE:
//
// ----------------------------------------------------------------------- //
void SeeingEye::Update()
{
CServerDE* pServerDE = GetServerDE();
pServerDE->SetNextUpdate(m_hObject, 0.001f);
if( pServerDE->GetTime( ) > m_fNextPingTime )
{
m_fNextPingTime = pServerDE->GetTime( ) + PINGPERIOD;
pServerDE->PingObjects(m_hObject);
}
if (m_bDropped)
{
DVector vVel;
VEC_SET(vVel, 0, 0, 0);
pServerDE->SetVelocity(m_hObject, &vVel);
}
if (m_hStuckObject)
{
// Move to keep up with what we hit
DVector vPos, vDims;
pServerDE->GetObjectPos(m_hStuckObject, &vPos);
pServerDE->GetObjectDims(m_hStuckObject, &vDims);
// Position the Eye at Eye Level...
vPos.y += vDims.y / 2.0f;
vPos.y -= 10; // on Players Back
vPos.z -= 10; // on Players Back
pServerDE->TeleportObject(m_hObject, &vPos);
}
return;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: SeeingEye::Remove
//
// PURPOSE: Removes the object
//
// ----------------------------------------------------------------------- //
void SeeingEye::Remove( DBOOL bClearInv )
{
// Make the Inventory Item NULL
if (m_hOwner)
{
if( IsPlayer( m_hOwner ))
{
CPlayerObj *pOwner = (CPlayerObj*)g_pServerDE->HandleToObject(m_hOwner);
if( pOwner )
{
if ( pOwner->m_InventoryMgr.IsItemActive(INV_THEEYE))
{
int nOff = 0;
if (m_hClient)
{
HMESSAGEWRITE hMsg;
// Turn off the eye
hMsg = g_pServerDE->StartMessage(m_hClient, SMSG_ALL_SEEING_EYE);
g_pServerDE->WriteToMessageByte(hMsg, (DBYTE)nOff);
g_pServerDE->WriteToMessageObject(hMsg, m_hObject);
g_pServerDE->EndMessage(hMsg);
// Blind the Player
hMsg = g_pServerDE->StartMessage(m_hClient, SMSG_BLIND);
g_pServerDE->WriteToMessageFloat(hMsg, (DFLOAT)10.0f);
g_pServerDE->EndMessage2(hMsg, MESSAGE_GUARANTEED);
}
}
if( bClearInv )
pOwner->m_InventoryMgr.RemoveItem(INV_THEEYE);
}
}
m_hOwner = DNULL;
m_hClient = DNULL;
}
g_pServerDE->RemoveObject( m_hObject );
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: SeeingEye::Save
//
// PURPOSE: Save the object
//
// ----------------------------------------------------------------------- //
void SeeingEye::Save(HMESSAGEWRITE hWrite, DDWORD dwSaveType)
{
if (!hWrite) return;
g_pServerDE->WriteToLoadSaveMessageObject(hWrite, m_hOwner);
g_pServerDE->WriteToLoadSaveMessageObject(hWrite, m_hStuckObject);
g_pServerDE->WriteToMessageByte(hWrite, m_bDropped);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: SeeingEye::Save
//
// PURPOSE: Save the object
//
// ----------------------------------------------------------------------- //
void SeeingEye::Load(HMESSAGEREAD hRead, DDWORD dwLoadType)
{
if( !hRead ) return;
g_pServerDE->ReadFromLoadSaveMessageObject(hRead, &m_hOwner);
g_pServerDE->CreateInterObjectLink( m_hObject, m_hOwner );
g_pServerDE->ReadFromLoadSaveMessageObject(hRead, &m_hStuckObject);
if( m_hStuckObject )
Attach( );
m_bDropped = g_pServerDE->ReadFromMessageByte(hRead);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -