//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "cbase.h" #include "beam_shared.h" #include "ai_motor.h" #include "asw_ai_behavior_combat_stun.h" #include "ai_hint.h" #include "ai_navigator.h" #include "ai_memory.h" #include "asw_alien.h" #include "asw_marine.h" #include "particle_parse.h" #include "asw_marine_skills.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" BEGIN_DATADESC( CAI_ASW_CombatStunBehavior ) END_DATADESC(); LINK_BEHAVIOR_TO_CLASSNAME( CAI_ASW_CombatStunBehavior ); // todo: if we want more varied stuns, tie this to damage, etc static const float COMBAT_STUN_DURATION = 2.5f; // for now govern how often we check recent damage events static const float COMBAT_STUN_CHECK_TIME = 0.5f; //------------------------------------------------------------------------------ // Purpose: constructor //------------------------------------------------------------------------------ CAI_ASW_CombatStunBehavior::CAI_ASW_CombatStunBehavior( ) { m_flStunEndTime = 0.0f; } //------------------------------------------------------------------------------ // Purpose: function to set up parameters // Input : szKeyName - the name of the key // szValue - the value to be set // Output : returns true of we handled this key //------------------------------------------------------------------------------ bool CAI_ASW_CombatStunBehavior::KeyValue( const char *szKeyName, const char *szValue ) { return BaseClass::KeyValue( szKeyName, szValue ); } //------------------------------------------------------------------------------ // Purpose: precaches any additional assets this behavior needs //------------------------------------------------------------------------------ void CAI_ASW_CombatStunBehavior::Precache( void ) { BaseClass::Precache(); } //------------------------------------------------------------------------------ // Purpose: determines if we can use this behavior currently // Output : returns true if this behavior is able to run //------------------------------------------------------------------------------ bool CAI_ASW_CombatStunBehavior::CanSelectSchedule() { if ( !GetOuter()->IsInterruptable() ) { return false; } if ( !HasCondition( COND_BEGIN_COMBAT_STUN ) ) { return false; } return BaseClass::CanSelectSchedule(); } //------------------------------------------------------------------------------ // Purpose: sets / clears conditions for when the behavior is active. this is // generally a larger set of conditions to interrupt any tasks. //------------------------------------------------------------------------------ void CAI_ASW_CombatStunBehavior::GatherConditions( ) { BaseClass::GatherConditions(); } //------------------------------------------------------------------------------ // Purpose: sets / clears conditions for when the behavior is not active. this is // mainly to have a smaller set of conditions to wake up the behavior. //------------------------------------------------------------------------------ void CAI_ASW_CombatStunBehavior::GatherConditionsNotActive( ) { BaseClass::GatherConditionsNotActive(); ClearCondition( COND_BEGIN_COMBAT_STUN ); if ( !GetOuter() ) { return; } if ( !IsAlienClass( GetOuter()->Classify() ) ) { // This behavior isn't currently designed for non-aliens, relies on CASW_Alien::m_RecentDamage Assert( false ); return; } CASW_Alien *pAlien = static_cast( GetOuter() ); for ( int i = 0; i < pAlien->m_RecentDamage.Count(); i++ ) { int nDamageType = pAlien->m_RecentDamage[i].GetDamageType(); if ( (nDamageType & DMG_CLUB) && (nDamageType & DMG_SONIC) ) { if ( pAlien->m_RecentDamage[i].GetAttacker() && pAlien->m_RecentDamage[i].GetAttacker()->Classify() == CLASS_ASW_MARINE ) { m_flStunDuration = COMBAT_STUN_DURATION; SetCondition( COND_BEGIN_COMBAT_STUN ); break; } } } } //------------------------------------------------------------------------------ // Purpose: general purpose routine to collect conditions used both during active // and non-active states of the behavior. //------------------------------------------------------------------------------ void CAI_ASW_CombatStunBehavior::GatherCommonConditions( ) { BaseClass::GatherCommonConditions(); } //------------------------------------------------------------------------------ // Purpose: routine called to start when a task initially starts // Input : pTask - the task structure //------------------------------------------------------------------------------ void CAI_ASW_CombatStunBehavior::StartTask( const Task_t *pTask ) { if ( !GetOuter() || !IsAlienClass( GetOuter()->Classify() ) ) { TaskComplete(); // This behavior isn't currently designed for non-aliens Assert( false ); return; } CASW_Alien *pAlien = static_cast( GetOuter() ); switch( pTask->iTask ) { case TASK_COMBAT_STUN: { m_flStunEndTime = gpGlobals->curtime + m_flStunDuration; pAlien->m_RecentDamage.RemoveAll(); DispatchParticleEffect( "melee_stun", PATTACH_POINT_FOLLOW, pAlien, "attach_top" ); break; } default: { BaseClass::StartTask( pTask ); break; } } } //------------------------------------------------------------------------------ // Purpose: routine called every frame when a task is running // Input : pTask - the task structure //------------------------------------------------------------------------------ void CAI_ASW_CombatStunBehavior::RunTask( const Task_t *pTask ) { CASW_Alien *pAlien = dynamic_cast( GetOuter() ); if ( !pAlien ) { TaskComplete(); Assert( false ); return; } switch( pTask->iTask ) { case TASK_COMBAT_STUN: { if ( gpGlobals->curtime > m_flStunEndTime ) { TaskComplete(); } break; } default: { BaseClass::RunTask( pTask ); break; } } } //------------------------------------------------------------------------------ // Purpose: routine called to select what schedule we want to run // Output : returns the schedule id of the schedule we want to run //------------------------------------------------------------------------------ int CAI_ASW_CombatStunBehavior::SelectSchedule() { if ( HasCondition( COND_BEGIN_COMBAT_STUN ) ) { return SCHED_COMBAT_STUN; } // SelectSchedule() shouldn't be called unless we're ready to run this behavior... Assert( 0 ); return SCHED_NONE; } AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_ASW_CombatStunBehavior ) DECLARE_TASK( TASK_COMBAT_STUN ); DECLARE_CONDITION( COND_BEGIN_COMBAT_STUN ); DEFINE_SCHEDULE ( SCHED_COMBAT_STUN, " Tasks" " TASK_STOP_MOVING 0" " TASK_SET_ACTIVITY ACTIVITY:ACT_FLINCH_PHYSICS" " TASK_COMBAT_STUN 0" "" " Interrupts" "" ); AI_END_CUSTOM_SCHEDULE_PROVIDER() #include "tier0/memdbgoff.h"