diff options
Diffstat (limited to 'mp/src/game/server/triggers.cpp')
| -rw-r--r-- | mp/src/game/server/triggers.cpp | 162 |
1 files changed, 152 insertions, 10 deletions
diff --git a/mp/src/game/server/triggers.cpp b/mp/src/game/server/triggers.cpp index 742976fb..1e317567 100644 --- a/mp/src/game/server/triggers.cpp +++ b/mp/src/game/server/triggers.cpp @@ -475,6 +475,7 @@ void CBaseTrigger::StartTouch(CBaseEntity *pOther) { // First entity to touch us that passes our filters m_OnStartTouchAll.FireOutput( pOther, this ); + StartTouchAll(); } } } @@ -514,7 +515,10 @@ void CBaseTrigger::EndTouch(CBaseEntity *pOther) else if ( hOther->IsPlayer() && !hOther->IsAlive() ) { #ifdef STAGING_ONLY - AssertMsg( 0, CFmtStr( "Dead player [%s] is still touching this trigger at [%f %f %f]", hOther->GetEntityName().ToCStr(), XYZ( hOther->GetAbsOrigin() ) ) ); + if ( !HushAsserts() ) + { + AssertMsg( false, "Dead player [%s] is still touching this trigger at [%f %f %f]", hOther->GetEntityName().ToCStr(), XYZ( hOther->GetAbsOrigin() ) ); + } Warning( "Dead player [%s] is still touching this trigger at [%f %f %f]", hOther->GetEntityName().ToCStr(), XYZ( hOther->GetAbsOrigin() ) ); #endif m_hTouchingEntities.Remove( i ); @@ -530,6 +534,7 @@ void CBaseTrigger::EndTouch(CBaseEntity *pOther) if ( !bFoundOtherTouchee /*&& !m_bDisabled*/ ) { m_OnEndTouchAll.FireOutput(pOther, this); + EndTouchAll(); } } } @@ -634,8 +639,8 @@ void CTriggerRemove::Touch( CBaseEntity *pOther ) BEGIN_DATADESC( CTriggerHurt ) // Function Pointers - DEFINE_FUNCTION( RadiationThink ), - DEFINE_FUNCTION( HurtThink ), + DEFINE_FUNCTION( CTriggerHurtShim::RadiationThinkShim ), + DEFINE_FUNCTION( CTriggerHurtShim::HurtThinkShim ), // Fields DEFINE_FIELD( m_flOriginalDamage, FIELD_FLOAT ), @@ -661,6 +666,7 @@ END_DATADESC() LINK_ENTITY_TO_CLASS( trigger_hurt, CTriggerHurt ); +IMPLEMENT_AUTO_LIST( ITriggerHurtAutoList ); //----------------------------------------------------------------------------- // Purpose: Called when spawning, after keyvalues have been handled. @@ -677,7 +683,7 @@ void CTriggerHurt::Spawn( void ) SetThink( NULL ); if (m_bitsDamageInflict & DMG_RADIATION) { - SetThink ( &CTriggerHurt::RadiationThink ); + SetThink ( &CTriggerHurtShim::RadiationThinkShim ); SetNextThink( gpGlobals->curtime + random->RandomFloat(0.0, 0.5) ); } } @@ -723,6 +729,15 @@ bool CTriggerHurt::HurtEntity( CBaseEntity *pOther, float damage ) if ( !pOther->m_takedamage || !PassesTriggerFilters(pOther) ) return false; + // If player is disconnected, we're probably in this routine via the + // PhysicsRemoveTouchedList() function to make sure all Untouch()'s are called for the + // player. Calling TakeDamage() in this case can get into the speaking criteria, which + // will then loop through the control points and the touched list again. We shouldn't + // need to hurt players that are disconnected, so skip all of this... + bool bPlayerDisconnected = pOther->IsPlayer() && ( ((CBasePlayer *)pOther)->IsConnected() == false ); + if ( bPlayerDisconnected ) + return false; + if ( damage < 0 ) { pOther->TakeHealth( -damage, m_bitsDamageInflict ); @@ -862,11 +877,29 @@ void CTriggerHurt::Touch( CBaseEntity *pOther ) { if ( m_pfnThink == NULL ) { - SetThink( &CTriggerHurt::HurtThink ); + SetThink( &CTriggerHurtShim::HurtThinkShim ); SetNextThink( gpGlobals->curtime ); } } +//----------------------------------------------------------------------------- +// Purpose: Checks if this point is in any trigger_hurt zones with positive damage +//----------------------------------------------------------------------------- +bool IsTakingTriggerHurtDamageAtPoint( const Vector &vecPoint ) +{ + for ( int i = 0; i < ITriggerHurtAutoList::AutoList().Count(); i++ ) + { + // Some maps use trigger_hurt with negative values as healing triggers; don't consider those + CTriggerHurt *pTrigger = static_cast<CTriggerHurt*>( ITriggerHurtAutoList::AutoList()[i] ); + if ( !pTrigger->m_bDisabled && pTrigger->PointIsWithin( vecPoint ) && pTrigger->m_flDamage > 0.f ) + { + return true; + } + } + + return false; +} + // ################################################################################## // >> TriggerMultiple @@ -2310,8 +2343,8 @@ class CTriggerTeleport : public CBaseTrigger public: DECLARE_CLASS( CTriggerTeleport, CBaseTrigger ); - void Spawn( void ); - void Touch( CBaseEntity *pOther ); + virtual void Spawn( void ) OVERRIDE; + virtual void Touch( CBaseEntity *pOther ) OVERRIDE; string_t m_iLandmark; @@ -2326,14 +2359,11 @@ BEGIN_DATADESC( CTriggerTeleport ) END_DATADESC() - - void CTriggerTeleport::Spawn( void ) { InitTrigger(); } - //----------------------------------------------------------------------------- // Purpose: Teleports the entity that touched us to the location of our target, // setting the toucher's angles to our target's angles if they are a @@ -2416,6 +2446,46 @@ LINK_ENTITY_TO_CLASS( info_teleport_destination, CPointEntity ); //----------------------------------------------------------------------------- +// Teleport Relative trigger +//----------------------------------------------------------------------------- +class CTriggerTeleportRelative : public CBaseTrigger +{ +public: + DECLARE_CLASS(CTriggerTeleportRelative, CBaseTrigger); + + virtual void Spawn( void ) OVERRIDE; + virtual void Touch( CBaseEntity *pOther ) OVERRIDE; + + Vector m_TeleportOffset; + + DECLARE_DATADESC(); +}; + +LINK_ENTITY_TO_CLASS( trigger_teleport_relative, CTriggerTeleportRelative ); +BEGIN_DATADESC( CTriggerTeleportRelative ) + DEFINE_KEYFIELD( m_TeleportOffset, FIELD_VECTOR, "teleportoffset" ) +END_DATADESC() + + +void CTriggerTeleportRelative::Spawn( void ) +{ + InitTrigger(); +} + +void CTriggerTeleportRelative::Touch( CBaseEntity *pOther ) +{ + if ( !PassesTriggerFilters(pOther) ) + { + return; + } + + const Vector finalPos = m_TeleportOffset + WorldSpaceCenter(); + const Vector *momentum = &vec3_origin; + + pOther->Teleport( &finalPos, NULL, momentum ); +} + +//----------------------------------------------------------------------------- // Purpose: Saves the game when the player touches the trigger. Can be enabled or disabled //----------------------------------------------------------------------------- class CTriggerToggleSave : public CBaseTrigger @@ -4822,6 +4892,78 @@ void CServerRagdollTrigger::EndTouch(CBaseEntity *pOther) } } + +//----------------------------------------------------------------------------- +// Purpose: A trigger that adds impulse to touching entities +//----------------------------------------------------------------------------- +class CTriggerApplyImpulse : public CBaseTrigger +{ +public: + DECLARE_CLASS( CTriggerApplyImpulse, CBaseTrigger ); + DECLARE_DATADESC(); + + CTriggerApplyImpulse(); + + void Spawn( void ); + + void InputApplyImpulse( inputdata_t& ); + +private: + Vector m_vecImpulseDir; + float m_flForce; +}; + + +BEGIN_DATADESC( CTriggerApplyImpulse ) + DEFINE_KEYFIELD( m_vecImpulseDir, FIELD_VECTOR, "impulse_dir" ), + DEFINE_KEYFIELD( m_flForce, FIELD_FLOAT, "force" ), + DEFINE_INPUTFUNC( FIELD_VOID, "ApplyImpulse", InputApplyImpulse ), +END_DATADESC() + + +LINK_ENTITY_TO_CLASS( trigger_apply_impulse, CTriggerApplyImpulse ); + + +CTriggerApplyImpulse::CTriggerApplyImpulse() +{ + m_flForce = 300.f; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerApplyImpulse::Spawn() +{ + // Convert pushdir from angles to a vector + Vector vecAbsDir; + QAngle angPushDir = QAngle(m_vecImpulseDir.x, m_vecImpulseDir.y, m_vecImpulseDir.z); + AngleVectors(angPushDir, &vecAbsDir); + + // Transform the vector into entity space + VectorIRotate( vecAbsDir, EntityToWorldTransform(), m_vecImpulseDir ); + + BaseClass::Spawn(); + + InitTrigger(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerApplyImpulse::InputApplyImpulse( inputdata_t& ) +{ + Vector vecImpulse = m_flForce * m_vecImpulseDir; + FOR_EACH_VEC( m_hTouchingEntities, i ) + { + if ( m_hTouchingEntities[i] ) + { + m_hTouchingEntities[i]->ApplyAbsVelocityImpulse( vecImpulse ); + } + } +} + #ifdef HL1_DLL //---------------------------------------------------------------------------------- // func_friction |