summaryrefslogtreecommitdiff
path: root/game/server/tf/tf_props.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/tf/tf_props.cpp')
-rw-r--r--game/server/tf/tf_props.cpp158
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;
+ }
+}
+