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.
237 lines
5.7 KiB
237 lines
5.7 KiB
//========= 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 ); |
|
} |
|
|
|
|