All pastes #498419 Raw Edit

SteveUK

public cpp v1 · immutable
·published 2007-05-20 12:19 UTC
rendered paste body
BEGIN_DATADESC( CMissile )	DEFINE_FIELD( m_hOwner,					FIELD_EHANDLE ),	DEFINE_FIELD( m_hRocketTrail,			FIELD_EHANDLE ),	DEFINE_FIELD( m_flAugerTime,			FIELD_TIME ),	DEFINE_FIELD( m_flMarkDeadTime,			FIELD_TIME ),	DEFINE_FIELD( m_flGracePeriodEndsAt,	FIELD_TIME ),	DEFINE_FIELD( m_flDamage,				FIELD_FLOAT ),		// Function Pointers	DEFINE_FUNCTION( MissileTouch ),	DEFINE_FUNCTION( AccelerateThink ),	DEFINE_FUNCTION( AugerThink ),	DEFINE_FUNCTION( IgniteThink ),	DEFINE_FUNCTION( SeekThink ),END_DATADESC()LINK_ENTITY_TO_CLASS( rpg_missile, CMissile );class CWeaponRPG;//-----------------------------------------------------------------------------// Constructor//-----------------------------------------------------------------------------CMissile::CMissile(){	m_hRocketTrail = NULL;}CMissile::~CMissile(){}//-----------------------------------------------------------------------------// Purpose: //////-----------------------------------------------------------------------------void CMissile::Precache( void ){	PrecacheModel( "models/weapons/w_missile.mdl" );	PrecacheModel( "models/weapons/w_missile_launch.mdl" );	PrecacheModel( "models/weapons/w_missile_closed.mdl" );}//-----------------------------------------------------------------------------// Purpose: //////-----------------------------------------------------------------------------void CMissile::Spawn( void ){	Precache();	SetSolid( SOLID_BBOX );	SetModel("models/weapons/w_missile_launch.mdl");	UTIL_SetSize( this, -Vector(4,4,4), Vector(4,4,4) );	SetTouch( &CMissile::MissileTouch );	SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );	SetThink( &CMissile::IgniteThink );		SetNextThink( gpGlobals->curtime + 0.3f );	m_takedamage = DAMAGE_YES;	m_iHealth = m_iMaxHealth = 100;	m_bloodColor = DONT_BLEED;	m_flGracePeriodEndsAt = 0;	AddFlag( FL_OBJECT );}//---------------------------------------------------------//---------------------------------------------------------void CMissile::Event_Killed( const CTakeDamageInfo &info ){	m_takedamage = DAMAGE_NO;	ShotDown();}unsigned int CMissile::PhysicsSolidMaskForEntity( void ) const{ 	return BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX;}//---------------------------------------------------------//---------------------------------------------------------int CMissile::OnTakeDamage_Alive( const CTakeDamageInfo &info ){	if ( ( info.GetDamageType() & (DMG_MISSILEDEFENSE | DMG_AIRBOAT) ) == false )		return 0;	bool bIsDamaged;	if( m_iHealth <= AugerHealth() )	{		// This missile is already damaged (i.e., already running AugerThink)		bIsDamaged = true;	}	else	{		// This missile isn't damaged enough to wobble in flight yet		bIsDamaged = false;	}		int nRetVal = BaseClass::OnTakeDamage_Alive( info );	if( !bIsDamaged )	{		if ( m_iHealth <= AugerHealth() )		{			ShotDown();		}	}	return nRetVal;}//-----------------------------------------------------------------------------// Purpose: Stops any kind of tracking and shoots dumb//-----------------------------------------------------------------------------void CMissile::DumbFire( void ){	SetThink( NULL );	SetMoveType( MOVETYPE_FLY );	SetModel("models/weapons/w_missile.mdl");	UTIL_SetSize( this, vec3_origin, vec3_origin );	EmitSound( "Missile.Ignite" );	// Smoke trail.	CreateSmokeTrail();}//-----------------------------------------------------------------------------// Purpose: //-----------------------------------------------------------------------------void CMissile::SetGracePeriod( float flGracePeriod ){	m_flGracePeriodEndsAt = gpGlobals->curtime + flGracePeriod;	// Go non-solid until the grace period ends	AddSolidFlags( FSOLID_NOT_SOLID );}//---------------------------------------------------------//---------------------------------------------------------void CMissile::AccelerateThink( void ){	Vector vecForward;	// !!!UNDONE - make this work exactly the same as HL1 RPG, lest we have looping sound bugs again!	EmitSound( "Missile.Accelerate" );	// SetEffects( EF_LIGHT );	AngleVectors( GetLocalAngles(), &vecForward );	SetAbsVelocity( vecForward * RPG_SPEED );	SetThink( &CMissile::SeekThink );	SetNextThink( gpGlobals->curtime + 0.1f );}#define AUGER_YDEVIANCE 20.0f#define AUGER_XDEVIANCEUP 8.0f#define AUGER_XDEVIANCEDOWN 1.0f//---------------------------------------------------------//---------------------------------------------------------void CMissile::AugerThink( void ){	// If we've augered long enough, then just explode	if ( m_flAugerTime < gpGlobals->curtime )	{		Explode();		return;	}	if ( m_flMarkDeadTime < gpGlobals->curtime )	{		m_lifeState = LIFE_DYING;	}	QAngle angles = GetLocalAngles();	angles.y += random->RandomFloat( -AUGER_YDEVIANCE, AUGER_YDEVIANCE );	angles.x += random->RandomFloat( -AUGER_XDEVIANCEDOWN, AUGER_XDEVIANCEUP );	SetLocalAngles( angles );	Vector vecForward;	AngleVectors( GetLocalAngles(), &vecForward );		SetAbsVelocity( vecForward * 1000.0f );	SetNextThink( gpGlobals->curtime + 0.05f );}//-----------------------------------------------------------------------------// Purpose: Causes the missile to spiral to the ground and explode, due to damage//-----------------------------------------------------------------------------void CMissile::ShotDown( void ){	CEffectData	data;	data.m_vOrigin = GetAbsOrigin();	DispatchEffect( "RPGShotDown", data );	if ( m_hRocketTrail != NULL )	{		m_hRocketTrail->m_bDamaged = true;	}	SetThink( &CMissile::AugerThink );	SetNextThink( gpGlobals->curtime );	m_flAugerTime = gpGlobals->curtime + 1.5f;	m_flMarkDeadTime = gpGlobals->curtime + 0.75;	// Let the RPG start reloading immediately	if ( m_hOwner != NULL )	{		m_hOwner->NotifyRocketDied();		m_hOwner = NULL;	}}//-----------------------------------------------------------------------------// The actual explosion //-----------------------------------------------------------------------------void CMissile::DoExplosion( void ){	// Explode	ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), GetDamage(), GetDamage() * 2, 		SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, this);}//-----------------------------------------------------------------------------// Purpose: //-----------------------------------------------------------------------------void CMissile::Explode( void ){	// Don't explode against the skybox. Just pretend that 	// the missile flies off into the distance.	Vector forward;	GetVectors( &forward, NULL, NULL );	trace_t tr;	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + forward * 16, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );	m_takedamage = DAMAGE_NO;	SetSolid( SOLID_NONE );	if( tr.fraction == 1.0 || !(tr.surface.flags & SURF_SKY) )	{		DoExplosion();	}	if( m_hRocketTrail )	{		m_hRocketTrail->SetLifetime(0.1f);		m_hRocketTrail = NULL;	}	if ( m_hOwner != NULL )	{		m_hOwner->NotifyRocketDied();		m_hOwner = NULL;	}	StopSound( "Missile.Ignite" );	UTIL_Remove( this );}//-----------------------------------------------------------------------------// Purpose: // Input  : *pOther - //-----------------------------------------------------------------------------void CMissile::MissileTouch( CBaseEntity *pOther ){	Assert( pOther );		// Don't touch triggers (but DO hit weapons)	if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER|FSOLID_VOLUME_CONTENTS) && pOther->GetCollisionGroup() != COLLISION_GROUP_WEAPON )		return;	Explode();}//-----------------------------------------------------------------------------// Purpose: //-----------------------------------------------------------------------------void CMissile::CreateSmokeTrail( void ){	if ( m_hRocketTrail )		return;	// Smoke trail.	if ( (m_hRocketTrail = RocketTrail::CreateRocketTrail()) != NULL )	{		m_hRocketTrail->m_Opacity = 0.2f;		m_hRocketTrail->m_SpawnRate = 100;		m_hRocketTrail->m_ParticleLifetime = 0.5f;		m_hRocketTrail->m_StartColor.Init( 0.65f, 0.65f , 0.65f );		m_hRocketTrail->m_EndColor.Init( 0.0, 0.0, 0.0 );		m_hRocketTrail->m_StartSize = 8;		m_hRocketTrail->m_EndSize = 32;		m_hRocketTrail->m_SpawnRadius = 4;		m_hRocketTrail->m_MinSpeed = 2;		m_hRocketTrail->m_MaxSpeed = 16;				m_hRocketTrail->SetLifetime( 999 );		m_hRocketTrail->FollowEntity( this, "0" );	}}//-----------------------------------------------------------------------------// Purpose: //-----------------------------------------------------------------------------void CMissile::IgniteThink( void ){	SetMoveType( MOVETYPE_FLY );	SetModel("models/weapons/w_missile.mdl");	UTIL_SetSize( this, vec3_origin, vec3_origin ); 	RemoveSolidFlags( FSOLID_NOT_SOLID );	//TODO: Play opening sound	Vector vecForward;	EmitSound( "Missile.Ignite" );	AngleVectors( GetLocalAngles(), &vecForward );	SetAbsVelocity( vecForward * RPG_SPEED );	SetThink( &CMissile::SeekThink );	SetNextThink( gpGlobals->curtime );	if ( m_hOwner && m_hOwner->GetOwner() )	{		CBasePlayer *pPlayer = ToBasePlayer( m_hOwner->GetOwner() );		color32 white = { 255,225,205,64 };		UTIL_ScreenFade( pPlayer, white, 0.1f, 0.0f, FFADE_IN );	}	CreateSmokeTrail();}//-----------------------------------------------------------------------------// Gets the shooting position //-----------------------------------------------------------------------------void CMissile::GetShootPosition( CLaserDot *pLaserDot, Vector *pShootPosition ){	if ( pLaserDot->GetOwnerEntity() != NULL )	{		//FIXME: Do we care this isn't exactly the muzzle position?		*pShootPosition = pLaserDot->GetOwnerEntity()->WorldSpaceCenter();	}	else	{		*pShootPosition = pLaserDot->GetChasePosition();	}}	//-----------------------------------------------------------------------------// Purpose: //-----------------------------------------------------------------------------#define	RPG_HOMING_SPEED	0.125fvoid CMissile::ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ){	*pHomingSpeed = RPG_HOMING_SPEED;	if ( pLaserDot->GetTargetEntity() )	{		*pActualDotPosition = pLaserDot->GetChasePosition();		return;	}	Vector vLaserStart;	GetShootPosition( pLaserDot, &vLaserStart );	//Get the laser's vector	Vector vLaserDir;	VectorSubtract( pLaserDot->GetChasePosition(), vLaserStart, vLaserDir );		//Find the length of the current laser	float flLaserLength = VectorNormalize( vLaserDir );		//Find the length from the missile to the laser's owner	float flMissileLength = GetAbsOrigin().DistTo( vLaserStart );	//Find the length from the missile to the laser's position	Vector vecTargetToMissile;	VectorSubtract( GetAbsOrigin(), pLaserDot->GetChasePosition(), vecTargetToMissile ); 	float flTargetLength = VectorNormalize( vecTargetToMissile );	// See if we should chase the line segment nearest us	if ( ( flMissileLength < flLaserLength ) || ( flTargetLength <= 512.0f ) )	{		*pActualDotPosition = UTIL_PointOnLineNearestPoint( vLaserStart, pLaserDot->GetChasePosition(), GetAbsOrigin() );		*pActualDotPosition += ( vLaserDir * 256.0f );	}	else	{		// Otherwise chase the dot		*pActualDotPosition = pLaserDot->GetChasePosition();	}//	NDebugOverlay::Line( pLaserDot->GetChasePosition(), vLaserStart, 0, 255, 0, true, 0.05f );//	NDebugOverlay::Line( GetAbsOrigin(), *pActualDotPosition, 255, 0, 0, true, 0.05f );//	NDebugOverlay::Cross3D( *pActualDotPosition, -Vector(4,4,4), Vector(4,4,4), 255, 0, 0, true, 0.05f );}//-----------------------------------------------------------------------------// Purpose: //-----------------------------------------------------------------------------void CMissile::SeekThink( void ){	CBaseEntity	*pBestDot	= NULL;	float		flBestDist	= MAX_TRACE_LENGTH;	float		dotDist;	// If we have a grace period, go solid when it ends	if ( m_flGracePeriodEndsAt )	{		if ( m_flGracePeriodEndsAt < gpGlobals->curtime )		{			RemoveSolidFlags( FSOLID_NOT_SOLID );			m_flGracePeriodEndsAt = 0;		}	}	//Search for all dots relevant to us	for( CLaserDot *pEnt = GetLaserDotList(); pEnt != NULL; pEnt = pEnt->m_pNext )	{		if ( !pEnt->IsOn() )			continue;		if ( pEnt->GetOwnerEntity() != GetOwnerEntity() )			continue;		dotDist = (GetAbsOrigin() - pEnt->GetAbsOrigin()).Length();		//Find closest		if ( dotDist < flBestDist )		{			pBestDot	= pEnt;			flBestDist	= dotDist;		}	}	//If we have a dot target	if ( pBestDot == NULL )	{		//Think as soon as possible		SetNextThink( gpGlobals->curtime );		return;	}	CLaserDot *pLaserDot = (CLaserDot *)pBestDot;	Vector	targetPos;	float flHomingSpeed; 	Vector vecLaserDotPosition;	ComputeActualDotPosition( pLaserDot, &targetPos, &flHomingSpeed );	if ( IsSimulatingOnAlternateTicks() )		flHomingSpeed *= 2;	Vector	vTargetDir;	VectorSubtract( targetPos, GetAbsOrigin(), vTargetDir );	float flDist = VectorNormalize( vTargetDir );	Vector	vDir	= GetAbsVelocity();	float	flSpeed	= VectorNormalize( vDir );	Vector	vNewVelocity = vDir;	if ( gpGlobals->frametime > 0.0f )	{		if ( flSpeed != 0 )		{			vNewVelocity = ( flHomingSpeed * vTargetDir ) + ( ( 1 - flHomingSpeed ) * vDir );			// This computation may happen to cancel itself out exactly. If so, slam to targetdir.			if ( VectorNormalize( vNewVelocity ) < 1e-3 )			{				vNewVelocity = (flDist != 0) ? vTargetDir : vDir;			}		}		else		{			vNewVelocity = vTargetDir;		}	}	QAngle	finalAngles;	VectorAngles( vNewVelocity, finalAngles );	SetAbsAngles( finalAngles );	vNewVelocity *= flSpeed;	SetAbsVelocity( vNewVelocity );	if( GetAbsVelocity() == vec3_origin )	{		// Strange circumstances have brought this missile to halt. Just blow it up.		Explode();		return;	}	// Think as soon as possible	SetNextThink( gpGlobals->curtime );}//-----------------------------------------------------------------------------// Purpose: //// Input  : &vecOrigin - //			&vecAngles - //			NULL - //// Output : CMissile//-----------------------------------------------------------------------------CMissile *CMissile::Create( const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner = NULL ){	//CMissile *pMissile = (CMissile *)CreateEntityByName("rpg_missile" );	CMissile *pMissile = (CMissile *) CBaseEntity::Create( "rpg_missile", vecOrigin, vecAngles, CBaseEntity::Instance( pentOwner ) );	pMissile->SetOwnerEntity( Instance( pentOwner ) );	pMissile->Spawn();	pMissile->AddEffects( EF_NOSHADOW );		Vector vecForward;	AngleVectors( vecAngles, &vecForward );	pMissile->SetAbsVelocity( vecForward * 300 + Vector( 0,0, 128 ) );	return pMissile;}