diff options
Diffstat (limited to 'game/server/tf/tf_props.cpp')
| -rw-r--r-- | game/server/tf/tf_props.cpp | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/game/server/tf/tf_props.cpp b/game/server/tf/tf_props.cpp new file mode 100644 index 0000000..6a68e89 --- /dev/null +++ b/game/server/tf/tf_props.cpp @@ -0,0 +1,158 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: static_prop - don't move, don't animate, don't do anything. +// physics_prop - move, take damage, but don't animate +// +//===========================================================================// + + +#include "cbase.h" +#include "tf_gamerules.h" +#include "tf_props.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +ConVar tf_soccer_ball_up_max( "tf_soccer_ball_up_max", "350", FCVAR_CHEAT ); +ConVar tf_soccer_ball_multiplier( "tf_soccer_ball_multiplier", "4", FCVAR_CHEAT ); +ConVar tf_soccer_ball_min_speed( "tf_soccer_ball_min_speed", "30", FCVAR_CHEAT ); + +// Ranges from ~ .3 (side swipe) to 1 (full head on hit). When it's >= this value, +// treat the hit as a full frontal 1.0 collision. +ConVar tf_soccer_front_hit_range( "tf_soccer_front_hit_range", ".95", FCVAR_CHEAT ); + +extern ConVar tf_halloween_kart_dash_speed; +extern ConVar tf_halloween_kart_normal_speed; + + +LINK_ENTITY_TO_CLASS( prop_soccer_ball, CPropSoccerBall ); + +BEGIN_DATADESC( CPropSoccerBall ) + DEFINE_KEYFIELD( m_iszTriggers, FIELD_STRING, "trigger_name" ), +END_DATADESC() + + +void CPropSoccerBall::Precache() +{ + PrecacheScriptSound( "BumperCar.HitBall" ); +} + +void CPropSoccerBall::Spawn() +{ + BaseClass::Spawn(); + + SetSolid( SOLID_VPHYSICS ); // Use our vphys model for collision + SetSolidFlags( FSOLID_TRIGGER ); // Generate Touch functions, but dont collide + SetCollisionGroup( TFCOLLISION_GROUP_ROCKETS ); // Need this one too so players dont get stopped + + SetTouch( &CPropSoccerBall::BallTouch ); + SetContextThink( &CPropSoccerBall::TriggerTouchThink, gpGlobals->curtime + 0.2f, "TriggerTouchThink" ); +} + +// Here's the deal. The ball is a trigger, but triggers are not allowed to touch other triggers. To get around this, +// we're going to specify the names of the triggers we actually want to touch and then we're going to manually try to +// touch them. Our collision system is a vortex of insanity. +void CPropSoccerBall::TriggerTouchThink() +{ + FOR_EACH_VEC( m_vecTriggers, i ) + { + if ( m_vecTriggers[i]->PointIsWithin( GetAbsOrigin() ) ) + { + m_vecTriggers[i]->StartTouch( this ); + m_vecTriggers[i]->EndTouch( this ); + } + } + + SetContextThink( &CPropSoccerBall::TriggerTouchThink, gpGlobals->curtime + 0.2f, "TriggerTouchThink" ); +} + +void CPropSoccerBall::Activate() +{ + CBaseTrigger* pTrigger = NULL; + do + { + pTrigger = dynamic_cast<CBaseTrigger *> ( gEntList.FindEntityByName( pTrigger, m_iszTriggers.ToCStr() ) ); + if ( pTrigger ) + { + m_vecTriggers.AddToTail( pTrigger ); + } + } while ( pTrigger ); + + BaseClass::Activate(); +} + +bool CPropSoccerBall::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) +{ + TestHitboxes( ray, 0xFFFFFFFF, trace ); + + if ( trace.DidHit() ) + { + IPhysicsObject *pObj = VPhysicsGetObject(); + if ( pObj ) + pObj->Wake(); + } + + return false; +} + +void CPropSoccerBall::BallTouch( CBaseEntity *pOther ) +{ + if ( gpGlobals->curtime < m_flNextAllowedImpactTime ) + return; + + CTFPlayer *pTFPlayer = ToTFPlayer( pOther ); + if ( pTFPlayer ) + { + const float flSoccerBallMultiplier = tf_soccer_ball_multiplier.GetFloat(); + + // Get player direction and speed. + Vector vPlayer( pOther->GetAbsVelocity().x, pOther->GetAbsVelocity().y, 0.0f ); + float flSpeed = vPlayer.Length2D(); + vPlayer.NormalizeInPlace(); + + // Linearly scale up based on kart speed. + float fUp = tf_soccer_ball_up_max.GetFloat(); + float fUpScale = flSpeed / tf_halloween_kart_dash_speed.GetFloat(); + fUp = Clamp( fUp * fUpScale, 5.0f, fUp ) * flSoccerBallMultiplier; + + // Get vector to ball from player. + Vector vToBall = GetAbsOrigin() - pOther->GetAbsOrigin(); + vToBall.z = 0.0f; + vToBall.NormalizeInPlace(); + + // cosTheta ranges from about .3 (side swipe) to 1 (full head on hit). + float cosTheta = Max( 0.1f, vToBall.Dot( vPlayer ) ); + + // Scale speed based on incident angle and soccer ball multiplier hack. + flSpeed = Max( flSpeed * cosTheta, tf_soccer_ball_min_speed.GetFloat() ); + flSpeed *= flSoccerBallMultiplier; + + Vector vecVelocity; + if ( cosTheta >= tf_soccer_front_hit_range.GetFloat() ) + { + // Front hit - snag player velocity and direction and use that. + //DevMsg( "%s cosTheta: %.2f front hit\n", __FUNCTION__, cosTheta ); + vecVelocity = vPlayer; + } + else + { + // Side swipe. Scale vector by player speed and hit angle. + //DevMsg( "%s cosTheta: %.2f side hit\n", __FUNCTION__, cosTheta ); + vecVelocity = vToBall; + } + + vecVelocity *= flSpeed; + vecVelocity.z = fUp; + + IPhysicsObject *pObj = VPhysicsGetObject(); + pObj->Wake(); + pObj->AddVelocity( &vecVelocity, NULL ); + m_flNextAllowedImpactTime = gpGlobals->curtime + 0.1f; + + EmitSound( "BumperCar.HitBall" ); + + ChangeTeam( pTFPlayer->GetTeamNumber() ); + m_hLastToucher = pTFPlayer; + } +} + |