You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
548 lines
13 KiB
548 lines
13 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "beam_shared.h" |
|
#include "ai_motor.h" |
|
#include "asw_ai_behavior_shield.h" |
|
#include "ai_hint.h" |
|
#include "ai_navigator.h" |
|
#include "ai_memory.h" |
|
#include "asw_alien.h" |
|
#include "movevars_shared.h" |
|
#include "asw_marine.h" |
|
#include "asw_player.h" |
|
#include "asw_director.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
|
|
BEGIN_DATADESC( CAI_ASW_ShieldBehavior ) |
|
END_DATADESC(); |
|
|
|
LINK_BEHAVIOR_TO_CLASSNAME( CAI_ASW_ShieldBehavior ); |
|
|
|
|
|
//#define DRAW_DEBUG 1 |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: constructor |
|
//------------------------------------------------------------------------------ |
|
CAI_ASW_ShieldBehavior::CAI_ASW_ShieldBehavior( ) |
|
{ |
|
m_flDistance = 200.0f; |
|
m_flMaxFrozenTime = 3.0f; |
|
m_flSFrozenDownTime = 3.0f; |
|
m_flFrozenTimeReductionMultiplier = 10.0f; |
|
m_flFrozenTimeExpansionMultiplier = 50.0f; |
|
m_FrozenParm = UTL_INVAL_SYMBOL; |
|
m_bShieldLowering = false; |
|
m_bBeganFrozen = false; |
|
m_flStartFrozenTime = -1.0f; |
|
m_flEndFrozenTime = -1.0f; |
|
m_flStartDownTime = -1.0f; |
|
m_bReachedFrozenLimit = false; |
|
m_TurningGesture = ACT_INVALID; |
|
m_Freezer = NULL; |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// 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_ShieldBehavior::KeyValue( const char *szKeyName, const char *szValue ) |
|
{ |
|
if ( V_stricmp( szKeyName, "distance") == 0 ) |
|
{ |
|
m_flDistance = atof( szValue ); |
|
return true; |
|
} |
|
else if ( V_stricmp( szKeyName, "max_frozen_time") == 0 ) |
|
{ |
|
m_flMaxFrozenTime = atof( szValue ); |
|
return true; |
|
} |
|
else if ( V_stricmp( szKeyName, "frozen_down_time") == 0 ) |
|
{ |
|
m_flSFrozenDownTime = atof( szValue ); |
|
return true; |
|
} |
|
else if ( V_stricmp( szKeyName, "frozen_param" ) == 0 ) |
|
{ |
|
m_FrozenParm = GetSymbol( szValue ); |
|
return true; |
|
} |
|
else if ( V_stricmp( szKeyName, "frozen_time_reduction_multiplier" ) == 0 ) |
|
{ |
|
m_flFrozenTimeReductionMultiplier = atof( szValue ); |
|
return true; |
|
} |
|
else if ( V_stricmp( szKeyName, "frozen_time_expansion_multiplier" ) == 0 ) |
|
{ |
|
m_flFrozenTimeExpansionMultiplier = atof( szValue ); |
|
return true; |
|
} |
|
|
|
return BaseClass::KeyValue( szKeyName, szValue ); |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: precaches any additional assets this behavior needs |
|
//------------------------------------------------------------------------------ |
|
void CAI_ASW_ShieldBehavior::Precache( void ) |
|
{ |
|
BaseClass::Precache(); |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: |
|
//------------------------------------------------------------------------------ |
|
void CAI_ASW_ShieldBehavior::Init( ) |
|
{ |
|
CASW_Alien *pNPC = static_cast< CASW_Alien * >( GetOuter() ); |
|
if ( !pNPC ) |
|
{ |
|
return; |
|
} |
|
|
|
pNPC->meleeAttack2.Init( 0.0f, m_flDistance, COMBAT_COND_NO_FACING_CHECK, true ); |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: determines if we can use this behavior currently |
|
// Output : returns true if this behavior is able to run |
|
//------------------------------------------------------------------------------ |
|
bool CAI_ASW_ShieldBehavior::CanSelectSchedule() |
|
{ |
|
if ( m_bShieldLowering ) |
|
{ |
|
return true; |
|
} |
|
|
|
if ( !GetOuter()->IsInterruptable() ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( !HasCondition( COND_CAN_MELEE_ATTACK2 ) ) |
|
{ |
|
if ( GetBehaviorParam( m_StatusParm ) == 0 ) |
|
{ |
|
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_ShieldBehavior::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_ShieldBehavior::GatherConditionsNotActive( ) |
|
{ |
|
BaseClass::GatherConditionsNotActive(); |
|
} |
|
|
|
|
|
void CAI_ASW_ShieldBehavior::BeginScheduleSelection( ) |
|
{ |
|
m_TurningGesture = ACT_INVALID; |
|
} |
|
|
|
|
|
void CAI_ASW_ShieldBehavior::EndScheduleSelection( ) |
|
{ |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: general purpose routine to collect conditions used both during active |
|
// and non-active states of the behavior. |
|
//------------------------------------------------------------------------------ |
|
void CAI_ASW_ShieldBehavior::GatherCommonConditions( ) |
|
{ |
|
BaseClass::GatherCommonConditions(); |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: routine called to start when a task initially starts |
|
// Input : pTask - the task structure |
|
//------------------------------------------------------------------------------ |
|
void CAI_ASW_ShieldBehavior::StartTask( const Task_t *pTask ) |
|
{ |
|
switch( pTask->iTask ) |
|
{ |
|
case TASK_SHIELD_RAISE: |
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP ); |
|
break; |
|
|
|
case TASK_SHIELD_LOWER: |
|
GetOuter()->SetIdealActivity( ACT_SHIELD_DOWN ); |
|
break; |
|
|
|
case TASK_SHIELD_MAINTAIN: |
|
m_TurningGesture = ACT_INVALID; |
|
|
|
if ( m_flEndFrozenTime < gpGlobals->curtime ) |
|
{ |
|
CBaseEntity *pTarget = GetEnemy(); |
|
|
|
if ( pTarget ) |
|
{ |
|
float flIdealYaw = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetLocalOrigin() ); |
|
float flYawDiff = UTIL_AngleMod( GetLocalAngles().y - flIdealYaw ); |
|
if ( flYawDiff > 180.0f && flYawDiff < 330.0f ) |
|
{ |
|
m_TurningGesture = ACT_GESTURE_TURN_LEFT45; |
|
GetOuter()->RestartGesture( m_TurningGesture ); |
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP_IDLE ); |
|
} |
|
else if ( flYawDiff <= 180.0f && flYawDiff > 30.0f ) |
|
{ |
|
m_TurningGesture = ACT_GESTURE_TURN_RIGHT45; |
|
GetOuter()->RestartGesture( m_TurningGesture ); |
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP_IDLE ); |
|
} |
|
} |
|
} |
|
|
|
if ( m_TurningGesture == ACT_INVALID ) |
|
{ |
|
if ( m_flEndFrozenTime > gpGlobals->curtime ) |
|
{ |
|
if ( m_bBeganFrozen == false ) |
|
{ |
|
m_bBeganFrozen = true; |
|
GetOuter()->SetIdealActivity( ACT_CROUCHING_SHIELD_UP ); |
|
} |
|
else |
|
{ |
|
GetOuter()->SetIdealActivity( ACT_CROUCHING_SHIELD_UP_IDLE ); |
|
} |
|
} |
|
else |
|
{ |
|
GetOuter()->SetIdealActivity( ACT_SHIELD_UP_IDLE ); |
|
} |
|
} |
|
break; |
|
|
|
case TASK_SHIELD_MAINTAIN_FLIP: |
|
{ |
|
bool bNeedFlip = false; |
|
|
|
if ( HaveSequenceForActivity( ACT_SPINAROUND ) == true ) |
|
{ |
|
CBaseEntity *pTarget = GetEnemy(); |
|
if ( pTarget ) |
|
{ |
|
float flIdealYaw = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetLocalOrigin() ); |
|
float flYawDiff = UTIL_AngleMod( GetLocalAngles().y - flIdealYaw ); |
|
|
|
if ( fabs( flYawDiff - 180.0f ) <= 40.0f ) |
|
{ |
|
bNeedFlip = true; |
|
} |
|
} |
|
} |
|
|
|
if ( bNeedFlip == false ) |
|
{ |
|
TaskComplete(); |
|
} |
|
else |
|
{ |
|
GetOuter()->SetIdealActivity( ACT_SPINAROUND ); |
|
} |
|
|
|
} |
|
break; |
|
|
|
default: |
|
BaseClass::StartTask( pTask ); |
|
break; |
|
} |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: routine called every frame when a task is running |
|
// Input : pTask - the task structure |
|
//------------------------------------------------------------------------------ |
|
void CAI_ASW_ShieldBehavior::RunTask( const Task_t *pTask ) |
|
{ |
|
switch( pTask->iTask ) |
|
{ |
|
case TASK_SHIELD_RAISE: |
|
{ |
|
CBaseEntity *pTarget = GetEnemy(); |
|
|
|
if ( pTarget ) |
|
{ |
|
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin(), AI_KEEP_YAW_SPEED ); |
|
} |
|
|
|
if ( GetOuter()->IsActivityFinished() ) |
|
{ |
|
TaskComplete(); |
|
SetBehaviorParam( m_StatusParm, 1 ); |
|
} |
|
} |
|
break; |
|
|
|
case TASK_SHIELD_LOWER: |
|
if ( GetOuter()->IsActivityFinished() ) |
|
{ |
|
TaskComplete(); |
|
SetBehaviorParam( m_StatusParm, 0 ); |
|
m_bShieldLowering = false; |
|
} |
|
break; |
|
|
|
case TASK_SHIELD_MAINTAIN: |
|
{ |
|
bool bNoReset = false; |
|
|
|
if ( m_TurningGesture != ACT_INVALID ) |
|
{ |
|
CBaseEntity *pTarget = GetEnemy(); |
|
|
|
if ( pTarget ) |
|
{ |
|
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin(), AI_KEEP_YAW_SPEED ); |
|
} |
|
|
|
if ( GetOuter()->IsPlayingGesture( m_TurningGesture ) == false ) |
|
{ |
|
TaskComplete(); |
|
m_TurningGesture = ACT_INVALID; |
|
|
|
if ( pTarget ) |
|
{ |
|
float flIdealYaw = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetLocalOrigin() ); |
|
float flYawDiff = UTIL_AngleMod( GetLocalAngles().y - flIdealYaw ); |
|
if ( flYawDiff > 25.0f && flYawDiff < 335.0f ) |
|
{ |
|
bNoReset = true; |
|
} |
|
} |
|
} |
|
} |
|
else if ( GetOuter()->IsActivityFinished() ) |
|
{ |
|
TaskComplete(); |
|
} |
|
|
|
if ( m_flStartFrozenTime != -1.0f && m_flEndFrozenTime < gpGlobals->curtime && bNoReset == false ) |
|
{ |
|
m_flStartFrozenTime = -1.0f; |
|
m_flStartDownTime = gpGlobals->curtime + m_flSFrozenDownTime; |
|
SetBehaviorParam( m_FrozenParm, 0 ); |
|
} |
|
} |
|
break; |
|
|
|
case TASK_SHIELD_MAINTAIN_FLIP: |
|
{ |
|
CBaseEntity *pTarget = GetEnemy(); |
|
if ( pTarget ) |
|
{ |
|
GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin(), AI_KEEP_YAW_SPEED ); |
|
} |
|
|
|
if ( GetOuter()->IsActivityFinished() ) |
|
{ |
|
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_ShieldBehavior::SelectSchedule() |
|
{ |
|
if ( !HasCondition( COND_CAN_MELEE_ATTACK2 ) ) |
|
{ |
|
return SCHED_SHIELD_LOWER; |
|
} |
|
|
|
if ( GetBehaviorParam( m_StatusParm ) == 0 ) |
|
{ |
|
return SCHED_SHIELD_PREPARE; |
|
} |
|
else |
|
{ |
|
return SCHED_SHIELD_MAINTAIN; |
|
} |
|
|
|
#if 0 |
|
if ( m_bShieldLowering == true ) |
|
{ |
|
return SCHED_SHIELD_LOWER; |
|
} |
|
|
|
if ( GetBehaviorParam( m_StatusParm ) == 0 ) |
|
{ |
|
return SCHED_SHIELD_PREPARE; |
|
} |
|
|
|
if ( HasCondition( COND_SHIELD_CAN_FLICK ) ) |
|
{ |
|
return SCHED_SHIELD_FLICK; |
|
} |
|
|
|
return SCHED_SHIELD_MAINTAIN; |
|
#endif |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: |
|
// Input : |
|
// Output : |
|
//------------------------------------------------------------------------------ |
|
void CAI_ASW_ShieldBehavior::HandleBehaviorEvent( CBaseEntity *pInflictor, BehaviorEvent_t eEvent, int nParm ) |
|
{ |
|
switch( eEvent ) |
|
{ |
|
case BEHAVIOR_EVENT_TOOK_DAMAGE: |
|
{ |
|
float flPercent = ( float )nParm / ( float )GetOuter()->GetMaxHealth(); |
|
if ( m_Freezer != pInflictor ) |
|
{ |
|
flPercent *= 3.0f; |
|
} |
|
m_flEndFrozenTime -= flPercent * m_flFrozenTimeReductionMultiplier; |
|
} |
|
break; |
|
|
|
case BEHAVIOR_EVENT_DEFLECTED_DAMAGE: |
|
{ |
|
if ( m_flStartDownTime > gpGlobals->curtime ) |
|
{ |
|
break; |
|
} |
|
|
|
if ( m_flStartFrozenTime == -1.0f ) |
|
{ |
|
m_flStartFrozenTime = gpGlobals->curtime; |
|
m_flEndFrozenTime = m_flStartFrozenTime; |
|
m_bReachedFrozenLimit = false; |
|
SetBehaviorParam( m_FrozenParm, 1 ); |
|
m_Freezer = pInflictor; |
|
m_bBeganFrozen = false; |
|
} |
|
else |
|
{ |
|
m_flEndFrozenTime += gpGlobals->curtime - m_flStartFrozenTime; |
|
/* if ( m_bReachedFrozenLimit == false ) |
|
{ |
|
m_flStartFrozenTime = gpGlobals->curtime; |
|
} |
|
*/ |
|
} |
|
|
|
float flPercent = ( float )nParm / ( float )GetOuter()->GetMaxHealth(); |
|
m_flEndFrozenTime += flPercent * m_flFrozenTimeExpansionMultiplier; |
|
if ( ( m_flEndFrozenTime - m_flStartFrozenTime ) > m_flMaxFrozenTime ) |
|
{ |
|
m_flEndFrozenTime = m_flStartFrozenTime + m_flMaxFrozenTime; |
|
m_bReachedFrozenLimit = true; |
|
} |
|
// Msg( "Time to awake: %g\n", m_flEndFrozenTime - gpGlobals->curtime ); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
|
|
#if 0 |
|
bool CAI_ASW_ShieldBehavior::GetBehaviorParam( BehaviorParam_t eParam, bool &bResult ) |
|
{ |
|
switch( eParam ) |
|
{ |
|
case BEHAVIOR_PARAM_IS_SHIELDED: |
|
bResult = ( GetBehaviorParam( m_StatusParm ) == 1 ); |
|
return true; |
|
} |
|
|
|
return BaseClass::GetBehaviorParam( eParam, bResult ); |
|
} |
|
#endif |
|
|
|
|
|
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_ASW_ShieldBehavior ) |
|
|
|
DECLARE_TASK( TASK_SHIELD_RAISE ) |
|
DECLARE_TASK( TASK_SHIELD_MAINTAIN ) |
|
DECLARE_TASK( TASK_SHIELD_MAINTAIN_FLIP ) |
|
DECLARE_TASK( TASK_SHIELD_LOWER ) |
|
|
|
DEFINE_SCHEDULE |
|
( |
|
SCHED_SHIELD_PREPARE, |
|
" Tasks" |
|
" TASK_STOP_MOVING 0" |
|
" TASK_SHIELD_RAISE 0" |
|
"" |
|
" Interrupts" |
|
); |
|
|
|
DEFINE_SCHEDULE |
|
( |
|
SCHED_SHIELD_MAINTAIN, |
|
" Tasks" |
|
// " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_SHIELD_UP_IDLE" |
|
" TASK_SHIELD_MAINTAIN_FLIP 0" |
|
" TASK_SHIELD_MAINTAIN 0" |
|
"" |
|
" Interrupts" |
|
); |
|
|
|
DEFINE_SCHEDULE |
|
( |
|
SCHED_SHIELD_LOWER, |
|
" Tasks" |
|
" TASK_SHIELD_LOWER 0" |
|
"" |
|
" Interrupts" |
|
); |
|
|
|
|
|
|
|
AI_END_CUSTOM_SCHEDULE_PROVIDER() |
|
|
|
#include "tier0/memdbgoff.h"
|
|
|