mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,843 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "plasmaprojectile.h"
|
||||
//#include "smoke_trail.h"
|
||||
#include "basecombatweapon_shared.h"
|
||||
#include "tf_shareddefs.h"
|
||||
#if !defined( CLIENT_DLL )
|
||||
#include "tf_shield.h"
|
||||
#else
|
||||
#include "c_tracer.h"
|
||||
#include "hud.h"
|
||||
#include "view.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#endif
|
||||
#include "IEffects.h"
|
||||
//#include "tf_player.h"
|
||||
#include "basetfplayer_shared.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "worldsize.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "ammodef.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
extern ConVar tf_knockdowntime;
|
||||
|
||||
#define PLASMA_LIFETIME 2.0
|
||||
|
||||
// Time intervals at which we should simulate plasma projectiles
|
||||
#define PLASMA_SIM_DELTA 0.01
|
||||
#define PLASMA_VELOCITY_SQR (PLASMA_VELOCITY*PLASMA_VELOCITY)
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
ConVar shot_width( "shot_width","8", 0, "Shot" );
|
||||
ConVar shot_length( "shot_length","140", 0, "Shot" );
|
||||
ConVar shot_head_size( "shot_head_size","6", 0, "Shot" );
|
||||
#endif
|
||||
|
||||
#if !defined( CLIENT_DLL )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: PLASMA PROJECTILE
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CBasePlasmaProjectile )
|
||||
|
||||
DEFINE_FIELD( m_flDamage, FIELD_FLOAT ),
|
||||
|
||||
// Function Pointers
|
||||
DEFINE_ENTITYFUNC( MissileTouch ),
|
||||
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
BEGIN_NETWORK_TABLE_NOBASE( CPlasmaProjectileShared, DT_PlasmaProjectileShared )
|
||||
#if !defined( CLIENT_DLL )
|
||||
// These are parameters that are used to generate the entire motion
|
||||
SendPropVector(SENDINFO(m_vecSpawnPosition), 0, SPROP_COORD),
|
||||
SendPropVector(SENDINFO(m_vTracerDir), 0, SPROP_NOSCALE), //SPROP_NORMAL),
|
||||
SendPropTime(SENDINFO(m_flSpawnTime)),
|
||||
SendPropTime(SENDINFO(m_flDeathTime)),
|
||||
SendPropFloat(SENDINFO(m_flSpawnSpeed), 0, SPROP_NOSCALE),
|
||||
#else
|
||||
RecvPropVector(RECVINFO(m_vecSpawnPosition)),
|
||||
RecvPropVector(RECVINFO(m_vTracerDir)),
|
||||
RecvPropTime(RECVINFO(m_flSpawnTime)),
|
||||
RecvPropTime(RECVINFO(m_flDeathTime)),
|
||||
RecvPropFloat(RECVINFO(m_flSpawnSpeed)),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA_NO_BASE( CPlasmaProjectileShared )
|
||||
|
||||
DEFINE_PRED_FIELD_TOL( m_vecSpawnPosition, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.125f ),
|
||||
DEFINE_PRED_FIELD_TOL( m_vTracerDir, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.01f ),
|
||||
DEFINE_PRED_FIELD( m_flSpawnTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_flDeathTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_flSpawnSpeed, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
BEGIN_PREDICTION_DATA_NO_BASE( PositionHistory_t )
|
||||
|
||||
DEFINE_FIELD( m_Position, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_Time, FIELD_FLOAT ),
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( BasePlasmaProjectile, DT_BasePlasmaProjectile)
|
||||
|
||||
BEGIN_NETWORK_TABLE( CBasePlasmaProjectile, DT_BasePlasmaProjectile )
|
||||
#if !defined( CLIENT_DLL )
|
||||
SendPropDataTable(SENDINFO_DT(m_Shared), &REFERENCE_SEND_TABLE(DT_PlasmaProjectileShared)),
|
||||
|
||||
SendPropExclude( "DT_BaseEntity", "m_vecVelocity" ),
|
||||
SendPropExclude( "DT_BaseEntity", "m_vecAbsOrigin" ),
|
||||
|
||||
//SendPropVector(SENDINFO(m_vecGunOriginOffset), 0, SPROP_COORD),
|
||||
|
||||
#else
|
||||
RecvPropDataTable(RECVINFO_DT(m_Shared), 0, &REFERENCE_RECV_TABLE(DT_PlasmaProjectileShared)),
|
||||
|
||||
//RecvPropVector(RECVINFO(m_vecGunOriginOffset)),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( base_plasmaprojectile, CBasePlasmaProjectile );
|
||||
PRECACHE_REGISTER(base_plasmaprojectile);
|
||||
|
||||
BEGIN_PREDICTION_DATA( CBasePlasmaProjectile )
|
||||
|
||||
DEFINE_PRED_TYPEDESCRIPTION( m_Shared, CPlasmaProjectileShared ),
|
||||
|
||||
DEFINE_PRED_FIELD( m_vecAbsOrigin, FIELD_VECTOR, FTYPEDESC_PRIVATE | FTYPEDESC_OVERRIDE ),
|
||||
DEFINE_PRED_FIELD( m_vecVelocity, FIELD_VECTOR, FTYPEDESC_PRIVATE | FTYPEDESC_OVERRIDE ),
|
||||
|
||||
DEFINE_FIELD( m_flMaxRange, FIELD_FLOAT ),
|
||||
|
||||
// Predicted, but not in networking stream
|
||||
DEFINE_PRED_TYPEDESCRIPTION( m_pPreviousPositions[0], PositionHistory_t ),
|
||||
DEFINE_PRED_TYPEDESCRIPTION( m_pPreviousPositions[1], PositionHistory_t ),
|
||||
DEFINE_PRED_TYPEDESCRIPTION( m_pPreviousPositions[2], PositionHistory_t ),
|
||||
DEFINE_PRED_TYPEDESCRIPTION( m_pPreviousPositions[3], PositionHistory_t ),
|
||||
DEFINE_PRED_TYPEDESCRIPTION( m_pPreviousPositions[4], PositionHistory_t ),
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBasePlasmaProjectile::CBasePlasmaProjectile()
|
||||
{
|
||||
#if defined( CLIENT_DLL )
|
||||
m_pHeadParticle = NULL;
|
||||
m_pTrailParticle = NULL;
|
||||
m_pParticleMgr = NULL;
|
||||
#endif
|
||||
|
||||
SetPredictionEligible( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CBasePlasmaProjectile::~CBasePlasmaProjectile()
|
||||
{
|
||||
#if defined( CLIENT_DLL )
|
||||
if( m_pParticleMgr )
|
||||
{
|
||||
m_pParticleMgr->RemoveEffect( &m_ParticleEffect );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::Precache( void )
|
||||
{
|
||||
SetCollisionGroup( TFCOLLISION_GROUP_WEAPON );
|
||||
|
||||
PrecacheScriptSound( "BasePlasmaProjectile.ShieldBlock" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::Spawn( void )
|
||||
{
|
||||
Precache();
|
||||
|
||||
SetSolid( SOLID_BBOX );
|
||||
SetSize( vec3_origin, vec3_origin );
|
||||
SetCollisionGroup( TFCOLLISION_GROUP_WEAPON );
|
||||
SetTouch( MissileTouch );
|
||||
m_DamageType = DMG_ENERGYBEAM;
|
||||
SetMoveType( MOVETYPE_CUSTOM );
|
||||
m_flDamage = 0;
|
||||
// SetMaxRange( 0 );
|
||||
SetExplosive( 0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::Activate( void )
|
||||
{
|
||||
BaseClass::Activate();
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
if ( IsClientCreated() && !m_pParticleMgr )
|
||||
{
|
||||
Start(ParticleMgr(), NULL);
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::SetDamage( float flDamage )
|
||||
{
|
||||
m_flDamage = flDamage;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CBasePlasmaProjectile::GetDamage( void )
|
||||
{
|
||||
return m_flDamage;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::SetMaxRange( float flRange )
|
||||
{
|
||||
m_flMaxRange = flRange;
|
||||
|
||||
// If we have a max range, calculate death time based upon velocity
|
||||
if ( m_flMaxRange )
|
||||
{
|
||||
float flSpeed = GetAbsVelocity().Length();
|
||||
Assert( flSpeed );
|
||||
m_Shared.SetDeathTime( m_Shared.GetSpawnTime() + (flRange / flSpeed) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Shared.SetDeathTime( m_Shared.GetSpawnTime() + PLASMA_LIFETIME );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Set the radius of the explosion created when this shot impacts
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::SetExplosive( float flRadius )
|
||||
{
|
||||
m_flExplosiveRadius = flRadius;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Perform custom physics on this dude (when we're in ballistic mode)
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::PerformCustomPhysics( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
RecalculatePositions( pNewPosition, pNewVelocity, pNewAngles, pNewAngVelocity );
|
||||
#else
|
||||
// Simulate next position
|
||||
m_Shared.ComputePosition( gpGlobals->curtime, pNewPosition, pNewVelocity, pNewAngles, pNewAngVelocity );
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pOther -
|
||||
// tr -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBasePlasmaProjectile::ProjectileHitShield( CBaseEntity *pOther, trace_t& tr )
|
||||
{
|
||||
if ( !pOther )
|
||||
return false;
|
||||
|
||||
if ( !pOther->IsPlayer() )
|
||||
return false;
|
||||
#if !defined( CLIENT_DLL )
|
||||
CBaseTFPlayer* pPlayer = static_cast<CBaseTFPlayer*>(pOther);
|
||||
float flDamage = GetDamage();
|
||||
if ( !pPlayer->IsHittingShield( GetAbsVelocity(), &flDamage ) )
|
||||
return false;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pOther -
|
||||
// tr -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::HandleShieldImpact( CBaseEntity *pOther, trace_t& tr )
|
||||
{
|
||||
// Block
|
||||
EmitSound( "BasePlasmaProjectile.ShieldBlock" );
|
||||
|
||||
// Remove the particle, and make a particle shower
|
||||
g_pEffects->EnergySplash( tr.endpos, tr.plane.normal, ( m_flExplosiveRadius != 0 ) );
|
||||
|
||||
Remove( );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::MissileTouch( CBaseEntity *pOther )
|
||||
{
|
||||
Assert( pOther );
|
||||
if ( !pOther->IsSolid() )
|
||||
return;
|
||||
|
||||
// Create a plasma effect
|
||||
trace_t tr;
|
||||
Vector velDir = GetAbsVelocity();
|
||||
VectorNormalize( velDir );
|
||||
Vector vecSpot = GetLocalOrigin() - velDir * 32;
|
||||
|
||||
// First, just clip to the box
|
||||
Ray_t ray;
|
||||
ray.Init( vecSpot, vecSpot + velDir * 64 );
|
||||
enginetrace->ClipRayToEntity( ray, MASK_SHOT, pOther, &tr );
|
||||
|
||||
// Create the appropriate impact
|
||||
bool bHurtTarget = ( !InSameTeam( pOther ) && pOther->m_takedamage != DAMAGE_NO );
|
||||
WeaponImpact( &tr, velDir, bHurtTarget, pOther, GetDamageType() );
|
||||
|
||||
#if !defined( CLIENT_DLL )
|
||||
CBaseEntity *pOwner = m_hOwner;
|
||||
|
||||
// Do damage (unless I'm explosive, in which case I'll do damage later)
|
||||
if ( m_flDamage && !m_flExplosiveRadius )
|
||||
{
|
||||
ClearMultiDamage();
|
||||
// Assume it's a projectile, so use its velocity instead
|
||||
Vector vecDamageOrigin = GetAbsVelocity();
|
||||
VectorNormalize( vecDamageOrigin );
|
||||
vecDamageOrigin = GetAbsOrigin() - (vecDamageOrigin * 32);
|
||||
CTakeDamageInfo info( this, pOwner, m_flDamage, m_DamageType );
|
||||
CalculateBulletDamageForce( &info, GetAmmoDef()->Index("MediumRound"), GetAbsVelocity(), vecDamageOrigin );
|
||||
pOther->DispatchTraceAttack( info, velDir, &tr );
|
||||
ApplyMultiDamage();
|
||||
}
|
||||
#endif
|
||||
|
||||
Detonate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Plasma projectiles return their owner as their scorer
|
||||
//-----------------------------------------------------------------------------
|
||||
CBasePlayer *CBasePlasmaProjectile::GetScorer( void )
|
||||
{
|
||||
return ToBasePlayer( m_hOwner );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Explode and die
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::Detonate( void )
|
||||
{
|
||||
#if !defined( CLIENT_DLL )
|
||||
// Should I explode?
|
||||
if ( m_flExplosiveRadius )
|
||||
{
|
||||
RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), m_flDamage, m_DamageType | DMG_BLAST ), GetAbsOrigin(), m_flExplosiveRadius, CLASS_NONE, NULL );
|
||||
}
|
||||
#endif
|
||||
Remove( );
|
||||
}
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Add the position to the history
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::AddPositionToHistory( const Vector& org, float flSimTime )
|
||||
{
|
||||
// Store the particle position history
|
||||
// Push the others down the stack
|
||||
for ( int i = MAX_HISTORY-1; i >= 1; i-- )
|
||||
{
|
||||
m_pPreviousPositions[i].m_Position = m_pPreviousPositions[i-1].m_Position;
|
||||
m_pPreviousPositions[i].m_Time = m_pPreviousPositions[i-1].m_Time;
|
||||
}
|
||||
|
||||
m_pPreviousPositions[0].m_Position = org;
|
||||
m_pPreviousPositions[0].m_Time = flSimTime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : org -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::ResetPositionHistories( const Vector& org )
|
||||
{
|
||||
for ( int i = 0; i < MAX_HISTORY; i++ )
|
||||
{
|
||||
m_pPreviousPositions[ i ].m_Position = org; //; - (m_Shared.TracerDir() * 48 * i);;
|
||||
m_pPreviousPositions[ i ].m_Time = gpGlobals->curtime;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::OnDataChanged(DataUpdateType_t updateType)
|
||||
{
|
||||
BaseClass::OnDataChanged(updateType);
|
||||
|
||||
if ( updateType != DATA_UPDATE_CREATED )
|
||||
return;
|
||||
|
||||
if ( !m_pParticleMgr )
|
||||
{
|
||||
Start(ParticleMgr(), NULL);
|
||||
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::RecalculatePositions( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity )
|
||||
{
|
||||
// Recalculate all points?
|
||||
float flSimTime;
|
||||
if ( !m_pPreviousPositions[0].m_Time )
|
||||
{
|
||||
flSimTime = m_Shared.GetSpawnTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
flSimTime = gpGlobals->curtime;
|
||||
}
|
||||
|
||||
// Simulate the points
|
||||
for ( int i = 0; i < MAX_HISTORY; i++ )
|
||||
{
|
||||
if ( flSimTime < m_Shared.GetSpawnTime() )
|
||||
{
|
||||
flSimTime = m_Shared.GetSpawnTime();
|
||||
}
|
||||
|
||||
Vector vecVelocity, vNewOrigin;
|
||||
QAngle vecAngles, vecAngularVelocity;
|
||||
// Only fill out the data with the most recent sim
|
||||
if ( i == 0 )
|
||||
{
|
||||
m_Shared.ComputePosition( flSimTime, &vNewOrigin, &vecVelocity, pNewAngles, pNewAngVelocity );
|
||||
*pNewPosition = vNewOrigin;
|
||||
*pNewVelocity =vecVelocity;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Shared.ComputePosition( flSimTime, &vNewOrigin, &vecVelocity, &vecAngles, &vecAngularVelocity );
|
||||
}
|
||||
AddPositionToHistory( vNewOrigin, flSimTime );
|
||||
|
||||
// As we slow down, simulate slower
|
||||
float flSpeed = vecVelocity.LengthSqr();
|
||||
if ( flSpeed )
|
||||
{
|
||||
flSimTime -= PLASMA_SIM_DELTA * (PLASMA_VELOCITY_SQR / flSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
flSimTime -= PLASMA_SIM_DELTA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::ClientThink( void )
|
||||
{
|
||||
BaseClass::ClientThink();
|
||||
|
||||
// Don't mess with origin if it's being forward simulated on the client
|
||||
if ( GetPredictable() || IsClientCreated() )
|
||||
return;
|
||||
|
||||
Assert( !GetMoveParent() );
|
||||
|
||||
Vector pNewPosition, pNewVelocity;
|
||||
QAngle pNewAngles, pNewAngVelocity;
|
||||
RecalculatePositions( &pNewPosition, &pNewVelocity, &pNewAngles, &pNewAngVelocity );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : isbeingremoved -
|
||||
// *predicted -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBasePlasmaProjectile::OnPredictedEntityRemove( bool isbeingremoved, C_BaseEntity *predicted )
|
||||
{
|
||||
BaseClass::OnPredictedEntityRemove( isbeingremoved, predicted );
|
||||
|
||||
CBasePlasmaProjectile *bpp = dynamic_cast< CBasePlasmaProjectile * >( predicted );
|
||||
if ( !bpp )
|
||||
{
|
||||
// Hrm, we didn't link up to correct type!!!
|
||||
Assert( 0 );
|
||||
// Delete right away since it's fucked up
|
||||
return true;
|
||||
}
|
||||
|
||||
memcpy( m_pPreviousPositions, bpp->m_pPreviousPositions, sizeof( m_pPreviousPositions ) );
|
||||
|
||||
m_vecGunOriginOffset = bpp->m_vecGunOriginOffset;
|
||||
|
||||
// Don't delete right away
|
||||
return true; // isbeingremoved;
|
||||
}
|
||||
|
||||
#define REMAP_BLEND_TIME 0.5f
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : slot -
|
||||
// curtime -
|
||||
// outpos -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::RemapPosition( Vector &vecStart, float curtime, Vector& outpos )
|
||||
{
|
||||
outpos = vecStart;
|
||||
if ( curtime > m_Shared.GetSpawnTime() + REMAP_BLEND_TIME )
|
||||
return;
|
||||
|
||||
float frac = ( curtime - m_Shared.GetSpawnTime() ) / REMAP_BLEND_TIME;
|
||||
frac = 1.0f - clamp( frac, 0.0f, 1.0f );
|
||||
|
||||
Vector scaledOffset;
|
||||
VectorScale( m_vecGunOriginOffset, frac, scaledOffset );
|
||||
|
||||
outpos += scaledOffset;
|
||||
}
|
||||
|
||||
#define TIME_TILL_MAX_LENGTH 1.0
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Update state + render
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBasePlasmaProjectile::SimulateAndRender(Particle *pInParticle, ParticleDraw *pDraw, float &sortKey)
|
||||
{
|
||||
if ( IsDormantPredictable() )
|
||||
return true;
|
||||
|
||||
if ( GetMoveType() == MOVETYPE_NONE )
|
||||
return true;
|
||||
|
||||
// Update the particle position
|
||||
pInParticle->m_Pos = GetAbsOrigin();
|
||||
|
||||
// Add our blended offset
|
||||
if ( gpGlobals->curtime < m_Shared.GetSpawnTime() + REMAP_BLEND_TIME )
|
||||
{
|
||||
float frac = ( gpGlobals->curtime - m_Shared.GetSpawnTime() ) / REMAP_BLEND_TIME;
|
||||
frac = 1.0f - clamp( frac, 0.0f, 1.0f );
|
||||
Vector scaledOffset;
|
||||
VectorScale( m_vecGunOriginOffset, frac, scaledOffset );
|
||||
pInParticle->m_Pos += scaledOffset;
|
||||
}
|
||||
|
||||
float timeDelta = pDraw->GetTimeDelta();
|
||||
|
||||
// Render the head particle
|
||||
if ( pInParticle == m_pHeadParticle )
|
||||
{
|
||||
SimpleParticle *pParticle = (SimpleParticle *) pInParticle;
|
||||
pParticle->m_flLifetime += timeDelta;
|
||||
|
||||
// Render
|
||||
Vector tPos, vecOrigin;
|
||||
RemapPosition( m_pPreviousPositions[MAX_HISTORY-1].m_Position, m_pPreviousPositions[MAX_HISTORY-1].m_Time, vecOrigin );
|
||||
|
||||
TransformParticle( ParticleMgr()->GetModelView(), vecOrigin, tPos );
|
||||
sortKey = (int) tPos.z;
|
||||
|
||||
//Render it
|
||||
RenderParticle_ColorSizeAngle(
|
||||
pDraw,
|
||||
tPos,
|
||||
UpdateColor( pParticle, timeDelta ),
|
||||
UpdateAlpha( pParticle, timeDelta ) * GetAlphaDistanceFade( tPos, 16, 64 ),
|
||||
UpdateScale( pParticle, timeDelta ),
|
||||
UpdateRoll( pParticle, timeDelta ) );
|
||||
|
||||
/*
|
||||
if ( m_flNextSparkEffect < gpGlobals->curtime )
|
||||
{
|
||||
// Drop sparks?
|
||||
if ( GetTeamNumber() == TEAM_HUMANS )
|
||||
{
|
||||
g_pEffects->Sparks( pInParticle->m_Pos, 1, 3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pEffects->EnergySplash( pInParticle->m_Pos, vec3_origin );
|
||||
}
|
||||
m_flNextSparkEffect = gpGlobals->curtime + RandomFloat( 0.5, 2 );
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Render the trail
|
||||
TrailParticle *pParticle = (TrailParticle *) pInParticle;
|
||||
pParticle->m_flLifetime += timeDelta;
|
||||
Vector vecScreenStart, vecScreenDelta;
|
||||
sortKey = pParticle->m_Pos.z;
|
||||
|
||||
// NOTE: We need to do everything in screen space
|
||||
float flFragmentLength = (MAX_HISTORY > 1) ? 1.0 / (float)(MAX_HISTORY-1) : 1.0;
|
||||
|
||||
for ( int i = 0; i < (MAX_HISTORY-1); i++ )
|
||||
{
|
||||
Vector vecWorldStart, vecWorldEnd, vecScreenEnd;
|
||||
float flStartV, flEndV;
|
||||
|
||||
// Did we just appear?
|
||||
if ( m_pPreviousPositions[i].m_Time == 0 )
|
||||
continue;
|
||||
|
||||
RemapPosition( m_pPreviousPositions[i+1].m_Position, m_pPreviousPositions[i+1].m_Time, vecWorldStart );
|
||||
RemapPosition( m_pPreviousPositions[i].m_Position, m_pPreviousPositions[i].m_Time, vecWorldEnd );
|
||||
|
||||
// Texture wrapping
|
||||
flStartV = (flFragmentLength * (i+1));
|
||||
flEndV = (flFragmentLength * i);
|
||||
|
||||
TransformParticle( ParticleMgr()->GetModelView(), vecWorldStart, vecScreenStart );
|
||||
TransformParticle( ParticleMgr()->GetModelView(), vecWorldEnd, vecScreenEnd );
|
||||
Vector vecScreenDelta = (vecScreenEnd - vecScreenStart);
|
||||
if ( vecScreenDelta == vec3_origin )
|
||||
continue;
|
||||
|
||||
/*
|
||||
Vector vecForward, vecRight;
|
||||
AngleVectors( MainViewAngles(), &vecForward, &vecRight, NULL );
|
||||
Vector vecWorldDelta = ( vecWorldEnd - vecWorldStart );
|
||||
VectorNormalize( vecWorldDelta );
|
||||
float flDot = fabs(DotProduct( vecWorldDelta, vecForward ));
|
||||
if ( flDot > 0.99 )
|
||||
{
|
||||
// Remap alpha
|
||||
pParticle->m_flColor[3] = 1.0 - MIN( 1.0, RemapVal( flDot, 0.99, 1.0, 0, 1 ) );
|
||||
}
|
||||
*/
|
||||
|
||||
// See if we should fade
|
||||
float color[4];
|
||||
Color32ToFloat4( color, pParticle->m_color );
|
||||
Tracer_Draw( pDraw, vecScreenStart, vecScreenDelta, pParticle->m_flWidth, color, flStartV, flEndV );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
|
||||
{
|
||||
m_pParticleMgr = pParticleMgr;
|
||||
m_pParticleMgr->AddEffect( &m_ParticleEffect, this );
|
||||
|
||||
PMaterialHandle HeadMaterial, TrailMaterial;
|
||||
|
||||
// Load the projectile material
|
||||
if ( GetTeamNumber() == TEAM_HUMANS )
|
||||
{
|
||||
HeadMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/human_tracers/human_sparksprite_A1" );
|
||||
TrailMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/human_tracers/human_sparktracer_A_" );
|
||||
}
|
||||
else
|
||||
{
|
||||
HeadMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/alien_tracers/alien_pbsprite_A1" );
|
||||
TrailMaterial = m_ParticleEffect.FindOrAddMaterial( "effects/alien_tracers/alien_pbtracer_A_" );
|
||||
}
|
||||
|
||||
// Create the head & trail
|
||||
m_pHeadParticle = (SimpleParticle *)m_ParticleEffect.AddParticle(sizeof(SimpleParticle), HeadMaterial );
|
||||
m_pTrailParticle = (TrailParticle *)m_ParticleEffect.AddParticle(sizeof(TrailParticle), TrailMaterial );
|
||||
if ( !m_pHeadParticle || !m_pTrailParticle )
|
||||
return;
|
||||
|
||||
// 3rd person particles are larger
|
||||
bool bFirst = (GetOwnerEntity() == C_BasePlayer::GetLocalPlayer());
|
||||
|
||||
m_pHeadParticle->m_Pos = GetRenderOrigin();
|
||||
m_pHeadParticle->m_uchColor[0] = 255;
|
||||
m_pHeadParticle->m_uchColor[1] = 255;
|
||||
m_pHeadParticle->m_uchColor[2] = 255;
|
||||
if ( bFirst )
|
||||
{
|
||||
m_pHeadParticle->m_uchStartSize = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pHeadParticle->m_uchStartSize = shot_head_size.GetInt();
|
||||
}
|
||||
m_pHeadParticle->m_uchEndSize = m_pHeadParticle->m_uchStartSize;
|
||||
m_pHeadParticle->m_uchStartAlpha = 255;
|
||||
m_pHeadParticle->m_uchEndAlpha = 255;
|
||||
m_pHeadParticle->m_flRoll = 0;
|
||||
m_pHeadParticle->m_flRollDelta = 10;
|
||||
m_pHeadParticle->m_iFlags = 0;
|
||||
|
||||
m_pTrailParticle->m_flLifetime = 0;
|
||||
m_pTrailParticle->m_Pos = GetRenderOrigin();
|
||||
if ( bFirst )
|
||||
{
|
||||
m_pTrailParticle->m_flWidth = 25;
|
||||
m_pTrailParticle->m_flLength = 140;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pTrailParticle->m_flWidth = shot_width.GetFloat();
|
||||
m_pTrailParticle->m_flLength = shot_length.GetFloat();
|
||||
}
|
||||
Color32Init( m_pTrailParticle->m_color, 255, 255, 255, 255 );
|
||||
|
||||
m_flNextSparkEffect = gpGlobals->curtime + RandomFloat( 0.05, 0.4 );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Setup this projectile's starting values
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBasePlasmaProjectile::SetupProjectile( const Vector &vecOrigin, const Vector &vecForward, int damageType, CBaseEntity *pOwner )
|
||||
{
|
||||
UTIL_SetOrigin( this, vecOrigin );
|
||||
|
||||
QAngle angles;
|
||||
VectorAngles( vecForward, angles );
|
||||
SetLocalAngles( angles );
|
||||
|
||||
SetOwnerEntity( pOwner );
|
||||
Spawn();
|
||||
|
||||
float flMySpeed = PLASMA_VELOCITY;// + RandomFloat( -500, 500 );
|
||||
SetAbsVelocity( vecForward * flMySpeed );
|
||||
m_DamageType = damageType;
|
||||
m_Shared.Init( vecOrigin, vecForward, flMySpeed );
|
||||
#ifdef CLIENT_DLL
|
||||
ResetPositionHistories( GetAbsOrigin() );
|
||||
#endif
|
||||
m_Shared.SetSpawnTime( gpGlobals->curtime );
|
||||
|
||||
// Set my team
|
||||
ChangeTeam( pOwner->GetTeamNumber() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Create a missile
|
||||
//-----------------------------------------------------------------------------
|
||||
CBasePlasmaProjectile *CBasePlasmaProjectile::Create( const Vector &vecOrigin, const Vector &vecForward, int damageType, CBaseEntity *pOwner = NULL )
|
||||
{
|
||||
CBasePlasmaProjectile *pMissile = (CBasePlasmaProjectile*)CreateEntityByName("base_plasmaprojectile");
|
||||
pMissile->SetupProjectile( vecOrigin, vecForward, damageType, pOwner );
|
||||
|
||||
return pMissile;
|
||||
}
|
||||
|
||||
CBasePlasmaProjectile *CBasePlasmaProjectile::CreatePredicted( const Vector &vecOrigin, const Vector &vecForward, const Vector& gunOffset, int damageType, CBasePlayer *pOwner )
|
||||
{
|
||||
CBasePlasmaProjectile *pMissile = (CBasePlasmaProjectile*)CREATE_PREDICTED_ENTITY("base_plasmaprojectile");
|
||||
if ( pMissile )
|
||||
{
|
||||
pMissile->SetOwnerEntity( pOwner );
|
||||
pMissile->SetPlayerSimulated( pOwner );
|
||||
pMissile->SetupProjectile( vecOrigin, vecForward, damageType, pOwner );
|
||||
pMissile->m_vecGunOriginOffset = gunOffset;
|
||||
}
|
||||
|
||||
return pMissile;
|
||||
}
|
||||
|
||||
//===============================================================================================================
|
||||
// Power Projectile
|
||||
//===============================================================================================================
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Create a power projectile
|
||||
//-----------------------------------------------------------------------------
|
||||
CPowerPlasmaProjectile *CPowerPlasmaProjectile::Create( const Vector &vecOrigin, const Vector &vecForward, int damageType, CBaseEntity *pOwner = NULL )
|
||||
{
|
||||
CPowerPlasmaProjectile *pMissile = (CPowerPlasmaProjectile*)CreateEntityByName("powerplasmaprojectile");
|
||||
pMissile->SetupProjectile( vecOrigin, vecForward, damageType, pOwner );
|
||||
pMissile->SetPower( 1.0 );
|
||||
|
||||
return pMissile;
|
||||
}
|
||||
|
||||
CPowerPlasmaProjectile *CPowerPlasmaProjectile::CreatePredicted( const Vector &vecOrigin, const Vector &vecForward, const Vector& gunOffset, int damageType, CBasePlayer *pOwner )
|
||||
{
|
||||
CPowerPlasmaProjectile *pMissile = (CPowerPlasmaProjectile*)CREATE_PREDICTED_ENTITY("powerplasmaprojectile");
|
||||
if ( pMissile )
|
||||
{
|
||||
pMissile->SetOwnerEntity( pOwner );
|
||||
pMissile->SetPlayerSimulated( pOwner );
|
||||
pMissile->SetupProjectile( vecOrigin, vecForward, damageType, pOwner );
|
||||
pMissile->SetPower( 1.0 );
|
||||
pMissile->m_vecGunOriginOffset = gunOffset;
|
||||
}
|
||||
|
||||
return pMissile;
|
||||
}
|
||||
|
||||
CPowerPlasmaProjectile::CPowerPlasmaProjectile( void )
|
||||
{
|
||||
m_flPower = 0;
|
||||
SetPredictionEligible( true );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Factor power into size
|
||||
//-----------------------------------------------------------------------------
|
||||
float CPowerPlasmaProjectile::GetSize( void )
|
||||
{
|
||||
return ( 2 * (m_flPower * 2));
|
||||
}
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( PowerPlasmaProjectile, DT_PowerPlasmaProjectile);
|
||||
|
||||
BEGIN_NETWORK_TABLE( CPowerPlasmaProjectile, DT_PowerPlasmaProjectile)
|
||||
#if !defined( CLIENT_DLL )
|
||||
SendPropFloat( SENDINFO( m_flPower ), 7, SPROP_ROUNDDOWN, 1.0f, 10.0 ),
|
||||
#else
|
||||
RecvPropFloat(RECVINFO(m_flPower)),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( powerplasmaprojectile, CPowerPlasmaProjectile );
|
||||
PRECACHE_REGISTER(powerplasmaprojectile);
|
||||
|
||||
BEGIN_PREDICTION_DATA( CPowerPlasmaProjectile )
|
||||
|
||||
DEFINE_PRED_FIELD_TOL( m_flPower, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, 0.05f ),
|
||||
|
||||
END_PREDICTION_DATA()
|
||||
Reference in New Issue
Block a user