//-----------------------------------------------------------------------------
// Purpose: Called when we have no scripted target. Looks for new enemies to track.
//-----------------------------------------------------------------------------
CBaseEntity *CNPC_CombineCamera::MaintainEnemy()
{
	if (HasSpawnFlags(SF_COMBINE_CAMERA_IGNOREENEMIES))
		return NULL;

	GetSenses()->Look(m_nOuterRadius);

	CBaseEntity *pEnemy = BestEnemy();
	if (pEnemy)
	{
		// See if our best enemy is too far away to care about.
		Vector vecDelta = pEnemy->GetAbsOrigin() - GetAbsOrigin();
		float flDist = vecDelta.Length();
		if (flDist < m_nOuterRadius)
		{
			if (FInViewCone(pEnemy))
			{
				// dvs: HACK: for checking multiple view cones
				float flSaveFieldOfView = m_flFieldOfView;
				m_flFieldOfView = CAMERA_FOV_NARROW;

				// Is the target visible?
				bool bVisible = FVisible(pEnemy);
				m_flFieldOfView = flSaveFieldOfView;
				if ( bVisible )
					return pEnemy;
			}
		}
	}
	
	return NULL;
}
//=========================================================
// IdleHello
// Try to greet player first time he's seen
//=========================================================
int CAI_PlayerAlly::FIdleHello( void )
{
	if (!IsOkToSpeak())
		return false;

	// if this is first time scientist has seen player, greet him
	if (!GetExpresser()->SpokeConcept(TLK_HELLO))
	{
		// get a player
		CBaseEntity *pPlayer = FindNearestFriend(true);

		if (pPlayer)
		{
			if (FInViewCone(pPlayer) && FVisible(pPlayer))
			{
				SetSpeechTarget( pPlayer );

				Speak( TLK_HELLO );
				
				return true;
			}
		}
	}
	return false;
}
Esempio n. 3
0
//=========================================================
// IdleHello
// Try to greet player first time he's seen
//=========================================================
bool CTalkMonster::FIdleHello()
{
	if (!FOkToSpeak())
		return false;

	// if this is first time scientist has seen player, greet him
	if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer))
	{
		// get a player
		CBaseEntity *pPlayer = FindNearestFriend(true);

		if (pPlayer)
		{
			if (FInViewCone(pPlayer) && FVisible(pPlayer))
			{
				m_hTalkTarget = pPlayer;

				if ( GetSpawnFlags().Any( SF_MONSTER_PREDISASTER ) )
					PlaySentence( m_szGrp[TLK_PHELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM,  ATTN_IDLE );
				else
					PlaySentence( m_szGrp[TLK_HELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM,  ATTN_IDLE );

				SetBits(m_bitsSaid, bit_saidHelloPlayer);
				
				return true;
			}
		}
	}
	return false;
}
Esempio n. 4
0
// here bot updates important info that is used multiple times along the thinking process
void CSDKBot::InfoGathering()
{
	if (!GetEnemy())
	{
		m_flBotToEnemyDist = 9999;
		m_flHeightDifToEnemy = 0;
		m_bEnemyOnSights = false;

		m_flDistTraveled += fabs(GetLocalVelocity().Length()); // this is used for stuck checking,
		return;
	}

	m_flBotToEnemyDist = (GetLocalOrigin() - GetEnemy()->GetLocalOrigin()).Length();

	trace_t tr;
	UTIL_TraceHull( EyePosition(), GetEnemy()->EyePosition() - Vector(0,0,20), -BotTestHull, BotTestHull, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );

	if( tr.m_pEnt == GetEnemy() ) // vision line between both
		m_bEnemyOnSights = true;
	else
		m_bEnemyOnSights = false;

	m_bInRangeToAttack = (m_flBotToEnemyDist < m_flMinRangeAttack) && FInViewCone( GetEnemy() );

	m_flDistTraveled += fabs(GetLocalVelocity().Length()); // this is used for stuck checking,

	m_flHeightDifToEnemy = GetLocalOrigin().z - GetEnemy()->GetLocalOrigin().z;
}
Esempio n. 5
0
// This function takes a lot of CPU, so make sure it's not called often!  Don't call this function directly, use UpdateEnemy instead whenever possible.
CBaseEntity* AvHTurret::FindBestEnemy()
{
    PROFILE_START()
	CBaseEntity* theEntityList[100];
	
	int theMaxRange = this->GetXYRange();
	
	Vector delta = Vector(theMaxRange, theMaxRange, theMaxRange);
	CBaseEntity* theCurrentEntity = NULL;
	CBaseEntity* theBestPlayer = NULL;
	CBaseEntity* theBestStructure = NULL;

	float theCurrentEntityRange = 100000;
	
	// Find only monsters/clients in box, NOT limited to PVS
	int theCount = UTIL_EntitiesInBox(theEntityList, 100, this->pev->origin - delta, this->pev->origin + delta, FL_CLIENT | FL_MONSTER);
	for(int i = 0; i < theCount; i++ )
	{
		theCurrentEntity = theEntityList[i];
		if((theCurrentEntity != this) && theCurrentEntity->IsAlive())
		{
			// the looker will want to consider this entity
			// don't check anything else about an entity that can't be seen, or an entity that you don't care about.
			if(this->IRelationship(theCurrentEntity ) != R_NO && FInViewCone(theCurrentEntity) && !FBitSet(theCurrentEntity->pev->flags, FL_NOTARGET))
			{
				AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(theCurrentEntity);
				if(!thePlayer || thePlayer->GetCanBeAffectedByEnemies())
				{
					if(this->GetIsValidTarget(theCurrentEntity))
					{
						// Find nearest enemy
						float theRangeToTarget = VectorDistance2D(this->pev->origin, theCurrentEntity->pev->origin);
						if(theRangeToTarget < theCurrentEntityRange)
						{
                            // FVisible is expensive, so defer until necessary
                            if(!this->GetRequiresLOS() || FVisible(theCurrentEntity))
                            {
                                theCurrentEntityRange = theRangeToTarget;
								if ( thePlayer ) 
								{
									theBestPlayer = theCurrentEntity;
								}
								else
								{
									theBestStructure = theCurrentEntity;
								}
                            }
						}
					}
				}
			}
		}
	}
    PROFILE_END(kAvHTurretFindBestEnemy);

	return (theBestPlayer != NULL ) ? theBestPlayer : theBestStructure;
}
//-----------------------------------------------------------------------------
// Purpose: Enemies are only valid if they're inside our radius
//-----------------------------------------------------------------------------
bool CNPC_CombineCamera::IsValidEnemy( CBaseEntity *pEnemy )
{
	Vector vecDelta = pEnemy->GetAbsOrigin() - GetAbsOrigin();
	float flDist = vecDelta.Length();
	if ( (flDist > m_nOuterRadius) || !FInViewCone(pEnemy) )
		return false;

	return BaseClass::IsValidEnemy( pEnemy );
}
//---------------------------------------------------------
//---------------------------------------------------------
bool CNPC_GroundTurret::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker )
{
	if ( BaseClass::FVisible( pEntity, traceMask, ppBlocker ) )
		return true;
	if ( ( pEntity->GetAbsOrigin().AsVector2D() - GetAbsOrigin().AsVector2D() ).LengthSqr() < Square(10*12) &&
		 FInViewCone( pEntity->GetAbsOrigin() ) &&
		 BaseClass::FVisible( pEntity->GetAbsOrigin() + Vector( 0, 0, 1 ), traceMask, ppBlocker ) )
		return true;
	return false;
}
Esempio n. 8
0
void CBaseMonster::Look(int iDistance)
{
    int iSighted = 0;
    ClearConditions(bits_COND_SEE_HATE | bits_COND_SEE_DISLIKE | bits_COND_SEE_ENEMY | bits_COND_SEE_FEAR | bits_COND_SEE_NEMESIS | bits_COND_SEE_CLIENT);
    m_pLink = NULL;

    CBaseEntity *pSightEnt = NULL;
    CBaseEntity *pList[100];
    Vector delta = Vector(iDistance, iDistance, iDistance);
    int count = UTIL_EntitiesInBox(pList, 100, pev->origin - delta, pev->origin + delta, FL_CLIENT | FL_MONSTER);

    for (int i = 0; i < count; i++)
    {
        pSightEnt = pList[i];

        if (pSightEnt != this && pSightEnt->pev->health > 0)
        {
            if (IRelationship(pSightEnt) != R_NO && FInViewCone(pSightEnt) && !FBitSet(pSightEnt->pev->flags, FL_NOTARGET) && FVisible(pSightEnt))
            {
                if (pSightEnt->IsPlayer())
                    iSighted |= bits_COND_SEE_CLIENT;

                pSightEnt->m_pLink = m_pLink;
                m_pLink = pSightEnt;

                if (pSightEnt == m_hEnemy)
                    iSighted |= bits_COND_SEE_ENEMY;

                switch (IRelationship(pSightEnt))
                {
                case R_NM:
                    iSighted |= bits_COND_SEE_NEMESIS;
                    break;
                case R_HT:
                    iSighted |= bits_COND_SEE_HATE;
                    break;
                case R_DL:
                    iSighted |= bits_COND_SEE_DISLIKE;
                    break;
                case R_FR:
                    iSighted |= bits_COND_SEE_FEAR;
                    break;
                case R_AL:
                    break;
                }
            }
        }
    }

    SetConditions(iSighted);
}
Esempio n. 9
0
//-----------------------------------------------------------------------------
// Purpose: Try to greet player first time he's seen
// Output : int
//-----------------------------------------------------------------------------
int CNPCSimpleTalker::FIdleHello( void )
{
	// Filter might be preventing us from ever greeting the player
	if ( !CanSayHello() )
		return false;

	// get a player
	CBaseEntity *pPlayer = FindNearestFriend(true);

	if (pPlayer)
	{
		if (FInViewCone(pPlayer) && FVisible(pPlayer))
		{
			SayHelloToPlayer( pPlayer );
			return true;
		}
	}

	return false;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CNPC_SecobModportal1::CanBeAnEnemyOf( CBaseEntity *pEnemy )
{
	static const float flFullFov = cos( DEG2RAD(360) / 2.0 );
	if ( fabsf( m_flFieldOfView - flFullFov ) > .01 )
	{
		if ( !FInViewCone( pEnemy ) )
		{
			return false;
		}
	}

	if ( m_flMinDistValidEnemy > 0 )
	{
		float distSq = ( GetAbsOrigin().AsVector2D() - pEnemy->GetAbsOrigin().AsVector2D() ).LengthSqr();
		if ( distSq < Square( m_flMinDistValidEnemy ) )
		{
			return false;
		}
	}
	return BaseClass::CanBeAnEnemyOf( pEnemy );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CNPC_Combine_Cannon::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC )
{
	Disposition_t disp = IRelationType(pEntity);
	if ( disp != D_HT )
	{
		// Don't bother with anything I wouldn't shoot.
		return false;
	}

	if ( !FInViewCone(pEntity) )
	{
		// Yes, this does call FInViewCone twice a frame for all entities checked for 
		// visibility, but doing this allows us to cut out a bunch of traces that would
		// be done by VerifyShot for entities that aren't even in our viewcone.
		return false;
	}

	if ( VerifyShot( pEntity ) )
		return BaseClass::QuerySeeEntity( pEntity, bOnlyHateOrFearIfNPC );

	return false;
}
//=========================================================
// follower boids execute this code when flocking
//=========================================================
void CFlockingFlyer :: FlockFollowerThink( void )	
{
	TraceResult		tr;
	Vector			vecDist;
	Vector			vecDir;
	Vector			vecDirToLeader;
	float			flDistToLeader;

	pev->nextthink = gpGlobals->time + 0.1;

	if ( IsLeader() || !InSquad() )
	{
		// the leader has been killed and this flyer suddenly finds himself the leader. 
		SetThink ( &CFlockingFlyer::FlockLeaderThink );
		return;
	}

	vecDirToLeader = ( m_pSquadLeader->pev->origin - pev->origin );
	flDistToLeader = vecDirToLeader.Length();
	
	// match heading with leader
	pev->angles = m_pSquadLeader->pev->angles;

	//
	// We can see the leader, so try to catch up to it
	//
	if ( FInViewCone ( m_pSquadLeader ) )
	{
		// if we're too far away, speed up
		if ( flDistToLeader > AFLOCK_TOO_FAR )
		{
			m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 1.5;
		}

		// if we're too close, slow down
		else if ( flDistToLeader < AFLOCK_TOO_CLOSE )
		{
			m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5;
		}
	}
	else
	{
		// wait up! the leader isn't out in front, so we slow down to let him pass
		m_flGoalSpeed = m_pSquadLeader->pev->velocity.Length() * 0.5;
	}

	SpreadFlock2();

	pev->speed = pev->velocity.Length();
	pev->velocity = pev->velocity.Normalize();

	// if we are too far from leader, average a vector towards it into our current velocity
	if ( flDistToLeader > AFLOCK_TOO_FAR )
	{
		vecDirToLeader = vecDirToLeader.Normalize();
		pev->velocity = (pev->velocity + vecDirToLeader) * 0.5; 	
	}

	// clamp speeds and handle acceleration
	if ( m_flGoalSpeed > AFLOCK_FLY_SPEED * 2 )
	{
		m_flGoalSpeed  = AFLOCK_FLY_SPEED * 2;
	}

	if ( pev->speed < m_flGoalSpeed )
	{
		pev->speed += AFLOCK_ACCELERATE;
	}
	else if ( pev->speed > m_flGoalSpeed )
	{
		pev->speed -= AFLOCK_ACCELERATE;
	}

	pev->velocity = pev->velocity * pev->speed;

	BoidAdvanceFrame( );
}
Esempio n. 13
0
//=========================================================
// Look - Base class monster function to find enemies or 
// food by sight. iDistance is distance ( in units ) that the 
// monster can see.
//
// Sets the sight bits of the m_afConditions mask to indicate
// which types of entities were sighted.
// Function also sets the Looker's m_pLink 
// to the head of a link list that contains all visible ents.
// (linked via each ent's m_pLink field)
//
//=========================================================
void CBaseMonster :: Look ( int iDistance )
{
	int	iSighted = 0;

	// DON'T let visibility information from last frame sit around!
	ClearConditions(bits_COND_SEE_HATE | bits_COND_SEE_DISLIKE | bits_COND_SEE_ENEMY | bits_COND_SEE_FEAR | bits_COND_SEE_NEMESIS | bits_COND_SEE_CLIENT);

	m_pLink = NULL;

	CBaseEntity	*pSightEnt = NULL;// the current visible entity that we're dealing with

	CBaseEntity *pList[100];

	Vector delta = Vector( iDistance, iDistance, iDistance );

	// Find only monsters/clients in box, NOT limited to PVS
	int count = UTIL_EntitiesInBox( pList, 100, pev->origin - delta, pev->origin + delta, FL_CLIENT|FL_MONSTER );
	for ( int i = 0; i < count; i++ )
	{
		pSightEnt = pList[i];
		if ( pSightEnt != this && pSightEnt->pev->health > 0 )
		{
			// the looker will want to consider this entity
			// don't check anything else about an entity that can't be seen, or an entity that you don't care about.
			if ( IRelationship( pSightEnt ) != R_NO && FInViewCone( pSightEnt ) && !FBitSet( pSightEnt->pev->flags, FL_NOTARGET ) && FVisible( pSightEnt ) )
			{
				if ( pSightEnt->IsPlayer() )
				{
					// if we see a client, remember that (mostly for scripted AI)
					iSighted |= bits_COND_SEE_CLIENT;
				}

				pSightEnt->m_pLink = m_pLink;
				m_pLink = pSightEnt;

				if ( pSightEnt == m_hEnemy )
				{
					// we know this ent is visible, so if it also happens to be our enemy, store that now.
					iSighted |= bits_COND_SEE_ENEMY;
				}

				// don't add the Enemy's relationship to the conditions. We only want to worry about conditions when
				// we see monsters other than the Enemy.
				switch ( IRelationship ( pSightEnt ) )
				{
				case	R_NM:
					iSighted |= bits_COND_SEE_NEMESIS;		
					break;
				case	R_HT:		
					iSighted |= bits_COND_SEE_HATE;		
					break;
				case	R_DL:
					iSighted |= bits_COND_SEE_DISLIKE;
					break;
				case	R_FR:
					iSighted |= bits_COND_SEE_FEAR;
					break;
				case    R_AL:
					break;
				default:
					ALERT ( at_aiconsole, "%s can't assess %s\n", STRING(pev->classname), STRING(pSightEnt->pev->classname ) );
					break;
				}
			}
		}
	}
	
	SetConditions( iSighted );
}
Esempio n. 14
0
void CBaseTurret::ActiveThink(void)
{
	int fAttack = 0;
	Vector vecDirToEnemy;

	SetNextThink( gpGlobals->curtime + 0.1f );
	StudioFrameAdvance( );

	if ((!m_iOn) || (GetEnemy() == NULL))
	{
		SetEnemy( NULL );
		m_flLastSight = gpGlobals->curtime + m_flMaxWait;
		SetThink(SearchThink);
		return;
	}
	
	// if it's dead, look for something new
	if ( !GetEnemy()->IsAlive() )
	{
		if (!m_flLastSight)
		{
			m_flLastSight = gpGlobals->curtime + 0.5; // continue-shooting timeout
		}
		else
		{
			if (gpGlobals->curtime > m_flLastSight)
			{	
				SetEnemy( NULL );
				m_flLastSight = gpGlobals->curtime + m_flMaxWait;
				SetThink(SearchThink);
				return;
			}
		}
	}

	Vector vecMid = EyePosition( );
	Vector vecMidEnemy = GetEnemy()->BodyTarget(vecMid);

	// g_pEffects->Sparks( vecMid );
	// g_pEffects->Sparks( vecMidEnemy );

	// Look for our current enemy
	//int fEnemyVisible = FBoxVisible( this, GetEnemy(), vecMidEnemy );	
	int fEnemyVisible = FInViewCone( GetEnemy() ) && FVisible( GetEnemy() );	

	vecDirToEnemy = vecMidEnemy - vecMid;	// calculate dir and dist to enemy
	// NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.1 );
	
	float flDistToEnemy = vecDirToEnemy.Length();

	QAngle vecAnglesToEnemy;
	VectorNormalize( vecDirToEnemy );
	VectorAngles( vecDirToEnemy, vecAnglesToEnemy );

	// Current enmey is not visible.
	if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE))
	{
		// DevMsg( "lost you\n" );

		if (!m_flLastSight)
		{
			m_flLastSight = gpGlobals->curtime + 0.5;
		}
		else
		{
			// Should we look for a new target?
			if (gpGlobals->curtime > m_flLastSight)
			{
				ClearEnemyMemory();
				SetEnemy( NULL );
				m_flLastSight = gpGlobals->curtime + m_flMaxWait;
				SetThink(SearchThink);
				return;
			}
		}
		fEnemyVisible = 0;
	}
	else
	{
		m_vecLastSight = vecMidEnemy;
	}

	Vector vecLOS = vecDirToEnemy; //vecMid - m_vecLastSight;
	VectorNormalize( vecLOS );

	Vector vecMuzzle, vecMuzzleDir;
	QAngle vecMuzzleAng;
	GetAttachment( "eyes", vecMuzzle, vecMuzzleAng );

	AngleVectors( vecMuzzleAng, &vecMuzzleDir );
	
	// Is the Gun looking at the target
	if (DotProduct(vecLOS, vecMuzzleDir) <= 0.9848) // 10 degree slop
	{
		fAttack = FALSE;
	}
	else
	{
		fAttack = TRUE;
	}

	// fire the gun
	if (fAttack || m_fBeserk)
	{
		m_Activity = ACT_RESET;
		SetActivity( (Activity)ACT_TURRET_FIRE );
		Shoot(vecMuzzle, vecMuzzleDir );
	} 
	else
	{
		SetActivity( (Activity)ACT_TURRET_OPEN_IDLE );
	}

	//move the gun
	if (m_fBeserk)
	{
		// DevMsg( "berserk" );

		if (random->RandomInt(0,9) == 0)
		{
			m_vecGoalAngles.y = random->RandomFloat(-180,180);
			m_vecGoalAngles.x = random->RandomFloat(-90,90);
			OnTakeDamage( CTakeDamageInfo( this, this, 1, DMG_GENERIC ) ); // don't beserk forever
			return;
		}
	} 
	else if (fEnemyVisible)
	{
		// DevMsg( "->[%.2f]\n", vec.x);
		m_vecGoalAngles.y = vecAnglesToEnemy.y;
		m_vecGoalAngles.x = vecAnglesToEnemy.x;

	}

	MoveTurret();
}
Esempio n. 15
0
bool CBaseBot::FindEnemy()
{
   // check if the health is decreased
   bool fHealthDecreased = m_iPrevHealth > GetHealth();
   m_iPrevHealth = GetHealth(); // store away the current health value

   float cur_dist;

   if (m_pEnemy && (!m_pEnemy->IsValid() || !m_pEnemy->IsAlive()))
      m_pEnemy = NULL; // null out the enemy pointer as it's no longer valid

   Vector                vecHisPos;
   unsigned char         cHit;

   // see if we can still see the current enemy...
   if (m_pEnemy) {
      if (FBoxVisible(m_pEnemy, &vecHisPos, &cHit)) {
         m_vecEnemy = vecHisPos;
         m_ucVisibility = cHit;
      } else {
         m_pEnemy = NULL; // we can no longer see this enemy
      }
   }

   // if we already have an enemy...
   if (m_pEnemy) {
      // don't discard important enemies (bomb/flag/hostage carrier, VIP, etc)
      if (g_pServer->ClientIsImportant(EnemyClient()))
         return false;
      // calculate the distance to the enemy
      cur_dist = (m_pEnemy->GetOrigin() - GetOrigin()).Length();
   } else {
      cur_dist = FLT_MAX; // just some crazy value
   }

   // loop through all the clients...
   for (int i = 0; i < g_pServer->GetMaxClients(); i++) {
      if (i == entindex() - 1 || (m_pEnemy && i == m_pEnemy->entindex() - 1))
         continue; // skip myself and the current enemy

      CClient *pClient = g_pServer->m_rgpClients[i];
      if (!pClient || !pClient->IsValid() || !pClient->IsAlive())
         continue;

      float dist = (pClient->GetOrigin() - GetOrigin()).Length();

      // if this enemy is further away than the current one...
      if (dist > cur_dist && !g_pServer->ClientIsImportant(pClient))
         continue; // skip it

      if (dist > 900 + 4000 * ((GetDifficulty() - 1) / 4.0))
         continue; // enemy is too far

      if (g_pServer->IsTeamplay() && GetTeam() == g_pServer->GetTeam(pClient))
         continue; // skip our teammates

      float fov;

      // if the bot's health decreased or the enemy is shooting
      if (!m_pEnemy && (fHealthDecreased || pClient->IsShooting()))
         fov = 360;
      else
         fov = GetFov() * 2 - (GetFov() - (dist > GetFov() * 9 ? GetFov() * 9 : dist) / 9);

      // check if enemy is in the view cone
      if (!FInViewCone(pClient, fov))
         continue; // enemy isn't in bot's view cone

      // check if enemy is visible
      if (!FBoxVisible(pClient, &vecHisPos, &cHit)) {
         continue; // skip this enemy
      }

      // if the enemy is quite far away, not shooting and the bot is not damaged
      if (!m_pEnemy && dist > 200 && !fHealthDecreased && !pClient->IsShooting()) {
         // if the bot isn't in the fov of the enemy and the bot doesn't really want to fight
         if (!pClient->FInViewCone(this, 120) /*&& BotWantsToRetreat()*/)
            continue; // skip this enemy
      }

      m_pEnemy = pClient; // found a new enemy
      m_vecEnemy = vecHisPos;
      m_ucVisibility = cHit;

      DebugMsg(DEBUG_BOTCOMBAT, "Found new enemy: %s", m_pEnemy->GetNetName());

      return true;
   }

   return false; // no new enemy is found
}
Esempio n. 16
0
//=========================================================
// GetSchedule 
//=========================================================
int CNPC_Bullsquid::SelectSchedule( void )
{
	switch	( m_NPCState )
	{
	case NPC_STATE_ALERT:
		{
			if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) )
			{
				return SCHED_SQUID_HURTHOP;
			}

			if ( HasCondition( COND_SQUID_SMELL_FOOD ) )
			{
				CSound		*pSound;

				pSound = GetBestScent();
				
				if ( pSound && (!FInViewCone ( pSound->GetSoundOrigin() ) || !FVisible ( pSound->GetSoundOrigin() )) )
				{
					// scent is behind or occluded
					return SCHED_SQUID_SNIFF_AND_EAT;
				}

				// food is right out in the open. Just go get it.
				return SCHED_SQUID_EAT;
			}

			if ( HasCondition( COND_SMELL ) )
			{
				// there's something stinky. 
				CSound		*pSound;

				pSound = GetBestScent();
				if ( pSound )
					return SCHED_SQUID_WALLOW;
			}

			break;
		}
	case NPC_STATE_COMBAT:
		{
// dead enemy
			if ( HasCondition( COND_ENEMY_DEAD ) )
			{
				// call base class, all code to handle dead enemies is centralized there.
				return BaseClass::SelectSchedule();
			}

			if ( HasCondition( COND_NEW_ENEMY ) )
			{
				if ( m_fCanThreatDisplay && IRelationType( GetEnemy() ) == D_HT && FClassnameIs( GetEnemy(), "monster_headcrab" ) )
				{
					// this means squid sees a headcrab!
					m_fCanThreatDisplay = FALSE;// only do the headcrab dance once per lifetime.
					return SCHED_SQUID_SEECRAB;
				}
				else
				{
					return SCHED_WAKE_ANGRY;
				}
			}

			if ( HasCondition( COND_SQUID_SMELL_FOOD ) )
			{
				CSound		*pSound;

				pSound = GetBestScent();
				
				if ( pSound && (!FInViewCone ( pSound->GetSoundOrigin() ) || !FVisible ( pSound->GetSoundOrigin() )) )
				{
					// scent is behind or occluded
					return SCHED_SQUID_SNIFF_AND_EAT;
				}

				// food is right out in the open. Just go get it.
				return SCHED_SQUID_EAT;
			}

			if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) )
			{
				return SCHED_RANGE_ATTACK1;
			}

			if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) )
			{
				return SCHED_MELEE_ATTACK1;
			}

			if ( HasCondition( COND_CAN_MELEE_ATTACK2 ) )
			{
				return SCHED_MELEE_ATTACK2;
			}
			
			return SCHED_CHASE_ENEMY;

			break;
		}
	}

	return BaseClass::SelectSchedule();
}
Esempio n. 17
0
//=========================================================
// GetSchedule
//=========================================================
Schedule_t *CBullsquid :: GetSchedule( void )
{
	switch	( m_MonsterState )
	{
	case MONSTERSTATE_ALERT:
		{
			if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE) )
			{
				return GetScheduleOfType ( SCHED_SQUID_HURTHOP );
			}

			if ( HasConditions(bits_COND_SMELL_FOOD) )
			{
				CSound		*pSound;

				pSound = PBestScent();

				if ( pSound && (!FInViewCone ( &pSound->m_vecOrigin ) || !FVisible ( pSound->m_vecOrigin )) )
				{
					// scent is behind or occluded
					return GetScheduleOfType( SCHED_SQUID_SNIFF_AND_EAT );
				}

				// food is right out in the open. Just go get it.
				return GetScheduleOfType( SCHED_SQUID_EAT );
			}

			if ( HasConditions(bits_COND_SMELL) )
			{
				// there's something stinky.
				CSound		*pSound;

				pSound = PBestScent();
				if ( pSound )
					return GetScheduleOfType( SCHED_SQUID_WALLOW);
			}

			break;
		}
	case MONSTERSTATE_COMBAT:
		{
// dead enemy
			if ( HasConditions( bits_COND_ENEMY_DEAD ) )
			{
				// call base class, all code to handle dead enemies is centralized there.
				return CBaseMonster :: GetSchedule();
			}

			if ( HasConditions(bits_COND_NEW_ENEMY) )
			{
				if ( m_fCanThreatDisplay && IRelationship( m_hEnemy ) == R_HT )
				{
					// this means squid sees a headcrab!
					m_fCanThreatDisplay = FALSE;// only do the headcrab dance once per lifetime.
					return GetScheduleOfType ( SCHED_SQUID_SEECRAB );
				}
				else
				{
					return GetScheduleOfType ( SCHED_WAKE_ANGRY );
				}
			}

			if ( HasConditions(bits_COND_SMELL_FOOD) )
			{
				CSound		*pSound;

				pSound = PBestScent();

				if ( pSound && (!FInViewCone ( &pSound->m_vecOrigin ) || !FVisible ( pSound->m_vecOrigin )) )
				{
					// scent is behind or occluded
					return GetScheduleOfType( SCHED_SQUID_SNIFF_AND_EAT );
				}

				// food is right out in the open. Just go get it.
				return GetScheduleOfType( SCHED_SQUID_EAT );
			}

			if ( HasConditions( bits_COND_CAN_RANGE_ATTACK1 ) )
			{
				return GetScheduleOfType ( SCHED_RANGE_ATTACK1 );
			}

			if ( HasConditions( bits_COND_CAN_MELEE_ATTACK1 ) )
			{
				return GetScheduleOfType ( SCHED_MELEE_ATTACK1 );
			}

			if ( HasConditions( bits_COND_CAN_MELEE_ATTACK2 ) )
			{
				return GetScheduleOfType ( SCHED_MELEE_ATTACK2 );
			}

			return GetScheduleOfType ( SCHED_CHASE_ENEMY );

			break;
		}
	}

	return CBaseMonster :: GetSchedule();
}
Esempio n. 18
0
//-----------------------------------------------------------------------------
// Purpose: Allows the turret to fire on targets if they're visible
//-----------------------------------------------------------------------------
void CNPC_CeilingTurret::ActiveThink( void )
{
	//Allow descended classes a chance to do something before the think function
	if ( PreThink( TURRET_ACTIVE ) )
		return;

	//Update our think time
	SetNextThink( gpGlobals->curtime + 0.1f );

	//If we've become inactive, go back to searching
	if ( ( m_bActive == false ) || ( GetEnemy() == NULL ) )
	{
		SetEnemy( NULL );
		SetLastSightTime();
		SetThink( &CNPC_CeilingTurret::SearchThink );
		m_vecGoalAngles = GetAbsAngles();
		return;
	}
	
	//Get our shot positions
	Vector vecMid = EyePosition();
	Vector vecMidEnemy = GetEnemy()->GetAbsOrigin();

	//Store off our last seen location
	UpdateEnemyMemory( GetEnemy(), vecMidEnemy );

	//Look for our current enemy
	bool bEnemyVisible = FInViewCone( GetEnemy() ) && FVisible( GetEnemy() ) && GetEnemy()->IsAlive();

	//Calculate dir and dist to enemy
	Vector	vecDirToEnemy = vecMidEnemy - vecMid;	
	float	flDistToEnemy = VectorNormalize( vecDirToEnemy );

	//We want to look at the enemy's eyes so we don't jitter
	Vector	vecDirToEnemyEyes = GetEnemy()->WorldSpaceCenter() - vecMid;
	VectorNormalize( vecDirToEnemyEyes );

	QAngle vecAnglesToEnemy;
	VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy );

	//Draw debug info
	if ( g_debug_turret_ceiling.GetBool() )
	{
		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( GetEnemy()->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, GetEnemy()->WorldSpaceCenter(), 0, 255, 0, false, 0.05 );

		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( vecMidEnemy, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.05f );
	}

	//Current enemy is not visible
	if ( ( bEnemyVisible == false ) || ( flDistToEnemy > CEILING_TURRET_RANGE ))
	{
		if ( m_flLastSight )
		{
			m_flLastSight = gpGlobals->curtime + 0.5f;
		}
		else if ( gpGlobals->curtime > m_flLastSight )
		{
			// Should we look for a new target?
			ClearEnemyMemory();
			SetEnemy( NULL );
			SetLastSightTime();
			SetThink( &CNPC_CeilingTurret::SearchThink );
			m_vecGoalAngles = GetAbsAngles();
			
			SpinDown();

			return;
		}

		bEnemyVisible = false;
	}

	Vector vecMuzzle, vecMuzzleDir;
	QAngle vecMuzzleAng;
	
	GetAttachment( "eyes", vecMuzzle, vecMuzzleAng );
	AngleVectors( vecMuzzleAng, &vecMuzzleDir );
	
	if ( m_flShotTime < gpGlobals->curtime )
	{
		//Fire the gun
		if ( DotProduct( vecDirToEnemy, vecMuzzleDir ) >= 0.9848 ) // 10 degree slop
		{
			if ( m_spawnflags & SF_CEILING_TURRET_OUT_OF_AMMO )
			{
				SetActivity( (Activity) ACT_CEILING_TURRET_DRYFIRE );
			}
			else
			{
				SetActivity( (Activity) ACT_CEILING_TURRET_FIRE );
			}
			
			//Fire the weapon
			Shoot( vecMuzzle, vecMuzzleDir );
		} 
	}
	else
	{
		SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE );
	}

	//If we can see our enemy, face it
	if ( bEnemyVisible )
	{
		m_vecGoalAngles.y = vecAnglesToEnemy.y;
		m_vecGoalAngles.x = vecAnglesToEnemy.x;
	}

	//Turn to face
	UpdateFacing();
}
//-----------------------------------------------------------------------------
// Purpose: Target doesn't exist or has eluded us, so search for one
//-----------------------------------------------------------------------------
void CNPC_Portal_FloorTurret::SearchThink( void )
{
	//Allow descended classes a chance to do something before the think function
	if ( PreThink( TURRET_SEARCHING ) )
		return;

	SetNextThink( gpGlobals->curtime + 0.05f );

	SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );

	//If our enemy has died, pick a new enemy
	if ( ( GetEnemy() != NULL ) && ( GetEnemy()->IsAlive() == false ) )
	{
		SetEnemy( NULL );
	}

	//Acquire the target
	if ( GetEnemy() == NULL )
	{
		HackFindEnemy();
	}

	LaserOn();

	CBaseEntity *pEnemy = GetEnemy();

	//If we've found a target, spin up the barrel and start to attack
	if ( pEnemy != NULL )
	{
		//Get our shot positions
		Vector vecMid = EyePosition();
		Vector vecMidEnemy = pEnemy->BodyTarget( vecMid );

		//Look for our current enemy
		bool bEnemyInFOV = FInViewCone( pEnemy );
		bool bEnemyVisible = FVisible( pEnemy );

		//Calculate dir and dist to enemy
		Vector	vecDirToEnemy = vecMidEnemy - vecMid;	
		m_flDistToEnemy = VectorNormalize( vecDirToEnemy );

		// If the enemy isn't in the normal fov, check the fov through portals
		CProp_Portal *pPortal = NULL;
		pPortal = FInViewConeThroughPortal( pEnemy );

		if ( pPortal && FVisibleThroughPortal( pPortal, pEnemy ) )
		{
			// Translate our target across the portal
			Vector vecMidEnemyTransformed;
			UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecMidEnemy, vecMidEnemyTransformed );

			//Calculate dir and dist to enemy
			Vector	vecDirToEnemyTransformed = vecMidEnemyTransformed - vecMid;	
			float	flDistToEnemyTransformed = VectorNormalize( vecDirToEnemyTransformed );

			// If it's not visible through normal means or the enemy is closer through the portal, use the translated info
			if ( !bEnemyInFOV || !bEnemyVisible || flDistToEnemyTransformed < m_flDistToEnemy )
			{
				bEnemyInFOV = true;
				bEnemyVisible = true;
				vecMidEnemy = vecMidEnemyTransformed;
				vecDirToEnemy = vecDirToEnemyTransformed;
				m_flDistToEnemy = flDistToEnemyTransformed;
			}
		}

		// Give enemies that are farther away a longer grace period
		float fDistanceRatio = m_flDistToEnemy / PORTAL_FLOOR_TURRET_RANGE;
		m_flShotTime = gpGlobals->curtime + fDistanceRatio * fDistanceRatio * PORTAL_FLOOR_TURRET_MAX_SHOT_DELAY;

		m_flLastSight = 0;
		SetThink( &CNPC_FloorTurret::ActiveThink );
		SetEyeState( TURRET_EYE_SEE_TARGET );

		SpinUp();

		if ( gpGlobals->curtime > m_flNextActivateSoundTime )
		{
			EmitSound( "NPC_FloorTurret.Activate" );
			m_flNextActivateSoundTime = gpGlobals->curtime + 3.0;
		}
		return;
	}

	//Are we out of time and need to retract?
	if ( gpGlobals->curtime > m_flLastSight )
	{
		//Before we retrace, make sure that we are spun down.
		m_flLastSight = 0;
		SetThink( &CNPC_FloorTurret::Retire );
		return;
	}

	//Display that we're scanning
	m_vecGoalAngles.x = GetAbsAngles().x + ( sin( ( m_flLastSight + gpGlobals->curtime * m_fSearchSpeed ) * 1.5f ) * 20.0f );
	m_vecGoalAngles.y = GetAbsAngles().y + ( sin( ( m_flLastSight + gpGlobals->curtime * m_fSearchSpeed ) * 2.5f ) * 20.0f );

	//Turn and ping
	UpdateFacing();
	Ping();

	// Update rope positions
	for ( int iRope = 0; iRope < PORTAL_FLOOR_TURRET_NUM_ROPES; ++iRope )
	{
		if ( m_hRopes[ iRope ] )
		{
			m_hRopes[ iRope ]->EndpointsChanged();
		}
	}
}
void CNPC_Portal_FloorTurret::ActiveThink( void )
{
	LaserOn();

	//Allow descended classes a chance to do something before the think function
	if ( PreThink( TURRET_ACTIVE ) )
		return;

	HackFindEnemy();

	//Update our think time
	SetNextThink( gpGlobals->curtime + 0.1f );

	CBaseEntity *pEnemy = GetEnemy();

	//If we've become inactive, go back to searching
	if ( ( m_bActive == false ) || ( pEnemy == NULL ) )
	{
		SetEnemy( NULL );
		m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT;
		SetThink( &CNPC_FloorTurret::SearchThink );
		m_vecGoalAngles = GetAbsAngles();
		return;
	}

	//Get our shot positions
	Vector vecMid = EyePosition();
	Vector vecMidEnemy = pEnemy->BodyTarget( vecMid );

	// Store off our last seen location so we can suppress it later
	m_vecEnemyLKP = vecMidEnemy;

	//Look for our current enemy
	bool bEnemyInFOV = FInViewCone( pEnemy );
	bool bEnemyVisible = FVisible( pEnemy ) && pEnemy->IsAlive();

	//Calculate dir and dist to enemy
	Vector	vecDirToEnemy = vecMidEnemy - vecMid;	
	m_flDistToEnemy = VectorNormalize( vecDirToEnemy );

	// If the enemy isn't in the normal fov, check the fov through portals
	CProp_Portal *pPortal = NULL;
	if ( pEnemy->IsAlive() )
	{
		pPortal = FInViewConeThroughPortal( pEnemy );

		if ( pPortal && FVisibleThroughPortal( pPortal, pEnemy ) )
		{
			// Translate our target across the portal
			Vector vecMidEnemyTransformed;
			UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecMidEnemy, vecMidEnemyTransformed );

			//Calculate dir and dist to enemy
			Vector	vecDirToEnemyTransformed = vecMidEnemyTransformed - vecMid;	
			float	flDistToEnemyTransformed = VectorNormalize( vecDirToEnemyTransformed );

			// If it's not visible through normal means or the enemy is closer through the portal, use the translated info
			if ( !bEnemyInFOV || !bEnemyVisible || flDistToEnemyTransformed < m_flDistToEnemy )
			{
				bEnemyInFOV = true;
				bEnemyVisible = true;
				vecMidEnemy = vecMidEnemyTransformed;
				vecDirToEnemy = vecDirToEnemyTransformed;
				m_flDistToEnemy = flDistToEnemyTransformed;
			}
			else
			{
				pPortal = NULL;
			}
		}
		else
		{
			pPortal = NULL;
		}
	}

	//Draw debug info
	if ( g_debug_turret.GetBool() )
	{
		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( GetEnemy()->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, GetEnemy()->WorldSpaceCenter(), 0, 255, 0, false, 0.05 );

		NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Cross3D( vecMidEnemy, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 );
		NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.05f );
	}

	//See if they're past our FOV of attack
	if ( bEnemyInFOV == false )
	{
		// Should we look for a new target?
		ClearEnemyMemory();
		SetEnemy( NULL );

		if ( m_spawnflags & SF_FLOOR_TURRET_FASTRETIRE )
		{
			// Retire quickly in this case. (The case where we saw the player, but he hid again).
			m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_SHORT_WAIT;
		}
		else
		{
			m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT;
		}

		SetThink( &CNPC_FloorTurret::SearchThink );
		m_vecGoalAngles = GetAbsAngles();

		SpinDown();

		return;
	}

	//Current enemy is not visible
	if ( ( bEnemyVisible == false ) || ( m_flDistToEnemy > PORTAL_FLOOR_TURRET_RANGE ))
	{
		m_flLastSight = gpGlobals->curtime + 2.0f;

		ClearEnemyMemory();
		SetEnemy( NULL );
		SetThink( &CNPC_FloorTurret::SuppressThink );

		return;
	}

	if ( g_debug_turret.GetBool() )
	{
		Vector vecMuzzle, vecMuzzleDir;

		UpdateMuzzleMatrix();
		MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir );
		MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle );

		// Visualize vertical firing ranges
		for ( int i = 0; i < 4; i++ )
		{
			QAngle angMaxDownPitch = GetAbsAngles();

			switch( i )
			{
			case 0:	angMaxDownPitch.x -= 15; break;
			case 1:	angMaxDownPitch.x += 15; break;
			case 2:	angMaxDownPitch.x -= 25; break;
			case 3:	angMaxDownPitch.x += 25; break;
			default:
				break;
			}

			Vector vecMaxDownPitch;
			AngleVectors( angMaxDownPitch, &vecMaxDownPitch );
			NDebugOverlay::Line( vecMuzzle, vecMuzzle + (vecMaxDownPitch*256), 255, 255, 255, false, 0.1 );
		}
	}

	if ( m_flShotTime < gpGlobals->curtime )
	{
		Vector vecMuzzle, vecMuzzleDir;

		UpdateMuzzleMatrix();
		MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir );
		MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle );

		Vector2D vecDirToEnemy2D = vecDirToEnemy.AsVector2D();
		Vector2D vecMuzzleDir2D = vecMuzzleDir.AsVector2D();

		bool bCanShoot = true;
		float minCos3d = DOT_10DEGREE; // 10 degrees slop

		if ( m_flDistToEnemy < 60.0 )
		{
			vecDirToEnemy2D.NormalizeInPlace();
			vecMuzzleDir2D.NormalizeInPlace();

			bCanShoot = ( vecDirToEnemy2D.Dot(vecMuzzleDir2D) >= DOT_10DEGREE );
			minCos3d = 0.7071; // 45 degrees
		}

		//Fire the gun
		if ( bCanShoot ) // 10 degree slop XY
		{
			float dot3d = DotProduct( vecDirToEnemy, vecMuzzleDir );

			if( m_bOutOfAmmo )
			{
				DryFire();
			}
			else
			{
				if ( dot3d >= minCos3d ) 
				{
					SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );
					SetActivity( (Activity)( ( m_bShootWithBottomBarrels ) ? ( ACT_FLOOR_TURRET_FIRE2 ) : ( ACT_FLOOR_TURRET_FIRE ) ) );

					//Fire the weapon
#if !DISABLE_SHOT
					Shoot( vecMuzzle, vecMuzzleDir, (dot3d < DOT_10DEGREE) );
#endif
				}
			}
		} 
	}
	else
	{
		SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE );
	}

	//If we can see our enemy, face it
	if ( bEnemyVisible )
	{
		//We want to look at the enemy's eyes so we don't jitter
		Vector vEnemyWorldSpaceCenter = pEnemy->WorldSpaceCenter();
		if ( pPortal && pPortal->IsActivedAndLinked() )
		{
			// Translate our target across the portal
			UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vEnemyWorldSpaceCenter, vEnemyWorldSpaceCenter );
		}

		Vector	vecDirToEnemyEyes = vEnemyWorldSpaceCenter - vecMid;
		VectorNormalize( vecDirToEnemyEyes );

		QAngle vecAnglesToEnemy;
		VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy );

		m_vecGoalAngles.y = vecAnglesToEnemy.y;
		m_vecGoalAngles.x = vecAnglesToEnemy.x;
	}

	//Turn to face
	UpdateFacing();
}
Esempio n. 21
0
//-----------------------------------------------------------------------------
// Purpose: Think while actively tracking a target.
//-----------------------------------------------------------------------------
void CNPC_CombineCamera::ActiveThink()
{
	// Allow descended classes a chance to do something before the think function
	if (PreThink(CAMERA_ACTIVE))
		return;

	// No active target, look for suspicious characters.
	CBaseEntity *pTarget = MaintainEnemy();
	if ( !pTarget )
	{
		// Nobody suspicious. Go back to being idle.
		m_hEnemyTarget = NULL;
		EmitSound("NPC_CombineCamera.BecomeIdle");
		SetAngry(false);
		SetThink(&CNPC_CombineCamera::SearchThink);
		SetNextThink( gpGlobals->curtime );
		return;
	}

	// Examine the target until it reaches our inner radius
	if ( pTarget != m_hEnemyTarget )
	{
		Vector vecDelta = pTarget->GetAbsOrigin() - GetAbsOrigin();
		float flDist = vecDelta.Length();
		if ( (flDist < m_nInnerRadius) && FInViewCone(pTarget) )
		{
			m_OnFoundEnemy.Set(pTarget, pTarget, this);

			// If it's a citizen, it's ok. If it's the player, it's not ok.
			if ( pTarget->IsPlayer() )
			{
				SetEyeState(CAMERA_EYE_FOUND_TARGET);

				if (HasSpawnFlags(SF_COMBINE_CAMERA_BECOMEANGRY))
				{
					SetAngry(true);
				}
				else
				{
					EmitSound("NPC_CombineCamera.Active");
				}

				m_OnFoundPlayer.Set(pTarget, pTarget, this);
				m_hEnemyTarget = pTarget;
			}
			else
			{
				SetEyeState(CAMERA_EYE_HAPPY);
				m_flEyeHappyTime = gpGlobals->curtime + 2.0;

				// Now forget about this target forever
				AddEntityRelationship( pTarget, D_NU, 99 );
			}
		}
		else
		{
			// If we get angry automatically, we get un-angry automatically
			if ( HasSpawnFlags(SF_COMBINE_CAMERA_BECOMEANGRY) && m_bAngry )
			{
				SetAngry(false);
			}
			m_hEnemyTarget = NULL;

			// We don't quite see this guy, but we sense him.
			SetEyeState(CAMERA_EYE_SEEKING_TARGET);
		}
	}

	// Update our think time
	SetNextThink( gpGlobals->curtime + 0.1f );

	TrackTarget(pTarget);
	MaintainEye();
}
Esempio n. 22
0
bool CEntity::FInViewCone(CEntity *pEntity, float fov)
{
    Vector v_origin = pEntity->GetOrigin();
    return FInViewCone(&v_origin, fov);
}
Esempio n. 23
0
bool BotFollowUser( bot_t *pBot )
{
   bool user_visible;
   float f_distance;
   edict_t *pEdict = pBot->pEdict;

   Vector vecEnd = pBot->pBotUser->v.origin + pBot->pBotUser->v.view_ofs;

   if (pBot->pEdict->v.waterlevel != 3)  // is bot NOT under water?
      pEdict->v.v_angle.x = 0;  // reset pitch to 0 (level horizontally)

   pEdict->v.v_angle.z = 0;  // reset roll to 0 (straight up and down)

   pEdict->v.angles.x = 0;
   pEdict->v.angles.y = pEdict->v.v_angle.y;
   pEdict->v.angles.z = 0;

   // Stop following when person crouches
   if (!IsAlive( pBot->pBotUser ) || (pBot->pBotUser->v.flags & FL_DUCKING))
   {
      // the bot's user is dead!
      pBot->pBotUser = NULL;
      return FALSE;
   }

   user_visible = FInViewCone( &vecEnd, pEdict ) &&
                  FVisible( vecEnd, pEdict );

   // check if the "user" is still visible or if the user has been visible
   // in the last 5 seconds (or the player just starting "using" the bot)

   if (user_visible || (pBot->f_bot_use_time + 5 > gpGlobals->time))
   {
      if (user_visible)
         pBot->f_bot_use_time = gpGlobals->time;  // reset "last visible time"

      // face the user
      Vector v_user = pBot->pBotUser->v.origin - pEdict->v.origin;
      Vector bot_angles = UTIL_VecToAngles( v_user );

      pEdict->v.ideal_yaw = bot_angles.y;

      BotFixIdealYaw(pEdict);

      f_distance = v_user.Length( );  // how far away is the "user"?

      if (f_distance > 200)      // run if distance to enemy is far
         pBot->f_move_speed = pBot->f_max_speed;
      else if (f_distance > 50)  // walk if distance is closer
         pBot->f_move_speed = pBot->f_max_speed / 2;
      else                     // don't move if close enough
         pBot->f_move_speed = 0.0;

      return TRUE;
   }
   else
   {
      // person to follow has gone out of sight...
      pBot->pBotUser = NULL;

      return FALSE;
   }
}