📄 hl1_npc_nihilanth.cpp
字号:
m_irritation = 3;
if (m_irritation != 3)
{
Vector vecBlood = (ptr->endpos - GetAbsOrigin() );
VectorNormalize( vecBlood );
UTIL_BloodStream( ptr->endpos, vecBlood, BloodColor(), info.GetDamage() + (100 - 100 * (m_iHealth / sk_nihilanth_health.GetFloat() )));
}
// SpawnBlood(ptr->vecEndPos, BloodColor(), flDamage * 5.0);// a little surface blood.
AddMultiDamage( info, this );
}
bool CNPC_Nihilanth::EmitSphere( void )
{
m_iActiveSpheres = 0;
int empty = 0;
for (int i = 0; i < N_SPHERES; i++)
{
if (m_hSphere[i] != NULL)
{
m_iActiveSpheres++;
}
else
{
empty = i;
}
}
if (m_iActiveSpheres >= N_SPHERES)
return false;
Vector vecSrc = m_hRecharger->GetAbsOrigin();
CNihilanthHVR *pEntity = (CNihilanthHVR *)CREATE_ENTITY( CNihilanthHVR, "nihilanth_energy_ball" );
pEntity->SetAbsOrigin( vecSrc );
pEntity->SetAbsAngles( GetAbsAngles() );
pEntity->SetOwnerEntity( this );
pEntity->Spawn();
pEntity->SetAbsVelocity( GetAbsOrigin() - vecSrc );
pEntity->CircleInit( this );
m_hSphere[empty] = pEntity;
return true;
}
void CNPC_Nihilanth::NullThink( void )
{
StudioFrameAdvance( );
SetNextThink( gpGlobals->curtime + 0.5 );
}
void CNPC_Nihilanth::StartupThink( void )
{
m_irritation = 0;
m_flAdj = 512;
CBaseEntity *pEntity;
pEntity = gEntList.FindEntityByName( NULL, "n_min", NULL );
if (pEntity)
m_flMinZ = pEntity->GetAbsOrigin().z;
else
m_flMinZ = -4096;
pEntity = gEntList.FindEntityByName( NULL, "n_max", NULL );
if (pEntity)
m_flMaxZ = pEntity->GetAbsOrigin().z;
else
m_flMaxZ = 4096;
m_hRecharger = this;
//TODO
for (int i = 0; i < N_SPHERES; i++)
{
EmitSphere();
}
m_hRecharger = NULL;
SetUse( NULL );
SetThink( &CNPC_Nihilanth::HuntThink);
SetNextThink( gpGlobals->curtime + 0.1 );
}
void CNPC_Nihilanth::InputTurnBabyOn( inputdata_t &inputdata )
{
if ( m_irritation == 0 )
{
m_irritation = 1;
}
}
void CNPC_Nihilanth::InputTurnBabyOff( inputdata_t &inputdata )
{
CBaseEntity *pTouch = gEntList.FindEntityByName( NULL, m_szDeadTouch, NULL );
if ( pTouch && GetEnemy() != NULL )
pTouch->Touch( GetEnemy() );
}
bool CNPC_Nihilanth::AbsorbSphere( void )
{
for (int i = 0; i < N_SPHERES; i++)
{
if (m_hSphere[i] != NULL)
{
CNihilanthHVR *pSphere = (CNihilanthHVR *)m_hSphere[i].Get();
pSphere->AbsorbInit();
m_hSphere[i] = NULL;
m_iActiveSpheres--;
return TRUE;
}
}
return FALSE;
}
void CNPC_Nihilanth::HuntThink( void )
{
SetNextThink( gpGlobals->curtime + 0.1 );
DispatchAnimEvents( this );
StudioFrameAdvance( );
ShootBalls();
// if dead, force cancelation of current animation
if ( m_iHealth <= 0)
{
SetThink( &CNPC_Nihilanth::DyingThink );
m_flCycle = 1.0f;
StudioFrameAdvance();
return;
}
// ALERT( at_console, "health %.0f\n", pev->health );
// if damaged, try to abosorb some spheres
if ( m_iHealth < sk_nihilanth_health.GetFloat() && AbsorbSphere() )
{
m_iHealth += sk_nihilanth_health.GetFloat() / N_SPHERES;
}
// get new sequence
if ( IsSequenceFinished() )
{
m_flCycle = 0;
NextActivity( );
ResetSequenceInfo( );
m_flPlaybackRate = 2.0 - 1.0 * ( m_iHealth / sk_nihilanth_health.GetFloat() );
}
// look for current enemy
if ( GetEnemy() != NULL && m_hRecharger == NULL)
{
if (FVisible( GetEnemy() ))
{
if (m_flLastSeen < gpGlobals->curtime - 5)
m_flPrevSeen = gpGlobals->curtime;
m_flLastSeen = gpGlobals->curtime;
m_posTarget = GetEnemy()->GetAbsOrigin();
m_vecTarget = m_posTarget - GetAbsOrigin();
VectorNormalize( m_vecTarget );
m_vecDesired = m_vecTarget;
m_posDesired = Vector( GetAbsOrigin().x, GetAbsOrigin().y, m_posTarget.z + m_flAdj );
}
else
{
m_flAdj = min( m_flAdj + 10, 1000 );
}
}
// don't go too high
if (m_posDesired.z > m_flMaxZ)
m_posDesired.z = m_flMaxZ;
// don't go too low
if (m_posDesired.z < m_flMinZ)
m_posDesired.z = m_flMinZ;
Flight( );
}
void CNPC_Nihilanth::Flight( void )
{
Vector vForward, vRight, vUp;
QAngle vAngle = QAngle( GetAbsAngles().x + m_avelocity.x, GetAbsAngles().y + m_avelocity.y, GetAbsAngles().z + m_avelocity.z );
AngleVectors( vAngle, &vForward, &vRight, &vUp );
float flSide = DotProduct( m_vecDesired, vRight );
if (flSide < 0)
{
if (m_avelocity.y < 180)
{
m_avelocity.y += 6; // 9 * (3.0/2.0);
}
}
else
{
if (m_avelocity.y > -180)
{
m_avelocity.y -= 6; // 9 * (3.0/2.0);
}
}
m_avelocity.y *= 0.98;
// estimate where I'll be in two seconds
Vector vecEst = GetAbsOrigin() + m_velocity * 2.0 + vUp * m_flForce * 20;
// add immediate force
AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
m_velocity.x += vUp.x * m_flForce;
m_velocity.y += vUp.y * m_flForce;
m_velocity.z += vUp.z * m_flForce;
float flSpeed = m_velocity.Length();
float flDir = DotProduct( Vector( vForward.x, vForward.y, 0 ), Vector( m_velocity.x, m_velocity.y, 0 ) );
if (flDir < 0)
flSpeed = -flSpeed;
// sideways drag
m_velocity.x = m_velocity.x * (1.0 - fabs( vRight.x ) * 0.05);
m_velocity.y = m_velocity.y * (1.0 - fabs( vRight.y ) * 0.05);
m_velocity.z = m_velocity.z * (1.0 - fabs( vRight.z ) * 0.05);
// general drag
m_velocity = m_velocity * 0.995;
// apply power to stay correct height
if (m_flForce < 100 && vecEst.z < m_posDesired.z)
{
m_flForce += 10;
}
else if (m_flForce > -100 && vecEst.z > m_posDesired.z)
{
if (vecEst.z > m_posDesired.z)
m_flForce -= 10;
}
UTIL_SetOrigin( this, GetAbsOrigin() + m_velocity * 0.1 );
vAngle = QAngle( GetAbsAngles().x + m_avelocity.x * 0.1, GetAbsAngles().y + m_avelocity.y * 0.1, GetAbsAngles().z + m_avelocity.z * 0.1 );
SetAbsAngles( vAngle );
// ALERT( at_console, "%5.0f %5.0f : %4.0f : %3.0f : %2.0f\n", m_posDesired.z, pev->origin.z, m_velocity.z, m_avelocity.y, m_flForce );
}
void CNPC_Nihilanth::NextActivity( )
{
Vector vForward, vRight, vUp;
SetIdealActivity( ACT_DO_NOT_DISTURB );
AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
if (m_irritation >= 2)
{
if (m_pBall == NULL)
{
m_pBall = CSprite::SpriteCreate( "sprites/tele1.vmt", GetAbsOrigin(), true );
if (m_pBall)
{
m_pBall->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation );
m_pBall->SetAttachment( this, 1 );
m_pBall->SetScale( 4.0 );
m_pBall->m_flSpriteFramerate = 10.0f;
m_pBall->TurnOn( );
}
}
if (m_pBall)
{
CBroadcastRecipientFilter filterlight;
Vector vOrigin;
QAngle vAngle;
GetAttachment( 2, vOrigin, vAngle );
te->DynamicLight( filterlight, 0.0, &vOrigin, 255, 192, 64, 0, 256, 20, 0 );
}
}
if (( m_iHealth < sk_nihilanth_health.GetFloat() / 2 || m_iActiveSpheres < N_SPHERES / 2) && m_hRecharger == NULL && m_iLevel <= 9)
{
char szName[64];
CBaseEntity *pEnt = NULL;
CBaseEntity *pRecharger = NULL;
float flDist = 8192;
Q_snprintf(szName, sizeof( szName ), "%s%d", m_szRechargerTarget, m_iLevel );
while ((pEnt = gEntList.FindEntityByName( pEnt, szName , NULL )) != NULL )
{
float flLocal = (pEnt->GetAbsOrigin() - GetAbsOrigin() ).Length();
if ( flLocal < flDist )
{
flDist = flLocal;
pRecharger = pEnt;
}
}
if (pRecharger)
{
m_hRecharger = pRecharger;
m_posDesired = Vector( GetAbsOrigin().x, GetAbsOrigin().y, pRecharger->GetAbsOrigin().z );
m_vecDesired = pRecharger->GetAbsOrigin() - m_posDesired;
VectorNormalize( m_vecDesired );
m_vecDesired.z = 0;
VectorNormalize( m_vecDesired );
}
else
{
m_hRecharger = NULL;
Msg( "nihilanth can't find %s\n", szName );
m_iLevel++;
if ( m_iLevel > 9 )
m_irritation = 2;
}
}
float flDist = ( m_posDesired - GetAbsOrigin() ).Length();
float flDot = DotProduct( m_vecDesired, vForward );
if (m_hRecharger != NULL)
{
// at we at power up yet?
if (flDist < 128.0)
{
int iseq = LookupSequence( "recharge" );
if (iseq != GetSequence())
{
char szText[64];
Q_snprintf( szText, sizeof( szText ), "%s%d", m_szDrawUse, m_iLevel );
FireTargets( szText, this, this, USE_ON, 1.0 );
Msg( "fireing %s\n", szText );
}
SetSequence ( LookupSequence( "recharge" ) );
}
else
{
FloatSequence( );
}
return;
}
if (GetEnemy() != NULL && !GetEnemy()->IsAlive())
{
SetEnemy( NULL );
}
if (m_flLastSeen + 15 < gpGlobals->curtime)
{
SetEnemy( NULL );
}
if ( GetEnemy() == NULL)
{
GetSenses()->Look( 4096 );
SetEnemy( BestEnemy() );
}
if ( GetEnemy() != NULL && m_irritation != 0)
{
if (m_flLastSeen + 5 > gpGlobals->curtime && flDist < 256 && flDot > 0)
{
if (m_irritation >= 2 && m_iHealth < sk_nihilanth_health.GetFloat() / 2.0)
{
SetSequence( LookupSequence( "attack1_open" ) );
}
else
{
if ( random->RandomInt(0, 1 ) == 0)
{
SetSequence( LookupSequence( "attack1" ) ); // zap
}
else
{
char szText[64];
Q_snprintf( szText, sizeof( szText ), "%s%d", m_szTeleportTouch, m_iTeleport );
CBaseEntity *pTouch = gEntList.FindEntityByName( NULL, szText, NULL );
Q_snprintf( szText, sizeof( szText ), "%s%d", m_szTeleportUse, m_iTeleport );
CBaseEntity *pTrigger = gEntList.FindEntityByName( NULL, szText, NULL );
if (pTrigger != NULL || pTouch != NULL)
{
SetSequence( LookupSequence( "attack2" ) ); // teleport
}
else
{
m_iTeleport++;
SetSequence( LookupSequence( "attack1" ) ); // zap
}
}
}
return;
}
}
FloatSequence( );
}
void CNPC_Nihilanth::MakeFriend( Vector vecStart )
{
int i;
for (i = 0; i < 3; i++)
{
if (m_hFriend[i] != NULL && !m_hFriend[i]->IsAlive())
{
if ( m_nRenderMode == kRenderNormal) // don't do it if they are already fading
m_hFriend[i]->MyNPCPointer()->CorpseFade();
m_hFriend[i] = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -