📄 hl1_npc_controller.cpp
字号:
for (int i = 0; i < 2; i++)
{
if (m_pBall[i] == NULL)
{
m_pBall[i] = CSprite::SpriteCreate( "sprites/xspark4.vmt", GetAbsOrigin(), TRUE );
m_pBall[i]->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
m_pBall[i]->SetAttachment( this, (i + 3) );
m_pBall[i]->SetScale( 1.0 );
}
float t = m_iBallTime[i] - gpGlobals->curtime;
if (t > 0.1)
t = 0.1 / t;
else
t = 1.0;
m_iBallCurrent[i] += (m_iBall[i] - m_iBallCurrent[i]) * t;
m_pBall[i]->SetBrightness( m_iBallCurrent[i] );
GetAttachment( i + 2, vecStart, angleGun );
m_pBall[i]->SetAbsOrigin( vecStart );
CBroadcastRecipientFilter filter;
GetAttachment( i + 3, vecStart, angleGun );
te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0/*exponent*/, m_iBallCurrent[i] / 8 /*radius*/, 0.5, 0 );
}
}
//=========================================================
// Stop -
//=========================================================
void CNPC_Controller::Stop( void )
{
SetIdealActivity( GetStoppedActivity() );
}
//-----------------------------------------------------------------------------
// Purpose: Handles movement towards the last move target.
// Input : flInterval -
//-----------------------------------------------------------------------------
bool CNPC_Controller::OverridePathMove( float flInterval )
{
CBaseEntity *pMoveTarget = (GetTarget()) ? GetTarget() : GetEnemy();
Vector waypointDir = GetNavigator()->GetCurWaypointPos() - GetLocalOrigin();
float flWaypointDist = waypointDir.Length2D();
VectorNormalize(waypointDir);
// cut corner?
if (flWaypointDist < 128)
{
if (m_flGroundSpeed > 100)
m_flGroundSpeed -= 40;
}
else
{
if (m_flGroundSpeed < 400)
m_flGroundSpeed += 10;
}
m_velocity = m_velocity * 0.8 + m_flGroundSpeed * waypointDir * 0.5;
SetAbsVelocity( m_velocity );
// -----------------------------------------------------------------
// Check route is blocked
// ------------------------------------------------------------------
Vector checkPos = GetLocalOrigin() + (waypointDir * (m_flGroundSpeed * flInterval));
AIMoveTrace_t moveTrace;
GetMoveProbe()->MoveLimit( NAV_FLY, GetLocalOrigin(), checkPos, MASK_NPCSOLID|CONTENTS_WATER,
pMoveTarget, &moveTrace);
if (IsMoveBlocked( moveTrace ))
{
TaskFail(FAIL_NO_ROUTE);
GetNavigator()->ClearGoal();
return true;
}
// ----------------------------------------------
Vector lastPatrolDir = GetNavigator()->GetCurWaypointPos() - GetLocalOrigin();
if ( ProgressFlyPath( flInterval, pMoveTarget, MASK_NPCSOLID, false, 64 ) == AINPP_COMPLETE )
{
{
m_vLastPatrolDir = lastPatrolDir;
VectorNormalize(m_vLastPatrolDir);
}
return true;
}
return false;
}
bool CNPC_Controller::OverrideMove( float flInterval )
{
if (m_flGroundSpeed == 0)
{
m_flGroundSpeed = 100;
}
// ----------------------------------------------
// Select move target
// ----------------------------------------------
CBaseEntity *pMoveTarget = NULL;
if (GetTarget() != NULL )
{
pMoveTarget = GetTarget();
}
else if (GetEnemy() != NULL )
{
pMoveTarget = GetEnemy();
}
// ----------------------------------------------
// Select move target position
// ----------------------------------------------
Vector vMoveTargetPos(0,0,0);
if (GetTarget())
{
vMoveTargetPos = GetTarget()->GetAbsOrigin();
}
else if (GetEnemy() != NULL)
{
vMoveTargetPos = GetEnemy()->GetAbsOrigin();
}
// -----------------------------------------
// See if we can fly there directly
// -----------------------------------------
if (pMoveTarget /*|| HaveInspectTarget()*/)
{
trace_t tr;
if (pMoveTarget)
{
UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos,
MASK_NPCSOLID_BRUSHONLY, pMoveTarget, GetCollisionGroup(), &tr);
}
else
{
UTIL_TraceEntity( this, GetAbsOrigin(), vMoveTargetPos, MASK_NPCSOLID_BRUSHONLY, &tr);
}
/*
float fTargetDist = (1-tr.fraction)*(GetAbsOrigin() - vMoveTargetPos).Length();
if (fTargetDist > 50)
{
//SetCondition( COND_SCANNER_FLY_BLOCKED );
}
else
{
//SetCondition( COND_SCANNER_FLY_CLEAR );
}
*/
}
// -----------------------------------------------------------------
// If I have a route, keep it updated and move toward target
// ------------------------------------------------------------------
if (GetNavigator()->IsGoalActive())
{
if ( OverridePathMove( flInterval ) )
return true;
}
else
{
//do nothing
Stop();
TaskComplete();
}
return true;
}
void CNPC_Controller::MoveToTarget( float flInterval, const Vector &vecMoveTarget )
{
const float myAccel = 300.0;
const float myDecay = 9.0;
//TurnHeadToTarget( flInterval, MoveTarget );
MoveToLocation( flInterval, vecMoveTarget, myAccel, (2 * myAccel), myDecay );
}
//=========================================================
// Controller bouncy ball attack
//=========================================================
LINK_ENTITY_TO_CLASS( controller_head_ball, CNPC_ControllerHeadBall );
BEGIN_DATADESC( CNPC_ControllerHeadBall )
DEFINE_THINKFUNC( CNPC_ControllerHeadBall, HuntThink ),
DEFINE_THINKFUNC( CNPC_ControllerHeadBall, KillThink ),
DEFINE_ENTITYFUNC( CNPC_ControllerHeadBall, BounceTouch ),
END_DATADESC()
void CNPC_ControllerHeadBall::Spawn( void )
{
Precache( );
// motor
SetMoveType( MOVETYPE_FLY );
SetSolid( SOLID_BBOX );
SetSize( vec3_origin, vec3_origin );
m_pSprite = CSprite::SpriteCreate( "sprites/xspark4.vmt", GetAbsOrigin(), FALSE );
m_pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation );
m_pSprite->SetAttachment( this, 0 );
m_pSprite->SetScale( 2.0 );
UTIL_SetSize( this, Vector( 0, 0, 0), Vector(0, 0, 0) );
UTIL_SetOrigin( this, GetAbsOrigin() );
SetThink( &CNPC_ControllerHeadBall::HuntThink );
SetTouch( &CNPC_ControllerHeadBall::BounceTouch );
// m_vecIdeal = vec3_origin; //(0,0,0)
SetNextThink( gpGlobals->curtime + 0.1 );
m_hOwner = GetOwnerEntity();
m_flSpawnTime = gpGlobals->curtime;
}
void CNPC_ControllerHeadBall :: Precache( void )
{
engine->PrecacheModel( "sprites/xspark4.vmt");
enginesound->PrecacheSound("debris/zap4.wav");
enginesound->PrecacheSound("weapons/electro4.wav");
}
extern short g_sModelIndexLaser;
void CNPC_ControllerHeadBall :: HuntThink( void )
{
SetNextThink( gpGlobals->curtime + 0.1 );
m_pSprite->SetBrightness( m_pSprite->GetBrightness() - 5, 0.1f );
CBroadcastRecipientFilter filter;
te->DynamicLight( filter, 0.0, &GetAbsOrigin(), 255, 255, 255, 0, m_pSprite->GetBrightness() / 16, 0.2, 0 );
// check world boundaries
if (gpGlobals->curtime - m_flSpawnTime > 5 || m_pSprite->GetBrightness() < 64 /*|| GetEnemy() == NULL || m_hOwner == NULL*/ || !IsInWorld() )
{
SetTouch( NULL );
SetThink( KillThink );
SetNextThink( gpGlobals->curtime );
return;
}
if( !GetEnemy() )
return;
MovetoTarget( GetEnemy()->GetAbsOrigin() );
if ((GetEnemy()->WorldSpaceCenter() - GetAbsOrigin()).Length() < 64)
{
trace_t tr;
UTIL_TraceLine( GetAbsOrigin(), GetEnemy()->WorldSpaceCenter(), MASK_ALL, this, COLLISION_GROUP_NONE, &tr );
CBaseEntity *pEntity = tr.m_pEnt;
if (pEntity != NULL && pEntity->m_takedamage == DAMAGE_YES)
{
ClearMultiDamage( );
Vector dir = GetAbsVelocity();
VectorNormalize( dir );
CTakeDamageInfo info( this, this, sk_controller_dmgball.GetFloat(), DMG_SHOCK );
CalculateMeleeDamageForce( &info, dir, tr.endpos );
pEntity->DispatchTraceAttack( info, dir, &tr );
ApplyMultiDamage();
int haloindex = 0;
int fadelength = 0;
int amplitude = 0;
const Vector vecEnd = tr.endpos;
te->BeamEntPoint( filter, 0.0, entindex(), NULL, 0, &(tr.m_pEnt->GetAbsOrigin()),
g_sModelIndexLaser, haloindex /* no halo */, 0, 10, 3, 20, 20, fadelength,
amplitude, 255, 255, 255, 255, 10 );
}
UTIL_EmitAmbientSound( this, GetAbsOrigin(), "weapons/electro4.wav", 0.5, SNDLVL_NORM, 0, 100 );
SetNextAttack( gpGlobals->curtime + 3.0 );
SetThink( KillThink );
SetNextThink( gpGlobals->curtime + 0.3 );
}
}
void CNPC_ControllerHeadBall::MovetoTarget( Vector vecTarget )
{
// accelerate
float flSpeed = m_vecIdeal.Length();
if (flSpeed == 0)
{
m_vecIdeal = GetAbsVelocity();
flSpeed = m_vecIdeal.Length();
}
if (flSpeed > 400)
{
VectorNormalize( m_vecIdeal );
m_vecIdeal = m_vecIdeal * 400;
}
Vector t = vecTarget - GetAbsOrigin();
VectorNormalize(t);
m_vecIdeal = m_vecIdeal + t * 100;
SetAbsVelocity(m_vecIdeal);
}
void CNPC_ControllerHeadBall::BounceTouch( CBaseEntity *pOther )
{
Vector vecDir = m_vecIdeal;
VectorNormalize( vecDir );
trace_t tr = CBaseEntity::GetTouchTrace( );
float n = -DotProduct(tr.plane.normal, vecDir);
vecDir = 2.0 * tr.plane.normal * n + vecDir;
m_vecIdeal = vecDir * m_vecIdeal.Length();
}
void CNPC_ControllerHeadBall::KillThink( void )
{
UTIL_Remove( m_pSprite );
UTIL_Remove( this );
}
//=========================================================
// Controller Zap attack
//=========================================================
LINK_ENTITY_TO_CLASS( controller_energy_ball, CNPC_ControllerZapBall );
BEGIN_DATADESC( CNPC_ControllerZapBall )
DEFINE_THINKFUNC( CNPC_ControllerZapBall, AnimateThink ),
DEFINE_ENTITYFUNC( CNPC_ControllerZapBall, ExplodeTouch ),
END_DATADESC()
void CNPC_ControllerZapBall::Spawn( void )
{
Precache( );
// motor
SetMoveType( MOVETYPE_FLY );
// SetSolid( SOLID_CUSTOM );
SetSolid( SOLID_BBOX );
SetSize( vec3_origin, vec3_origin );
m_pSprite = CSprite::SpriteCreate( "sprites/xspark4.vmt", GetAbsOrigin(), FALSE );
m_pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation );
m_pSprite->SetAttachment( this, 0 );
m_pSprite->SetScale( 0.5 );
UTIL_SetSize( this, Vector( 0, 0, 0), Vector(0, 0, 0) );
UTIL_SetOrigin( this, GetAbsOrigin() );
SetThink( &CNPC_ControllerZapBall::AnimateThink );
SetTouch( &CNPC_ControllerZapBall::ExplodeTouch );
m_hOwner = GetOwnerEntity();
m_flSpawnTime = gpGlobals->curtime; // keep track of when ball spawned
SetNextThink( gpGlobals->curtime + 0.1 );
}
void CNPC_ControllerZapBall :: Precache( void )
{
engine->PrecacheModel( "sprites/xspark4.vmt");
}
void CNPC_ControllerZapBall::AnimateThink( void )
{
SetNextThink( gpGlobals->curtime + 0.1 );
m_flCycle = ((int)m_flCycle + 1) % 11;
if (gpGlobals->curtime - m_flSpawnTime > 5 || GetAbsVelocity().Length() < 10)
{
SetTouch( NULL );
Kill();
}
}
void CNPC_ControllerZapBall::ExplodeTouch( CBaseEntity *pOther )
{
if (m_takedamage = DAMAGE_YES )
{
trace_t tr = GetTouchTrace( );
ClearMultiDamage( );
Vector vecAttackDir = GetAbsVelocity();
VectorNormalize( vecAttackDir );
if (m_hOwner != NULL)
{
CTakeDamageInfo info( this, m_hOwner, sk_controller_dmgball.GetFloat(), DMG_ENERGYBEAM );
CalculateMeleeDamageForce( &info, vecAttackDir, tr.endpos );
pOther->DispatchTraceAttack( info, vecAttackDir, &tr );
}
else
{
CTakeDamageInfo info( this, this, sk_controller_dmgball.GetFloat(), DMG_ENERGYBEAM );
CalculateMeleeDamageForce( &info, vecAttackDir, tr.endpos );
pOther->DispatchTraceAttack( info, vecAttackDir, &tr );
}
ApplyMultiDamage();
// void UTIL_EmitAmbientSound( CBaseEntity *entity, const Vector &vecOrigin, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float soundtime /*= 0.0f*/ )
UTIL_EmitAmbientSound( this, tr.endpos, "weapons/electro4.wav", 0.3, SNDLVL_NORM, 0, random->RandomInt( 90, 99 ) );
}
Kill();
}
void CNPC_ControllerZapBall::Kill( void )
{
UTIL_Remove( m_pSprite );
UTIL_Remove( this );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -