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,488 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "beam_shared.h"
|
||||
#include "ai_motor.h"
|
||||
#include "asw_ai_behavior_flick.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"
|
||||
#include "asw_gamerules.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
BEGIN_DATADESC( CAI_ASW_FlickBehavior )
|
||||
END_DATADESC();
|
||||
|
||||
LINK_BEHAVIOR_TO_CLASSNAME( CAI_ASW_FlickBehavior );
|
||||
|
||||
|
||||
//#define DRAW_DEBUG 1
|
||||
|
||||
|
||||
typedef struct SFlickInfo
|
||||
{
|
||||
Activity m_Activity;
|
||||
float m_flMinDot;
|
||||
float m_flMaxDot;
|
||||
} TFlickInfo;
|
||||
|
||||
#define MAX_FLICKS 4
|
||||
|
||||
static TFlickInfo FlickInfo[ MAX_FLICKS ] =
|
||||
{
|
||||
{ ACT_FLICK_LEFT, 0.45f, 0.8f },
|
||||
{ ACT_FLICK_LEFT_MIDDLE, 0.0f, 0.45f },
|
||||
{ ACT_FLICK_RIGHT_MIDDLE, -0.45f, 0.0f },
|
||||
{ ACT_FLICK_RIGHT, -0.8f, -0.45f }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: constructor
|
||||
//------------------------------------------------------------------------------
|
||||
CAI_ASW_FlickBehavior::CAI_ASW_FlickBehavior( )
|
||||
{
|
||||
m_flDistance = -1;
|
||||
m_flDistanceSq = -1;
|
||||
m_flMinDamage = 1.0f;
|
||||
m_flMaxDamage = 1.0f;
|
||||
m_pPickedFlick = NULL;
|
||||
m_flNextFlickCheck = 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_FlickBehavior::KeyValue( const char *szKeyName, const char *szValue )
|
||||
{
|
||||
if ( V_stricmp( szKeyName, "distance" ) == 0 )
|
||||
{
|
||||
m_flDistance = atof( szValue );
|
||||
m_flDistanceSq = m_flDistance * m_flDistance;
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "propel_distance" ) == 0 )
|
||||
{
|
||||
m_flPropelDistance = atof( szValue );
|
||||
return true;
|
||||
}
|
||||
else if ( V_stricmp( szKeyName, "propel_height" ) == 0 )
|
||||
{
|
||||
m_flPropelHeight = 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;
|
||||
}
|
||||
|
||||
return BaseClass::KeyValue( szKeyName, szValue );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: precaches any additional assets this behavior needs
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::Precache( void )
|
||||
{
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::Init( )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: determines if we can use this behavior currently
|
||||
// Output : returns true if this behavior is able to run
|
||||
//------------------------------------------------------------------------------
|
||||
bool CAI_ASW_FlickBehavior::CanSelectSchedule()
|
||||
{
|
||||
if ( !GetOuter()->IsInterruptable() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( HasCondition( COND_SHIELD_CAN_FLICK ) == false )
|
||||
{
|
||||
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_FlickBehavior::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_FlickBehavior::GatherConditionsNotActive( )
|
||||
{
|
||||
BaseClass::GatherConditionsNotActive();
|
||||
|
||||
if ( m_flNextFlickCheck < gpGlobals->curtime )
|
||||
{
|
||||
if ( GetFlickActivity() != NULL )
|
||||
{
|
||||
SetCondition( COND_SHIELD_CAN_FLICK );
|
||||
}
|
||||
|
||||
m_flNextFlickCheck = gpGlobals->curtime + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CAI_ASW_FlickBehavior::BeginScheduleSelection( )
|
||||
{
|
||||
m_pPickedFlick = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CAI_ASW_FlickBehavior::EndScheduleSelection( )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: general purpose routine to collect conditions used both during active
|
||||
// and non-active states of the behavior.
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::GatherCommonConditions( )
|
||||
{
|
||||
BaseClass::GatherCommonConditions();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: routine called to start when a task initially starts
|
||||
// Input : pTask - the task structure
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::StartTask( const Task_t *pTask )
|
||||
{
|
||||
switch( pTask->iTask )
|
||||
{
|
||||
case TASK_SHIELD_FLICK:
|
||||
{
|
||||
ClearCondition( COND_SHIELD_CAN_FLICK );
|
||||
m_pPickedFlick = GetFlickActivity();
|
||||
if ( m_pPickedFlick != NULL )
|
||||
{
|
||||
GetOuter()->RestartGesture( m_pPickedFlick->m_Activity );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BaseClass::StartTask( pTask );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: routine called every frame when a task is running
|
||||
// Input : pTask - the task structure
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::RunTask( const Task_t *pTask )
|
||||
{
|
||||
switch( pTask->iTask )
|
||||
{
|
||||
case TASK_SHIELD_FLICK:
|
||||
if ( !m_pPickedFlick || GetOuter()->IsPlayingGesture( m_pPickedFlick->m_Activity ) == false )
|
||||
{
|
||||
TaskComplete();
|
||||
m_pPickedFlick = NULL;
|
||||
}
|
||||
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_FlickBehavior::SelectSchedule()
|
||||
{
|
||||
return SCHED_SHIELD_FLICK;
|
||||
}
|
||||
|
||||
|
||||
TFlickInfo *CAI_ASW_FlickBehavior::GetFlickActivity( )
|
||||
{
|
||||
Vector vRightNPC, vForwardNPC, vForwardEnemy;
|
||||
int nCount = 0;
|
||||
int nFlickTotal[ MAX_FLICKS ];
|
||||
|
||||
for( int i = 0; i < MAX_FLICKS; i++ )
|
||||
{
|
||||
nFlickTotal[ i ] = 0;
|
||||
}
|
||||
|
||||
AngleVectors( GetAbsAngles(), &vForwardNPC, &vRightNPC, NULL );
|
||||
#ifdef DRAW_DEBUG
|
||||
UTIL_AddDebugLine( GetAbsOrigin(), GetAbsOrigin() + vForwardNPC * 300.0f, true, false );
|
||||
#endif // #ifdef DRAW_DEBUG
|
||||
|
||||
AIEnemiesIter_t iter;
|
||||
for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) )
|
||||
{
|
||||
CBaseEntity *pEntity = pEMemory->hEnemy;
|
||||
|
||||
Vector vDelta = GetAbsOrigin() - pEntity->GetAbsOrigin();
|
||||
float flLenSq = vDelta.LengthSqr();
|
||||
|
||||
if ( flLenSq > m_flDistanceSq )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DRAW_DEBUG
|
||||
UTIL_AddDebugLine( GetAbsOrigin(), pEntity->GetAbsOrigin(), true, false );
|
||||
#endif // #ifdef DRAW_DEBUG
|
||||
|
||||
vForwardEnemy = vDelta;
|
||||
vForwardEnemy.NormalizeInPlace();
|
||||
|
||||
float flResult = vForwardNPC.Dot( vForwardEnemy );
|
||||
if ( flResult > 0.0f )
|
||||
{ // we are behind
|
||||
continue;
|
||||
}
|
||||
|
||||
flResult = vRightNPC.Dot( vForwardEnemy );
|
||||
for( int j = 0; j < MAX_FLICKS; j++ )
|
||||
{
|
||||
if ( flResult >= FlickInfo[ j ].m_flMinDot && flResult <= FlickInfo[ j ].m_flMaxDot )
|
||||
{ // we are within the flick angle of this arm
|
||||
nFlickTotal[ j ]++;
|
||||
nCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( nCount > 0 )
|
||||
{
|
||||
int nTotal = 0;
|
||||
|
||||
nCount = RandomInt( 0, nCount - 1 );
|
||||
for( int j = 0; j < MAX_FLICKS; j++ )
|
||||
{
|
||||
nTotal += nFlickTotal[ j ];
|
||||
if ( nCount < nTotal )
|
||||
{
|
||||
return &FlickInfo[ j ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::TryFlicking( CBaseEntity *pEntity )
|
||||
{
|
||||
Vector vRightNPC, vForwardNPC, vForwardEnemy;
|
||||
Vector vDelta = GetAbsOrigin() - pEntity->GetAbsOrigin();
|
||||
float flLenSq = vDelta.LengthSqr();
|
||||
|
||||
if ( flLenSq > m_flDistanceSq )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vForwardEnemy = vDelta;
|
||||
vForwardEnemy.NormalizeInPlace();
|
||||
AngleVectors( GetAbsAngles(), &vForwardNPC, &vRightNPC, NULL );
|
||||
|
||||
float flResult = vForwardNPC.Dot( vForwardEnemy );
|
||||
if ( flResult > 0.0f )
|
||||
{ // we are behind
|
||||
return;
|
||||
}
|
||||
|
||||
flResult = vRightNPC.Dot( vForwardEnemy );
|
||||
if ( flResult < m_pPickedFlick->m_flMinDot || flResult > m_pPickedFlick->m_flMaxDot )
|
||||
{ // we are not within the flick angle of the flicking arm
|
||||
return;
|
||||
}
|
||||
|
||||
CASW_Alien *pOwner = dynamic_cast< CASW_Alien * >( GetOuter() );
|
||||
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 );
|
||||
|
||||
CTakeDamageInfo info( pOwner, pOwner, RandomFloat( flMinDamage, flMaxDamage ), DMG_GENERIC );
|
||||
Vector killDir = pEntity->GetAbsOrigin() - GetAbsOrigin();
|
||||
VectorNormalize( killDir );
|
||||
info.SetDamageForce( killDir );
|
||||
info.SetDamagePosition( GetAbsOrigin() );
|
||||
|
||||
float flTime = sqrt( ( 2.0f * m_flPropelHeight / sv_gravity.GetFloat() ) );
|
||||
|
||||
vDelta = -vDelta;
|
||||
vDelta.z = 0.0f;
|
||||
vDelta.NormalizeInPlace();
|
||||
vDelta *= m_flPropelDistance / ( flTime * 2.0f );
|
||||
vDelta.z = sv_gravity.GetFloat() * flTime;
|
||||
|
||||
CASW_Player *pPlayer = dynamic_cast< CASW_Player * >( pEntity );
|
||||
if ( pPlayer )
|
||||
{
|
||||
CASW_Marine *pBaseMarine = pPlayer->GetMarine();
|
||||
// CASW_Marine *pBaseMarine = CASW_Marine::AsMarine( pEntity );
|
||||
if ( pBaseMarine )
|
||||
{
|
||||
pBaseMarine->TakeDamage( info );
|
||||
pBaseMarine->m_bNoAirControl = true;
|
||||
pBaseMarine->SetAbsVelocity( vDelta );
|
||||
pBaseMarine->SetGroundEntity( NULL );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntity->TakeDamage( info );
|
||||
}
|
||||
|
||||
pEntity->SetAbsVelocity( vDelta );
|
||||
pEntity->SetGroundEntity( NULL );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::Flick( )
|
||||
{
|
||||
#if 0
|
||||
for( int i = 0; i < ASWDirector()->GetNPCListCount(); i++ )
|
||||
{
|
||||
CASW_Alien *pAlien = ASWDirector()->GetNPCFromList( i );
|
||||
|
||||
if ( !pAlien || !pAlien->IsAlive() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( GetOuter() != pAlien )
|
||||
{
|
||||
TryFlicking( pAlien );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < ASW_MAX_READY_PLAYERS; i++ )
|
||||
{
|
||||
// found a connected player?
|
||||
CASW_Player *pOtherPlayer = dynamic_cast< CASW_Player * >( UTIL_PlayerByIndex( i + 1 ) );
|
||||
// if they're not connected, skip them
|
||||
if ( !pOtherPlayer || !pOtherPlayer->IsConnected() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TryFlicking( pOtherPlayer );
|
||||
}
|
||||
#else
|
||||
AIEnemiesIter_t iter;
|
||||
for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) )
|
||||
{
|
||||
CBaseEntity *pEntity = pEMemory->hEnemy;
|
||||
|
||||
if ( pEntity->IsAlive() && GetOuter() != pEntity )
|
||||
{
|
||||
TryFlicking( pEntity );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// turn this into an area of affect
|
||||
// reverse his velocity - if he is coming towards the shield bug, add that back into his outgoing to increase it
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CAI_ASW_FlickBehavior::HandleBehaviorEvent( CBaseEntity *pInflictor, BehaviorEvent_t eEvent, int nParm )
|
||||
{
|
||||
switch( eEvent )
|
||||
{
|
||||
case BEHAVIOR_EVENT_FLICK:
|
||||
Flick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_ASW_FlickBehavior )
|
||||
|
||||
DECLARE_TASK( TASK_SHIELD_FLICK )
|
||||
|
||||
DECLARE_CONDITION( COND_SHIELD_CAN_FLICK )
|
||||
|
||||
DEFINE_SCHEDULE
|
||||
(
|
||||
SCHED_SHIELD_FLICK,
|
||||
" Tasks"
|
||||
" TASK_SHIELD_FLICK 0"
|
||||
""
|
||||
" Interrupts"
|
||||
" "
|
||||
);
|
||||
|
||||
AI_END_CUSTOM_SCHEDULE_PROVIDER()
|
||||
|
||||
#include "tier0/memdbgoff.h"
|
||||
Reference in New Issue
Block a user