diff options
Diffstat (limited to 'game/server/tf/halloween/merasmus/merasmus_behavior/merasmus_aoe_attack.cpp')
| -rw-r--r-- | game/server/tf/halloween/merasmus/merasmus_behavior/merasmus_aoe_attack.cpp | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/game/server/tf/halloween/merasmus/merasmus_behavior/merasmus_aoe_attack.cpp b/game/server/tf/halloween/merasmus/merasmus_behavior/merasmus_aoe_attack.cpp new file mode 100644 index 0000000..6698be0 --- /dev/null +++ b/game/server/tf/halloween/merasmus/merasmus_behavior/merasmus_aoe_attack.cpp @@ -0,0 +1,248 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// +// +//============================================================================= +#include "cbase.h" + +#include "tf_gamerules.h" +#include "particle_parse.h" +#include "nav_mesh/tf_nav_area.h" +#include "nav_mesh/tf_nav_mesh.h" +#include "tf/halloween/eyeball_boss/teleport_vortex.h" +#include "tf_weaponbase_grenadeproj.h" +#include "sceneentity.h" + +#include "../merasmus.h" +#include "merasmus_aoe_attack.h" + +//--------------------------------------------------------------------------------------------- +#define MAX_BOMBS_PER_TICK 4 + +//--------------------------------------------------------------------------------------------- +ActionResult< CMerasmus > CMerasmusAOEAttack::OnStart( CMerasmus *me, Action< CMerasmus > *priorAction ) +{ + m_aoeStartTimer.Start( 4.f ); + m_state = AOE_BEGIN; + + me->StartFlying(); + + CTFNavArea *pointArea = TheTFNavMesh()->GetControlPointCenterArea( 0 ); + + if ( !pointArea ) + { + return Done( "No control point!" ); + } + + const float surroundRange = 400.f; + CollectSurroundingAreas( &m_wanderAreaVector, pointArea, surroundRange, StepHeight, StepHeight ); + + if ( m_wanderAreaVector.Count() == 0 ) + { + return Done( "No nav areas near control point!" ); + } + + me->GetBodyInterface()->StartActivity( ACT_RANGE_ATTACK1 ); + + // This is only to play sound since animation doesn't work with the vcd + CFmtStr vcdName( "scenes/bot/merasmus/low/bomb_attack_00%d.vcd", RandomInt( 1, 9 ) ); + InstancedScriptedScene( me, vcdName.Get(), NULL, 0.0f, false, NULL, true ); + + m_wanderArea = NULL; + + return Continue(); +} + + +#define BOMB_SCALE 1.0f // 0.85f +#define BOMB_VERT_VEL 750.0f +#define BOMB_START_OFFSET Vector( 0.0f, 0.0f, 150.0f ) + +//--------------------------------------------------------------------------------------------- +void CMerasmusAOEAttack::QueueSingleGrenadeForLaunch( const Vector &vecVelocity ) +{ + m_vecGrenadesToCreate.AddToTail( MerasmusGrenadeCreateSpec_t( vecVelocity ) ); +} + +//--------------------------------------------------------------------------------------------- +void CMerasmusAOEAttack::ClearPendingGrenades() +{ + m_vecGrenadesToCreate.RemoveAll(); +} + +//--------------------------------------------------------------------------------------------- +void CMerasmusAOEAttack::LaunchPendingGrenades( CMerasmus *me ) +{ + int nNumGrenadesLeftToCreate = MIN( m_vecGrenadesToCreate.Count(), MAX_BOMBS_PER_TICK ); + while ( nNumGrenadesLeftToCreate > 0 ) + { + // Create the first one in the list + MerasmusGrenadeCreateSpec_t &info = m_vecGrenadesToCreate[0]; + CMerasmus::CreateMerasmusGrenade( me->WorldSpaceCenter() + BOMB_START_OFFSET, info.m_vecVelocity, me, BOMB_SCALE ); + + // Remove the first one in the list + m_vecGrenadesToCreate.Remove( 0 ); + + --nNumGrenadesLeftToCreate; + } +} + +//--------------------------------------------------------------------------------------------- +void CMerasmusAOEAttack::QueueBombRingsForLaunch( CMerasmus *me ) +{ + ClearPendingGrenades(); + + const float bombRingMinHorizVel = 100.0f; + const float bombRingMaxHorizVel = 2000.0f; + + QAngle myAngles = me->EyeAngles(); + + float deltaVel = bombRingMaxHorizVel - bombRingMinHorizVel; + const int ringCount = 2; + + for( int r=0; r<ringCount; ++r ) + { + float u = (float)(r+1)/(float)ringCount; + + float horizVel = bombRingMinHorizVel + u * deltaVel; + +// float angleDelta = 10.0f + 20.0f * ( 1.0f - u ); + float angleDelta = 20.0f + 30.0f * ( 1.0f - u ); + + for( float angle=0.0f; angle<360.0f; angle += angleDelta ) + { + Vector forward; + AngleVectors( myAngles, &forward ); + + Vector vecVelocity( horizVel * forward.x, horizVel * forward.y, BOMB_VERT_VEL ); + + QueueSingleGrenadeForLaunch( vecVelocity ); + + myAngles.y += angleDelta; + } + } +} + + +//--------------------------------------------------------------------------------------------- +void CMerasmusAOEAttack::QueueBombSpokesForLaunch( CMerasmus *me ) +{ + ClearPendingGrenades(); + + const float bombSpokeAngle = 45.0f; + const int bombSpokeCount = 4; // 10; + const float bombSpokeMinHorizVel = 100.0f; + const float bombSpokeMaxHorizVel = 2000.0f; + + float deltaVel = bombSpokeMaxHorizVel - bombSpokeMinHorizVel; + float angleDelta = bombSpokeAngle; + + QAngle myAngles = me->EyeAngles(); + + for( float angle=0.0f; angle<360.0f; angle += angleDelta ) + { + Vector forward; + AngleVectors( myAngles, &forward ); + + int spokeCount = bombSpokeCount; + + for( int i=0; i<spokeCount; ++i ) + { + float u = (float)(i+1)/(float)spokeCount; + + float horizVel = bombSpokeMinHorizVel + u * deltaVel; + + Vector vecVelocity( horizVel * forward.x, horizVel * forward.y, BOMB_VERT_VEL ); + + QueueSingleGrenadeForLaunch( vecVelocity ); + } + + myAngles.y += angleDelta; + } +} + + +//--------------------------------------------------------------------------------------------- +ActionResult< CMerasmus > CMerasmusAOEAttack::Update( CMerasmus *me, float interval ) +{ + if ( me->IsActivityFinished() ) + { + me->StopAOEAttack(); + + return Done(); + } + + switch ( m_state ) + { + case AOE_BEGIN: + { + if ( m_aoeStartTimer.IsElapsed() ) + { + m_launchTimer.Start( 0.5f ); + + m_state = AOE_FIRING; + } + } + break; + case AOE_FIRING: + { + // Start the AOE particles + me->StartAOEAttack(); + + CMerasmusFlyingLocomotion *fly = (CMerasmusFlyingLocomotion *)me->GetLocomotionInterface(); + + // float up and down a bit + fly->SetDesiredAltitude( 175.0f + 25.0f * FastCos( gpGlobals->curtime ) ); + + if ( m_launchTimer.IsElapsed() ) + { + if ( RandomInt( 1, 100 ) < 50 ) + { + QueueBombSpokesForLaunch( me ); + } + else + { + QueueBombRingsForLaunch( me ); + } + + m_launchTimer.Start( 2.0f ); + } + + // Go through and launch any pending grenades + LaunchPendingGrenades( me ); + + // wander among nav areas near the cap point + if ( m_wanderTimer.IsElapsed() || m_wanderArea == NULL ) + { + m_wanderTimer.Start( RandomFloat( 1.0f, 3.0f ) ); + + m_wanderArea = (CTFNavArea *)m_wanderAreaVector[ RandomInt( 0, m_wanderAreaVector.Count()-1 ) ]; + } + + if ( m_wanderArea ) + { + Vector flySpot = m_wanderArea->GetCenter(); + flySpot.z = me->GetAbsOrigin().z; + + me->GetLocomotionInterface()->Approach( flySpot ); + me->GetLocomotionInterface()->FaceTowards( flySpot ); + } + } + break; + } + + return Continue(); +} + + +//--------------------------------------------------------------------------------------------- +void CMerasmusAOEAttack::OnEnd( CMerasmus *me, Action< CMerasmus > *nextAction ) +{ + me->StopFlying(); + + // The animation sometime doesn't turn off the bodygroup correctly. Slam it in code. + int staffBodyGroup = me->FindBodygroupByName( "staff" ); + me->SetBodygroup( staffBodyGroup, 0 ); + + me->ResetBombHitCount(); +} |