⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tf_shield_mobile_shared.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// Set the shield angles
//-----------------------------------------------------------------------------
void CShieldMobile::SetCenterAngles( const QAngle& angles )
{
	// The tmp ang locked angles is simply there to prevent unnecessary network traffic
	m_tmpAngLockedAngles = angles;
	if ( ( m_ShieldState.Get() & SHIELD_ORIENT_TO_OWNER ) == 0 ) 
	{
		m_angLockedAngles.Set( angles );
	}
}

bool CShieldMobile::IsAlwaysOrienting( )
{
	return ( m_ShieldState.Get() & SHIELD_ORIENT_TO_OWNER ) != 0;
}

void CShieldMobile::SetAngularSpringConstant( float flConstant )
{
	m_flSpringConstant = flConstant;
	m_ShieldEffect.SetAngularSpringConstant( flConstant );
}

void CShieldMobile::SetFrontDistance( float flDistance )
{
	m_flFrontDistance = flDistance;
}

void CShieldMobile::SetThetaPhi( float flTheta, float flPhi )
{ 
	// This sets the bounds of the shield; how tall + wide is it?
	m_flShieldTheta = flTheta;
	m_flShieldPhi = flPhi;
	m_ShieldEffect.SetThetaPhi(flTheta, flPhi); 
}


//-----------------------------------------------------------------------------
// Computes the shield bounding box
//-----------------------------------------------------------------------------
void CShieldMobile::ComputeBoundingBox( void )
{
	Vector mins, maxs;
	m_ShieldEffect.ComputeBounds(mins, maxs); 
#ifdef CLIENT_DLL
	SetCollisionBounds( mins, maxs );
	Relink();
#else
	UTIL_SetSize( this, mins, maxs );
#endif
}


//-----------------------------------------------------------------------------
// Computes a surrounding box the the entity
//-----------------------------------------------------------------------------
void CShieldMobile::SetObjectCollisionBox( void )
{
	SetAbsMins( WorldAlignMins() + GetAbsOrigin() );
	SetAbsMaxs( WorldAlignMaxs() + GetAbsOrigin() );
}


//-----------------------------------------------------------------------------
// Determines shield obstructions 
//-----------------------------------------------------------------------------
void CShieldMobile::DetermineObstructions( )
{
	m_ShieldEffect.ComputeVertexActivity();
}


//-----------------------------------------------------------------------------
// Called by the enumerator call in ShieldThink 
//-----------------------------------------------------------------------------
bool CShieldMobile::EnumEntity( IHandleEntity *pHandleEntity )
{
#ifdef CLIENT_DLL
	CBaseEntity *pOther = cl_entitylist->GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() );
#else
	CBaseEntity *pOther = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() );
#endif

	if (!pOther)
		return true;

	// Blow off non-solid things
	if ( !::IsSolid(pOther->GetSolid(), pOther->GetSolidFlags()) )
		return true;

	// No model, blow it off
	if ( !pOther->GetModelIndex() )
		return true;
	
	// Blow off point-sized things....
	if ( pOther->IsPointSized() )
		return true;

	// Don't bother if we shouldn't be colliding with this guy...
	if (!m_pEnumCtx->m_Filter.ShouldHitEntity( pOther, MASK_SOLID ))
		return true;

	// The shield is in its final position, so we're gonna have to determine the
	// point of collision by working in the space of the final position....
	// We do this by moving the obstruction by the relative movement amount...
	Vector vecStart, vecEnd;
	VectorAdd( pOther->GetAbsOrigin(), m_pEnumCtx->m_vecStartDelta, vecStart );
	VectorAdd( vecStart, m_pEnumCtx->m_vecEndDelta, vecEnd );

	Ray_t ray;
	ray.Init( vecStart, vecEnd, pOther->WorldAlignMins(), pOther->WorldAlignMaxs() );

	trace_t tr;
	if (TestCollision( ray, pOther->PhysicsSolidMaskForEntity(), tr ))
	{
		// Ok, we got a collision. Let's indicate it happened...
		// At the moment, we'll report the collision point as being on the
		// surface of the shield in its final position, which is kind of bogus...
		pOther->PhysicsImpact( this, tr );
	}

	return true;
}


//-----------------------------------------------------------------------------
// Update the shield position: 
//-----------------------------------------------------------------------------
void CShieldMobile::SimulateShield( void )
{
	CBaseEntity *owner = GetOwnerEntity();
	Vector origin;
	if ( owner )
	{
		if ( m_ShieldState & SHIELD_ORIENT_TO_OWNER ) 
		{
			if ( owner->IsPlayer() )
			{
				m_ShieldEffect.SetDesiredAngles( owner->EyeAngles() );
			}
			else
			{
				m_ShieldEffect.SetDesiredAngles( owner->GetAbsAngles() );
			}
		}
		else
		{
			m_ShieldEffect.SetDesiredAngles( m_angLockedAngles );
		}

		if ( m_nAttachmentIndex == 0 )
		{
			origin = owner->EyePosition();
		}
		else
		{
			QAngle angles;
			CBaseAnimating *pAnim = dynamic_cast<CBaseAnimating*>( owner );
			if (pAnim)
			{
				pAnim->GetAttachment( m_nAttachmentIndex, origin, angles );
			}
			else
			{
				origin = owner->EyePosition();
			}
		}

		if ( m_flFrontDistance )
		{
			Vector vForward;
			AngleVectors( m_ShieldEffect.GetDesiredAngles(), &vForward );
			origin += vForward * m_flFrontDistance;
		}
	}
	else
	{
		Assert( 0 );
		origin = vec3_origin;
	}

	Vector vecOldOrigin = m_ShieldEffect.GetCurrentPosition();
	
	Vector vecDelta;
	VectorSubtract( origin, vecOldOrigin, vecDelta );

	float flMaxDist = 100 + m_flFrontDistance;
	if (vecDelta.LengthSqr() > flMaxDist * flMaxDist )
	{
		OnTeleported();
		return;
	}

	m_ShieldEffect.SetDesiredOrigin( origin );
	m_ShieldEffect.Simulate(gpGlobals->frametime);
	DetermineObstructions();
	SetAbsOrigin( m_ShieldEffect.GetCurrentPosition() );
	SetAbsAngles( m_ShieldEffect.GetCurrentAngles() );

#ifdef CLIENT_DLL
	// Necessary because we exclude the network origin
	SetNetworkOrigin( m_ShieldEffect.GetCurrentPosition() );
	SetNetworkAngles( m_ShieldEffect.GetCurrentAngles() );
#endif

	// Compute a composite bounding box surrounding the initial + new positions..
	Vector vecCompositeMins = WorldAlignMins() + vecOldOrigin;
	Vector vecCompositeMaxs = WorldAlignMaxs() + vecOldOrigin;

	ComputeBoundingBox();

	// Sweep the shield through the world + touch things it hits...
	SweepContext_t ctx( this, GetCollisionGroup() );
	VectorSubtract( GetAbsOrigin(), vecOldOrigin, ctx.m_vecStartDelta );

	if (ctx.m_vecStartDelta != vec3_origin)
	{
		// FIXME: Brutal hack; needed because IntersectRayWithTriangle misses stuff
		// especially with short rays; I'm not sure what to do about this.
		// This basically simulates a shield thickness of 15 units
		ctx.m_vecEndDelta = ctx.m_vecStartDelta;
		VectorNormalize( ctx.m_vecEndDelta );
		ctx.m_vecEndDelta *= -15.0f;

		Vector vecNewMins = WorldAlignMins() + GetAbsOrigin();
		Vector vecNewMaxs = WorldAlignMaxs() + GetAbsOrigin();
		VectorMin( vecCompositeMins, vecNewMins, vecCompositeMins );
		VectorMax( vecCompositeMaxs, vecNewMaxs, vecCompositeMaxs );

		m_pEnumCtx = &ctx;
		enginetrace->EnumerateEntities( vecCompositeMins, vecCompositeMaxs, this );
	}
}


//-----------------------------------------------------------------------------
// Update the shield position: 
//-----------------------------------------------------------------------------
void CShieldMobile::ShieldThink( void )
{
	SimulateShield();

#ifdef CLIENT_DLL
	m_ShieldEffect.ComputeControlPoints();
	m_ShieldEffect.ComputePanelActivity();
#endif

	SetNextThink( gpGlobals->curtime + 0.01f );
}

void CShieldMobile::ClientThink()
{
#ifdef CLIENT_DLL
	if ( GetPredictable() )
		return;

	SimulateShield();
	m_ShieldEffect.ComputeControlPoints();
	m_ShieldEffect.ComputePanelActivity();
#endif
}


//-----------------------------------------------------------------------------
// Teleport!
//-----------------------------------------------------------------------------
void CShieldMobile::OnTeleported(  )
{
	CBaseEntity *owner = GetOwnerEntity();
	if (!owner)
		return;

	m_ShieldEffect.SetCurrentAngles( owner->GetAbsAngles() );

	Vector origin;
	origin = owner->EyePosition();
	if ( m_flFrontDistance )
	{
		Vector vForward;
		AngleVectors( m_ShieldEffect.GetCurrentAngles(), &vForward );
		origin += vForward * m_flFrontDistance;
	}

	m_ShieldEffect.SetCurrentPosition( origin );
}



#ifdef CLIENT_DLL

//-----------------------------------------------------------------------------
// Get this after the data changes
//-----------------------------------------------------------------------------
void CShieldMobile::OnDataChanged( DataUpdateType_t updateType )
{
	BaseClass::OnDataChanged( updateType );
	m_ShieldEffect.SetThetaPhi( m_flShieldTheta, m_flShieldPhi );
	m_ShieldEffect.SetAngularSpringConstant( m_flSpringConstant );
}


//-----------------------------------------------------------------------------
// A little pre-render processing
//-----------------------------------------------------------------------------
void C_ShieldMobile::PreRender( )
{
	if (m_ShieldState & SHIELD_MOBILE_EMP)
	{
		// Decay fade if we've been EMPed or if we're inactive
		if (m_FadeValue > 0.0f)
		{
			m_FadeValue -= gpGlobals->frametime / SHIELD_EMP_FADE_TIME;
			if (m_FadeValue < 0.0f)
			{
				m_FadeValue = 0.0f;

				// Reset the shield to un-wobbled state
				m_ShieldEffect.ComputeControlPoints();
			}
			else
			{
				Vector dir;
				AngleVectors( m_ShieldEffect.GetCurrentAngles(), & dir, 0, 0 );

				// Futz with the control points if we've been EMPed
				for (int i = 0; i < SHIELD_NUM_CONTROL_POINTS; ++i)
				{
					// Get the direction for the point
					float factor = -EMP_WAVE_AMPLITUDE * sin( i * M_PI * 0.5f + gpGlobals->curtime * M_PI / SHIELD_EMP_WOBBLE_TIME );
					m_ShieldEffect.GetPoint(i) += dir * factor;
				}
			}
		}
	}
	else
	{
		// Fade back in, no longer EMPed
		if (m_FadeValue < 1.0f)
		{
			m_FadeValue += gpGlobals->frametime / SHIELD_EMP_FADE_TIME;
			if (m_FadeValue >= 1.0f)
			{
				m_FadeValue = 1.0f;
			}
		}
	}
}

void CShieldMobile::AddEntity( )
{
	BaseClass::AddEntity( );
	PreRender();
}


//-----------------------------------------------------------------------------
// Bounds computation
//-----------------------------------------------------------------------------
void CShieldMobile::GetBounds( Vector& mins, Vector& maxs )
{
	m_ShieldEffect.ComputeBounds( mins, maxs );
}


//-----------------------------------------------------------------------------
// Gets at the control point data; who knows how it was made?
//-----------------------------------------------------------------------------
void CShieldMobile::GetShieldData( const Vector** ppVerts, float* pOpacity, float* pBlend )
{
	for ( int i = 0; i < SHIELD_NUM_CONTROL_POINTS; ++i )
	{
		ppVerts[i] = &m_ShieldEffect.GetControlPoint(i);

		if ( m_pVertsActive[i >> 3] & (1 << (i & 0x7)) )
		{
			pOpacity[i] = m_ShieldEffect.ComputeOpacity( *ppVerts[i], GetAbsOrigin() );
			pBlend[i] = 1.0f;
		}
		else
		{
			pOpacity[i] = 192.0f;
			pBlend[i] = 0.0f;
		}
	}
}


#endif // CLIENT_DLL


#ifndef CLIENT_DLL

//-----------------------------------------------------------------------------
// Purpose: Create a mobile version of the shield
//-----------------------------------------------------------------------------
CShield *CreateMobileShield( CBaseEntity *owner, float flFrontDistance )
{
	CShieldMobile *pShield = (CShieldMobile*)CreateEntityByName("shield_mobile");

	pShield->SetOwnerEntity( owner );
	pShield->SetLocalAngles( owner->GetAbsAngles() );
	pShield->SetFrontDistance( flFrontDistance );

	// Start it in the right place
	Vector vForward;
	AngleVectors( owner->GetAbsAngles(), &vForward );
	Vector vecOrigin = owner->EyePosition() + (vForward * flFrontDistance);
	UTIL_SetOrigin( pShield, vecOrigin );

	pShield->ChangeTeam( owner->GetTeamNumber() );
	pShield->SetupRecharge( shield_mobile_power.GetFloat(), shield_mobile_recharge_delay.GetFloat(), shield_mobile_recharge_amount.GetFloat(), shield_mobile_recharge_time.GetFloat() );
	pShield->Spawn();

	return pShield;
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -