//=========================================================
// Tracking Hornet hit something
//=========================================================
void CNPC_Hornet::TrackTouch ( CBaseEntity *pOther )
{
	if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) )
	{
		return;
	}

	if ( pOther == GetOwnerEntity() || pOther->GetModelIndex() == GetModelIndex() )
	{// bumped into the guy that shot it.
		//SetSolid( SOLID_NOT );
		return;
	}

	int nRelationship = IRelationType( pOther );
	if ( (nRelationship == D_FR || nRelationship == D_NU || nRelationship == D_LI) )
	{
		// hit something we don't want to hurt, so turn around.
		Vector vecVel = GetAbsVelocity();

		VectorNormalize( vecVel );

		vecVel.x *= -1;
		vecVel.y *= -1;

		SetAbsOrigin( GetAbsOrigin() + vecVel * 4 ); // bounce the hornet off a bit.
		SetAbsVelocity( vecVel * m_flFlySpeed );

		return;
	}

	DieTouch( pOther );
}
예제 #2
0
int CNPC_Vortigaunt::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo )
{
    // don't slash one of your own
    if ( ( inputInfo.GetDamageType() & DMG_SLASH ) && inputInfo.GetAttacker() && IRelationType( inputInfo.GetAttacker() ) == D_NU )
        return 0;

    Remember( bits_MEMORY_PROVOKED );

    return BaseClass::OnTakeDamage_Alive( inputInfo );
}
예제 #3
0
void CAI_PlayerAlly::AlertFriends( CBaseEntity *pKiller )
{
	CBaseEntity *pFriend = NULL;
	int i;

	// for each friend in this bsp...
	for ( i = 0; i < TLK_CFRIENDS; i++ )
	{
		while (pFriend = EnumFriends( pFriend, i, true ))
		{
			CAI_BaseNPC *pNPC = pFriend->MyNPCPointer();
			if ( pNPC->IsAlive() )
			{
				// If a client killed me, make everyone else mad/afraid of him
				if ( pKiller->GetFlags() & FL_CLIENT )
				{
					pNPC->SetSchedule( SCHED_TALKER_BETRAYED );
#ifdef ALLIES_CAN_BE_PROVOKED
					pNPC->Remember( bits_MEMORY_PROVOKED );

					if( IsSelected() )
					{
						PlayerSelect( false );
					}
#endif
				}
				else
				{
					if( IRelationType(pKiller) == D_HT)
					{
						// Killed by an enemy!!!
						CAI_PlayerAlly *pAlly = (CAI_PlayerAlly *)pNPC;
						
						if( pAlly && pAlly->GetExpresser()->CanSpeakConcept( TLK_ALLY_KILLED ) )
						{
							pAlly->Speak( TLK_ALLY_KILLED );
						}
					}
				}
			}
		}
	}
}
예제 #4
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pEntity - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CNPC_CeilingTurret::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker )
{
	CBaseEntity	*pHitEntity = NULL;
	if ( BaseClass::FVisible( pEntity, traceMask, &pHitEntity ) )
		return true;

	// If we hit something that's okay to hit anyway, still fire
	if ( pHitEntity && pHitEntity->MyCombatCharacterPointer() )
	{
		if (IRelationType(pHitEntity) == D_HT)
			return true;
	}

	if (ppBlocker)
	{
		*ppBlocker = pHitEntity;
	}

	return false;
}
예제 #5
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pKiller - 
//-----------------------------------------------------------------------------
void CNPCSimpleTalker::AlertFriends( CBaseEntity *pKiller )
{
	CBaseEntity *pFriend = NULL;
	int i;

	// for each friend in this bsp...
	for ( i = 0; i < TLK_CFRIENDS; i++ )
	{
		while ((pFriend = EnumFriends( pFriend, i, true )) != NULL )
		{
			CAI_BaseNPC *pNPC = pFriend->MyNPCPointer();
			if ( pNPC->IsAlive() )
			{
				// If a client killed me, make everyone else mad/afraid of him
				if ( pKiller->GetFlags() & FL_CLIENT )
				{
					CNPCSimpleTalker*pTalkNPC = (CNPCSimpleTalker *)pFriend;

					if (pTalkNPC && pTalkNPC->IsOkToCombatSpeak())
					{
						// FIXME: need to check CanSpeakConcept?
						pTalkNPC->Speak( TLK_BETRAYED );
					}
				}
				else
				{
					if( IRelationType(pKiller) == D_HT)
					{
						// Killed by an enemy!!!
						CNPCSimpleTalker *pAlly = (CNPCSimpleTalker *)pNPC;
						
						if( pAlly && pAlly->GetExpresser()->CanSpeakConcept( TLK_ALLY_KILLED ) )
						{
							pAlly->Speak( TLK_ALLY_KILLED );
						}
					}
				}
			}
		}
	}
}
예제 #6
0
//-----------------------------------------------------------------------------
// Purpose: Override so can handle LOS to m_pScriptedTarget
// Input  :
// Output :
//-----------------------------------------------------------------------------
bool CNPC_Stalker::InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions )
{
	// --------------------
	// Check for occlusion
	// --------------------
	// Base class version assumes innate weapon position is at eye level
	Vector barrelPos = LaserStartPosition(ownerPos);
	trace_t tr;
	AI_TraceLine( barrelPos, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr);

	if ( tr.fraction == 1.0 )
	{
		return true;
	}

	CBaseEntity *pBE = tr.m_pEnt;
	CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pBE );
	if ( pBE == GetEnemy() )
	{
		return true;
	}
	else if (pBCC) 
	{
		if (IRelationType( pBCC ) == D_HT)
		{
			return true;
		}
		else if (bSetConditions)
		{
			SetCondition(COND_WEAPON_BLOCKED_BY_FRIEND);
		}
	}
	else if (bSetConditions)
	{
		SetCondition(COND_WEAPON_SIGHT_OCCLUDED);
		SetEnemyOccluder(pBE);
	}

	return false;
}
예제 #7
0
//------------------------------------------------------------------------------
bool CNPC_EnemyFinder::ShouldAlwaysThink()
{
	if ( BaseClass::ShouldAlwaysThink() )
		return true;
		
	CBasePlayer *pPlayer = AI_GetSinglePlayer();
	if ( pPlayer && IRelationType( pPlayer ) == D_HT )
	{
		float playerDistSqr = GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() );

		if ( !m_flMaxSearchDist || playerDistSqr <= Square(m_flMaxSearchDist) )
		{
			if ( !FBitSet( m_spawnflags, SF_ENEMY_FINDER_CHECK_VIS) )
				return true;
				
			if ( playerDistSqr <= Square( 50 * 12 ) )
				return true;
		}
	}
	
	return false;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
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;
}
예제 #9
0
void CASW_Parasite::LeapTouch( CBaseEntity *pOther )
{
	m_bMidJump = false;	

	if ( IRelationType( pOther ) == D_HT )
	{
		if (m_bDefanged)
		{
			if ( pOther->m_takedamage != DAMAGE_NO )
			{
				BiteSound();
				TouchDamage( pOther );
				//ClearSchedule( "About to gib self" );
				// gib us
				CTakeDamageInfo info(NULL, NULL, Vector(0,0,0), GetAbsOrigin(), GetHealth() * 2,
						DMG_ACID);
				TakeDamage(info);
				SetSchedule( SCHED_DIE );
				return;
			}
			else
			{
				//ImpactSound();
			}
		}
		// Don't hit if back on ground
		//if ( !( GetFlags() & FL_ONGROUND ) && m_bDefanged)	// if we're defanged, don't infest, just do some combat damage
		//{
	 		
		//}
		//else
		//{
			//ImpactSound();
		//}
	}
	else if( !(GetFlags() & FL_ONGROUND) )
	{
		// Still in the air...
		if( gpGlobals->curtime < m_flIgnoreWorldCollisionTime )
		{
			// Headcrabs try to ignore the world, static props, and friends for a 
			// fraction of a second after they jump. This is because they often brush
			// doorframes or props as they leap, and touching those objects turns off
			// this touch function, which can cause them to hit the player and not bite.
			// A timer probably isn't the best way to fix this, but it's one of our 
			// safer options at this point (sjb).
			return;
		}

		if( !pOther->IsSolid() )
		{
			// Touching a trigger or something.
			return;
		}
	}

	// make sure we're solid
	RemoveSolidFlags( FSOLID_NOT_SOLID );
	// Shut off the touch function.
	SetTouch( &CASW_Parasite::NormalTouch );
	SetThink ( &CASW_Parasite::CallNPCThink );

	SetCollisionGroup( ASW_COLLISION_GROUP_PARASITE );

	// if we hit a marine, infest him and go away
	NormalTouch( pOther );
}
예제 #10
0
int CASW_Harvester::SelectHarvesterCombatSchedule()
{
	int nSched = SelectFlinchSchedule_ASW();
	if ( nSched != SCHED_NONE )
	{
		// if we flinch, push forward the next attack
		float spawn_interval = 2.0f;
		m_flNextAttack = gpGlobals->curtime + spawn_interval;
		return nSched;
	}

	if ( HasCondition(COND_NEW_ENEMY) && gpGlobals->curtime - GetEnemies()->FirstTimeSeen(GetEnemy()) < 2.0 )
	{
		return SCHED_WAKE_ANGRY;
	}
	
	if ( HasCondition( COND_ENEMY_DEAD ) )
	{
		// clear the current (dead) enemy and try to find another.
		SetEnemy( NULL );
		 
		if ( ChooseEnemy() )
		{
			ClearCondition( COND_ENEMY_DEAD );
			return SelectSchedule();
		}

		SetState( NPC_STATE_ALERT );
		return SelectSchedule();
	}
#ifdef ASW_FEARFUL_HARVESTERS
	// If I'm scared of this enemy run away
	if ( IRelationType( GetEnemy() ) == D_FR )
	{
		if (HasCondition( COND_SEE_ENEMY )	|| 
			HasCondition( COND_LIGHT_DAMAGE )|| 
			HasCondition( COND_HEAVY_DAMAGE ))
		{
			FearSound();
			//ClearCommandGoal();
			return SCHED_RUN_FROM_ENEMY;
		}

		// If I've seen the enemy recently, cower. Ignore the time for unforgettable enemies.
		AI_EnemyInfo_t *pMemory = GetEnemies()->Find( GetEnemy() );
		if ( (pMemory && pMemory->bUnforgettable) || (GetEnemyLastTimeSeen() > (gpGlobals->curtime - 5.0)) )
		{
			// If we're facing him, just look ready. Otherwise, face him.
			if ( FInAimCone( GetEnemy()->EyePosition() ) )
				return SCHED_COMBAT_STAND;

			return SCHED_FEAR_FACE;
		}
	}
#endif
	// Check if need to reload
	if ( HasCondition( COND_LOW_PRIMARY_AMMO ) || HasCondition( COND_NO_PRIMARY_AMMO ) )
	{
		return SCHED_HIDE_AND_RELOAD;
	}

#ifdef ASW_FEARFUL_HARVESTERS
	if ( HasCondition(COND_TOO_CLOSE_TO_ATTACK) ) 
		return SCHED_RUN_FROM_ENEMY; //SCHED_BACK_AWAY_FROM_ENEMY;
#endif

	if ( GetShotRegulator()->IsInRestInterval() )
	{
		if ( HasCondition(COND_CAN_RANGE_ATTACK1) )
			return SCHED_COMBAT_FACE;
	}

	// we can see the enemy
	if ( HasCondition(COND_CAN_RANGE_ATTACK1) )
	{
		return SCHED_RANGE_ATTACK1;
	}

	if ( HasCondition(COND_CAN_RANGE_ATTACK2) )
		return SCHED_RANGE_ATTACK2;

	if ( HasCondition(COND_CAN_MELEE_ATTACK1) )
		return SCHED_MELEE_ATTACK1;

	if ( HasCondition(COND_CAN_MELEE_ATTACK2) )
		return SCHED_MELEE_ATTACK2;

	if ( HasCondition(COND_NOT_FACING_ATTACK) )
		return SCHED_COMBAT_FACE;

	// if we're not attacking, then back away
	return SCHED_RUN_FROM_ENEMY;
}
//------------------------------------------------------------------------------
// Purpose : The main think function for the helicopters
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CBaseHelicopter::HelicopterThink( void )
{
	CheckPVSCondition();

	SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );

	// Don't keep this around for more than one frame.
	ClearCondition( COND_ENEMY_DEAD );

	// Animate and dispatch animation events.
	StudioFrameAdvance( );
	DispatchAnimEvents( this );

	PrescheduleThink();

	if ( IsMarkedForDeletion() )
		return;

	ShowDamage( );

	// -----------------------------------------------
	// If AI is disabled, kill any motion and return
	// -----------------------------------------------
	if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI)
	{
		SetAbsVelocity( vec3_origin );
		SetLocalAngularVelocity( vec3_angle );
		SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL );
		return;
	}

	Hunt();

	// Finally, forget dead enemies, or ones we've been told to ignore.
	if( GetEnemy() != NULL && (!GetEnemy()->IsAlive() || GetEnemy()->GetFlags() & FL_NOTARGET || IRelationType( GetEnemy() ) == D_NU ) )
	{
		SetEnemy( NULL );
	}

	HelicopterPostThink();
}
예제 #12
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();
}