📄 tf_shield_mobile.cpp
字号:
}
//-----------------------------------------------------------------------------
// Set the shield angles
//-----------------------------------------------------------------------------
void CShieldMobile::SetCenterAngles( const QAngle &angles )
{
m_ShieldEffect.SetAngles( angles );
}
void CShieldMobile::SetAngularSpringConstant( float flConstant )
{
m_ShieldEffect.SetAngularSpringConstant( flConstant );
}
void CShieldMobile::SetFrontDistance( float flDistance )
{
m_flFrontDistance = flDistance;
}
//-----------------------------------------------------------------------------
// Computes the shield bounding box
//-----------------------------------------------------------------------------
void CShieldMobile::ComputeBoundingBox( void )
{
Vector mins, maxs;
m_ShieldEffect.ComputeBounds(mins, maxs);
UTIL_SetSize( this, mins, maxs );
}
//-----------------------------------------------------------------------------
// Purpose: Initialize absmin & absmax to the appropriate box
//-----------------------------------------------------------------------------
void CShieldMobile::SetObjectCollisionBox( void )
{
if ( !pev )
return;
SetAbsMins( GetAbsOrigin() + WorldAlignMins() );
SetAbsMaxs( GetAbsOrigin() + WorldAlignMaxs() );
}
//-----------------------------------------------------------------------------
// Determines shield obstructions
//-----------------------------------------------------------------------------
void CShieldMobile::DetermineObstructions( )
{
// Vector mins, maxs;
// m_ShieldEffect.ComputeBounds( mins, maxs );
// VectorMin( mins, m_ShieldEffect.GetCurrentPosition(), mins );
// VectorMax( maxs, m_ShieldEffect.GetCurrentPosition(), maxs );
// engine->BeginTraceSubtree( mins, maxs );
m_ShieldEffect.ComputeVertexActivity();
// engine->EndTraceSubtree( );
}
//-----------------------------------------------------------------------------
// Called by the enumerator call in ShieldThink
//-----------------------------------------------------------------------------
bool CShieldMobile::EnumEntity( IHandleEntity *pHandleEntity )
{
CBaseEntity *pOther = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() );
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->GetSize() == vec3_origin )
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::ShieldThink( void )
{
CBaseEntity *owner = GetOwnerEntity();
Vector origin;
if ( owner )
{
if ( m_bAlwaysOrientToOwner )
{
SetCenterAngles( owner->GetAbsAngles() );
}
origin = owner->EyePosition();
if ( m_flFrontDistance )
{
Vector vForward;
AngleVectors( m_ShieldEffect.GetAngles(), &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 )
{
Teleported();
SetNextThink( gpGlobals->curtime + 0.01f )
return;
}
m_ShieldEffect.SetOrigin( origin );
m_ShieldEffect.Simulate(gpGlobals->frametime);
DetermineObstructions();
SetAbsOrigin( m_ShieldEffect.GetCurrentPosition() );
SetAbsAngles( m_ShieldEffect.GetCurrentAngles() );
// 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 );
}
// Always think
SetNextThink( gpGlobals->curtime + 0.01f );
}
//-----------------------------------------------------------------------------
// Teleport!
//-----------------------------------------------------------------------------
void CShieldMobile::Teleported( )
{
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 );
}
//-----------------------------------------------------------------------------
// Purpose: Create a mobile version of the shield
//-----------------------------------------------------------------------------
CShield *CreateMobileShield( CBaseEntity *owner, float flFrontDistance )
{
CShieldMobile *pShield = (CShieldMobile*)CreateEntityByName("shield_mobile");
pShield->SetOwnerEntity( owner );
pShield->SetCenterAngles( owner->GetAbsAngles() );
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -