source-engine/game/server/hl2/look_door.cpp

238 lines
5.7 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implements doors that move when you look at them.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "basecombatcharacter.h"
#include "entitylist.h"
#include "func_movelinear.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define SF_LDOOR_THRESHOLD 8192
#define SF_LDOOR_INVERT 16384
#define SF_LDOOR_FROM_OPEN 32768
class CLookDoor : public CFuncMoveLinear
{
public:
DECLARE_CLASS( CLookDoor, CFuncMoveLinear );
void Spawn( void );
void MoveThink( void );
// Inputs
void InputInvertOn( inputdata_t &inputdata );
void InputInvertOff( inputdata_t &inputdata );
float m_flProximityDistance; // How far before I start reacting
float m_flProximityOffset;
float m_flFieldOfView;
EHANDLE m_hLooker; // Who is looking
DECLARE_DATADESC();
};
class CLookDoorThinker : public CLogicalEntity
{
public:
DECLARE_CLASS( CLookDoorThinker, CLogicalEntity );
void LookThink( void );
EHANDLE m_hLookDoor; // Who owns me
DECLARE_DATADESC();
};
BEGIN_DATADESC( CLookDoorThinker )
DEFINE_FIELD( m_hLookDoor, FIELD_EHANDLE ),
// Function Pointers
DEFINE_FUNCTION(LookThink),
END_DATADESC()
LINK_ENTITY_TO_CLASS( lookdoorthinker, CLookDoorThinker );
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void CLookDoorThinker::LookThink(void)
{
if (m_hLookDoor)
{
((CLookDoor*)(CBaseEntity*)m_hLookDoor)->MoveThink();
SetNextThink( gpGlobals->curtime + 0.01f );
}
else
{
UTIL_Remove(this);
}
}
BEGIN_DATADESC( CLookDoor )
DEFINE_KEYFIELD( m_flProximityDistance, FIELD_FLOAT, "ProximityDistance"),
DEFINE_KEYFIELD( m_flProximityOffset, FIELD_FLOAT, "ProximityOffset"),
DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ),
DEFINE_FIELD(m_hLooker, FIELD_EHANDLE),
// Inputs
DEFINE_INPUTFUNC( FIELD_VOID, "InvertOn", InputInvertOn ),
DEFINE_INPUTFUNC( FIELD_VOID, "InvertOff", InputInvertOff ),
// Function Pointers
DEFINE_FUNCTION(MoveThink),
END_DATADESC()
LINK_ENTITY_TO_CLASS( func_lookdoor, CLookDoor );
//------------------------------------------------------------------------------
// Purpose : Input handlers.
//------------------------------------------------------------------------------
void CLookDoor::InputInvertOn( inputdata_t &inputdata )
{
m_spawnflags |= SF_LDOOR_INVERT;
}
void CLookDoor::InputInvertOff( inputdata_t &inputdata )
{
m_spawnflags &= ~SF_LDOOR_INVERT;
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void CLookDoor::Spawn(void)
{
BaseClass::Spawn();
if (m_target == NULL_STRING)
{
Warning( "ERROR: DoorLook (%s) given no target. Rejecting spawn.\n",GetDebugName());
return;
}
CLookDoorThinker* pLookThinker = (CLookDoorThinker*)CreateEntityByName("lookdoorthinker");
if (pLookThinker)
{
pLookThinker->SetThink(&CLookDoorThinker::LookThink);
pLookThinker->m_hLookDoor = this;
pLookThinker->SetNextThink( gpGlobals->curtime + 0.1f );
}
}
//------------------------------------------------------------------------------
// Purpose :
//------------------------------------------------------------------------------
void CLookDoor::MoveThink(void)
{
// --------------------------------
// Make sure we have a looker
// --------------------------------
if (m_hLooker == NULL)
{
m_hLooker = (CBaseEntity*)gEntList.FindEntityByName( NULL, m_target );
if (m_hLooker == NULL)
{
return;
}
}
//--------------------------------------
// Calculate an orgin for the door
//--------------------------------------
Vector vOrigin = WorldSpaceCenter() - GetAbsOrigin();
// If FROM_OPEN flag is set, door proximity is measured
// from the open and not the closed position
if (FBitSet (m_spawnflags, SF_LDOOR_FROM_OPEN))
{
vOrigin += m_vecPosition2;
}
// ------------------------------------------------------
// First add movement based on proximity
// ------------------------------------------------------
float flProxMove = 0;
if (m_flProximityDistance > 0)
{
float flDist = (m_hLooker->GetAbsOrigin() - vOrigin).Length()-m_flProximityOffset;
if (flDist < 0) flDist = 0;
if (flDist < m_flProximityDistance)
{
if (FBitSet (m_spawnflags, SF_LDOOR_THRESHOLD))
{
flProxMove = 1.0;
}
else
{
flProxMove = 1-flDist/m_flProximityDistance;
}
}
}
// ------------------------------------------------------
// Then add movement based on view angle
// ------------------------------------------------------
float flViewMove = 0;
if (m_flFieldOfView > 0)
{
// ----------------------------------------
// Check that toucher is facing the target
// ----------------------------------------
Assert( dynamic_cast< CBaseCombatCharacter* >( m_hLooker.Get() ) );
CBaseCombatCharacter* pBCC = (CBaseCombatCharacter*)m_hLooker.Get();
Vector vTouchDir = pBCC->EyeDirection3D( );
Vector vTargetDir = vOrigin - pBCC->EyePosition();
VectorNormalize(vTargetDir);
float flDotPr = DotProduct(vTouchDir,vTargetDir);
if (flDotPr < m_flFieldOfView)
{
flViewMove = 0.0;
}
else
{
flViewMove = (flDotPr-m_flFieldOfView)/(1.0 - m_flFieldOfView);
}
}
//---------------------------------------
// Summate the two moves
//---------------------------------------
float flMove = flProxMove + flViewMove;
if (flMove > 1.0)
{
flMove = 1.0;
}
// If behavior is inverted do the reverse
if (FBitSet (m_spawnflags, SF_LDOOR_INVERT))
{
flMove = 1-flMove;
}
// Move the door
SetPosition( flMove );
}