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.
158 lines
4.7 KiB
158 lines
4.7 KiB
//========= 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; |
|
} |
|
} |
|
|
|
|