You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
5.7 KiB
238 lines
5.7 KiB
5 years ago
|
//========= 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 );
|
||
|
}
|
||
|
|