|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Frequently used global functions.
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "doors.h"
#include "entitylist.h"
#include "globals.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Landmark class
void CPointEntity::Spawn( void ) { SetSolid( SOLID_NONE ); // UTIL_SetSize(this, vec3_origin, vec3_origin);
}
class CNullEntity : public CBaseEntity { public: DECLARE_CLASS( CNullEntity, CBaseEntity );
void Spawn( void ); };
// Null Entity, remove on startup
void CNullEntity::Spawn( void ) { UTIL_Remove( this ); } LINK_ENTITY_TO_CLASS(info_null,CNullEntity);
class CBaseDMStart : public CPointEntity { public: DECLARE_CLASS( CBaseDMStart, CPointEntity );
bool IsTriggered( CBaseEntity *pEntity );
DECLARE_DATADESC();
string_t m_Master;
private: };
BEGIN_DATADESC( CBaseDMStart )
DEFINE_KEYFIELD( m_Master, FIELD_STRING, "master" ),
END_DATADESC()
// These are the new entry points to entities.
LINK_ENTITY_TO_CLASS(info_player_deathmatch,CBaseDMStart); LINK_ENTITY_TO_CLASS(info_player_start,CPointEntity); LINK_ENTITY_TO_CLASS(info_landmark,CPointEntity);
bool CBaseDMStart::IsTriggered( CBaseEntity *pEntity ) { bool master = UTIL_IsMasterTriggered( m_Master, pEntity );
return master; }
// Convenient way to delay removing oneself
void CBaseEntity::SUB_Remove( void ) { if (m_iHealth > 0) { // this situation can screw up NPCs who can't tell their entity pointers are invalid.
m_iHealth = 0; DevWarning( 2, "SUB_Remove called on entity with health > 0\n"); }
UTIL_Remove( this ); }
// Convenient way to explicitly do nothing (passed to functions that require a method)
void CBaseEntity::SUB_DoNothing( void ) { }
//-----------------------------------------------------------------------------
// Purpose: Finds all active entities with the given targetname and calls their
// 'Use' function.
// Input : targetName - Target name to search for.
// pActivator -
// pCaller -
// useType -
// value -
//-----------------------------------------------------------------------------
void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { CBaseEntity *pTarget = NULL; if ( !targetName || !targetName[0] ) return;
DevMsg( 2, "Firing: (%s)\n", targetName );
for (;;) { CBaseEntity *pSearchingEntity = pActivator; pTarget = gEntList.FindEntityByName( pTarget, targetName, pSearchingEntity, pActivator, pCaller ); if ( !pTarget ) break;
if (!pTarget->IsMarkedForDeletion() ) // Don't use dying ents
{ DevMsg( 2, "[%03d] Found: %s, firing (%s)\n", gpGlobals->tickcount%1000, pTarget->GetDebugName(), targetName ); pTarget->Use( pActivator, pCaller, useType, value ); } } }
enum togglemovetypes_t { MOVE_TOGGLE_NONE = 0, MOVE_TOGGLE_LINEAR = 1, MOVE_TOGGLE_ANGULAR = 2, };
// Global Savedata for Toggle
BEGIN_DATADESC( CBaseToggle )
DEFINE_FIELD( m_toggle_state, FIELD_INTEGER ), DEFINE_FIELD( m_flMoveDistance, FIELD_FLOAT ), DEFINE_FIELD( m_flWait, FIELD_FLOAT ), DEFINE_FIELD( m_flLip, FIELD_FLOAT ), DEFINE_FIELD( m_vecPosition1, FIELD_POSITION_VECTOR ), DEFINE_FIELD( m_vecPosition2, FIELD_POSITION_VECTOR ), DEFINE_FIELD( m_vecMoveAng, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
DEFINE_FIELD( m_vecAngle1, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
DEFINE_FIELD( m_vecAngle2, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle?
DEFINE_FIELD( m_flHeight, FIELD_FLOAT ), DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), DEFINE_FIELD( m_vecFinalDest, FIELD_POSITION_VECTOR ), DEFINE_FIELD( m_vecFinalAngle, FIELD_VECTOR ), DEFINE_FIELD( m_sMaster, FIELD_STRING), DEFINE_FIELD( m_movementType, FIELD_INTEGER ), // Linear or angular movement? (togglemovetypes_t)
END_DATADESC()
IMPLEMENT_SERVERCLASS_ST(CBaseToggle, DT_BaseToggle) SendPropVector( SENDINFO( m_vecFinalDest ) ), SendPropInt( SENDINFO( m_movementType ) ), SendPropFloat( SENDINFO( m_flMoveTargetTime ) ), END_SEND_TABLE()
CBaseToggle::CBaseToggle() { #ifdef _DEBUG
// necessary since in debug, we initialize vectors to NAN for debugging
m_vecPosition1.Init(); m_vecPosition2.Init(); m_vecAngle1.Init(); m_vecAngle2.Init(); m_vecFinalDest.Init(); m_vecFinalAngle.Init(); #endif
}
//-----------------------------------------------------------------------------
// Purpose: Returns the velocity imparted to players standing on us.
//-----------------------------------------------------------------------------
void CBaseToggle::GetGroundVelocityToApply( Vector &vecGroundVel ) { vecGroundVel = GetLocalVelocity(); }
bool CBaseToggle::KeyValue( const char *szKeyName, const char *szValue ) { if (FStrEq(szKeyName, "lip")) { m_flLip = atof(szValue); } else if (FStrEq(szKeyName, "wait")) { m_flWait = atof(szValue); } else if (FStrEq(szKeyName, "master")) { m_sMaster = AllocPooledString(szValue); } else if (FStrEq(szKeyName, "distance")) { m_flMoveDistance = atof(szValue); } else return BaseClass::KeyValue( szKeyName, szValue );
return true; }
//-----------------------------------------------------------------------------
// Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from
// GetOrigin() traveling at flSpeed.
// Input : Vector vecDest -
// flSpeed -
//-----------------------------------------------------------------------------
void CBaseToggle::LinearMove( const Vector &vecDest, float flSpeed ) { ASSERTSZ(flSpeed != 0, "LinearMove: no speed is defined!"); m_vecFinalDest = vecDest;
m_movementType = MOVE_TOGGLE_LINEAR; // Already there?
if (vecDest == GetLocalOrigin()) { MoveDone(); return; } // set destdelta to the vector needed to move
Vector vecDestDelta = vecDest - GetLocalOrigin(); // divide vector length by speed to get time to reach dest
float flTravelTime = vecDestDelta.Length() / flSpeed;
// set m_flNextThink to trigger a call to LinearMoveDone when dest is reached
SetMoveDoneTime( flTravelTime ); m_flMoveTargetTime = gpGlobals->curtime + flTravelTime;
// scale the destdelta vector by the time spent traveling to get velocity
SetLocalVelocity( vecDestDelta / flTravelTime ); }
void CBaseToggle::MoveDone( void ) { switch ( m_movementType ) { case MOVE_TOGGLE_LINEAR: LinearMoveDone(); break; case MOVE_TOGGLE_ANGULAR: AngularMoveDone(); break; } m_movementType = MOVE_TOGGLE_NONE; BaseClass::MoveDone(); } //-----------------------------------------------------------------------------
// Purpose: After moving, set origin to exact final destination, call "move done" function.
//-----------------------------------------------------------------------------
void CBaseToggle::LinearMoveDone( void ) { UTIL_SetOrigin( this, m_vecFinalDest); SetAbsVelocity( vec3_origin ); SetMoveDoneTime( -1 ); }
// DVS TODO: obselete, remove?
bool CBaseToggle::IsLockedByMaster( void ) { if (m_sMaster != NULL_STRING && !UTIL_IsMasterTriggered(m_sMaster, m_hActivator)) return true; else return false; }
//-----------------------------------------------------------------------------
// Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from
// GetLocalOrigin() traveling at flSpeed. Just like LinearMove, but rotational.
// Input : vecDestAngle -
// flSpeed -
//-----------------------------------------------------------------------------
void CBaseToggle::AngularMove( const QAngle &vecDestAngle, float flSpeed ) { ASSERTSZ(flSpeed != 0, "AngularMove: no speed is defined!"); m_vecFinalAngle = vecDestAngle;
m_movementType = MOVE_TOGGLE_ANGULAR; // Already there?
if (vecDestAngle == GetLocalAngles()) { MoveDone(); return; } // set destdelta to the vector needed to move
QAngle vecDestDelta = vecDestAngle - GetLocalAngles(); // divide by speed to get time to reach dest
float flTravelTime = vecDestDelta.Length() / flSpeed;
const float MinTravelTime = 0.01f; if ( flTravelTime < MinTravelTime ) { // If we only travel for a short time, we can fail WillSimulateGamePhysics()
flTravelTime = MinTravelTime; flSpeed = vecDestDelta.Length() / flTravelTime; }
// set m_flNextThink to trigger a call to AngularMoveDone when dest is reached
SetMoveDoneTime( flTravelTime );
// scale the destdelta vector by the time spent traveling to get velocity
SetLocalAngularVelocity( vecDestDelta * (1.0 / flTravelTime) ); }
//-----------------------------------------------------------------------------
// Purpose: After rotating, set angle to exact final angle, call "move done" function.
//-----------------------------------------------------------------------------
void CBaseToggle::AngularMoveDone( void ) { SetLocalAngles( m_vecFinalAngle ); SetLocalAngularVelocity( vec3_angle ); SetMoveDoneTime( -1 ); }
float CBaseToggle::AxisValue( int flags, const QAngle &angles ) { if ( FBitSet(flags, SF_DOOR_ROTATE_ROLL) ) return angles.z; if ( FBitSet(flags, SF_DOOR_ROTATE_PITCH) ) return angles.x;
return angles.y; }
void CBaseToggle::AxisDir( void ) { if ( m_spawnflags & SF_DOOR_ROTATE_ROLL ) m_vecMoveAng = QAngle( 0, 0, 1 ); // angles are roll
else if ( m_spawnflags & SF_DOOR_ROTATE_PITCH ) m_vecMoveAng = QAngle( 1, 0, 0 ); // angles are pitch
else m_vecMoveAng = QAngle( 0, 1, 0 ); // angles are yaw
}
float CBaseToggle::AxisDelta( int flags, const QAngle &angle1, const QAngle &angle2 ) { // UNDONE: Use AngleDistance() here?
if ( FBitSet (flags, SF_DOOR_ROTATE_ROLL) ) return angle1.z - angle2.z; if ( FBitSet (flags, SF_DOOR_ROTATE_PITCH) ) return angle1.x - angle2.x;
return angle1.y - angle2.y; }
|