mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-13 20:21:06 +00:00
1
This commit is contained in:
@@ -0,0 +1,402 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// TF Energy Ball
|
||||
//
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "tf_projectile_energy_ball.h"
|
||||
#include "soundent.h"
|
||||
#include "tf_fx.h"
|
||||
#include "props.h"
|
||||
#include "baseobject_shared.h"
|
||||
#include "SpriteTrail.h"
|
||||
#include "IEffects.h"
|
||||
#include "te_effect_dispatch.h"
|
||||
#include "collisionutils.h"
|
||||
#include "bone_setup.h"
|
||||
#include "decals.h"
|
||||
#include "tf_player.h"
|
||||
#include "te_effect_dispatch.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "tf_weapon_rocketlauncher.h"
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// TF Energy Ball Projectile functions (Server specific).
|
||||
//
|
||||
#define ENERGY_BALL_MODEL "models/weapons/w_models/w_drg_ball.mdl"
|
||||
#define ARROW_GRAVITY 0.3f
|
||||
|
||||
#define ENERGY_BALL_THINK_CONTEXT "CTFProjectile_EnergyBallThink"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
LINK_ENTITY_TO_CLASS( tf_projectile_energy_ball, CTFProjectile_EnergyBall );
|
||||
PRECACHE_WEAPON_REGISTER( tf_projectile_energy_ball );
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_EnergyBall, DT_TFProjectile_EnergyBall )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFProjectile_EnergyBall, DT_TFProjectile_EnergyBall )
|
||||
SendPropBool( SENDINFO( m_bChargedShot ) ),
|
||||
SendPropVector( SENDINFO( m_vColor1 ), 8, 0, 0, 1 ),
|
||||
SendPropVector( SENDINFO( m_vColor2 ), 8, 0, 0, 1 )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_DATADESC( CTFProjectile_EnergyBall )
|
||||
//DEFINE_THINKFUNC( ImpactThink ),
|
||||
END_DATADESC()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFProjectile_EnergyBall::CTFProjectile_EnergyBall()
|
||||
{
|
||||
m_bChargedShot = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFProjectile_EnergyBall::~CTFProjectile_EnergyBall()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFProjectile_EnergyBall *CTFProjectile_EnergyBall::Create( const Vector &vecOrigin, const QAngle &vecAngles, const float fSpeed, const float fGravity, CBaseEntity *pOwner, CBaseEntity *pScorer )
|
||||
{
|
||||
CTFProjectile_EnergyBall *pBall = static_cast<CTFProjectile_EnergyBall*>( CBaseEntity::Create( "tf_projectile_energy_ball", vecOrigin, vecAngles, pOwner ) );
|
||||
if ( pBall )
|
||||
{
|
||||
pBall->InitEnergyBall( vecOrigin, vecAngles, fSpeed, fGravity, pOwner, pScorer );
|
||||
}
|
||||
|
||||
return pBall;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::InitEnergyBall( const Vector &vecOrigin, const QAngle &vecAngles, const float fSpeed, const float fGravity, CBaseEntity *pOwner, CBaseEntity *pScorer )
|
||||
{
|
||||
// Initialize the owner.
|
||||
SetOwnerEntity( pOwner );
|
||||
|
||||
// Set team.
|
||||
ChangeTeam( pOwner->GetTeamNumber() );
|
||||
|
||||
// Spawn.
|
||||
Spawn();
|
||||
|
||||
SetGravity( fGravity );
|
||||
|
||||
SetCritical( true );
|
||||
|
||||
// Setup the initial velocity.
|
||||
Vector vecForward, vecRight, vecUp;
|
||||
AngleVectors( vecAngles, &vecForward, &vecRight, &vecUp );
|
||||
|
||||
Vector vecVelocity = vecForward * fSpeed;
|
||||
|
||||
SetAbsVelocity( vecVelocity );
|
||||
SetupInitialTransmittedGrenadeVelocity( vecVelocity );
|
||||
|
||||
// Setup the initial angles.
|
||||
QAngle angles;
|
||||
VectorAngles( vecVelocity, angles );
|
||||
SetAbsAngles( angles );
|
||||
|
||||
// Save the scoring player.
|
||||
SetScorer( pScorer );
|
||||
|
||||
if ( pScorer )
|
||||
{
|
||||
SetTruceValidForEnt( pScorer->IsTruceValidForEnt() );
|
||||
}
|
||||
|
||||
m_flInitTime = gpGlobals->curtime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::Spawn()
|
||||
{
|
||||
SetModel( ENERGY_BALL_MODEL );
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::Precache()
|
||||
{
|
||||
PrecacheParticleSystem( "drg_cow_rockettrail_charged" );
|
||||
PrecacheParticleSystem( "drg_cow_rockettrail_charged_blue" );
|
||||
PrecacheParticleSystem( "drg_cow_rockettrail_normal" );
|
||||
PrecacheParticleSystem( "drg_cow_rockettrail_normal_blue" );
|
||||
|
||||
PrecacheModel( ENERGY_BALL_MODEL );
|
||||
|
||||
PrecacheScriptSound( "Weapon_CowMangler.Explode" );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::SetScorer( CBaseEntity *pScorer )
|
||||
{
|
||||
m_Scorer = pScorer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBasePlayer *CTFProjectile_EnergyBall::GetScorer( void )
|
||||
{
|
||||
return dynamic_cast<CBasePlayer *>( m_Scorer.Get() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Plays an impact sound. Louder for the attacker.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::ImpactSound( const char *pszSoundName, bool bLoudForAttacker )
|
||||
{
|
||||
CTFPlayer *pAttacker = ToTFPlayer( GetScorer() );
|
||||
if ( !pAttacker )
|
||||
return;
|
||||
|
||||
if ( bLoudForAttacker )
|
||||
{
|
||||
float soundlen = 0;
|
||||
EmitSound_t params;
|
||||
params.m_flSoundTime = 0;
|
||||
params.m_pSoundName = pszSoundName;
|
||||
params.m_pflSoundDuration = &soundlen;
|
||||
CPASFilter filter( GetAbsOrigin() );
|
||||
filter.RemoveRecipient( ToTFPlayer(pAttacker) );
|
||||
EmitSound( filter, entindex(), params );
|
||||
|
||||
CSingleUserRecipientFilter attackerFilter( ToTFPlayer(pAttacker) );
|
||||
EmitSound( attackerFilter, pAttacker->entindex(), params );
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitSound( pszSoundName );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::FadeOut( int iTime )
|
||||
{
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
SetAbsVelocity( vec3_origin );
|
||||
AddSolidFlags( FSOLID_NOT_SOLID );
|
||||
AddEffects( EF_NODRAW );
|
||||
|
||||
// Start remove timer.
|
||||
SetContextThink( &CTFProjectile_EnergyBall::RemoveThink, gpGlobals->curtime + iTime, "ENERGY_BALL_REMOVE_THINK" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::RemoveThink( void )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Arrow was deflected.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::Deflected( CBaseEntity *pDeflectedBy, Vector &vecDir )
|
||||
{
|
||||
CTFPlayer *pTFDeflector = ToTFPlayer( pDeflectedBy );
|
||||
if ( !pTFDeflector )
|
||||
return;
|
||||
|
||||
ChangeTeam( pTFDeflector->GetTeamNumber() );
|
||||
SetLauncher( pTFDeflector->GetActiveWeapon() );
|
||||
|
||||
CTFPlayer* pOldOwner = ToTFPlayer( GetOwnerEntity() );
|
||||
SetOwnerEntity( pTFDeflector );
|
||||
|
||||
if ( pOldOwner )
|
||||
{
|
||||
pOldOwner->SpeakConceptIfAllowed( MP_CONCEPT_DEFLECTED, "projectile:1,victim:1" );
|
||||
}
|
||||
|
||||
if ( pTFDeflector->m_Shared.IsCritBoosted() )
|
||||
{
|
||||
SetCritical( true );
|
||||
}
|
||||
|
||||
CTFWeaponBase::SendObjectDeflectedEvent( pTFDeflector, pOldOwner, GetWeaponID(), this );
|
||||
|
||||
IncrementDeflected();
|
||||
SetScorer( pTFDeflector );
|
||||
|
||||
// Change particle color data.
|
||||
if ( GetTeamNumber() == TF_TEAM_BLUE )
|
||||
{
|
||||
m_vColor1 = TF_PARTICLE_WEAPON_BLUE_1;
|
||||
m_vColor2 = TF_PARTICLE_WEAPON_BLUE_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vColor1 = TF_PARTICLE_WEAPON_RED_1;
|
||||
m_vColor2 = TF_PARTICLE_WEAPON_RED_2;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFProjectile_EnergyBall::Explode( trace_t *pTrace, CBaseEntity *pOther )
|
||||
{
|
||||
if ( ShouldNotDetonate() )
|
||||
{
|
||||
Destroy( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// Save this entity as enemy, they will take 100% damage.
|
||||
m_hEnemy = pOther;
|
||||
|
||||
// Invisible.
|
||||
SetModelName( NULL_STRING );
|
||||
AddSolidFlags( FSOLID_NOT_SOLID );
|
||||
m_takedamage = DAMAGE_NO;
|
||||
|
||||
// Pull out a bit.
|
||||
if ( pTrace->fraction != 1.0 )
|
||||
{
|
||||
SetAbsOrigin( pTrace->endpos + ( pTrace->plane.normal * 1.0f ) );
|
||||
}
|
||||
|
||||
// Particle (oriented)
|
||||
Vector vecOrigin = GetAbsOrigin();
|
||||
CPVSFilter filter( vecOrigin );
|
||||
QAngle angExplosion( 0.f, 0.f, 0.f );
|
||||
VectorAngles( pTrace->plane.normal, angExplosion );
|
||||
TE_TFParticleEffect( filter, 0.f, GetExplosionParticleName(), vecOrigin, pTrace->plane.normal, angExplosion, NULL );
|
||||
|
||||
// Screenshake
|
||||
if ( m_bChargedShot )
|
||||
{
|
||||
UTIL_ScreenShake( WorldSpaceCenter(), 25.0, 150.0, 1.0, 750, SHAKE_START );
|
||||
}
|
||||
|
||||
// Sound
|
||||
ImpactSound( "Weapon_CowMangler.Explode" );
|
||||
CSoundEnt::InsertSound ( SOUND_COMBAT, vecOrigin, 1024, 3.0 );
|
||||
|
||||
// Damage.
|
||||
CBaseEntity *pAttacker = GetOwnerEntity();
|
||||
IScorer *pScorerInterface = dynamic_cast<IScorer*>( pAttacker );
|
||||
if ( pScorerInterface )
|
||||
{
|
||||
pAttacker = pScorerInterface->GetScorer();
|
||||
}
|
||||
|
||||
float flRadius = GetRadius();
|
||||
|
||||
if ( pAttacker ) // No attacker, deal no damage. Otherwise we could potentially kill teammates.
|
||||
{
|
||||
CTFPlayer *pTarget = ToTFPlayer( GetEnemy() );
|
||||
if ( pTarget )
|
||||
{
|
||||
// Rocket Specialist
|
||||
CheckForStunOnImpact( pTarget );
|
||||
|
||||
if ( pTarget->GetTeamNumber() != pAttacker->GetTeamNumber() )
|
||||
{
|
||||
IGameEvent *event = gameeventmanager->CreateEvent( "projectile_direct_hit" );
|
||||
if ( event )
|
||||
{
|
||||
event->SetInt( "attacker", pAttacker->entindex() );
|
||||
event->SetInt( "victim", pTarget->entindex() );
|
||||
|
||||
item_definition_index_t ownerWeaponDefIndex = INVALID_ITEM_DEF_INDEX;
|
||||
CTFWeaponBase *pWeapon = dynamic_cast< CTFWeaponBase * >( GetOriginalLauncher() );
|
||||
if ( pWeapon )
|
||||
{
|
||||
ownerWeaponDefIndex = pWeapon->GetAttributeContainer()->GetItem()->GetItemDefIndex();
|
||||
}
|
||||
event->SetInt( "weapon_def_index", ownerWeaponDefIndex );
|
||||
|
||||
gameeventmanager->FireEvent( event, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTakeDamageInfo info( this, pAttacker, m_hLauncher, vec3_origin, vecOrigin, GetDamage(), GetDamageType(), GetDamageCustom() );
|
||||
CTFRadiusDamageInfo radiusinfo( &info, vecOrigin, flRadius, NULL, m_bChargedShot ? TF_ROCKET_RADIUS_FOR_RJS*1.33 : TF_ROCKET_RADIUS_FOR_RJS );
|
||||
TFGameRules()->RadiusDamage( radiusinfo );
|
||||
}
|
||||
|
||||
// Don't decal players with scorch.
|
||||
if ( !pOther->IsPlayer() )
|
||||
{
|
||||
UTIL_DecalTrace( pTrace, "Scorch" );
|
||||
}
|
||||
|
||||
// Remove the rocket.
|
||||
UTIL_Remove( this );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CTFProjectile_EnergyBall::GetExplosionParticleName( void )
|
||||
{
|
||||
if ( m_bChargedShot )
|
||||
{
|
||||
return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_explosioncore_charged" : "drg_cow_explosioncore_charged_blue";
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( GetTeamNumber() == TF_TEAM_RED ) ? "drg_cow_explosioncore_normal" : "drg_cow_explosioncore_normal_blue";
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CTFProjectile_EnergyBall::GetDamage()
|
||||
{
|
||||
return m_flDamage;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CTFProjectile_EnergyBall::GetDamageType()
|
||||
{
|
||||
int iDamageType;
|
||||
if ( m_bChargedShot )
|
||||
{
|
||||
iDamageType = DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD | DMG_IGNITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
iDamageType = DMG_BLAST | DMG_HALF_FALLOFF | DMG_USEDISTANCEMOD;
|
||||
}
|
||||
|
||||
return iDamageType;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CTFProjectile_EnergyBall::GetDamageCustom()
|
||||
{
|
||||
return m_bChargedShot ? TF_DMG_CUSTOM_PLASMA_CHARGED : TF_DMG_CUSTOM_PLASMA;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user