mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-16 21:53:01 +00:00
1
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_behavior.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "CRagdollMagnet.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "tf_shareddefs.h"
|
||||
#include "player_vs_environment/monster_resource.h"
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_behavior.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_tactical_monitor.h"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
Action< CBossAlpha > *CBossAlphaBehavior::InitialContainedAction( CBossAlpha *me )
|
||||
{
|
||||
return new CBossAlphaTacticalMonitor;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaBehavior::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
if ( m_vocalTimer.IsElapsed() )
|
||||
{
|
||||
m_vocalTimer.Start( RandomFloat( 3.0f, 5.0f ) );
|
||||
|
||||
if ( !me->IsBusy() )
|
||||
{
|
||||
me->EmitSound( "RobotBoss.Vocalize" );
|
||||
}
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaBehavior::OnKilled( CBossAlpha *me, const CTakeDamageInfo &info )
|
||||
{
|
||||
// relay the event to the map logic
|
||||
me->m_outputOnKilled.FireOutput( me, me );
|
||||
|
||||
// Calculate death force
|
||||
Vector forceVector = me->CalcDamageForceVector( info );
|
||||
|
||||
// See if there's a ragdoll magnet that should influence our force.
|
||||
CRagdollMagnet *magnet = CRagdollMagnet::FindBestMagnet( me );
|
||||
if ( magnet )
|
||||
{
|
||||
forceVector += magnet->GetForceVector( me );
|
||||
}
|
||||
|
||||
if ( me->IsMiniBoss() )
|
||||
{
|
||||
me->EmitSound( "Cart.Explode" );
|
||||
me->BecomeRagdoll( info, forceVector );
|
||||
|
||||
if ( g_pMonsterResource )
|
||||
{
|
||||
g_pMonsterResource->HideBossHealthMeter();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// full end-of-game boss
|
||||
UTIL_Remove( me );
|
||||
|
||||
if ( TFGameRules()->IsBossBattleMode() )
|
||||
{
|
||||
// check that ALL bosses are dead
|
||||
bool isBossBattleWon = true;
|
||||
|
||||
CBossAlpha *boss = NULL;
|
||||
while( ( boss = (CBossAlpha *)gEntList.FindEntityByClassname( boss, "boss_alpha" ) ) != NULL )
|
||||
{
|
||||
if ( !me->IsSelf( boss ) && boss->IsAlive() && !boss->IsMiniBoss() )
|
||||
{
|
||||
isBossBattleWon = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isBossBattleWon )
|
||||
{
|
||||
TFGameRules()->SetWinningTeam( TF_TEAM_BLUE, WINREASON_OPPONENTS_DEAD );
|
||||
|
||||
if ( g_pMonsterResource )
|
||||
{
|
||||
g_pMonsterResource->HideBossHealthMeter();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TryDone();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaBehavior::OnContact( CBossAlpha *me, CBaseEntity *other, CGameTrace *result )
|
||||
{
|
||||
return TryContinue();
|
||||
}
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,30 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_behavior.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_BEHAVIOR_H
|
||||
#define BOSS_ALPHA_BEHAVIOR_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
class CBossAlphaBehavior : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual Action< CBossAlpha > *InitialContainedAction( CBossAlpha *me );
|
||||
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
|
||||
virtual EventDesiredResult< CBossAlpha > OnKilled( CBossAlpha *me, const CTakeDamageInfo &info );
|
||||
virtual EventDesiredResult< CBossAlpha > OnContact( CBossAlpha *me, CBaseEntity *other, CGameTrace *result = NULL );
|
||||
|
||||
virtual const char *GetName( void ) const { return "Behavior"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_vocalTimer;
|
||||
};
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_BEHAVIOR_H
|
||||
@@ -0,0 +1,170 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_chase_victim.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_chase_victim.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_lost_victim.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_nuke_attack.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_launch_grenades.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_launch_rockets.h"
|
||||
|
||||
extern ConVar tf_boss_alpha_grenade_launch_range;
|
||||
extern ConVar tf_boss_alpha_chase_range;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
CBossAlphaChaseVictim::CBossAlphaChaseVictim( CBaseCombatCharacter *chaseTarget )
|
||||
{
|
||||
m_chaseTarget = chaseTarget;
|
||||
m_lastKnownTargetSpot = chaseTarget->GetAbsOrigin();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaChaseVictim::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
if ( m_chaseTarget == NULL )
|
||||
{
|
||||
return Done( "Target is NULL" );
|
||||
}
|
||||
|
||||
m_lastKnownTargetSpot = m_chaseTarget->GetAbsOrigin();
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaChaseVictim::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
if ( m_chaseTarget == NULL || !m_chaseTarget->IsAlive() )
|
||||
{
|
||||
return ChangeTo( new CBossAlphaLostVictim, "No victim" );
|
||||
}
|
||||
|
||||
if ( m_chaseTarget != me->GetAttackTarget() )
|
||||
{
|
||||
return Done( "Changing targets" );
|
||||
}
|
||||
|
||||
Vector moveGoal = m_chaseTarget->GetAbsOrigin();
|
||||
|
||||
if ( me->IsLineOfSightClear( m_chaseTarget ) )
|
||||
{
|
||||
if ( !m_visibleTimer.HasStarted() )
|
||||
{
|
||||
m_visibleTimer.Start();
|
||||
}
|
||||
|
||||
if ( me->HasAbility( CBossAlpha::CAN_NUKE ) && me->GetNukeTimer()->IsElapsed() )
|
||||
{
|
||||
return SuspendFor( new CBossAlphaNukeAttack, "Nuking!" );
|
||||
}
|
||||
|
||||
m_lastKnownTargetSpot = m_chaseTarget->GetAbsOrigin();
|
||||
|
||||
if ( me->HasAbility( CBossAlpha::CAN_LAUNCH_STICKIES ) )
|
||||
{
|
||||
if ( ( me->GetGrenadeTimer()->IsElapsed() && me->IsRangeLessThan( m_chaseTarget, tf_boss_alpha_grenade_launch_range.GetFloat() ) ) ||
|
||||
me->IsInCondition( CBossAlpha::ENRAGED ) )
|
||||
{
|
||||
return SuspendFor( new CBossAlphaLaunchGrenades, "Target is close (or I am enraged) - grenades!" );
|
||||
}
|
||||
}
|
||||
|
||||
// chase into line of sight a bit so they can't immediately get behind cover again
|
||||
if ( me->HasAbility( CBossAlpha::CAN_FIRE_ROCKETS ) )
|
||||
{
|
||||
if ( m_visibleTimer.IsGreaterThen( 1.0f ) ||
|
||||
me->IsRangeLessThan( m_chaseTarget, tf_boss_alpha_chase_range.GetFloat() ) )
|
||||
{
|
||||
return SuspendFor( new CBossAlphaLaunchRockets, "Fire!" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( me->IsRangeLessThan( m_chaseTarget, 150.0f ) )
|
||||
{
|
||||
// too close - stand still
|
||||
if ( !me->GetBodyInterface()->IsActivity( ACT_MP_STAND_MELEE ) )
|
||||
{
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_STAND_MELEE );
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_visibleTimer.Invalidate();
|
||||
|
||||
// move to where we last saw our target
|
||||
moveGoal = m_lastKnownTargetSpot;
|
||||
|
||||
if ( me->IsRangeLessThan( m_lastKnownTargetSpot, 20.0f ) )
|
||||
{
|
||||
// reached spot where we last saw our victim - give up
|
||||
me->SetAttackTarget( NULL );
|
||||
|
||||
return ChangeTo( new CBossAlphaLostVictim, "I lost my chase victim" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// move into sight of target
|
||||
if ( m_path.GetAge() > 1.0f )
|
||||
{
|
||||
CBossAlphaPathCost cost( me );
|
||||
m_path.Compute( me, moveGoal, cost );
|
||||
}
|
||||
|
||||
me->GetLocomotionInterface()->Run();
|
||||
m_path.Update( me );
|
||||
|
||||
// play running animation
|
||||
if ( !me->GetBodyInterface()->IsActivity( ACT_MP_RUN_MELEE ) )
|
||||
{
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_RUN_MELEE );
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaChaseVictim::OnMoveToSuccess( CBossAlpha *me, const Path *path )
|
||||
{
|
||||
return TryDone( RESULT_CRITICAL, "Reached move goal" );
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaChaseVictim::OnMoveToFailure( CBossAlpha *me, const Path *path, MoveToFailureType reason )
|
||||
{
|
||||
return TryDone( RESULT_CRITICAL, "Path follow failed" );
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaChaseVictim::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaChaseVictim::OnStuck( CBossAlpha *me )
|
||||
{
|
||||
// we're stuck - just warp to the our next path goal
|
||||
if ( m_path.GetCurrentGoal() )
|
||||
{
|
||||
me->SetAbsOrigin( m_path.GetCurrentGoal()->pos + Vector( 0, 0, 10.0f ) );
|
||||
}
|
||||
|
||||
return TryContinue();
|
||||
}
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,41 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_chase_victim.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_CHASE_VICTIM_H
|
||||
#define BOSS_ALPHA_CHASE_VICTIM_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "nav_mesh/tf_path_follower.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------------------
|
||||
class CBossAlphaChaseVictim : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
CBossAlphaChaseVictim( CBaseCombatCharacter *chaseTarget );
|
||||
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
virtual EventDesiredResult< CBossAlpha > OnStuck( CBossAlpha *me );
|
||||
virtual EventDesiredResult< CBossAlpha > OnMoveToSuccess( CBossAlpha *me, const Path *path );
|
||||
virtual EventDesiredResult< CBossAlpha > OnMoveToFailure( CBossAlpha *me, const Path *path, MoveToFailureType reason );
|
||||
|
||||
virtual const char *GetName( void ) const { return "ChaseVictim"; } // return name of this action
|
||||
|
||||
private:
|
||||
CTFPathFollower m_path;
|
||||
IntervalTimer m_visibleTimer;
|
||||
CHandle< CBaseCombatCharacter > m_lastTarget;
|
||||
|
||||
CHandle< CBaseCombatCharacter > m_chaseTarget;
|
||||
Vector m_lastKnownTargetSpot;
|
||||
};
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_CHASE_VICTIM_H
|
||||
@@ -0,0 +1,93 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_get_off_me.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "tf_player.h"
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_get_off_me.h"
|
||||
|
||||
ConVar tf_boss_alpha_charge_pushaway_force( "tf_boss_alpha_charge_pushaway_force", "500"/*, FCVAR_CHEAT*/ );
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void PushawayPlayer( CTFPlayer *victim, const Vector &pushOrigin, float pushForce )
|
||||
{
|
||||
if ( !victim )
|
||||
return;
|
||||
|
||||
if ( victim->GetFlags() & FL_ONGROUND )
|
||||
{
|
||||
// launching into the air
|
||||
victim->SetAbsVelocity( vec3_origin );
|
||||
|
||||
const float stunTime = 0.5f;
|
||||
victim->m_Shared.StunPlayer( stunTime, 1.0, TF_STUN_MOVEMENT );
|
||||
|
||||
victim->ApplyPunchImpulseX( RandomInt( 10, 15 ) );
|
||||
victim->SpeakConceptIfAllowed( MP_CONCEPT_DEFLECTED, "projectile:0,victim:1" );
|
||||
}
|
||||
|
||||
victim->RemoveFlag( FL_ONGROUND );
|
||||
|
||||
Vector toVictim = victim->WorldSpaceCenter() - pushOrigin;
|
||||
toVictim.z = 0.0f;
|
||||
toVictim.NormalizeInPlace();
|
||||
toVictim.z = 1.0f;
|
||||
|
||||
victim->ApplyAbsVelocityImpulse( pushForce * toVictim );
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaGetOffMe::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
me->AddGestureSequence( me->LookupSequence( "gesture_melee_help" ) );
|
||||
m_timer.Start( 0.5f );
|
||||
|
||||
me->AddCondition( CBossAlpha::BUSY );
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaGetOffMe::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
if ( m_timer.IsElapsed() )
|
||||
{
|
||||
// blast players off of my head
|
||||
CUtlVector< CTFPlayer * > onMeVector;
|
||||
me->CollectPlayersStandingOnMe( &onMeVector );
|
||||
|
||||
Vector headPos;
|
||||
QAngle headAngles;
|
||||
if ( me->GetAttachment( "head", headPos, headAngles ) )
|
||||
{
|
||||
for( int i=0; i<onMeVector.Count(); ++i )
|
||||
{
|
||||
// push 'em off
|
||||
PushawayPlayer( onMeVector[i], headPos, tf_boss_alpha_charge_pushaway_force.GetFloat() );
|
||||
}
|
||||
}
|
||||
|
||||
me->EmitSound( "Weapon_FlameThrower.AirBurstAttack" );
|
||||
|
||||
return Done();
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaGetOffMe::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
me->RemoveCondition( CBossAlpha::BUSY );
|
||||
}
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,27 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_get_off_me.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_GET_OFF_ME_H
|
||||
#define BOSS_ALPHA_GET_OFF_ME_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class CBossAlphaGetOffMe : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
virtual const char *GetName( void ) const { return "GetOffMe"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_timer;
|
||||
};
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_GET_OFF_ME_H
|
||||
@@ -0,0 +1,129 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_guard_spot.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "tf_player.h"
|
||||
#include "nav_mesh/tf_nav_area.h"
|
||||
#include "tf_projectile_rocket.h"
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_guard_spot.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_chase_victim.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaGuardSpot::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
m_path.SetMinLookAheadDistance( 300.0f );
|
||||
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_STAND_ITEM1 );
|
||||
me->SetHomePosition( me->GetAbsOrigin() );
|
||||
|
||||
m_lookAtSpot = vec3_origin;
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaGuardSpot::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
CBaseCombatCharacter *target = me->GetAttackTarget();
|
||||
if ( target )
|
||||
{
|
||||
if ( me->IsLineOfSightClear( target ) || me->IsPrisonerOfMinion( target ) )
|
||||
{
|
||||
return SuspendFor( new CBossAlphaChaseVictim( me->GetAttackTarget() ), "Get 'em!" );
|
||||
}
|
||||
}
|
||||
|
||||
CBaseCombatCharacter *visible = me->GetNearestVisibleEnemy();
|
||||
if ( visible )
|
||||
{
|
||||
// look at visible victim out of range
|
||||
me->GetLocomotionInterface()->FaceTowards( visible->WorldSpaceCenter() );
|
||||
}
|
||||
|
||||
const float atHomeRange = 50.0f;
|
||||
if ( me->IsRangeGreaterThan( me->GetHomePosition(), atHomeRange ) )
|
||||
{
|
||||
if ( m_path.GetAge() > 3.0f )
|
||||
{
|
||||
CBossAlphaPathCost cost( me );
|
||||
if ( m_path.Compute( me, me->GetHomePosition(), cost ) == false )
|
||||
{
|
||||
// can't reach guard post - just jump there for now
|
||||
me->Teleport( &me->GetHomePosition(), NULL, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
m_path.Update( me );
|
||||
}
|
||||
else
|
||||
{
|
||||
// on guard spot - look around
|
||||
if ( m_lookTimer.IsElapsed() )
|
||||
{
|
||||
m_lookTimer.Start( RandomFloat( 1.0f, 2.0f ) );
|
||||
|
||||
CTFNavArea *myArea = (CTFNavArea *)me->GetLastKnownArea();
|
||||
if ( myArea )
|
||||
{
|
||||
const CUtlVector< CTFNavArea * > &invasionAreaVector = myArea->GetEnemyInvasionAreaVector( TF_TEAM_RED );
|
||||
|
||||
if ( invasionAreaVector.Count() > 0 )
|
||||
{
|
||||
// try to not look directly at walls
|
||||
const float minGazeRange = 300.0f;
|
||||
const int retryCount = 20.0f;
|
||||
for( int r=0; r<retryCount; ++r )
|
||||
{
|
||||
int which = RandomInt( 0, invasionAreaVector.Count()-1 );
|
||||
Vector gazeSpot = invasionAreaVector[ which ]->GetRandomPoint() + Vector( 0, 0, 0.75f * HumanHeight );
|
||||
|
||||
if ( me->IsRangeGreaterThan( gazeSpot, minGazeRange ) && me->GetVisionInterface()->IsLineOfSightClear( gazeSpot ) )
|
||||
{
|
||||
// use maxLookInterval so these looks override body aiming from path following
|
||||
m_lookAtSpot = gazeSpot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
me->GetLocomotionInterface()->FaceTowards( m_lookAtSpot );
|
||||
}
|
||||
|
||||
if ( me->GetLocomotionInterface()->IsAttemptingToMove() )
|
||||
{
|
||||
// play running animation
|
||||
if ( !me->GetBodyInterface()->IsActivity( ACT_MP_RUN_MELEE ) )
|
||||
{
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_RUN_MELEE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// standing still
|
||||
if ( !me->GetBodyInterface()->IsActivity( ACT_MP_STAND_ITEM1 ) )
|
||||
{
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_STAND_ITEM1 );
|
||||
}
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaGuardSpot::OnInjured( CBossAlpha *me, const CTakeDamageInfo &info )
|
||||
{
|
||||
return TryContinue();
|
||||
}
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,28 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_guard_spot.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "nav_mesh/tf_path_follower.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
class CBossAlphaGuardSpot : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual EventDesiredResult< CBossAlpha > OnInjured( CBossAlpha *me, const CTakeDamageInfo &info );
|
||||
|
||||
virtual const char *GetName( void ) const { return "GuardSpot"; } // return name of this action
|
||||
|
||||
private:
|
||||
CTFPathFollower m_path;
|
||||
CountdownTimer m_lookTimer;
|
||||
Vector m_lookAtSpot;
|
||||
};
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_launch_grenades.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_launch_grenades.h"
|
||||
|
||||
ConVar tf_boss_alpha_grenade_ring_min_horiz_vel( "tf_boss_alpha_grenade_ring_min_horiz_vel", "100"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_grenade_ring_max_horiz_vel( "tf_boss_alpha_grenade_ring_max_horiz_vel", "350"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_grenade_vert_vel( "tf_boss_alpha_grenade_vert_vel", "750"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_grenade_det_time( "tf_boss_alpha_grenade_det_time", "3"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_grenade_damage( "tf_boss_alpha_grenade_damage", "25"/*, FCVAR_CHEAT*/ );
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaLaunchGrenades::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_STAND_SECONDARY );
|
||||
m_animLayer = me->AddLayeredSequence( me->LookupSequence( "gesture_melee_cheer" ), 0 );
|
||||
|
||||
m_timer.Start( 1.0f );
|
||||
m_detonateTimer.Invalidate();
|
||||
me->AddCondition( CBossAlpha::BUSY );
|
||||
me->GetGrenadeTimer()->Start( me->GetGrenadeInterval() );
|
||||
|
||||
me->EmitSound( "RobotBoss.LaunchGrenades" );
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaLaunchGrenades::LaunchGrenade( CBossAlpha *me, const Vector &launchVel, CTFWeaponInfo *weaponInfo )
|
||||
{
|
||||
CTFGrenadePipebombProjectile *pProjectile = CTFGrenadePipebombProjectile::Create( me->WorldSpaceCenter() + Vector( 0, 0, 100 ), vec3_angle, launchVel,
|
||||
AngularImpulse( 600, random->RandomInt( -1200, 1200 ), 0 ),
|
||||
me, *weaponInfo, TF_PROJECTILE_PIPEBOMB_REMOTE, 1 );
|
||||
if ( pProjectile )
|
||||
{
|
||||
pProjectile->SetLauncher( me );
|
||||
pProjectile->SetDamage( tf_boss_alpha_grenade_damage.GetFloat() );
|
||||
|
||||
if ( me->IsInCondition( CBossAlpha::ENRAGED ) )
|
||||
{
|
||||
pProjectile->SetCritical( true );
|
||||
}
|
||||
|
||||
m_grenadeVector.AddToTail( pProjectile );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaLaunchGrenades::LaunchGrenadeRings( CBossAlpha *me )
|
||||
{
|
||||
const char *weaponAlias = WeaponIdToAlias( TF_WEAPON_GRENADELAUNCHER );
|
||||
if ( !weaponAlias )
|
||||
return;
|
||||
|
||||
WEAPON_FILE_INFO_HANDLE weaponInfoHandle = LookupWeaponInfoSlot( weaponAlias );
|
||||
if ( weaponInfoHandle == GetInvalidWeaponInfoHandle() )
|
||||
return;
|
||||
|
||||
CTFWeaponInfo *weaponInfo = static_cast< CTFWeaponInfo * >( GetFileWeaponInfoFromHandle( weaponInfoHandle ) );
|
||||
|
||||
QAngle myAngles = me->EyeAngles();
|
||||
|
||||
// create rings of stickies
|
||||
float deltaVel = tf_boss_alpha_grenade_ring_max_horiz_vel.GetFloat() - tf_boss_alpha_grenade_ring_min_horiz_vel.GetFloat();
|
||||
const int ringCount = 2;
|
||||
for( int r=0; r<ringCount; ++r )
|
||||
{
|
||||
float u = (float)r/(float)(ringCount-1);
|
||||
|
||||
float horizVel = tf_boss_alpha_grenade_ring_min_horiz_vel.GetFloat() + u * deltaVel;
|
||||
|
||||
float angleDelta = 10.0f + 20.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, tf_boss_alpha_grenade_vert_vel.GetFloat() );
|
||||
|
||||
LaunchGrenade( me, vecVelocity, weaponInfo );
|
||||
|
||||
myAngles.y += angleDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ConVar tf_boss_alpha_grenade_spoke_angle( "tf_boss_alpha_grenade_spoke_angle", "45"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_grenade_spoke_count( "tf_boss_alpha_grenade_spoke_count", "15"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_grenade_spoke_min_horiz_vel( "tf_boss_alpha_grenade_spoke_min_horiz_vel", "100"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_grenade_spoke_max_horiz_vel( "tf_boss_alpha_grenade_spoke_max_horiz_vel", "750"/*, FCVAR_CHEAT*/ );
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaLaunchGrenades::LaunchGrenadeSpokes( CBossAlpha *me )
|
||||
{
|
||||
const char *weaponAlias = WeaponIdToAlias( TF_WEAPON_GRENADELAUNCHER );
|
||||
if ( !weaponAlias )
|
||||
return;
|
||||
|
||||
WEAPON_FILE_INFO_HANDLE weaponInfoHandle = LookupWeaponInfoSlot( weaponAlias );
|
||||
if ( weaponInfoHandle == GetInvalidWeaponInfoHandle() )
|
||||
return;
|
||||
|
||||
CTFWeaponInfo *weaponInfo = static_cast< CTFWeaponInfo * >( GetFileWeaponInfoFromHandle( weaponInfoHandle ) );
|
||||
|
||||
// create spokes of stickies
|
||||
float deltaVel = tf_boss_alpha_grenade_spoke_max_horiz_vel.GetFloat() - tf_boss_alpha_grenade_spoke_min_horiz_vel.GetFloat();
|
||||
float angleDelta = tf_boss_alpha_grenade_spoke_angle.GetFloat();
|
||||
QAngle myAngles = me->EyeAngles();
|
||||
|
||||
for( float angle=0.0f; angle<360.0f; angle += angleDelta )
|
||||
{
|
||||
Vector forward;
|
||||
AngleVectors( myAngles, &forward );
|
||||
|
||||
int spokeCount = tf_boss_alpha_grenade_spoke_count.GetInt();
|
||||
|
||||
for( int i=0; i<spokeCount; ++i )
|
||||
{
|
||||
float u = (float)i/(float)(spokeCount-1);
|
||||
|
||||
float horizVel = tf_boss_alpha_grenade_spoke_min_horiz_vel.GetFloat() + u * deltaVel;
|
||||
|
||||
Vector vecVelocity( horizVel * forward.x, horizVel * forward.y, tf_boss_alpha_grenade_vert_vel.GetFloat() );
|
||||
|
||||
LaunchGrenade( me, vecVelocity, weaponInfo );
|
||||
}
|
||||
|
||||
myAngles.y += angleDelta;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaLaunchGrenades::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
QAngle myAngles = me->EyeAngles();
|
||||
|
||||
if ( m_timer.HasStarted() && m_timer.IsElapsed() )
|
||||
{
|
||||
m_timer.Invalidate();
|
||||
|
||||
if ( RandomInt( 0, 100 ) < 50 )
|
||||
{
|
||||
LaunchGrenadeRings( me );
|
||||
}
|
||||
else
|
||||
{
|
||||
LaunchGrenadeSpokes( me );
|
||||
}
|
||||
|
||||
me->EmitSound( "Weapon_Grenade_Normal.Single" );
|
||||
|
||||
m_detonateTimer.Start( tf_boss_alpha_grenade_det_time.GetFloat() );
|
||||
}
|
||||
|
||||
if ( m_detonateTimer.HasStarted() && m_detonateTimer.IsElapsed() )
|
||||
{
|
||||
// detonate the stickies
|
||||
for( int i=0; i<m_grenadeVector.Count(); ++i )
|
||||
{
|
||||
if ( m_grenadeVector[i] )
|
||||
{
|
||||
m_grenadeVector[i]->Detonate();
|
||||
}
|
||||
}
|
||||
|
||||
return Done();
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaLaunchGrenades::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
// fizzle any outstanding stickies
|
||||
for( int i=0; i<m_grenadeVector.Count(); ++i )
|
||||
{
|
||||
if ( m_grenadeVector[i] )
|
||||
{
|
||||
m_grenadeVector[i]->Fizzle();
|
||||
m_grenadeVector[i]->Detonate();
|
||||
}
|
||||
}
|
||||
|
||||
me->RemoveCondition( CBossAlpha::ENRAGED );
|
||||
me->RemoveCondition( CBossAlpha::BUSY );
|
||||
me->FastRemoveLayer( m_animLayer );
|
||||
}
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,36 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_launch_grenades.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_LAUNCH_GRENADES_H
|
||||
#define BOSS_ALPHA_LAUNCH_GRENADES_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "tf_weapon_grenade_pipebomb.h"
|
||||
|
||||
class CBossAlphaLaunchGrenades : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
// if anything interrupts this action, abort it
|
||||
virtual ActionResult< CBossAlpha > OnSuspend( CBossAlpha *me, Action< CBossAlpha > *interruptingAction ) { return Done(); }
|
||||
|
||||
virtual const char *GetName( void ) const { return "LaunchGrenades"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_timer;
|
||||
CountdownTimer m_detonateTimer;
|
||||
CUtlVector< CHandle< CTFGrenadePipebombProjectile > > m_grenadeVector;
|
||||
void LaunchGrenade( CBossAlpha *me, const Vector &launchVel, CTFWeaponInfo *weaponInfo );
|
||||
void LaunchGrenadeRings( CBossAlpha *me );
|
||||
void LaunchGrenadeSpokes( CBossAlpha *me );
|
||||
int m_animLayer;
|
||||
};
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_LAUNCH_GRENADES_H
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_launch_rockets.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "tf_projectile_rocket.h"
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_launch_rockets.h"
|
||||
|
||||
ConVar tf_boss_alpha_dont_shoot( "tf_boss_alpha_dont_shoot", "0"/*, FCVAR_CHEAT*/ );
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaLaunchRockets::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
// start animation
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_STAND_SECONDARY );
|
||||
|
||||
m_animLayer = me->AddLayeredSequence( me->LookupSequence( "taunt02" ), 0 );
|
||||
|
||||
m_timer.Start( 1.0f );
|
||||
|
||||
m_rocketsLeft = me->GetRocketLaunchCount();
|
||||
|
||||
me->AddCondition( CBossAlpha::BUSY );
|
||||
me->LockAttackTarget();
|
||||
|
||||
me->EmitSound( "RobotBoss.LaunchRockets" );
|
||||
|
||||
if ( me->GetAttackTarget() == NULL )
|
||||
{
|
||||
return Done( "No target" );
|
||||
}
|
||||
|
||||
m_target = me->GetAttackTarget();
|
||||
m_lastTargetPosition = m_target->WorldSpaceCenter();
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaLaunchRockets::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
if ( m_target != NULL )
|
||||
{
|
||||
m_lastTargetPosition = m_target->WorldSpaceCenter();
|
||||
}
|
||||
|
||||
me->GetLocomotionInterface()->FaceTowards( m_lastTargetPosition );
|
||||
|
||||
if ( m_timer.IsElapsed() && m_launchTimer.IsElapsed() )
|
||||
{
|
||||
if ( !m_rocketsLeft )
|
||||
{
|
||||
return Done();
|
||||
}
|
||||
|
||||
--m_rocketsLeft;
|
||||
m_launchTimer.Start( me->GetRocketInterval() );
|
||||
|
||||
QAngle launchAngles = me->GetAbsAngles();
|
||||
|
||||
if ( m_target == NULL )
|
||||
{
|
||||
Vector to = m_lastTargetPosition - me->WorldSpaceCenter();
|
||||
VectorAngles( to, launchAngles );
|
||||
}
|
||||
else
|
||||
{
|
||||
float range = me->GetRangeTo( m_target->EyePosition() );
|
||||
|
||||
const float rocketSpeed = me->GetRocketAimError() * 1100.0f; // 2000.0f; // 1100.0f; nerfing accuracy
|
||||
float flightTime = range / rocketSpeed;
|
||||
|
||||
Vector aimSpot = m_target->EyePosition() + m_target->GetAbsVelocity() * flightTime;
|
||||
|
||||
Vector to = aimSpot - me->WorldSpaceCenter();
|
||||
VectorAngles( to, launchAngles );
|
||||
}
|
||||
|
||||
if ( !tf_boss_alpha_dont_shoot.GetBool() )
|
||||
{
|
||||
CTFProjectile_Rocket *pRocket = CTFProjectile_Rocket::Create( me, me->WorldSpaceCenter(), launchAngles, me, me );
|
||||
if ( pRocket )
|
||||
{
|
||||
if ( me->IsInCondition( CBossAlpha::ENRAGED ) )
|
||||
{
|
||||
pRocket->SetCritical( true );
|
||||
pRocket->EmitSound( "Weapon_RPG.SingleCrit" );
|
||||
}
|
||||
else
|
||||
{
|
||||
me->EmitSound( me->GetRocketSoundEffect() );
|
||||
}
|
||||
|
||||
pRocket->SetDamage( me->GetRocketDamage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaLaunchRockets::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
me->RemoveCondition( CBossAlpha::ENRAGED );
|
||||
me->RemoveCondition( CBossAlpha::BUSY );
|
||||
me->FastRemoveLayer( m_animLayer );
|
||||
me->UnlockAttackTarget();
|
||||
}
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,38 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_launch_rockets.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_LAUNCH_ROCKETS_H
|
||||
#define BOSS_ALPHA_LAUNCH_ROCKETS_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
class CBossAlphaLaunchRockets : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
// if anything interrupts this action, abort it
|
||||
virtual ActionResult< CBossAlpha > OnSuspend( CBossAlpha *me, Action< CBossAlpha > *interruptingAction ) { return Done(); }
|
||||
|
||||
virtual const char *GetName( void ) const { return "LaunchRockets"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_timer;
|
||||
|
||||
CountdownTimer m_launchTimer;
|
||||
int m_rocketsLeft;
|
||||
|
||||
int m_animLayer;
|
||||
|
||||
CHandle< CBaseCombatCharacter > m_target;
|
||||
Vector m_lastTargetPosition;
|
||||
};
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_LAUNCH_ROCKETS_H
|
||||
@@ -0,0 +1,64 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_lost_victim.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_lost_victim.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaLostVictim::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
m_headTurn = 0.0f;
|
||||
m_headYawPoseParameter = me->LookupPoseParameter( "body_yaw" );
|
||||
|
||||
m_timer.Start( RandomFloat( 3.0f, 5.0f ) );
|
||||
|
||||
me->EmitSound( "RobotBoss.Scanning" );
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaLostVictim::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
if ( m_timer.IsElapsed() )
|
||||
{
|
||||
return Done( "Giving up" );
|
||||
}
|
||||
|
||||
CBaseCombatCharacter *target = me->GetAttackTarget();
|
||||
if ( target )
|
||||
{
|
||||
if ( me->IsLineOfSightClear( target ) || me->IsPrisonerOfMinion( target ) )
|
||||
{
|
||||
me->EmitSound( "RobotBoss.Acquire" );
|
||||
me->AddGesture( ACT_MP_GESTURE_FLINCH_CHEST );
|
||||
return Done( "Ah hah!" );
|
||||
}
|
||||
}
|
||||
|
||||
const float rate = M_PI / 3.0f;
|
||||
m_headTurn += rate * interval;
|
||||
|
||||
float s, c;
|
||||
SinCos( m_headTurn, &s, &c );
|
||||
|
||||
me->SetPoseParameter( m_headYawPoseParameter, 40.0f * s );
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaLostVictim::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
me->SetPoseParameter( m_headYawPoseParameter, 0 );
|
||||
}
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,28 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_lost_victim.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_LOST_VICTIM_H
|
||||
#define BOSS_ALPHA_LOST_VICTIM_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
class CBossAlphaLostVictim : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
virtual const char *GetName( void ) const { return "LostVictim"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_timer;
|
||||
float m_headTurn;
|
||||
int m_headYawPoseParameter;
|
||||
};
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_LOST_VICTIM_H
|
||||
@@ -0,0 +1,208 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_nuke_attack.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "tf_player.h"
|
||||
#include "tf_team.h"
|
||||
#include "player_vs_environment/monster_resource.h"
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_nuke_attack.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_stunned.h"
|
||||
|
||||
|
||||
ConVar tf_boss_alpha_nuke_charge_time( "tf_boss_alpha_nuke_charge_time", "5" );
|
||||
ConVar tf_boss_alpha_nuke_interval( "tf_boss_alpha_nuke_interval", "20" );
|
||||
ConVar tf_boss_alpha_nuke_lethal_time( "tf_boss_alpha_nuke_lethal_time", "999999999" ); // 300
|
||||
ConVar tf_boss_alpha_nuke_damage( "tf_boss_alpha_nuke_damage", "75"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_nuke_max_remaining_health( "tf_boss_alpha_nuke_max_remaining_health", "60"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_nuke_afterburn_time( "tf_boss_alpha_nuke_afterburn_time", "5"/*, FCVAR_CHEAT*/ );
|
||||
|
||||
extern ConVar tf_boss_alpha_stunned_duration;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaNukeAttack::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_JUMP_FLOAT_LOSERSTATE );
|
||||
me->StartNukeEffect();
|
||||
|
||||
me->EmitSound( "RobotBoss.ChargeUpNukeAttack" );
|
||||
// me->AddCondition( CBossAlpha::VULNERABLE_TO_STUN );
|
||||
|
||||
m_chargeUpTimer.Start( tf_boss_alpha_nuke_charge_time.GetFloat() );
|
||||
m_shakeTimer.Start( 0.25f );
|
||||
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaNukeAttack::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
float stunRatio = me->GetStunDamage() / me->GetBecomeStunnedDamage();
|
||||
|
||||
if ( me->HasAbility( CBossAlpha::CAN_BE_STUNNED ) && stunRatio >= 1.0f )
|
||||
{
|
||||
return ChangeTo( new CBossAlphaStunned( tf_boss_alpha_stunned_duration.GetFloat() ), "They got me" );
|
||||
}
|
||||
|
||||
// update the client's HUD
|
||||
if ( g_pMonsterResource )
|
||||
{
|
||||
g_pMonsterResource->SetBossStunPercentage( 1.0f - stunRatio );
|
||||
}
|
||||
|
||||
if ( m_shakeTimer.IsElapsed() )
|
||||
{
|
||||
m_shakeTimer.Reset();
|
||||
UTIL_ScreenShake( me->GetAbsOrigin(), 15.0f, 5.0f, 1.0f, 3000.0f, SHAKE_START );
|
||||
}
|
||||
|
||||
if ( m_chargeUpTimer.IsElapsed() )
|
||||
{
|
||||
// BLAST!
|
||||
CUtlVector< CTFPlayer * > playerVector;
|
||||
CollectPlayers( &playerVector, TF_TEAM_RED, COLLECT_ONLY_LIVING_PLAYERS );
|
||||
CollectPlayers( &playerVector, TF_TEAM_BLUE, COLLECT_ONLY_LIVING_PLAYERS, APPEND_PLAYERS );
|
||||
|
||||
me->EmitSound( "RobotBoss.NukeAttack" );
|
||||
|
||||
CUtlVector< CBaseCombatCharacter * > victimVector;
|
||||
|
||||
int i;
|
||||
|
||||
// players
|
||||
for ( i=0; i<playerVector.Count(); ++i )
|
||||
{
|
||||
CBasePlayer *player = playerVector[i];
|
||||
|
||||
if ( player && player->IsAlive() && player->GetTeamNumber() == TF_TEAM_BLUE )
|
||||
{
|
||||
victimVector.AddToTail( player );
|
||||
}
|
||||
}
|
||||
|
||||
// objects
|
||||
CTFTeam *team = GetGlobalTFTeam( TF_TEAM_BLUE );
|
||||
if ( team )
|
||||
{
|
||||
for ( i=0; i<team->GetNumObjects(); ++i )
|
||||
{
|
||||
CBaseObject *object = team->GetObject( i );
|
||||
if ( object )
|
||||
{
|
||||
victimVector.AddToTail( object );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SKIPME
|
||||
team = GetGlobalTFTeam( TF_TEAM_RED );
|
||||
if ( team )
|
||||
{
|
||||
for ( i=0; i<team->GetNumObjects(); ++i )
|
||||
{
|
||||
CBaseObject *object = team->GetObject( i );
|
||||
if ( object )
|
||||
{
|
||||
victimVector.AddToTail( object );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// non-player bots
|
||||
CUtlVector< INextBot * > botVector;
|
||||
TheNextBots().CollectAllBots( &botVector );
|
||||
for( i=0; i<botVector.Count(); ++i )
|
||||
{
|
||||
CBaseCombatCharacter *bot = botVector[i]->GetEntity();
|
||||
|
||||
if ( !bot->IsPlayer() && bot->IsAlive() )
|
||||
{
|
||||
victimVector.AddToTail( bot );
|
||||
}
|
||||
}
|
||||
#endif // SKIPME
|
||||
|
||||
for( int i=0; i<victimVector.Count(); ++i )
|
||||
{
|
||||
CBaseCombatCharacter *victim = victimVector[i];
|
||||
|
||||
if ( me->IsSelf( victim ) )
|
||||
continue;
|
||||
|
||||
if ( me->IsLineOfSightClear( victim ) )
|
||||
{
|
||||
Vector toVictim = victim->WorldSpaceCenter() - me->WorldSpaceCenter();
|
||||
toVictim.NormalizeInPlace();
|
||||
|
||||
float damage = tf_boss_alpha_nuke_damage.GetFloat();
|
||||
|
||||
if ( me->GetAge() > tf_boss_alpha_nuke_lethal_time.GetFloat() )
|
||||
{
|
||||
// nuke is now lethal
|
||||
damage = 999.9f;
|
||||
}
|
||||
else if ( tf_boss_alpha_nuke_max_remaining_health.GetFloat() >= 0.0f )
|
||||
{
|
||||
// nuke slams everyone's health to this
|
||||
if ( victim->GetHealth() > tf_boss_alpha_nuke_max_remaining_health.GetFloat() )
|
||||
{
|
||||
damage = victim->GetHealth() - tf_boss_alpha_nuke_max_remaining_health.GetFloat();
|
||||
}
|
||||
}
|
||||
|
||||
CTakeDamageInfo info( me, me, damage, DMG_ENERGYBEAM, TF_DMG_CUSTOM_NONE );
|
||||
CalculateMeleeDamageForce( &info, toVictim, me->WorldSpaceCenter(), 1.0f );
|
||||
victim->TakeDamage( info );
|
||||
|
||||
if ( victim->IsPlayer() )
|
||||
{
|
||||
CTFPlayer *playerVictim = ToTFPlayer( victim );
|
||||
|
||||
// catch them on fire (unless they are a Pyro)
|
||||
if ( !playerVictim->IsPlayerClass( TF_CLASS_PYRO ) )
|
||||
{
|
||||
playerVictim->m_Shared.Burn( me, tf_boss_alpha_nuke_afterburn_time.GetFloat() );
|
||||
}
|
||||
|
||||
color32 colorHit = { 255, 255, 255, 255 };
|
||||
UTIL_ScreenFade( victim, colorHit, 1.0f, 0.1f, FFADE_IN );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Done();
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaNukeAttack::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
me->RemoveCondition( CBossAlpha::VULNERABLE_TO_STUN );
|
||||
me->StopNukeEffect();
|
||||
me->ClearStunDamage();
|
||||
me->GetNukeTimer()->Start( tf_boss_alpha_nuke_interval.GetFloat() );
|
||||
|
||||
if ( g_pMonsterResource )
|
||||
{
|
||||
g_pMonsterResource->HideBossStunMeter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaNukeAttack::OnInjured( CBossAlpha *me, const CTakeDamageInfo &info )
|
||||
{
|
||||
return TryToSustain( RESULT_CRITICAL );
|
||||
}
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,31 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_nuke_attack.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_NUKE_ATTACK_H
|
||||
#define BOSS_ALPHA_NUKE_ATTACK_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
class CBossAlphaNukeAttack : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
// if anything interrupts this action, abort it
|
||||
virtual ActionResult< CBossAlpha > OnSuspend( CBossAlpha *me, Action< CBossAlpha > *interruptingAction ) { return Done(); }
|
||||
|
||||
virtual EventDesiredResult< CBossAlpha > OnInjured( CBossAlpha *me, const CTakeDamageInfo &info );
|
||||
|
||||
virtual const char *GetName( void ) const { return "NukeAttack"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_shakeTimer;
|
||||
CountdownTimer m_chargeUpTimer;
|
||||
};
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_NUKE_ATTACK_H
|
||||
@@ -0,0 +1,171 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_stunned.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "tf_shareddefs.h"
|
||||
#include "tf_ammo_pack.h"
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_stunned.h"
|
||||
|
||||
|
||||
extern ConVar tf_boss_alpha_min_nuke_after_stun_time;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
CBossAlphaStunned::CBossAlphaStunned( float duration, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
m_timer.Start( duration );
|
||||
m_nextAction = nextAction;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ConVar tf_boss_alpha_stun_ammo_count( "tf_boss_alpha_stun_ammo_count", "3"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_stun_ammo_amount( "tf_boss_alpha_stun_ammo_amount", "100"/*, FCVAR_CHEAT*/ );
|
||||
ConVar tf_boss_alpha_stun_ammo_velocity( "tf_boss_alpha_stun_ammo_velocity", "100"/*, FCVAR_CHEAT*/ );
|
||||
|
||||
void TossAmmoPack( CBossAlpha *me )
|
||||
{
|
||||
int iPrimary = tf_boss_alpha_stun_ammo_amount.GetInt();
|
||||
int iSecondary = tf_boss_alpha_stun_ammo_amount.GetInt();
|
||||
int iMetal = tf_boss_alpha_stun_ammo_amount.GetInt();
|
||||
|
||||
// Create the ammo pack.
|
||||
CTFAmmoPack *pAmmoPack = CTFAmmoPack::Create( me->GetAbsOrigin(), me->GetAbsAngles(), NULL, "models/items/ammopack_medium.mdl" );
|
||||
if ( pAmmoPack )
|
||||
{
|
||||
/*
|
||||
Vector vel;
|
||||
|
||||
vel.x = RandomFloat( -1.0f, 1.0f ) * tf_boss_alpha_stun_ammo_velocity.GetFloat();
|
||||
vel.y = RandomFloat( -1.0f, 1.0f ) * tf_boss_alpha_stun_ammo_velocity.GetFloat();
|
||||
vel.z = tf_boss_alpha_stun_ammo_velocity.GetFloat();
|
||||
|
||||
pAmmoPack->SetInitialVelocity( vel );
|
||||
*/
|
||||
pAmmoPack->m_nSkin = 0;
|
||||
|
||||
// Give the ammo pack some health, so that trains can destroy it.
|
||||
pAmmoPack->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
|
||||
pAmmoPack->m_takedamage = DAMAGE_YES;
|
||||
pAmmoPack->SetHealth( 900 );
|
||||
|
||||
pAmmoPack->SetBodygroup( 1, 1 );
|
||||
|
||||
pAmmoPack->ApplyLocalAngularVelocityImpulse( AngularImpulse( 600, random->RandomInt( -1200, 1200 ), 0 ) );
|
||||
|
||||
DispatchSpawn( pAmmoPack );
|
||||
|
||||
// Fill up the ammo pack.
|
||||
pAmmoPack->GiveAmmo( iPrimary, TF_AMMO_PRIMARY );
|
||||
pAmmoPack->GiveAmmo( iSecondary, TF_AMMO_SECONDARY );
|
||||
pAmmoPack->GiveAmmo( iMetal, TF_AMMO_METAL );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaStunned::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
// start animation
|
||||
me->GetBodyInterface()->StartActivity( ACT_MP_STAND_MELEE );
|
||||
m_layerUsed = me->AddLayeredSequence( me->LookupSequence( "PRIMARY_Stun_begin" ), 0 );
|
||||
m_state = BECOMING_STUNNED;
|
||||
|
||||
m_timer.Reset();
|
||||
|
||||
me->AddCondition( CBossAlpha::STUNNED );
|
||||
me->EmitSound( "RobotBoss.StunStart" );
|
||||
|
||||
// throw out some ammo
|
||||
for( int i=0; i<tf_boss_alpha_stun_ammo_count.GetInt(); ++i )
|
||||
{
|
||||
TossAmmoPack( me );
|
||||
}
|
||||
|
||||
// relay the event to the map logic
|
||||
me->m_outputOnStunned.FireOutput( me, me );
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaStunned::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
switch( m_state )
|
||||
{
|
||||
case BECOMING_STUNNED:
|
||||
if ( me->IsSequenceFinished() )
|
||||
{
|
||||
me->FastRemoveLayer( m_layerUsed );
|
||||
|
||||
m_state = STUNNED;
|
||||
m_layerUsed = me->AddLayeredSequence( me->LookupSequence( "PRIMARY_stun_middle" ), 0 );
|
||||
me->SetLayerLooping( m_layerUsed, true );
|
||||
me->EmitSound( "RobotBoss.Stunned" );
|
||||
}
|
||||
break;
|
||||
|
||||
case STUNNED:
|
||||
if ( m_timer.IsElapsed() )
|
||||
{
|
||||
me->FastRemoveLayer( m_layerUsed );
|
||||
|
||||
m_state = RECOVERING;
|
||||
m_layerUsed = me->AddLayeredSequence( me->LookupSequence( "PRIMARY_stun_end" ), 0 );
|
||||
me->StopSound( "RobotBoss.Stunned" );
|
||||
me->EmitSound( "RobotBoss.StunRecover" );
|
||||
}
|
||||
break;
|
||||
|
||||
case RECOVERING:
|
||||
if ( me->IsSequenceFinished() )
|
||||
{
|
||||
me->FastRemoveLayer( m_layerUsed );
|
||||
|
||||
if ( m_nextAction )
|
||||
{
|
||||
return ChangeTo( m_nextAction, "Stun finished" );
|
||||
}
|
||||
|
||||
return Done( "Stun finished" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaStunned::OnInjured( CBossAlpha *me, const CTakeDamageInfo &info )
|
||||
{
|
||||
return TryToSustain( RESULT_CRITICAL );
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaStunned::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
me->RemoveCondition( CBossAlpha::STUNNED );
|
||||
|
||||
if ( me->HasAbility( CBossAlpha::CAN_ENRAGE ) )
|
||||
{
|
||||
// being stunned makes the boss ANGRY!
|
||||
me->AddCondition( CBossAlpha::ENRAGED );
|
||||
}
|
||||
|
||||
// make sure the boss attacks at least once before he starts a nuke
|
||||
if ( me->GetNukeTimer()->GetRemainingTime() < tf_boss_alpha_min_nuke_after_stun_time.GetFloat() )
|
||||
{
|
||||
me->GetNukeTimer()->Start( tf_boss_alpha_min_nuke_after_stun_time.GetFloat() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
@@ -0,0 +1,39 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_stunned.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_STUNNED_H
|
||||
#define BOSS_ALPHA_STUNNED_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
class CBossAlphaStunned : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
CBossAlphaStunned( float duration, Action< CBossAlpha > *nextAction = NULL );
|
||||
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
virtual EventDesiredResult< CBossAlpha > OnInjured( CBossAlpha *me, const CTakeDamageInfo &info );
|
||||
|
||||
virtual const char *GetName( void ) const { return "Stunned"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_timer;
|
||||
enum StunStateType
|
||||
{
|
||||
BECOMING_STUNNED,
|
||||
STUNNED,
|
||||
RECOVERING
|
||||
}
|
||||
m_state;
|
||||
int m_layerUsed;
|
||||
|
||||
Action< CBossAlpha > *m_nextAction;
|
||||
};
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_STUNNED_H
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_tactical_monitor.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "tf_gamerules.h"
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_tactical_monitor.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_get_off_me.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_wait_for_players.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_stunned.h"
|
||||
|
||||
|
||||
ConVar tf_boss_alpha_get_off_me_duration( "tf_boss_alpha_get_off_me_duration", "3"/*, FCVAR_CHEAT */ );
|
||||
ConVar tf_boss_alpha_stunned_duration( "tf_boss_alpha_stunned_duration", "10" );
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
Action< CBossAlpha > *CBossAlphaTacticalMonitor::InitialContainedAction( CBossAlpha *me )
|
||||
{
|
||||
if ( TFGameRules()->IsBossBattleMode() )
|
||||
{
|
||||
return new CBossAlphaWaitForPlayers;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaTacticalMonitor::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
m_getOffMeTimer.Invalidate();
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaTacticalMonitor::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
if ( me->IsInCondition( CBossAlpha::STUNNED ) )
|
||||
{
|
||||
return SuspendFor( new CBossAlphaStunned( tf_boss_alpha_stunned_duration.GetFloat() ), "Ouch!" );
|
||||
}
|
||||
|
||||
if ( !m_getOffMeTimer.HasStarted() )
|
||||
{
|
||||
CUtlVector< CTFPlayer * > onMeVector;
|
||||
me->CollectPlayersStandingOnMe( &onMeVector );
|
||||
|
||||
if ( onMeVector.Count() )
|
||||
{
|
||||
// someone is standing on me - push them off soon
|
||||
m_getOffMeTimer.Start( tf_boss_alpha_get_off_me_duration.GetFloat() );
|
||||
}
|
||||
}
|
||||
else if ( m_getOffMeTimer.IsElapsed() )
|
||||
{
|
||||
if ( !me->IsBusy() )
|
||||
{
|
||||
m_getOffMeTimer.Invalidate();
|
||||
|
||||
// if someone is still on me, push them off
|
||||
CUtlVector< CTFPlayer * > onMeVector;
|
||||
me->CollectPlayersStandingOnMe( &onMeVector );
|
||||
if ( onMeVector.Count() )
|
||||
{
|
||||
return SuspendFor( new CBossAlphaGetOffMe, "Get offa me!" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_tactical_monitor.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_TACTICAL_MONITOR_H
|
||||
#define BOSS_ALPHA_TACTICAL_MONITOR_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
class CBossAlpha;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
class CBossAlphaTacticalMonitor : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual Action< CBossAlpha > *InitialContainedAction( CBossAlpha *me );
|
||||
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
|
||||
virtual const char *GetName( void ) const { return "TacticalMonitor"; } // return name of this action
|
||||
|
||||
private:
|
||||
CountdownTimer m_backOffCooldownTimer;
|
||||
CountdownTimer m_getOffMeTimer;
|
||||
};
|
||||
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_TACTICAL_MONITOR_H
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_wait_for_players.cpp
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "player_vs_environment/boss_alpha/boss_alpha.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_wait_for_players.h"
|
||||
#include "player_vs_environment/boss_alpha/behavior/boss_alpha_guard_spot.h"
|
||||
|
||||
|
||||
extern ConVar tf_boss_alpha_nuke_interval;
|
||||
|
||||
ConVar tf_boss_alpha_sleep( "tf_boss_alpha_sleep", "0"/*, FCVAR_CHEAT */ );
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaWaitForPlayers::OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction )
|
||||
{
|
||||
me->AddCondition( CBossAlpha::BUSY );
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
ActionResult< CBossAlpha > CBossAlphaWaitForPlayers::Update( CBossAlpha *me, float interval )
|
||||
{
|
||||
if ( tf_boss_alpha_sleep.GetBool() )
|
||||
{
|
||||
return Continue();
|
||||
}
|
||||
|
||||
CBaseCombatCharacter *target = me->GetAttackTarget();
|
||||
if ( target )
|
||||
{
|
||||
return ChangeTo( new CBossAlphaGuardSpot, "I see you..." );
|
||||
}
|
||||
|
||||
return Continue();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
void CBossAlphaWaitForPlayers::OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction )
|
||||
{
|
||||
me->RemoveCondition( CBossAlpha::BUSY );
|
||||
|
||||
me->GetNukeTimer()->Start( tf_boss_alpha_nuke_interval.GetFloat() );
|
||||
me->GetGrenadeTimer()->Reset();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaWaitForPlayers::OnInjured( CBossAlpha *me, const CTakeDamageInfo &info )
|
||||
{
|
||||
if ( tf_boss_alpha_sleep.GetBool() )
|
||||
{
|
||||
return TryContinue();
|
||||
}
|
||||
|
||||
return TryChangeTo( new CBossAlphaGuardSpot, RESULT_CRITICAL, "Ouch!" );
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
EventDesiredResult< CBossAlpha > CBossAlphaWaitForPlayers::OnContact( CBossAlpha *me, CBaseEntity *other, CGameTrace *result )
|
||||
{
|
||||
if ( other && other->IsPlayer() && !tf_boss_alpha_sleep.GetBool() )
|
||||
{
|
||||
return TryChangeTo( new CBossAlphaGuardSpot, RESULT_CRITICAL, "Don't touch me" );
|
||||
}
|
||||
|
||||
return TryContinue();
|
||||
}
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha_wait_for_players.h
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_WAIT_FOR_PLAYER_H
|
||||
#define BOSS_ALPHA_WAIT_FOR_PLAYER_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
class CBossAlphaWaitForPlayers : public Action< CBossAlpha >
|
||||
{
|
||||
public:
|
||||
virtual ActionResult< CBossAlpha > OnStart( CBossAlpha *me, Action< CBossAlpha > *priorAction );
|
||||
virtual ActionResult< CBossAlpha > Update( CBossAlpha *me, float interval );
|
||||
virtual void OnEnd( CBossAlpha *me, Action< CBossAlpha > *nextAction );
|
||||
|
||||
virtual EventDesiredResult< CBossAlpha > OnInjured( CBossAlpha *me, const CTakeDamageInfo &info );
|
||||
virtual EventDesiredResult< CBossAlpha > OnContact( CBossAlpha *me, CBaseEntity *other, CGameTrace *result = NULL );
|
||||
|
||||
virtual const char *GetName( void ) const { return "WaitForPlayers"; } // return name of this action
|
||||
};
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_WAIT_FOR_PLAYER_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,508 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
// boss_alpha.h
|
||||
// Our first "real" TF Boss
|
||||
// Michael Booth, November 2010
|
||||
|
||||
#ifndef BOSS_ALPHA_H
|
||||
#define BOSS_ALPHA_H
|
||||
|
||||
#ifdef TF_RAID_MODE
|
||||
|
||||
#include "NextBot.h"
|
||||
#include "NextBotBehavior.h"
|
||||
#include "NextBotGroundLocomotion.h"
|
||||
#include "Path/NextBotPathFollow.h"
|
||||
#include "bot_npc/bot_npc_body.h"
|
||||
#include "bot/map_entities/tf_spawner_boss.h"
|
||||
|
||||
class CTFPlayer;
|
||||
class CBossAlpha;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class CBossAlphaLocomotion : public NextBotGroundLocomotion
|
||||
{
|
||||
public:
|
||||
CBossAlphaLocomotion( INextBot *bot );
|
||||
virtual ~CBossAlphaLocomotion() { }
|
||||
|
||||
virtual float GetRunSpeed( void ) const; // get maximum running speed
|
||||
virtual float GetStepHeight( void ) const; // if delta Z is greater than this, we have to jump to get up
|
||||
virtual float GetMaxJumpHeight( void ) const; // return maximum height of a jump
|
||||
|
||||
virtual float GetMaxAcceleration( void ) const
|
||||
{
|
||||
return 2500.0f;
|
||||
}
|
||||
|
||||
virtual float GetMaxYawRate( void ) const // return max rate of yaw rotation
|
||||
{
|
||||
return 50.0f;
|
||||
}
|
||||
|
||||
private:
|
||||
float m_runSpeed;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class CBossAlphaIntention : public IIntention
|
||||
{
|
||||
public:
|
||||
CBossAlphaIntention( CBossAlpha *me );
|
||||
virtual ~CBossAlphaIntention();
|
||||
|
||||
virtual void Reset( void );
|
||||
virtual void Update( void );
|
||||
|
||||
virtual QueryResultType IsPositionAllowed( const INextBot *me, const Vector &pos ) const; // is the a place we can be?
|
||||
|
||||
virtual INextBotEventResponder *FirstContainedResponder( void ) const { return m_behavior; }
|
||||
virtual INextBotEventResponder *NextContainedResponder( INextBotEventResponder *current ) const { return NULL; }
|
||||
|
||||
private:
|
||||
Behavior< CBossAlpha > *m_behavior;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class CBossAlphaVision : public IVision
|
||||
{
|
||||
public:
|
||||
CBossAlphaVision( INextBot *bot ) : IVision( bot )
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CBossAlphaVision() { }
|
||||
|
||||
virtual bool IsIgnored( CBaseEntity *subject ) const; // return true to completely ignore this entity (may not be in sight when this is called)
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
class CBossAlpha : public NextBotCombatCharacter
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CBossAlpha, NextBotCombatCharacter );
|
||||
DECLARE_SERVERCLASS();
|
||||
DECLARE_DATADESC();
|
||||
|
||||
CBossAlpha();
|
||||
virtual ~CBossAlpha();
|
||||
|
||||
virtual void Precache();
|
||||
virtual void Spawn( void );
|
||||
|
||||
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
|
||||
|
||||
// INextBot
|
||||
virtual CBossAlphaIntention *GetIntentionInterface( void ) const { return m_intention; }
|
||||
virtual CBossAlphaLocomotion *GetLocomotionInterface( void ) const { return m_locomotor; }
|
||||
virtual CBotNPCBody *GetBodyInterface( void ) const { return m_body; }
|
||||
virtual CBossAlphaVision *GetVisionInterface( void ) const { return m_vision; }
|
||||
|
||||
virtual bool IsRemovedOnReset( void ) const { return false; } // remove this bot when the NextBot manager calls Reset
|
||||
|
||||
virtual void Update( void );
|
||||
|
||||
// virtual bool IsPotentiallyChaseable( CTFPlayer *victim );
|
||||
|
||||
void Break( void ); // bust into gibs
|
||||
|
||||
struct AttackerInfo
|
||||
{
|
||||
CHandle< CBaseCombatCharacter > m_attacker;
|
||||
float m_timestamp;
|
||||
float m_damage;
|
||||
bool m_wasCritical;
|
||||
};
|
||||
const CUtlVector< AttackerInfo > &GetAttackerVector( void ) const;
|
||||
void RememberAttacker( CBaseCombatCharacter *attacker, float damage, bool wasCritical );
|
||||
|
||||
struct ThreatInfo
|
||||
{
|
||||
CHandle< CBaseCombatCharacter > m_who;
|
||||
float m_threat;
|
||||
};
|
||||
|
||||
const ThreatInfo *GetMaxThreat( void ) const;
|
||||
const ThreatInfo *GetThreat( CBaseCombatCharacter *who ) const;
|
||||
|
||||
void SwingAxe( void );
|
||||
void UpdateAxeSwing( void );
|
||||
bool IsSwingingAxe( void ) const;
|
||||
|
||||
|
||||
//----------------------------------
|
||||
enum Ability
|
||||
{
|
||||
CAN_BE_STUNNED = 0x01,
|
||||
CAN_NUKE = 0x02,
|
||||
CAN_ENRAGE = 0x04,
|
||||
CAN_FIRE_ROCKETS = 0x08,
|
||||
CAN_LAUNCH_STICKIES = 0x10,
|
||||
CAN_LAUNCH_MINIONS = 0x20,
|
||||
};
|
||||
virtual bool HasAbility( Ability ability ) const;
|
||||
|
||||
virtual bool IsMiniBoss( void ) const { return false; }
|
||||
|
||||
virtual float GetMoveSpeed( void ) const { return 300.0f; }
|
||||
|
||||
virtual int GetRocketLaunchCount( void ) const { return 5; }
|
||||
virtual float GetRocketDamage( void ) const { return 25.0f; }
|
||||
virtual float GetRocketAimError( void ) const { return 1.81f; }
|
||||
virtual float GetRocketInterval( void ) const { return 0.3f; }
|
||||
virtual const char *GetRocketSoundEffect( void ) const { return "Weapon_RPG.Single"; }
|
||||
|
||||
virtual float GetGrenadeInterval( void ) const { return 10.0f; }
|
||||
|
||||
virtual float GetBecomeStunnedDamage( void ) const { return 500.0f; }
|
||||
|
||||
|
||||
//----------------------------------
|
||||
enum Condition
|
||||
{
|
||||
SHIELDED = 0x01,
|
||||
CHARGING = 0x02,
|
||||
STUNNED = 0x04,
|
||||
INVULNERABLE = 0x08,
|
||||
VULNERABLE_TO_STUN = 0x10,
|
||||
BUSY = 0x20,
|
||||
ENRAGED = 0x40,
|
||||
};
|
||||
|
||||
bool IsBusy( void ) const; // returns true if we're in a condition that means we can't start another action
|
||||
|
||||
void AddCondition( Condition c );
|
||||
void RemoveCondition( Condition c );
|
||||
bool IsInCondition( Condition c ) const;
|
||||
|
||||
bool IsAttackTarget( CBaseCombatCharacter *target ) const;
|
||||
bool HasAttackTarget( void ) const;
|
||||
void SetAttackTarget( CBaseCombatCharacter *target, float duration = 0.0f );
|
||||
CBaseCombatCharacter *GetAttackTarget( void ) const;
|
||||
void LockAttackTarget( void ); // don't allow target to change until it is unlocked or the target is destroyed
|
||||
void UnlockAttackTarget( void );
|
||||
|
||||
CBaseCombatCharacter *GetNearestVisibleEnemy( void ) const;
|
||||
|
||||
void SetHomePosition( const Vector &pos );
|
||||
const Vector &GetHomePosition( void ) const;
|
||||
|
||||
CBaseAnimating *GetWeapon( void ) const;
|
||||
CBaseAnimating *GetShield( void ) const;
|
||||
|
||||
CountdownTimer *GetNukeTimer( void );
|
||||
CountdownTimer *GetGrenadeTimer( void );
|
||||
|
||||
float GetReceivedDamagePerSecond( void ) const;
|
||||
float GetReceivedDamagePerSecondDelta( void ) const;
|
||||
|
||||
void ClearStunDamage( void );
|
||||
void AccumulateStunDamage( float damage );
|
||||
float GetStunDamage( void ) const;
|
||||
|
||||
CTFPlayer *GetClosestMinionPrisoner( void );
|
||||
bool IsPrisonerOfMinion( CBaseCombatCharacter *victim );
|
||||
|
||||
void StartNukeEffect( void );
|
||||
void StopNukeEffect( void );
|
||||
|
||||
float GetAge( void ) const; // how long have we been alive
|
||||
|
||||
void CollectPlayersStandingOnMe( CUtlVector< CTFPlayer * > *playerVector );
|
||||
|
||||
// Entity I/O
|
||||
COutputEvent m_outputOnStunned;
|
||||
|
||||
COutputEvent m_outputOnHealthBelow90Percent;
|
||||
COutputEvent m_outputOnHealthBelow80Percent;
|
||||
COutputEvent m_outputOnHealthBelow70Percent;
|
||||
COutputEvent m_outputOnHealthBelow60Percent;
|
||||
COutputEvent m_outputOnHealthBelow50Percent;
|
||||
COutputEvent m_outputOnHealthBelow40Percent;
|
||||
COutputEvent m_outputOnHealthBelow30Percent;
|
||||
COutputEvent m_outputOnHealthBelow20Percent;
|
||||
COutputEvent m_outputOnHealthBelow10Percent;
|
||||
|
||||
COutputEvent m_outputOnKilled;
|
||||
|
||||
protected:
|
||||
virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
|
||||
|
||||
private:
|
||||
CBossAlphaIntention *m_intention;
|
||||
CBossAlphaLocomotion *m_locomotor;
|
||||
CBotNPCBody *m_body;
|
||||
CBossAlphaVision *m_vision;
|
||||
|
||||
CBaseAnimating *m_axe;
|
||||
CBaseAnimating *m_shield;
|
||||
|
||||
CountdownTimer m_axeSwingTimer;
|
||||
CountdownTimer m_attackTimer;
|
||||
CountdownTimer m_nukeTimer;
|
||||
CountdownTimer m_grenadeTimer;
|
||||
CountdownTimer m_ouchTimer;
|
||||
CountdownTimer m_hateTauntTimer;
|
||||
|
||||
CNetworkVar( bool, m_isNuking );
|
||||
|
||||
CHandle< CBaseCombatCharacter > m_nearestVisibleEnemy;
|
||||
void UpdateNearestVisibleEnemy( void );
|
||||
CountdownTimer m_nearestVisibleEnemyTimer;
|
||||
|
||||
CUtlVector< AttackerInfo > m_attackerVector; // list of everyone who injured me, and when
|
||||
CUtlVector< ThreatInfo > m_threatVector; // list of attackers and their current damage/second on me
|
||||
|
||||
float m_currentDamagePerSecond;
|
||||
float m_lastDamagePerSecond;
|
||||
void UpdateDamagePerSecond( void );
|
||||
|
||||
CHandle< CBaseCombatCharacter > m_attackTarget;
|
||||
CountdownTimer m_attackTargetTimer;
|
||||
bool m_isAttackTargetLocked;
|
||||
void UpdateAttackTarget( void );
|
||||
|
||||
int m_damagePoseParameter;
|
||||
|
||||
bool m_isShielded;
|
||||
Vector m_homePos;
|
||||
|
||||
bool IsIgnored( CTFPlayer *player ) const;
|
||||
|
||||
unsigned int m_conditionFlags;
|
||||
|
||||
float m_stunDamage;
|
||||
float m_lastHealthPercentage;
|
||||
|
||||
IntervalTimer m_ageTimer;
|
||||
|
||||
void UpdateSkillShots( void );
|
||||
|
||||
bool CheckSkillShots( const CTakeDamageInfo &info );
|
||||
CountdownTimer m_headStunTimer;
|
||||
CountdownTimer m_consecutiveRocketTimer;
|
||||
int m_consecutiveRockets;
|
||||
|
||||
CountdownTimer m_ricochetSoundTimer;
|
||||
|
||||
void ResetSkillShots( void );
|
||||
void OnSkillShotComboStarted( void );
|
||||
void OnSkillShot( void );
|
||||
|
||||
CountdownTimer m_skillShotComboTimer;
|
||||
int m_skillShotCount;
|
||||
|
||||
bool m_isPrecisionShotDone;
|
||||
CountdownTimer m_precisionSkillShotTimer;
|
||||
bool m_isPrecisionShotHit[3];
|
||||
|
||||
bool m_isDamageSpongeSkillShotDone;
|
||||
float m_damageSpongeSkillShotAmount;
|
||||
|
||||
bool m_isHardHitSkillShotDone;
|
||||
|
||||
trace_t m_lastTraceAttackTrace;
|
||||
Vector m_lastTraceAttackDir;
|
||||
};
|
||||
|
||||
|
||||
inline bool CBossAlpha::HasAbility( Ability ability ) const
|
||||
{
|
||||
const int myAbilities = CAN_BE_STUNNED | CAN_NUKE | CAN_ENRAGE | CAN_FIRE_ROCKETS | CAN_LAUNCH_STICKIES | CAN_LAUNCH_MINIONS;
|
||||
|
||||
return myAbilities & ability ? true : false;
|
||||
}
|
||||
|
||||
inline bool CBossAlpha::IsAttackTarget( CBaseCombatCharacter *target ) const
|
||||
{
|
||||
if ( HasAttackTarget() )
|
||||
{
|
||||
return ( m_attackTarget == target ) ? true : false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool CBossAlpha::HasAttackTarget( void ) const
|
||||
{
|
||||
return ( m_attackTarget == NULL || !m_attackTarget->IsAlive() ) ? false : true;
|
||||
}
|
||||
|
||||
inline void CBossAlpha::LockAttackTarget( void )
|
||||
{
|
||||
m_isAttackTargetLocked = HasAttackTarget();
|
||||
}
|
||||
|
||||
inline void CBossAlpha::UnlockAttackTarget( void )
|
||||
{
|
||||
m_isAttackTargetLocked = false;
|
||||
}
|
||||
|
||||
inline float CBossAlpha::GetAge( void ) const
|
||||
{
|
||||
return m_ageTimer.GetElapsedTime();
|
||||
}
|
||||
|
||||
inline void CBossAlpha::StartNukeEffect( void )
|
||||
{
|
||||
m_isNuking = true;
|
||||
}
|
||||
|
||||
inline void CBossAlpha::StopNukeEffect( void )
|
||||
{
|
||||
m_isNuking = false;
|
||||
}
|
||||
|
||||
inline void CBossAlpha::ClearStunDamage( void )
|
||||
{
|
||||
m_stunDamage = 0.0f;
|
||||
}
|
||||
|
||||
inline void CBossAlpha::AccumulateStunDamage( float damage )
|
||||
{
|
||||
m_stunDamage += damage;
|
||||
}
|
||||
|
||||
inline float CBossAlpha::GetStunDamage( void ) const
|
||||
{
|
||||
return m_stunDamage;
|
||||
}
|
||||
|
||||
inline float CBossAlpha::GetReceivedDamagePerSecond( void ) const
|
||||
{
|
||||
return m_currentDamagePerSecond;
|
||||
}
|
||||
|
||||
inline float CBossAlpha::GetReceivedDamagePerSecondDelta( void ) const
|
||||
{
|
||||
return m_currentDamagePerSecond - m_lastDamagePerSecond;
|
||||
}
|
||||
|
||||
inline CountdownTimer *CBossAlpha::GetNukeTimer( void )
|
||||
{
|
||||
return &m_nukeTimer;
|
||||
}
|
||||
|
||||
inline CountdownTimer *CBossAlpha::GetGrenadeTimer( void )
|
||||
{
|
||||
return &m_grenadeTimer;
|
||||
}
|
||||
|
||||
inline CBaseAnimating *CBossAlpha::GetWeapon( void ) const
|
||||
{
|
||||
return m_axe;
|
||||
}
|
||||
|
||||
inline CBaseAnimating *CBossAlpha::GetShield( void ) const
|
||||
{
|
||||
return m_shield;
|
||||
}
|
||||
|
||||
inline void CBossAlpha::SetHomePosition( const Vector &pos )
|
||||
{
|
||||
m_homePos = pos;
|
||||
}
|
||||
|
||||
inline const Vector &CBossAlpha::GetHomePosition( void ) const
|
||||
{
|
||||
return m_homePos;
|
||||
}
|
||||
|
||||
inline CBaseCombatCharacter *CBossAlpha::GetNearestVisibleEnemy( void ) const
|
||||
{
|
||||
return m_nearestVisibleEnemy;
|
||||
}
|
||||
|
||||
inline void CBossAlpha::AddCondition( Condition c )
|
||||
{
|
||||
m_conditionFlags |= c;
|
||||
}
|
||||
|
||||
inline bool CBossAlpha::IsInCondition( Condition c ) const
|
||||
{
|
||||
return ( m_conditionFlags & c ) ? true : false;
|
||||
}
|
||||
|
||||
inline const CUtlVector< CBossAlpha::AttackerInfo > &CBossAlpha::GetAttackerVector( void ) const
|
||||
{
|
||||
return m_attackerVector;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
class CBossAlphaPathCost : public IPathCost
|
||||
{
|
||||
public:
|
||||
CBossAlphaPathCost( CBossAlpha *me )
|
||||
{
|
||||
m_me = me;
|
||||
}
|
||||
|
||||
// return the cost (weighted distance between) of moving from "fromArea" to "area", or -1 if the move is not allowed
|
||||
virtual float operator()( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder, const CFuncElevator *elevator, float length ) const
|
||||
{
|
||||
if ( fromArea == NULL )
|
||||
{
|
||||
// first area in path, no cost
|
||||
return 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !m_me->GetLocomotionInterface()->IsAreaTraversable( area ) )
|
||||
{
|
||||
// our locomotor says we can't move here
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
// compute distance traveled along path so far
|
||||
float dist;
|
||||
|
||||
if ( ladder )
|
||||
{
|
||||
dist = ladder->m_length;
|
||||
}
|
||||
else if ( length > 0.0 )
|
||||
{
|
||||
// optimization to avoid recomputing length
|
||||
dist = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist = ( area->GetCenter() - fromArea->GetCenter() ).Length();
|
||||
}
|
||||
|
||||
float cost = dist + fromArea->GetCostSoFar();
|
||||
|
||||
// check height change
|
||||
float deltaZ = fromArea->ComputeAdjacentConnectionHeightChange( area );
|
||||
if ( deltaZ >= m_me->GetLocomotionInterface()->GetStepHeight() )
|
||||
{
|
||||
if ( deltaZ >= m_me->GetLocomotionInterface()->GetMaxJumpHeight() )
|
||||
{
|
||||
// too high to reach
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
// jumping is slower than flat ground
|
||||
const float jumpPenalty = 5.0f;
|
||||
cost += jumpPenalty * dist;
|
||||
}
|
||||
else if ( deltaZ < -m_me->GetLocomotionInterface()->GetDeathDropHeight() )
|
||||
{
|
||||
// too far to drop
|
||||
return -1.0f;
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
|
||||
CBossAlpha *m_me;
|
||||
};
|
||||
|
||||
#endif // TF_RAID_MODE
|
||||
|
||||
#endif // BOSS_ALPHA_H
|
||||
Reference in New Issue
Block a user