|
|
//========= 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 ); }
|