You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
4.8 KiB
182 lines
4.8 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// eyeball_boss_launch_rockets.cpp |
|
// The 2011 Halloween Boss |
|
// Michael Booth, October 2011 |
|
|
|
#include "cbase.h" |
|
|
|
#include "tf_projectile_rocket.h" |
|
#include "tf_obj_sentrygun.h" |
|
|
|
#include "../eyeball_boss.h" |
|
#include "eyeball_boss_launch_rockets.h" |
|
|
|
|
|
//--------------------------------------------------------------------------------------------- |
|
ActionResult< CEyeballBoss > CEyeballBossLaunchRockets::OnStart( CEyeballBoss *me, Action< CEyeballBoss > *priorAction ) |
|
{ |
|
if ( me->GetVictim() == NULL ) |
|
{ |
|
return Done( "No target" ); |
|
} |
|
|
|
m_lastTargetPosition = me->GetVictim()->GetAbsOrigin(); |
|
|
|
const char *firingAnimation = NULL; |
|
|
|
if ( me->IsEnraged() ) |
|
{ |
|
m_rocketsLeft = 3; |
|
m_initialDelayTimer.Start( 0.25f ); |
|
firingAnimation = "firing3"; |
|
|
|
me->EmitSound( "Halloween.EyeballBossRage" ); |
|
} |
|
else if ( me->IsGrumpy() ) |
|
{ |
|
m_rocketsLeft = 3; |
|
m_initialDelayTimer.Start( 0.25f ); |
|
firingAnimation = "firing2"; |
|
} |
|
else |
|
{ |
|
m_rocketsLeft = 1; |
|
m_initialDelayTimer.Start( 0.5f ); |
|
firingAnimation = "firing1"; |
|
} |
|
|
|
int animSequence = me->LookupSequence( firingAnimation ); |
|
if ( animSequence ) |
|
{ |
|
me->SetSequence( animSequence ); |
|
me->SetPlaybackRate( 1.0f ); |
|
me->SetCycle( 0 ); |
|
me->ResetSequenceInfo(); |
|
} |
|
|
|
return Continue(); |
|
} |
|
|
|
|
|
//--------------------------------------------------------------------------------------------- |
|
ActionResult< CEyeballBoss > CEyeballBossLaunchRockets::Update( CEyeballBoss *me, float interval ) |
|
{ |
|
if ( me->GetVictim() && me->GetVictim()->IsAlive() ) |
|
{ |
|
m_lastTargetPosition = me->GetVictim()->GetAbsOrigin(); |
|
|
|
// target upper part of sentry guns |
|
if ( me->GetVictim()->IsBaseObject() ) |
|
{ |
|
CObjectSentrygun *sentry = dynamic_cast< CObjectSentrygun * >( const_cast< CBaseCombatCharacter * >( me->GetVictim() ) ); |
|
if ( sentry ) |
|
{ |
|
m_lastTargetPosition = sentry->EyePosition(); |
|
} |
|
} |
|
|
|
// circle around them |
|
Vector forward, right; |
|
me->GetVectors( &forward, &right, NULL ); |
|
|
|
me->GetLocomotionInterface()->SetDesiredSpeed( tf_eyeball_boss_speed.GetFloat() ); |
|
|
|
if ( !me->IsSpell() ) |
|
{ |
|
if ( me->GetVictim()->entindex() & 0x1 ) |
|
{ |
|
me->GetLocomotionInterface()->Approach( 100.0f * right + me->WorldSpaceCenter() ); |
|
} |
|
else |
|
{ |
|
me->GetLocomotionInterface()->Approach( -100.0f * right + me->WorldSpaceCenter() ); |
|
} |
|
} |
|
|
|
me->GetBodyInterface()->AimHeadTowards( me->GetVictim() ); |
|
} |
|
else |
|
{ |
|
me->GetBodyInterface()->AimHeadTowards( m_lastTargetPosition ); |
|
} |
|
|
|
// fire rockets |
|
if ( m_initialDelayTimer.IsElapsed() && m_launchTimer.IsElapsed() ) |
|
{ |
|
--m_rocketsLeft; |
|
m_launchTimer.Start( 0.3f ); |
|
|
|
const float rocketDamage = 50.0f; |
|
|
|
// if I'm enraged, shoot full speed rockets, otherwise shoot slow ones |
|
float speedFactor = me->IsEnraged() ? 1.0f : 0.3f; |
|
float rocketSpeed = 1100.0f * speedFactor; |
|
|
|
Vector targetSpot = m_lastTargetPosition; |
|
|
|
if ( me->IsEnraged() && me->GetVictim() ) |
|
{ |
|
// lead our target |
|
float rangeBetween = me->GetRangeTo( targetSpot ); |
|
|
|
const float veryCloseRange = 150.0f; |
|
if ( rangeBetween > veryCloseRange ) |
|
{ |
|
float timeToTravel = rangeBetween / rocketSpeed; |
|
|
|
Vector leadOffset = timeToTravel * me->GetVictim()->GetAbsVelocity(); |
|
|
|
CTraceFilterNoNPCsOrPlayer filter( me, COLLISION_GROUP_NONE ); |
|
trace_t result; |
|
|
|
UTIL_TraceLine( me->WorldSpaceCenter(), me->GetVictim()->GetAbsOrigin() + leadOffset, MASK_SOLID_BRUSHONLY, &filter, &result ); |
|
|
|
if ( result.DidHit() ) |
|
{ |
|
const float errorTolerance = 300.0f; |
|
if ( ( result.endpos - targetSpot ).IsLengthGreaterThan( errorTolerance ) ) |
|
{ |
|
// rocket is going to hit an obstruction not near our victim - just aim right for them and hope for splash |
|
leadOffset = vec3_origin; |
|
} |
|
} |
|
|
|
targetSpot = me->GetVictim()->GetAbsOrigin() + leadOffset; |
|
} |
|
} |
|
|
|
QAngle launchAngles; |
|
Vector toTarget = targetSpot - me->WorldSpaceCenter(); |
|
VectorAngles( toTarget, launchAngles ); |
|
|
|
CBaseEntity *pScorer = me->GetOwnerEntity() ? me->GetOwnerEntity() : me; |
|
|
|
CTFProjectile_Rocket *pRocket = CTFProjectile_Rocket::Create( me, me->WorldSpaceCenter(), launchAngles, me, pScorer ); |
|
if ( pRocket ) |
|
{ |
|
pRocket->SetModel( "models/props_halloween/eyeball_projectile.mdl" ); |
|
|
|
Vector forward; |
|
AngleVectors( launchAngles, &forward, NULL, NULL ); |
|
|
|
Vector vecVelocity = forward * rocketSpeed; |
|
pRocket->SetAbsVelocity( vecVelocity ); |
|
pRocket->SetupInitialTransmittedGrenadeVelocity( vecVelocity ); |
|
|
|
pRocket->EmitSound( "Weapon_RPG.SingleCrit" ); |
|
pRocket->SetDamage( rocketDamage ); |
|
pRocket->SetCritical( !me->IsSpell() ); |
|
pRocket->SetEyeBallRocket( !me->IsSpell() ); |
|
pRocket->SetSpell( me->IsSpell() ); |
|
pRocket->ChangeTeam( me->GetTeamNumber() ); |
|
} |
|
|
|
if ( !m_rocketsLeft ) |
|
{ |
|
return Done(); |
|
} |
|
} |
|
|
|
return Continue(); |
|
} |
|
|
|
|