mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-31 22:49:19 +00:00
upload "kind" alien swarm
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: NPC does a melee attack against his enemy when close enough. Uses MeleeAttack1Conditions.
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "beam_shared.h"
|
||||
#include "ai_motor.h"
|
||||
#include "asw_ai_behavior_melee.h"
|
||||
#include "ai_hint.h"
|
||||
#include "ai_navigator.h"
|
||||
#include "ai_memory.h"
|
||||
#include "asw_alien.h"
|
||||
#include "asw_marine.h"
|
||||
#include "asw_gamerules.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
BEGIN_DATADESC( CAI_ASW_MeleeBehavior )
|
||||
END_DATADESC();
|
||||
|
||||
LINK_BEHAVIOR_TO_CLASSNAME( CAI_ASW_MeleeBehavior );
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: constructor
|
||||
//------------------------------------------------------------------------------
|
||||
CAI_ASW_MeleeBehavior::CAI_ASW_MeleeBehavior( )
|
||||
{
|
||||
m_flMinRange = 0.0f;
|
||||
m_flMaxRange = 100.0f;
|
||||
m_flAttackDotAngle = 0.7f;
|
||||
m_flMinDamage = 1.0f;
|
||||
m_flMaxDamage = 1.0f;
|
||||
m_flForce = 1.0f;
|
||||
m_flPunchVelocity = 200.0f;
|
||||
m_flPunchAngle = 45.0f;
|
||||
m_AttackHitSound = UTL_INVAL_SYMBOL;
|
||||
m_MissHitSound = UTL_INVAL_SYMBOL;
|
||||
m_bNoTurnDuringAttack = false;
|
||||
m_bKnockdown = false;
|
||||
m_flKnockdownLift = 200.0f;
|
||||
m_flKnockdownSpeed = 400.0f;
|
||||
m_bSecondaryMelee = false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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_MeleeBehavior::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( V_stricmp( szKeyName, "min_range" ) == 0 )
|
||||
{
|
||||
m_flMinRange = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "max_range" ) == 0 )
|
||||
{
|
||||
m_flMaxRange = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "attack_dot_angle" ) == 0 )
|
||||
{
|
||||
m_flAttackDotAngle = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "min_damage" ) == 0 )
|
||||
{
|
||||
m_flMinDamage = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "max_damage" ) == 0 )
|
||||
{
|
||||
m_flMaxDamage = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "force" ) == 0 )
|
||||
{
|
||||
m_flForce = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "punch_velocity" ) == 0 )
|
||||
{
|
||||
m_flPunchVelocity = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "punch_angle" ) == 0 )
|
||||
{
|
||||
m_flPunchAngle = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "attack_hit_sound" ) == 0 )
|
||||
{
|
||||
m_AttackHitSound = GetSymbol( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "attack_miss_sound" ) == 0 )
|
||||
{
|
||||
m_MissHitSound = GetSymbol( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "allow_turning" ) == 0 )
|
||||
{
|
||||
m_bNoTurnDuringAttack = ( atoi( szValue ) == 0 );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "knockdown" ) == 0 )
|
||||
{
|
||||
m_bKnockdown = ( atoi( szValue ) == 1 );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "knockdown_speed" ) == 0 )
|
||||
{
|
||||
m_flKnockdownSpeed = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "knockdown_lift" ) == 0 )
|
||||
{
|
||||
m_flKnockdownLift = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "secondary_melee" ) == 0 )
|
||||
{
|
||||
m_bSecondaryMelee = ( atoi( szValue ) == 1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: precaches any additional assets this behavior needs
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_MeleeBehavior::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_MeleeBehavior::Init( )
|
||||
{
|
||||
CASW_Alien *pNPC = static_cast< CASW_Alien * >( GetOuter() );
|
||||
if ( !pNPC )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pNPC->meleeAttack1.Init( m_flMinRange, m_flMaxRange, m_flAttackDotAngle, true );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: determines if we can use this behavior currently
|
||||
// Output : returns true if this behavior is able to run
|
||||
//------------------------------------------------------------------------------
|
||||
bool CAI_ASW_MeleeBehavior::CanSelectSchedule()
|
||||
{
|
||||
if ( !GetOuter()->IsInterruptable() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !m_bSecondaryMelee && !HasCondition( COND_CAN_MELEE_ATTACK1 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( m_bSecondaryMelee && !HasCondition( COND_CAN_MELEE_ATTACK2 ) )
|
||||
{
|
||||
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_MeleeBehavior::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_MeleeBehavior::GatherConditionsNotActive( )
|
||||
{
|
||||
BaseClass::GatherConditionsNotActive();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: general purpose routine to collect conditions used both during active
|
||||
// and non-active states of the behavior.
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_MeleeBehavior::GatherCommonConditions( )
|
||||
{
|
||||
BaseClass::GatherCommonConditions();
|
||||
}
|
||||
|
||||
|
||||
void CAI_ASW_MeleeBehavior::BeginScheduleSelection( )
|
||||
{
|
||||
SetBehaviorParam( m_StatusParm, -1 );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: routine called to start when a task initially starts
|
||||
// Input : pTask - the task structure
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_MeleeBehavior::StartTask( const Task_t *pTask )
|
||||
{
|
||||
switch( pTask->iTask )
|
||||
{
|
||||
case TASK_MELEE_FLIP_AROUND:
|
||||
{
|
||||
Assert( 0 ); // NOT DONE. See example in shield behavior: TASK_SHIELD_MAINTAIN_FLIP
|
||||
#if 0
|
||||
bool bNeedFlip = false;
|
||||
|
||||
if ( HaveSequenceForActivity( ACT_SPINAROUND ) == true )
|
||||
{
|
||||
CBaseEntity *pTarget = GetEnemy();
|
||||
if ( pTarget )
|
||||
{
|
||||
float flFacing = UTIL_VecToYaw( pTarget->GetAbsOrigin() - GetAbsOrigin() );
|
||||
float flDiff = UTIL_AngleDiff( GetAbsAngles()[ YAW ], flFacing );
|
||||
}
|
||||
}
|
||||
|
||||
if ( bNeedFlip == false )
|
||||
{
|
||||
TaskComplete();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetOuter()->SetIdealActivity( ACT_SPINAROUND );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BaseClass::StartTask( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: routine called every frame when a task is running
|
||||
// Input : pTask - the task structure
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_MeleeBehavior::RunTask( const Task_t *pTask )
|
||||
{
|
||||
switch( pTask->iTask )
|
||||
{
|
||||
case TASK_MELEE_FLIP_AROUND:
|
||||
{
|
||||
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_MeleeBehavior::SelectSchedule()
|
||||
{
|
||||
if ( m_bNoTurnDuringAttack == true )
|
||||
{
|
||||
if ( m_bSecondaryMelee )
|
||||
return SCHED_MELEE2_DO_ATTACK_NO_TURNING;
|
||||
else
|
||||
return SCHED_MELEE1_DO_ATTACK_NO_TURNING;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_bSecondaryMelee )
|
||||
return SCHED_MELEE2_DO_ATTACK;
|
||||
else
|
||||
return SCHED_MELEE1_DO_ATTACK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
bool CAI_ASW_MeleeBehavior::BehaviorHandleAnimEvent( animevent_t *pEvent )
|
||||
{
|
||||
int nEvent = pEvent->Event();
|
||||
|
||||
if ( nEvent == AE_ALIEN_MELEE_HIT )
|
||||
{
|
||||
float flMinDamage = ASWGameRules()->ModifyAlienDamageBySkillLevel( m_flMinDamage );
|
||||
float flMaxDamage = ASWGameRules()->ModifyAlienDamageBySkillLevel( m_flMaxDamage );
|
||||
|
||||
flMinDamage = ( flMinDamage < 1.0f ? 1.0f : flMinDamage );
|
||||
flMaxDamage = ( flMaxDamage < 1.0f ? 1.0f : flMaxDamage );
|
||||
|
||||
HullAttack( m_flMaxRange, RandomFloat( flMinDamage, flMaxDamage ), m_flForce, m_AttackHitSound, m_MissHitSound );
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
case BEHAVIOR_EVENT_MELEE1_SPHERE_ATTACK:
|
||||
{
|
||||
float flMinDamage = ASWGameRules()->ModifyAlienDamageBySkillLevel( m_flMinDamage );
|
||||
float flMaxDamage = ASWGameRules()->ModifyAlienDamageBySkillLevel( m_flMaxDamage );
|
||||
|
||||
flMinDamage = ( flMinDamage < 1.0f ? 1.0f : flMinDamage );
|
||||
flMaxDamage = ( flMaxDamage < 1.0f ? 1.0f : flMaxDamage );
|
||||
|
||||
SphereAttack( m_flMaxRange, RandomFloat( flMinDamage, flMaxDamage ), m_flForce, m_AttackHitSound, m_MissHitSound );
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_MeleeBehavior::HullAttack( float flDistance, float flDamage, float flForce, CUtlSymbol &AttackHitSound, CUtlSymbol &AttackMissSound )
|
||||
{
|
||||
Vector vecForceDir;
|
||||
|
||||
CBaseEntity *pHurt = GetOuter()->CheckTraceHullAttack( flDistance, -Vector( 16.0f, 16.0f, 32.0f ), Vector( 16.0f, 16.0f, 32.0f ), flDamage, DMG_SLASH, flForce );
|
||||
if ( pHurt )
|
||||
{
|
||||
SetBehaviorParam( m_StatusParm, 1 );
|
||||
// Play a random attack hit sound
|
||||
if ( AttackHitSound != UTL_INVAL_SYMBOL )
|
||||
{
|
||||
GetOuter()->EmitSound( GetSymbolText( AttackHitSound ) );
|
||||
}
|
||||
|
||||
// change our sequence to one with the hit in it
|
||||
if ( !m_bSecondaryMelee && ( GetActivity() == ACT_MELEE_ATTACK1 ) )
|
||||
{
|
||||
if ( GetOuter()->HaveSequenceForActivity( (Activity) ACT_MELEE_ATTACK1_HIT ) )
|
||||
{
|
||||
SetActivity( (Activity) ACT_MELEE_ATTACK1_HIT );
|
||||
}
|
||||
}
|
||||
else if ( m_bSecondaryMelee && ( GetActivity() == ACT_MELEE_ATTACK2 ) )
|
||||
{
|
||||
if ( GetOuter()->HaveSequenceForActivity( (Activity) ACT_MELEE_ATTACK2_HIT ) )
|
||||
{
|
||||
SetActivity( (Activity) ACT_MELEE_ATTACK2_HIT );
|
||||
}
|
||||
}
|
||||
if ( m_bKnockdown && pHurt->Classify() == CLASS_ASW_MARINE )
|
||||
{
|
||||
CASW_Marine *pMarine = static_cast<CASW_Marine*>( pHurt );
|
||||
Vector vecImpulse = ( GetOuter()->BodyDirection2D() * m_flKnockdownSpeed ) + Vector( 0, 0, m_flKnockdownLift );
|
||||
pMarine->Knockdown( GetOuter(), vecImpulse );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play a miss sound.
|
||||
GetOuter()->EmitSound( GetSymbolText( AttackMissSound ) );
|
||||
SetBehaviorParam( m_StatusParm, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_MeleeBehavior::SphereAttack( float flDistance, float flDamage, float flForce, CUtlSymbol &AttackHitSound, CUtlSymbol &AttackMissSound )
|
||||
{
|
||||
// TODO: Fixme
|
||||
/*
|
||||
CUtlVector<CBaseEntity*> aHitList;
|
||||
|
||||
CASW_Alien *pAlien = static_cast< CASW_Alien * >( GetOuter() );
|
||||
bool bHit = pAlien->CheckSphereAttack( flDistance, flDamage, DMG_SLASH, 1.0f, aHitList );
|
||||
if ( bHit )
|
||||
{
|
||||
SetBehaviorParam( m_StatusParm, 1 );
|
||||
// Play a random attack hit sound
|
||||
GetOuter()->EmitSound( GetSymbolText( AttackHitSound ) );
|
||||
|
||||
Vector vecVelocityPunch;
|
||||
AngleVectors( GetLocalAngles(), &vecVelocityPunch );
|
||||
vecVelocityPunch = vecVelocityPunch * m_flPunchVelocity;
|
||||
|
||||
QAngle angViewPunch( m_flPunchAngle, random->RandomFloat( -5.0f, 5.0f ), random->RandomFloat( -5.0f, 5.0f ) );
|
||||
|
||||
// Set punch angles on all players hit.
|
||||
int nHitCount = aHitList.Count();
|
||||
for ( int iHit = 0; iHit < nHitCount; ++iHit )
|
||||
{
|
||||
if ( m_bKnockdown && aHitList[iHit]->Classify() == CLASS_ASW_MARINE )
|
||||
{
|
||||
CASW_Marine *pMarine = static_cast<CASW_Marine*>( aHitList[iHit] );
|
||||
Vector vecImpulse = ( GetOuter()->BodyDirection2D() * m_flKnockdownSpeed ) + Vector( 0, 0, m_flKnockdownLift );
|
||||
pMarine->Knockdown( GetOuter(), vecImpulse );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Play a miss sound.
|
||||
GetOuter()->EmitSound( GetSymbolText( AttackMissSound ) );
|
||||
SetBehaviorParam( m_StatusParm, 0 );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_ASW_MeleeBehavior )
|
||||
|
||||
DECLARE_TASK( TASK_MELEE_FLIP_AROUND )
|
||||
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_MELEE1_DO_ATTACK,
|
||||
|
||||
" Tasks"
|
||||
" TASK_STOP_MOVING 0"
|
||||
// " TASK_MELEE_FLIP_AROUND 0"
|
||||
" TASK_FACE_ENEMY 0"
|
||||
" TASK_MELEE_ATTACK1 0"
|
||||
""
|
||||
" Interrupts"
|
||||
" COND_LIGHT_DAMAGE"
|
||||
" COND_HEAVY_DAMAGE"
|
||||
)
|
||||
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_MELEE1_DO_ATTACK_NO_TURNING,
|
||||
|
||||
" Tasks"
|
||||
" TASK_STOP_MOVING 0"
|
||||
// " TASK_MELEE_FLIP_AROUND 0"
|
||||
" TASK_MELEE_ATTACK1 0"
|
||||
""
|
||||
" Interrupts"
|
||||
" COND_LIGHT_DAMAGE"
|
||||
" COND_HEAVY_DAMAGE"
|
||||
)
|
||||
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_MELEE2_DO_ATTACK,
|
||||
|
||||
" Tasks"
|
||||
" TASK_STOP_MOVING 0"
|
||||
// " TASK_MELEE_FLIP_AROUND 0"
|
||||
" TASK_FACE_ENEMY 0"
|
||||
" TASK_MELEE_ATTACK2 0"
|
||||
""
|
||||
" Interrupts"
|
||||
" COND_LIGHT_DAMAGE"
|
||||
" COND_HEAVY_DAMAGE"
|
||||
)
|
||||
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_MELEE2_DO_ATTACK_NO_TURNING,
|
||||
|
||||
" Tasks"
|
||||
" TASK_STOP_MOVING 0"
|
||||
// " TASK_MELEE_FLIP_AROUND 0"
|
||||
" TASK_MELEE_ATTACK2 0"
|
||||
""
|
||||
" Interrupts"
|
||||
" COND_LIGHT_DAMAGE"
|
||||
" COND_HEAVY_DAMAGE"
|
||||
)
|
||||
|
||||
|
||||
AI_END_CUSTOM_SCHEDULE_PROVIDER()
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
Reference in New Issue
Block a user