Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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

//========= 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"