//=========================================================
// Revela la posición de los jugadores.
//=========================================================
void CDirector_Manager::Disclose()
{
	CAI_BaseNPC *pNPC = NULL;

	do
	{
		// Buscamos a todos los hijos en el mapa.
		pNPC = (CAI_BaseNPC *)gEntList.FindEntityByName(pNPC, CHILD_NAME);

		// No existe o esta muerto.
		if ( !pNPC || !pNPC->IsAlive() )
			continue;

		// Ya tiene a un jugador como enemigo.
		if ( pNPC->GetEnemy() && pNPC->GetEnemy()->IsPlayer() )
			continue;

		// Seleccionamos al jugador más cercano.
		float flDistance = 0.0f;
		CIN_Player *pPlayer = UTIL_GetNearestInPlayer(pPlayer->GetAbsOrigin(), flDistance);

		if ( !pPlayer )
			continue;

		// Le decimos que su nuevo enemigo es el jugador y le damos la ubicación de este.
		pNPC->SetEnemy(pPlayer);
		pNPC->UpdateEnemyMemory(pPlayer, pPlayer->GetAbsOrigin());

	}
	while ( pNPC );
}
Example #2
0
void CAI_Squad::SquadNewEnemy( CBaseEntity *pEnemy )
{
	if ( !pEnemy )
	{
		DevMsg( "ERROR: SquadNewEnemy() - pEnemy is NULL!\n" );
		return;
	}

	for (int i = 0; i < m_SquadMembers.Count(); i++)
	{
		CAI_BaseNPC *pMember = m_SquadMembers[i];
		if (pMember)
		{
			// reset members who aren't activly engaged in fighting (only do this if the NPC's using the squad memory, or it'll fail)
			if ( !pMember->GetEnemy() || 
				 ( pMember->GetEnemy() != pEnemy && 
				   !pMember->HasCondition( COND_SEE_ENEMY) &&
				   gpGlobals->curtime - pMember->GetEnemyLastTimeSeen() > 3.0 ) )
			{
				// give them a new enemy
				if( !hl2_episodic.GetBool() || pMember->IsValidEnemy(pEnemy) )
				{
					pMember->SetEnemy( pEnemy );
				}
				// pMember->SetLastAttackTime( 0 );
			}
		}
	}
}
//=========================================================
// Crea un Jefe.
//=========================================================
CAI_BaseNPC *CDirectorSpawn::MakeBoss()
{
	// Desactivado
	if ( Disabled )
		return NULL;

	// Seleccionamos una clase de NPC para crear.
	const char *pClass	= SelectRandomBoss();
	CAI_BaseNPC *pNPC	= VerifyClass(pClass);

	// Ocurrio algún problema.
	if ( !pNPC )
	{
		Warning("[DIRECTOR SPAWN] Ha ocurrido un problema al intentar crear un Jefe. \r\n");
		return NULL;
	}

	Vector origin;

	// Verificamos si podemos crear el Grunt en el radio.
	if ( !CanMakeNPC(pNPC, &origin) )
		return NULL;

	// Lugar de creación.
	pNPC->SetAbsOrigin(origin);

	// Nombre del Jefe.
	pNPC->SetName(MAKE_STRING(BOSS_NAME));

	QAngle angles	= GetAbsAngles();
	angles.x		= 0.0;
	angles.z		= 0.0;

	pNPC->SetAbsAngles(angles);

	// Tiene que caer al suelo.
	pNPC->AddSpawnFlags(SF_NPC_FALL_TO_GROUND);

	// Creamos al Jefe, le decimos quien es su dios (creador) y lo activamos.
	DispatchSpawn(pNPC);
	pNPC->SetOwnerEntity(this);
	DispatchActivate(pNPC);

	// Al parecer se atoro en una pared.
	if ( !PostSpawn(pNPC) )
		return NULL;

	// Debe conocer la ubicación del jugador (Su enemigo)
	CIN_Player *pPlayer = UTIL_GetRandomInPlayer();

	if ( pPlayer )
	{
		// Ataca al jugador YA
		pNPC->SetEnemy(pPlayer);
		pNPC->UpdateEnemyMemory(pPlayer, pPlayer->GetAbsOrigin());
	}

	return pNPC;
}
//=========================================================
// HandleAnimEvent - catches the monster-specific messages
// that occur when tagged animation frames are played.
//=========================================================
void CNPC_Controller::HandleAnimEvent( animevent_t *pEvent )
{
	switch( pEvent->event )
	{
		case CONTROLLER_AE_HEAD_OPEN:
		{
			Vector vecStart;
			QAngle angleGun;
			
			GetAttachment( 0, vecStart, angleGun );

			// BUGBUG - attach to attachment point!

			CBroadcastRecipientFilter filter;
			te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0, 1 /*radius*/, 0.2, -32 );
		
			m_iBall[0] = 192;
			m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
			m_iBall[1] = 255;
			m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;

		}
		break;

		case CONTROLLER_AE_BALL_SHOOT:
		{
			Vector vecStart;
			QAngle angleGun;
			
			GetAttachment( 1, vecStart, angleGun );

			CBroadcastRecipientFilter filter;
			te->DynamicLight( filter, 0.0, &vecStart, 255, 192, 64, 0, 1 /*radius*/, 0.1, 32 );

			CAI_BaseNPC *pBall = (CAI_BaseNPC*)Create( "controller_head_ball", vecStart, angleGun );

			pBall->SetAbsVelocity( Vector(0,0,32) );
			pBall->SetEnemy( GetEnemy() );

//			DevMsg( 1, "controller shooting head ball\n" );

			m_iBall[0] = 0;
			m_iBall[1] = 0;
		}
		break;

		case CONTROLLER_AE_SMALL_SHOOT:
		{
			AttackSound( );
			m_flShootTime = gpGlobals->curtime;
			m_flShootEnd = m_flShootTime + atoi( pEvent->options ) / 15.0;
		}
		break;
		case CONTROLLER_AE_POWERUP_FULL:
		{
			m_iBall[0] = 255;
			m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
			m_iBall[1] = 255;
			m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
		}
		break;
		case CONTROLLER_AE_POWERUP_HALF:
		{
			m_iBall[0] = 192;
			m_iBallTime[0] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
			m_iBall[1] = 192;
			m_iBallTime[1] = gpGlobals->curtime + atoi( pEvent->options ) / 15.0;
		}
		break;
		default:
			BaseClass::HandleAnimEvent( pEvent );
			break;
	}
}
void CAI_MoveAndShootOverlay::RunShootWhileMove()
{
	if ( m_flNextMoveShootTime == FLT_MAX )
		return;

	CAI_BaseNPC *pOuter = GetOuter();

	// keep enemy if dead but try to look for a new one
	if (!pOuter->GetEnemy() || !pOuter->GetEnemy()->IsAlive())
	{
		CBaseEntity *pNewEnemy = pOuter->BestEnemy();

		if( pNewEnemy != NULL )
		{
			//New enemy! Clear the timers and set conditions.
			pOuter->SetCondition( COND_NEW_ENEMY );
			pOuter->SetEnemy( pNewEnemy );
			pOuter->SetState( NPC_STATE_COMBAT );
		}
		else
		{
			pOuter->ClearAttackConditions();
		}
		// SetEnemy( NULL );
	}

	if ( GetEnemy() == NULL || !pOuter->GetNavigator()->IsGoalActive() )
		return;

	bool bMoveAimAtEnemy = CanAimAtEnemy();

	UpdateMoveShootActivity( bMoveAimAtEnemy );

	if (bMoveAimAtEnemy)
	{
		Assert( pOuter->GetActiveWeapon() ); // This should have been caught at task start

		// time to fire?
		if ( pOuter->HasCondition( COND_CAN_RANGE_ATTACK1 ) && gpGlobals->curtime >= m_flNextMoveShootTime )
		{
			if ( m_bMovingAndShooting || GetOuter()->OnBeginMoveAndShoot() )
			{
				m_bMovingAndShooting = true;
				Activity activity = pOuter->TranslateActivity( ACT_GESTURE_RANGE_ATTACK1 );

				Assert( activity != ACT_INVALID );

				if (--m_nMoveShots > 0)
				{
					pOuter->SetLastAttackTime( gpGlobals->curtime );
					pOuter->AddGesture( activity );
					// FIXME: this seems a bit wacked
					pOuter->Weapon_SetActivity( pOuter->Weapon_TranslateActivity( ACT_RANGE_ATTACK1 ), 0 );
					m_flNextMoveShootTime = gpGlobals->curtime + pOuter->GetActiveWeapon()->GetFireRate() - 0.1;
				}
				else
				{
					m_nMoveShots = random->RandomInt( m_minBurst, m_maxBurst );
					m_flNextMoveShootTime = gpGlobals->curtime + random->RandomFloat( m_minPause, m_maxPause );
					m_bMovingAndShooting = false;
					GetOuter()->OnEndMoveAndShoot();
				}
			}
		}

		// try to keep facing towards the last known position of the enemy
		Vector vecEnemyLKP = pOuter->GetEnemyLKP();
		pOuter->AddFacingTarget( pOuter->GetEnemy(), vecEnemyLKP, 1.0, 0.8 );
	}
	else
	{
		if ( m_bMovingAndShooting )
		{
			m_bMovingAndShooting = false;
			GetOuter()->OnEndMoveAndShoot();
		}
	}
}
Example #6
0
void CAI_MoveAndShootOverlay::RunShootWhileMove()
{
	if ( m_bNoShootWhileMove )
		return;

	if ( gpGlobals->curtime < m_flSuspendUntilTime )
		return;

	m_flSuspendUntilTime = MOVESHOOT_DO_NOT_SUSPEND;

	CAI_BaseNPC *pOuter = GetOuter();

	// keep enemy if dead but try to look for a new one
	if (!pOuter->GetEnemy() || !pOuter->GetEnemy()->IsAlive())
	{
		CBaseEntity *pNewEnemy = pOuter->BestEnemy();

		if( pNewEnemy != NULL )
		{
			//New enemy! Clear the timers and set conditions.
			pOuter->SetEnemy( pNewEnemy );
			pOuter->SetState( NPC_STATE_COMBAT );
		}
		else
		{
			pOuter->ClearAttackConditions();
		}
		// SetEnemy( NULL );
	}

	/*if( !pOuter->GetNavigator()->IsGoalActive() )
		return;*/

	if ( GetEnemy() == NULL )
	{
		if ( pOuter->GetAlternateMoveShootTarget() )
		{
			// Aim at this other thing if I can't aim at my enemy.
			pOuter->AddFacingTarget( pOuter->GetAlternateMoveShootTarget(), pOuter->GetAlternateMoveShootTarget()->GetAbsOrigin(), 1.0, 0.2 );
		}

		return;
	}

	bool bMoveAimAtEnemy = CanAimAtEnemy();
	UpdateMoveShootActivity( bMoveAimAtEnemy );
	if ( !bMoveAimAtEnemy )
	{
		EndShootWhileMove();
		return;
	}

	Assert( HasAvailableRangeAttack() ); // This should have been caught at task start

	Activity activity;
	bool bIsReloading = false;

	if ( ( activity = pOuter->TranslateActivity( ACT_GESTURE_RELOAD ) ) != ACT_INVALID )
	{
		bIsReloading = pOuter->IsPlayingGesture( activity );
	}

	if ( !bIsReloading && HasAvailableRangeAttack() )
	{
		// time to fire?
		if ( pOuter->HasCondition( COND_CAN_RANGE_ATTACK1, false ) )
		{
			if ( pOuter->GetShotRegulator()->IsInRestInterval() )
			{
				EndShootWhileMove();
			}
			else if ( pOuter->GetShotRegulator()->ShouldShoot() )
			{
				if ( m_bMovingAndShooting || pOuter->OnBeginMoveAndShoot() )
				{
					m_bMovingAndShooting = true;
					pOuter->OnRangeAttack1();

					activity = pOuter->TranslateActivity( ACT_GESTURE_RANGE_ATTACK1 );
					Assert( activity != ACT_INVALID );

					pOuter->RestartGesture( activity );

					// FIXME: this seems a bit wacked
					pOuter->Weapon_SetActivity( pOuter->Weapon_TranslateActivity( ACT_RANGE_ATTACK1 ), 0 );
				}
			}
		}
	}

	// try to keep facing towards the last known position of the enemy
	Vector vecEnemyLKP = pOuter->GetEnemyLKP();
	pOuter->AddFacingTarget( pOuter->GetEnemy(), vecEnemyLKP, 1.0, 0.8 );
}
//=========================================================
// Crea un hijo en la ubicación especificada.
//=========================================================
bool CDirector_Manager::AddChild(const Vector &vecPosition, int flag)
{
	// No se ha podido acceder al Director.
	if ( !Director() )
		return false;

	// No es posible crear un hijo aquí.
	if ( !CanMake(vecPosition) )
		return false;

	// Creamos un hijo de la lista.
	const char *pChildName	= GetChildClass();
	CAI_BaseNPC *pChild		= (CAI_BaseNPC *)CreateEntityByName(pChildName);

	QAngle angles = RandomAngle(0, 360);
	angles.x = 0.0;
	angles.z = 0.0;	
	pChild->SetAbsAngles(angles);

	// Establecemos la ubicación de creación.
	pChild->SetAbsOrigin(vecPosition);

	// Debe caer al suelo y desaparecer.
	pChild->AddSpawnFlags(SF_NPC_FALL_TO_GROUND);
	pChild->AddSpawnFlags(SF_NPC_FADE_CORPSE);

	UTIL_DropToFloor(pChild, MASK_SOLID);

	ConVarRef director_debug("director_debug");

	DispatchSpawn(pChild);
	pChild->SetOwnerEntity(Director());
	DispatchActivate(pChild);

	// ¡¡NO CAMBIAR!!
	pChild->SetName(MAKE_STRING(CHILD_NAME));

	// Sin colisiones.
	if ( flag == SPAWN_NO_COLLISION || flag == SPAWN_NO_COLLISION_AND_POWERFUL )
	{
		pChild->SetCollisionGroup(COLLISION_GROUP_SPECIAL_NPC);
		Vector vecOriginRadius;

		if ( Director()->Status == PANIC && RandomInt(0, 4) == 2 )
			pChild->SetCollisionGroup(COLLISION_GROUP_NPC);

		// Intentamos crearlo en un radio de 100
		if ( CAI_BaseNPC::FindSpotForNPCInRadius(&vecOriginRadius, vecPosition, pChild, 150, false) )
		{
			// Evitamos que se mueva por debajo del suelo.
			vecOriginRadius.z = vecPosition.z;

			// Movemos hacia esta ubicación.
			pChild->SetAbsOrigin(vecOriginRadius);

			// Marcamos al nodo afortunado. (Naranja)
			if ( director_debug.GetBool() )
				NDebugOverlay::Box(vecOriginRadius, -Vector(10, 10, 10), Vector(10, 10, 10), 255, 128, 0, 10, 20.0f);
		}
	}

	// Poderoso.
	if ( flag == SPAWN_POWERFUL || flag == SPAWN_NO_COLLISION_AND_POWERFUL )
	{
		int moreHealth = 3;

		// Normal: 5 más de salud.
		if ( InGameRules()->IsSkillLevel(SKILL_MEDIUM) ) 
			moreHealth = 5;

		// Dificil: 8 más de salud.
		if ( InGameRules()->IsSkillLevel(SKILL_HARD) )
			moreHealth = 8;

		// Más rápido.
		pChild->SetAddAccel(40);

		// Establecemos la nueva salud.
		pChild->SetMaxHealth(pChild->GetMaxHealth() + moreHealth);
		pChild->SetHealth(pChild->GetMaxHealth());

		// Seleccionamos al jugador más cercano.
		float flDistance = 0.0f;
		CIN_Player *pPlayer = UTIL_GetNearestInPlayer(pChild->GetAbsOrigin(), flDistance);

		if ( pPlayer )
		{
			// Le decimos que su nuevo enemigo es el jugador y le damos la ubicación de este.
			pChild->SetEnemy(pPlayer);
			pChild->UpdateEnemyMemory(pPlayer, pPlayer->GetAbsOrigin());
		}
	}

	// Al parecer se atoro en una pared.
	if ( !PostSpawn(pChild) )
	{
		// Marcamos al nodo desafortunado. (Negro)
		if ( director_debug.GetBool() )
			NDebugOverlay::Box(vecPosition, -Vector(10, 10, 10), Vector(10, 10, 10), 0, 0, 0, 10, 3.0f);

		return false;
	}

	// Marcamos al nodo afortunado. (Rojo)
	if ( director_debug.GetBool() )
		NDebugOverlay::Box(vecPosition, -Vector(10, 10, 10), Vector(10, 10, 10), 223, 1, 1, 10, 3.0f);

	DevMsg("[MANAGER] Se ha creado <%s> (faltan %i) \r\n", pChildName, Director()->SpawnQueue);
	++Director()->ChildsSpawned;

	return true;
}