mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-09-01 15:09:19 +00:00
upload "kind" alien swarm
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
#include "cbase.h"
|
||||
#include "props.h"
|
||||
#include "asw_sentry_base.h"
|
||||
#include "asw_sentry_top_cannon.h"
|
||||
#include "asw_player.h"
|
||||
#include "asw_marine.h"
|
||||
#include "ammodef.h"
|
||||
#include "asw_gamerules.h"
|
||||
#include "beam_shared.h"
|
||||
#include "asw_rifle_grenade.h"
|
||||
#include "asw_weapon_grenades.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#define SENTRY_TOP_MODEL "models/sentry_gun/grenade_top.mdl"
|
||||
|
||||
|
||||
extern ConVar asw_sentry_friendly_target;
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS( asw_sentry_top_cannon, CASW_Sentry_Top_Cannon );
|
||||
PRECACHE_REGISTER( asw_sentry_top_cannon );
|
||||
|
||||
/*
|
||||
IMPLEMENT_SERVERCLASS_ST(CASW_Sentry_Top_Cannon, DT_ASW_Sentry_Top_cannon )
|
||||
END_SEND_TABLE()
|
||||
*/
|
||||
|
||||
BEGIN_DATADESC( CASW_Sentry_Top_Cannon )
|
||||
END_DATADESC()
|
||||
|
||||
void CASW_Sentry_Top_Cannon::SetTopModel()
|
||||
{
|
||||
SetModel(SENTRY_TOP_MODEL);
|
||||
}
|
||||
|
||||
|
||||
CASW_Sentry_Top_Cannon::CASW_Sentry_Top_Cannon()
|
||||
{
|
||||
m_flShootRange = 1000;
|
||||
}
|
||||
|
||||
#define ASW_SENTRY_CANNON_FIRE_RATE 1.75f // time in seconds between each shot
|
||||
|
||||
/// @TODO: lead target
|
||||
void CASW_Sentry_Top_Cannon::Fire()
|
||||
{
|
||||
if ( !m_hEnemy.IsValid() || !m_hEnemy.Get() || !HasAmmo() )
|
||||
return;
|
||||
|
||||
BaseClass::Fire();
|
||||
|
||||
Vector diff = m_hEnemy->WorldSpaceCenter() - GetFiringPosition();
|
||||
diff.NormalizeInPlace();
|
||||
//FireBulletsInfo_t( int nShots, const Vector &vecSrc, const Vector &vecDir, const Vector &vecSpread, float flDistance, int nAmmoType, bool bPrimaryAttack = true )
|
||||
|
||||
Vector launchVector = diff * 1000.0f;
|
||||
|
||||
CASW_Marine * RESTRICT pMarineDeployer = GetSentryBase()->m_hDeployer.Get();
|
||||
Assert( pMarineDeployer );
|
||||
|
||||
float fGrenadeDamage = CASW_Weapon_Grenades::GetBoomDamage(pMarineDeployer) * 0.5f;
|
||||
float fGrenadeRadius = CASW_Weapon_Grenades::GetBoomRadius(pMarineDeployer) * 0.5f;
|
||||
|
||||
CASW_Rifle_Grenade::Rifle_Grenade_Create(
|
||||
fGrenadeDamage, fGrenadeRadius,
|
||||
GetFiringPosition() + (diff * ( WorldAlignSize().Length() * 0.5f ) ), GetAbsAngles(), launchVector, AngularImpulse(0,0,0),
|
||||
pMarineDeployer, this );
|
||||
|
||||
if( pMarineDeployer )
|
||||
pMarineDeployer->OnWeaponFired( this, 1 );
|
||||
|
||||
EmitSound("ASW_Sentry.CannonFire");
|
||||
|
||||
m_fNextFireTime = gpGlobals->curtime + ASW_SENTRY_CANNON_FIRE_RATE;
|
||||
|
||||
// use ammo
|
||||
if ( GetSentryBase() )
|
||||
{
|
||||
GetSentryBase()->OnFiredShots();
|
||||
}
|
||||
}
|
||||
|
||||
CAI_BaseNPC *CASW_Sentry_Top_Cannon::SelectOptimalEnemy()
|
||||
{
|
||||
// prioritize unfrozen aliens who are going to leave the cone soon.
|
||||
// prioritize aliens less the more frozen they get.
|
||||
CUtlVectorFixedGrowable< CAI_BaseNPC *,16 > candidates;
|
||||
CUtlVectorFixedGrowable< float, 16 > candidatescores;
|
||||
|
||||
// search through all npcs, any that are in LOS and have health
|
||||
CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
|
||||
for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
|
||||
{
|
||||
if (ppAIs[i]->GetHealth() > 0 && CanSee(ppAIs[i]))
|
||||
{
|
||||
// don't shoot marines
|
||||
if ( !asw_sentry_friendly_target.GetBool() && ppAIs[i]->Classify() == CLASS_ASW_MARINE )
|
||||
continue;
|
||||
|
||||
if ( ppAIs[i]->Classify() == CLASS_SCANNER )
|
||||
continue;
|
||||
|
||||
if ( !IsValidEnemy( ppAIs[i] ) )
|
||||
continue;
|
||||
|
||||
candidates.AddToTail( ppAIs[i] );
|
||||
}
|
||||
}
|
||||
|
||||
// bail out if we don't have anyone
|
||||
if ( candidates.Count() < 1 )
|
||||
return NULL;
|
||||
|
||||
else if ( candidates.Count() == 1 ) // just one candidate is an obvious result
|
||||
return candidates[0];
|
||||
|
||||
// score each of the candidates
|
||||
candidatescores.EnsureCount( candidates.Count() );
|
||||
for ( int i = candidates.Count() - 1; i >= 0 ; --i )
|
||||
{
|
||||
CAI_BaseNPC * RESTRICT pCandidate = candidates[i];
|
||||
|
||||
// is the candidate moving into or out of the cone?
|
||||
Vector vCandVel = GetEnemyVelocity(pCandidate);
|
||||
Vector vMeToTarget = pCandidate->GetAbsOrigin() - GetFiringPosition();
|
||||
Vector vBaseForward = UTIL_YawToVector( m_fDeployYaw );
|
||||
|
||||
// crush everything to 2d for simplicity
|
||||
vMeToTarget.z = 0.0f;
|
||||
vCandVel.z = 0.0f;
|
||||
vBaseForward.z = 0.0f;
|
||||
|
||||
Vector velCross = vBaseForward.Cross(vCandVel); // this encodes also some info on perpendicularity
|
||||
Vector vAimCross = vBaseForward.Cross(vMeToTarget);
|
||||
bool bTargetHeadedOutOfCone = !vCandVel.IsZero() && velCross.z * vAimCross.z >= 0; // true if same sign
|
||||
float flConeLeavingUrgency;
|
||||
|
||||
if ( bTargetHeadedOutOfCone )
|
||||
{
|
||||
flConeLeavingUrgency = fabs( velCross.z / vCandVel.Length2D() );
|
||||
// just the sin; varies 0..1 where 1 means moving perpendicular to my aim
|
||||
}
|
||||
else
|
||||
{
|
||||
flConeLeavingUrgency = 0; // not at threat of leaving just yet
|
||||
}
|
||||
|
||||
// the angle between my current yaw and what's needed to hit the target
|
||||
float flSwivelNeeded = fabs( UTIL_AngleDiff( // i wish we weren't storing euler angles
|
||||
UTIL_VecToYaw( vMeToTarget ), m_fDeployYaw ) );
|
||||
flSwivelNeeded /= ASW_SENTRY_ANGLE; // normalize to 0..2
|
||||
|
||||
float fBigness = 0.0f;
|
||||
|
||||
int nClassify = pCandidate->Classify();
|
||||
switch( nClassify )
|
||||
{
|
||||
case CLASS_ASW_SHIELDBUG:
|
||||
case CLASS_ASW_MORTAR_BUG:
|
||||
fBigness = 4.0f;
|
||||
break;
|
||||
|
||||
case CLASS_ASW_HARVESTER:
|
||||
case CLASS_ASW_RANGER:
|
||||
fBigness = 2.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
candidatescores[i] = Vector( 3.0f, -1.5f, 4.0f ).Dot( Vector( flConeLeavingUrgency, flSwivelNeeded, fBigness ) );
|
||||
}
|
||||
// find the highest scoring candidate
|
||||
int best = 0;
|
||||
for ( int i = 1 ; i < candidatescores.Count() ; ++i )
|
||||
{
|
||||
if ( candidatescores[i] > candidatescores[best] )
|
||||
best = i;
|
||||
}
|
||||
|
||||
// NDebugOverlay::EntityBounds(candidates[best], 255, 255, 0, 255, 0.2f );
|
||||
|
||||
return candidates[best];
|
||||
}
|
||||
Reference in New Issue
Block a user