⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hl1_npc_nihilanth.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		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 + -