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.
 
 
 
 
 
 

338 lines
8.2 KiB

#include "cbase.h"
#include "asw_simple_grub.h"
#include "asw_trace_filter_melee.h"
#include "te_effect_dispatch.h"
#include "asw_util_shared.h"
#include "asw_marine.h"
#include "asw_marine_resource.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define SWARM_GRUB_MODEL "models/swarm/Grubs/Grub.mdl"
LINK_ENTITY_TO_CLASS( asw_grub, CASW_Simple_Grub );
PRECACHE_REGISTER( asw_grub );
BEGIN_DATADESC( CASW_Simple_Grub )
DEFINE_ENTITYFUNC(GrubTouch),
END_DATADESC()
extern ConVar asw_debug_simple_alien;
//IMPLEMENT_SERVERCLASS_ST(CASW_Simple_Grub, DT_ASW_Simple_Drone)
//END_SEND_TABLE()
// =========================================
// Creation
// =========================================
CASW_Simple_Grub::CASW_Simple_Grub()
{
m_bSkipGravity = false;
}
CASW_Simple_Grub::~CASW_Simple_Grub()
{
}
void CASW_Simple_Grub::Spawn(void)
{
BaseClass::Spawn();
SetCollisionGroup( ASW_COLLISION_GROUP_GRUBS );
SetModel( SWARM_GRUB_MODEL );
SetHullType( HULL_TINY );
AddSolidFlags(FSOLID_TRIGGER);
UTIL_SetSize(this, Vector(-12,-12, 0), Vector(12, 12, 12));
SetTouch( &CASW_Simple_Grub::GrubTouch );
m_iHealth = 1;
SetBlocksLOS(false);
}
void CASW_Simple_Grub::GrubTouch( CBaseEntity *pOther )
{
if (!pOther)
return;
if (pOther->Classify() == CLASS_ASW_MARINE && pOther->GetAbsVelocity().Length() > 100)
{
Vector xydiff = GetAbsOrigin() - pOther->GetAbsOrigin();
xydiff.z = 0;
if (xydiff.Length() < 20)
{
CTakeDamageInfo dmg(pOther, pOther, Vector(0, 0, -1), GetAbsOrigin() + Vector(0, 0, 1), 20, DMG_CRUSH);
TakeDamage(dmg);
}
}
}
void CASW_Simple_Grub::Precache()
{
BaseClass::Precache();
PrecacheModel( SWARM_GRUB_MODEL );
PrecacheModel( "Models/Swarm/Grubs/GrubGib4.mdl" );
PrecacheScriptSound("ASW_Grub.Pain");
PrecacheScriptSound("ASW_Parasite.Attack");
PrecacheScriptSound("ASW_Parasite.Idle");
PrecacheParticleSystem( "grub_death" );
PrecacheParticleSystem( "grub_death_fire" );
}
// =========================================
// Anims
// =========================================
void CASW_Simple_Grub::PlayRunningAnimation()
{
ResetSequence(LookupSequence("CrawlA"));
m_flPlaybackRate = 1.25f;
}
void CASW_Simple_Grub::PlayFallingAnimation()
{
ResetSequence(LookupSequence("Jump"));
m_flPlaybackRate = 1.25f;
}
void CASW_Simple_Grub::PlayAttackingAnimation()
{
ResetSequence(LookupSequence("CrawlA"));
m_flPlaybackRate = 1.25f;
}
// =========================================
// Sounds
// =========================================
void CASW_Simple_Grub::PainSound( const CTakeDamageInfo &info )
{
if (gpGlobals->curtime > m_fNextPainSound)
{
EmitSound("ASW_Grub.Pain");
m_fNextPainSound = gpGlobals->curtime + 0.5f;
}
}
void CASW_Simple_Grub::AlertSound()
{
}
void CASW_Simple_Grub::DeathSound( const CTakeDamageInfo &info )
{
}
void CASW_Simple_Grub::AttackSound()
{
}
// =========================================
// Gibbing
// =========================================
bool CASW_Simple_Grub::ShouldGib( const CTakeDamageInfo &info )
{
return true;
}
bool CASW_Simple_Grub::CorpseGib( const CTakeDamageInfo &info )
{
CEffectData data;
data.m_vOrigin = WorldSpaceCenter();
data.m_vNormal = data.m_vOrigin - info.GetDamagePosition();
VectorNormalize( data.m_vNormal );
data.m_flScale = RemapVal( m_iHealth, 0, -500, 1, 3 );
data.m_flScale = clamp( data.m_flScale, 1, 3 );
data.m_fFlags = (IsOnFire() || (info.GetDamageType() & DMG_BURN)) ? ASW_GIBFLAG_ON_FIRE : 0;
CPASFilter filter( data.m_vOrigin );
filter.SetIgnorePredictionCull(true);
DispatchEffect( filter, 0.0, "GrubGib", data );
//DispatchEffect( "GrubGib", data );
return true;
}
// =========================================
// Movement
// =========================================
float CASW_Simple_Grub::GetIdealSpeed() const
{
return 100.0f;
}
void CASW_Simple_Grub::AlienThink()
{
float delta = gpGlobals->curtime - m_fLastThinkTime;
BaseClass::AlienThink();
UpdatePitch(delta);
/*
if (GetEnemy() && GetAbsOrigin().DistTo(GetEnemy()->GetAbsOrigin()) < 800)
{
// check if a marine is standing on us
trace_t tr;
UTIL_TraceLine( GetAbsOrigin() - Vector(5, 5, -1), GetAbsOrigin() + Vector(5, 5, 5), MASK_SOLID, this, COLLISION_GROUP_PLAYER, &tr );
if (tr.fraction < 1 && tr.m_pEnt)
{
if (tr.m_pEnt->Classify() == CLASS_ASW_MARINE)
{
CTakeDamageInfo dmg(tr.m_pEnt, tr.m_pEnt, Vector(0, 0, -1), GetAbsOrigin() + Vector(0, 0, 1), 20, DMG_CRUSH);
TakeDamage(dmg);
}
}
// think more frequently so we don't miss a player stomping on us
SetNextThink( gpGlobals->curtime + 0.025f );
}*/
}
void CASW_Simple_Grub::UpdatePitch(float delta)
{
float current = UTIL_AngleMod( GetLocalAngles()[PITCH] );
float ideal = UTIL_AngleMod( GetIdealPitch() );
float dt = MIN( 0.2, delta );
float newPitch = ASW_ClampYaw( GetPitchSpeed(), current, ideal, dt );
if (newPitch != current)
{
QAngle angles = GetLocalAngles();
angles[PITCH] = newPitch;
SetLocalAngles( angles );
}
}
float CASW_Simple_Grub::GetPitchSpeed() const
{
return 2000.0f;
}
float CASW_Simple_Grub::GetIdealPitch()
{
if (m_bSkipGravity) // we're climbing
return -90;
return 0;
}
float CASW_Simple_Grub::GetFaceEnemyDistance() const
{
return 50.0f;
}
float CASW_Simple_Grub::GetZigZagChaseDistance() const
{
return 50.0f;
}
bool CASW_Simple_Grub::ApplyGravity(Vector &vecTarget, float deltatime)
{
if (m_bSkipGravity)
{
if (asw_debug_simple_alien.GetBool())
Msg("Skipping grav\n");
return false;
}
return BaseClass::ApplyGravity(vecTarget, deltatime);
}
// run towards the target like a normal simple alien, but if he hit some geometry, try to climb up over it
// todo: perform move could check if gravity was skipped and switch us to a climbing anim instead of a running
bool CASW_Simple_Grub::TryMove(const Vector &vecSrc, Vector &vecTarget, float deltatime, bool bStepMove)
{
m_bSkipGravity = false;
// do a trace to the dest
Ray_t ray;
trace_t trace;
CTraceFilterSimple traceFilter(this, GetCollisionGroup() );
ray.Init( vecSrc, vecTarget, GetHullMins(), GetHullMaxs() );
enginetrace->TraceRay( ray, MASK_NPCSOLID, &traceFilter, &trace );
if (trace.startsolid)
{
// doh, we're stuck in something!
// todo: move us to a safe spot? wait for push out phys props?
if (asw_debug_simple_alien.GetBool())
Msg("CASW_Simple_Grub stuck!\n");
m_MoveFailure.trace = trace;
m_MoveFailure.vecStartPos = vecSrc;
m_MoveFailure.vecTargetPos = vecTarget;
return false;
}
if (trace.fraction < 0.1f) // barely/didn't move
{
// try and do a 'stepped up' move to the target
if (!bStepMove)
{
Vector vecStepSrc = vecSrc;
vecStepSrc.z += 24;
Vector vecStepTarget = vecTarget;
vecTarget.z += 24;
if (TryMove(vecStepSrc, vecStepTarget, deltatime, true))
{
vecTarget = vecStepTarget;
return true;
}
}
// if we collide with geometry, try to climb up over it
if (trace.m_pEnt && trace.m_pEnt->IsWorld() && GetEnemy() && !bStepMove)
{
// check our enemy is on the other side of this obstruction
Vector vecEnemyDiff = GetEnemy()->GetAbsOrigin() - GetAbsOrigin();
vecEnemyDiff.NormalizeInPlace();
if (vecEnemyDiff.Dot(trace.plane.normal) < 0)
{
Vector vecClimbSrc = vecSrc;
Vector vecClimbTarget = vecSrc;
vecClimbTarget.z += GetIdealSpeed() * deltatime * 0.7f; // 70% speed when climbing...
if (TryMove(vecClimbSrc, vecClimbTarget, deltatime, true))
{
m_bSkipGravity = true;
if (asw_debug_simple_alien.GetBool())
Msg("Setting skip grav, moved %f z=%f\n", GetIdealSpeed() * deltatime * 0.7f, vecClimbTarget.z); // 70% speed when climbing...
vecTarget = vecClimbTarget;
return true;
}
}
}
m_MoveFailure.trace = trace;
m_MoveFailure.vecStartPos = vecSrc;
m_MoveFailure.vecTargetPos = vecTarget;
return false;
}
else if (trace.fraction < 1) // we hit something early, but we did move
{
// we hit something early
m_MoveFailure.trace = trace;
m_MoveFailure.vecStartPos = vecSrc;
m_MoveFailure.vecTargetPos = vecTarget;
vecTarget = trace.endpos;
}
return true;
}
void CASW_Simple_Grub::Event_Killed( const CTakeDamageInfo &info )
{
CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>(info.GetAttacker());
if (pMarine && pMarine->GetMarineResource())
{
pMarine->GetMarineResource()->m_iGrubKills++;
}
BaseClass::Event_Killed(info);
}