Example #1
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
Vector CNPC_Monk::GetActualShootTrajectory( const Vector &shootOrigin )
{
	if( GetEnemy() && GetEnemy()->Classify() == CLASS_ZOMBIE )
	{
		Vector vecShootDir;

		if( m_bPerfectAccuracy || random->RandomInt( 1, monk_headshot_freq.GetInt() ) == 1 )
		{
			vecShootDir = GetEnemy()->HeadTarget( shootOrigin ) - shootOrigin;
		}
		else
		{
			vecShootDir = GetEnemy()->BodyTarget( shootOrigin ) - shootOrigin;
		}

		VectorNormalize( vecShootDir );
		return vecShootDir;
	}

	return BaseClass::GetActualShootTrajectory( shootOrigin );
}
//-----------------------------------------------------------------------------
// Purpose: Fire!
//-----------------------------------------------------------------------------
void CNPC_CeilingTurret::Shoot( const Vector &vecSrc, const Vector &vecDirToEnemy )
{
	if ( m_spawnflags & SF_CEILING_TURRET_OUT_OF_AMMO )
	{
		EmitSound( "NPC_FloorTurret.DryFire");
		EmitSound( "NPC_CeilingTurret.Activate" );

  		if ( RandomFloat( 0, 1 ) > 0.7 )
		{
			m_flShotTime = gpGlobals->curtime + random->RandomFloat( 0.5, 1.5 );
		}
		else
		{
			m_flShotTime = gpGlobals->curtime;
		}
		return;
	}

	FireBulletsInfo_t info;

	if ( GetEnemy() != NULL )
	{
		Vector vecDir = GetActualShootTrajectory( vecSrc );

		info.m_vecSrc = vecSrc;
		info.m_vecDirShooting = vecDir;
		info.m_iTracerFreq = 1;
		info.m_iShots = 1;
		info.m_pAttacker = this;
		info.m_vecSpread = VECTOR_CONE_PRECALCULATED;
		info.m_flDistance = MAX_COORD_RANGE;
		info.m_iAmmoType = m_iAmmoType;
	}
	else
	{
		// Just shoot where you're facing!
		Vector vecMuzzle, vecMuzzleDir;
		QAngle vecMuzzleAng;
		
		info.m_vecSrc = vecSrc;
		info.m_vecDirShooting = vecDirToEnemy;
		info.m_iTracerFreq = 1;
		info.m_iShots = 1;
		info.m_pAttacker = this;
		info.m_vecSpread = GetAttackSpread( NULL, NULL );
		info.m_flDistance = MAX_COORD_RANGE;
		info.m_iAmmoType = m_iAmmoType;
	}

	FireBullets( info );
	EmitSound( "NPC_CeilingTurret.ShotSounds" );
	DoMuzzleFlash();
}
Example #3
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int CNPC_Crow::DrawDebugTextOverlays( void )
{
	int nOffset = BaseClass::DrawDebugTextOverlays();

	if (m_debugOverlays & OVERLAY_TEXT_BIT) 
	{
		char tempstr[512];
		Q_snprintf( tempstr, sizeof( tempstr ), "morale: %d", m_nMorale );
		EntityText( nOffset, tempstr, 0 );
		nOffset++;

		if ( GetEnemy() != NULL )
		{
			Q_snprintf( tempstr, sizeof( tempstr ), "enemy (dist): %s (%g)", GetEnemy()->GetClassname(), ( double )m_flEnemyDist );
			EntityText( nOffset, tempstr, 0 );
			nOffset++;
		}
	}

	return nOffset;
}
Example #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;
}
Example #5
0
void CNPC_Stalker::UpdateAttackBeam( void )
{
	CBaseEntity *pEnemy = GetEnemy();
	// If not burning at a target 
	if (pEnemy)
	{
		if (gpGlobals->curtime > m_fBeamEndTime)
		{
			TaskComplete();
		}
		else 
		{
			Vector enemyLKP = GetEnemyLKP();
			m_vLaserTargetPos = enemyLKP + pEnemy->GetViewOffset();

			// Face my enemy
			GetMotor()->SetIdealYawToTargetAndUpdate( enemyLKP );

			// ---------------------------------------------
			//	Get beam end point
			// ---------------------------------------------
			Vector vecSrc = LaserStartPosition(GetAbsOrigin());
			Vector targetDir = m_vLaserTargetPos - vecSrc;
			VectorNormalize(targetDir);
			// --------------------------------------------------------
			//	If beam position and laser dir are way off, end attack
			// --------------------------------------------------------
			if ( DotProduct(targetDir,m_vLaserDir) < 0.5 )
			{
				TaskComplete();
				return;
			}

			trace_t tr;
			AI_TraceLine( vecSrc, vecSrc + m_vLaserDir * MAX_STALKER_FIRE_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr);
			// ---------------------------------------------
			//  If beam not long enough, stop attacking
			// ---------------------------------------------
			if (tr.fraction == 1.0)
			{
				TaskComplete();
				return;
			}

			CSoundEnt::InsertSound(SOUND_DANGER, tr.endpos, 60, 0.025, this);
		}
	}
	else
	{
		TaskFail(FAIL_NO_ENEMY);
	}
}
Example #6
0
//=========================================================
// RunAI
//=========================================================
void CBaseMonster :: RunAI ( void )
{
	// to test model's eye height
	//UTIL_ParticleEffect ( pev->origin + pev->view_ofs, g_vecZero, 255, 10 );

	// IDLE sound permitted in ALERT state is because monsters were silent in ALERT state. Only play IDLE sound in IDLE state
	// once we have sounds for that state.
	if ( ( m_MonsterState == MONSTERSTATE_IDLE || m_MonsterState == MONSTERSTATE_ALERT ) && RANDOM_LONG(0,99) == 0 && !(pev->flags & SF_MONSTER_GAG) )
	{
		IdleSound();
	}

	if ( m_MonsterState != MONSTERSTATE_NONE	&& 
		 m_MonsterState != MONSTERSTATE_PRONE   && 
		 m_MonsterState != MONSTERSTATE_DEAD )// don't bother with this crap if monster is prone. 
	{
		// collect some sensory Condition information.
		// don't let monsters outside of the player's PVS act up, or most of the interesting
		// things will happen before the player gets there!
		// UPDATE: We now let COMBAT state monsters think and act fully outside of player PVS. This allows the player to leave 
		// an area where monsters are fighting, and the fight will continue.
		if ( !FNullEnt( FIND_CLIENT_IN_PVS( edict() ) ) || ( m_MonsterState == MONSTERSTATE_COMBAT ) )
		{
			Look( m_flDistLook );
			Listen();// check for audible sounds. 

			// now filter conditions.
			ClearConditions( IgnoreConditions() );

			GetEnemy();
		}

		// do these calculations if monster has an enemy.
		if ( m_hEnemy != NULL )
		{
			CheckEnemy( m_hEnemy );
		}

		CheckAmmo();
	}

	FCheckAITrigger();

	PrescheduleThink();

	MaintainSchedule();

	// if the monster didn't use these conditions during the above call to MaintainSchedule() or CheckAITrigger()
	// we throw them out cause we don't want them sitting around through the lifespan of a schedule
	// that doesn't use them. 
	m_afConditions &= ~( bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE );
}
//-----------------------------------------------------------------------------
// Purpose: Handles movement towards the last move target.
// Input  : flInterval - 
//-----------------------------------------------------------------------------
bool CNPC_Controller::OverridePathMove( float flInterval )
{
	CBaseEntity *pMoveTarget = (GetTarget()) ? GetTarget() : GetEnemy();
	Vector waypointDir = GetNavigator()->GetCurWaypointPos() - GetLocalOrigin();

	float flWaypointDist = waypointDir.Length2D();
	VectorNormalize(waypointDir);

	// cut corner?
	if (flWaypointDist < 128)
	{
		if (m_flGroundSpeed > 100)
			m_flGroundSpeed -= 40;
	}
	else
	{
		if (m_flGroundSpeed < 400)
			m_flGroundSpeed += 10;
	}

	m_velocity = m_velocity * 0.8 + m_flGroundSpeed * waypointDir * 0.5;
	SetAbsVelocity( m_velocity );

	// -----------------------------------------------------------------
	// Check route is blocked
	// ------------------------------------------------------------------
	Vector checkPos = GetLocalOrigin() + (waypointDir * (m_flGroundSpeed * flInterval));

	AIMoveTrace_t moveTrace;
	GetMoveProbe()->MoveLimit( NAV_FLY, GetLocalOrigin(), checkPos, MASK_NPCSOLID|CONTENTS_WATER,
		pMoveTarget, &moveTrace);
	if (IsMoveBlocked( moveTrace ))
	{
		TaskFail(FAIL_NO_ROUTE);
		GetNavigator()->ClearGoal();
		return true;
	}

	// ----------------------------------------------
	
	Vector lastPatrolDir = GetNavigator()->GetCurWaypointPos() - GetLocalOrigin();
	
	if ( ProgressFlyPath( flInterval, pMoveTarget, MASK_NPCSOLID, false, 64 ) == AINPP_COMPLETE )
	{
		{
			m_vLastPatrolDir = lastPatrolDir;
			VectorNormalize(m_vLastPatrolDir);
		}
		return true;
	}
	return false;
}
Example #8
0
bool CNPC_Zombine::AllowedToSprint( void )
{
	if ( IsOnFire() )
		return false;
	
	//If you're sprinting then there's no reason to sprint again.
	if ( IsSprinting() )
		return false;

	int iChance = SPRINT_CHANCE_VALUE;

	CHL2_Player *pPlayer = dynamic_cast <CHL2_Player*> ( AI_GetSinglePlayer() );

	if ( pPlayer )
	{
		if ( HL2GameRules()->IsAlyxInDarknessMode() && pPlayer->FlashlightIsOn() == false )
		{
			iChance = SPRINT_CHANCE_VALUE_DARKNESS;
		}

		//Bigger chance of this happening if the player is not looking at the zombie
		if ( pPlayer->FInViewCone( this ) == false )
		{
			iChance *= 2;
		}
	}

	if ( HasGrenade() ) 
	{
		iChance *= 4;
	}

	//Below 25% health they'll always sprint
	if ( ( GetHealth() > GetMaxHealth() * 0.5f ) )
	{
		if ( IsStrategySlotRangeOccupied( SQUAD_SLOT_ZOMBINE_SPRINT1, SQUAD_SLOT_ZOMBINE_SPRINT2 ) == true )
			return false;
		
		if ( random->RandomInt( 0, 100 ) > iChance )
			return false;
		
		if ( m_flSprintRestTime > gpGlobals->curtime )
			return false;
	}

	float flLength = ( GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter() ).Length();

	if ( flLength > MAX_SPRINT_DISTANCE )
		return false;

	return true;
}
Example #9
0
//------------------------------------------------------------------------------
// Purpose : For innate range attack
// Input   :
// Output  :
//------------------------------------------------------------------------------
int CNPC_Vortigaunt::RangeAttack1Conditions( float flDot, float flDist )
{
    if ( GetEnemy() == NULL )
        return( COND_LOST_ENEMY );

    if ( gpGlobals->curtime < m_flNextAttack )
        return COND_NONE;

    if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) )
        return COND_NONE;

    return COND_CAN_RANGE_ATTACK1;
}
Example #10
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flDot - 
//			flDist - 
// Output : int
//-----------------------------------------------------------------------------
int CNPC_AntlionGrub::MeleeAttack1Conditions( float flDot, float flDist )
{
	ClearCondition( COND_ANTLIONGRUB_IN_HEAL_RANGE );

	//If we're outside the heal range, then reset our timer
	if ( flDist > ANTLIONGRUB_HEAL_RANGE )
	{
		m_flNearTime = gpGlobals->curtime + 2.0f;
		return COND_TOO_FAR_TO_ATTACK;
	}
	
	//Otherwise if we've been in range for long enough signal it
	if ( m_flNearTime < gpGlobals->curtime )
	{
		if ( ( m_nHealthReserve > 0 ) && ( GetEnemy()->m_iHealth < GetEnemy()->m_iMaxHealth ) )
		{
			SetCondition( COND_ANTLIONGRUB_IN_HEAL_RANGE );
		}
	}

	return COND_CAN_MELEE_ATTACK1;
}
Example #11
0
//=========================================================
// TakeDamage - overridden for bullsquid so we can keep track
// of how much time has passed since it was last injured
//=========================================================
int CNPC_Bullsquid::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo )
{

#if 0 //Fix later.

	float flDist;
	Vector vecApex, vOffset;

	// if the squid is running, has an enemy, was hurt by the enemy, hasn't been hurt in the last 3 seconds, and isn't too close to the enemy,
	// it will swerve. (whew).
	if ( GetEnemy() != NULL && IsMoving() && pevAttacker == GetEnemy() && gpGlobals->curtime - m_flLastHurtTime > 3 )
	{
		flDist = ( GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).Length2D();
		
		if ( flDist > SQUID_SPRINT_DIST )
		{
			AI_Waypoint_t*	pRoute = GetNavigator()->GetPath()->Route();

			if ( pRoute )
			{
				flDist = ( GetAbsOrigin() - pRoute[ pRoute->iNodeID ].vecLocation ).Length2D();// reusing flDist. 

				if ( GetNavigator()->GetPath()->BuildTriangulationRoute( GetAbsOrigin(), pRoute[ pRoute->iNodeID ].vecLocation, flDist * 0.5, GetEnemy(), &vecApex, &vOffset, NAV_GROUND ) )
				{
					GetNavigator()->PrependWaypoint( vecApex, bits_WP_TO_DETOUR | bits_WP_DONT_SIMPLIFY );
				}
			}
		}
	}
#endif

	if ( !FClassnameIs ( inputInfo.GetAttacker(), "monster_headcrab" ) )
	{
		// don't forget about headcrabs if it was a headcrab that hurt the squid.
		m_flLastHurtTime = gpGlobals->curtime;
	}

	return BaseClass::OnTakeDamage_Alive ( inputInfo );
}
Example #12
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CAI_AssaultBehavior::IsAllowedToDivert( void )
{
	if ( m_hAssaultPoint && m_hAssaultPoint->m_bAllowDiversion )
	{
		if ( m_hAssaultPoint->m_flAllowDiversionRadius == 0.0f || (m_bHitAssaultPoint && GetEnemy() != NULL && GetEnemy()->GetAbsOrigin().DistToSqr(m_hAssaultPoint->GetAbsOrigin()) <= Square(m_hAssaultPoint->m_flAllowDiversionRadius)) ) 
		{
			if ( m_flLastSawAnEnemyAt && ((gpGlobals->curtime - m_flLastSawAnEnemyAt) < ASSAULT_DIVERSION_TIME) )
				return true;
		}
	}

	return false;
}
Example #13
0
int CASW_Harvester::TranslateSchedule( int scheduleType )
{
	if ( scheduleType == SCHED_RANGE_ATTACK1 )
	{
		RemoveAllGestures();
		return SCHED_ASW_HARVESTER_LAY_CRITTER;
	}

	if ( scheduleType == SCHED_COMBAT_FACE && IsUnreachable( GetEnemy() ) )
		return SCHED_TAKE_COVER_FROM_ENEMY;

	return BaseClass::TranslateSchedule( scheduleType );
}
Example #14
0
//=========================================================
// CheckMeleeAttack1 - alien grunts zap the crap out of 
// any enemy that gets too close. 
//=========================================================
int CNPC_AlienGrunt::MeleeAttack1Conditions ( float flDot, float flDist )
{
	if ( flDist > AGRUNT_MELEE_DIST )
		 return COND_NONE;

	if ( flDot < 0.6 )
		 return COND_NONE;

	if ( HasCondition ( COND_SEE_ENEMY ) && GetEnemy() != NULL )
		 return COND_CAN_MELEE_ATTACK1;

	return COND_NONE;
}
Example #15
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : flDot - 
//			flDist - 
// Output : int CNPC_Assassin::MeleeAttack1Conditions
//-----------------------------------------------------------------------------
int CNPC_Assassin::MeleeAttack1Conditions ( float flDot, float flDist )
{
	if ( flDist > 84 )
		return COND_TOO_FAR_TO_ATTACK;
	
	if ( flDot < 0.7f )
		return 0;

	if ( GetEnemy() == NULL )
		return 0;

	return COND_CAN_MELEE_ATTACK1;
}
Example #16
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CUnitBase::AimGun()
{
	if( GetEnemy() )
	{
		Vector vecShootOrigin = Weapon_ShootPosition();
		Vector vecShootDir = GetShootEnemyDir( vecShootOrigin, false );
		SetAim(vecShootDir);
	}
	else
	{
		RelaxAim();
	}
}
Example #17
0
//=========================================================
// Start task - selects the correct activity and performs
// any necessary calculations to start the next task on the
// schedule.  OVERRIDDEN for bullsquid because it needs to
// know explicitly when the last attempt to chase the enemy
// failed, since that impacts its attack choices.
//=========================================================
void CNPC_Bullsquid::StartTask ( const Task_t *pTask )
{
	switch ( pTask->iTask )
	{
	case TASK_MELEE_ATTACK2:
		{
			CPASAttenuationFilter filter( this );
			EmitSound( filter, entindex(), "Bullsquid.Growl" );		
			BaseClass::StartTask ( pTask );
			break;
		}
	case TASK_SQUID_HOPTURN:
		{
			SetActivity ( ACT_HOP );
			
			if ( GetEnemy() )
			{
				Vector	vecFacing = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() );
				VectorNormalize( vecFacing );

				GetMotor()->SetIdealYaw( vecFacing );
			}

			break;
		}
	case TASK_SQUID_EAT:
		{
			m_flHungryTime = gpGlobals->curtime + pTask->flTaskData;
			break;
		}

	default:
		{
			BaseClass::StartTask ( pTask );
			break;
		}
	}
}
Example #18
0
int CNPC_HL1Barney::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo )
{
	// make sure friends talk about it if player hurts talkmonsters...
	int ret = BaseClass::OnTakeDamage_Alive( inputInfo );
	
	if ( !IsAlive() || m_lifeState == LIFE_DYING )
		  return ret;

	if ( m_NPCState != NPC_STATE_PRONE && ( inputInfo.GetAttacker()->GetFlags() & FL_CLIENT ) )
	{
		// This is a heurstic to determine if the player intended to harm me
		// If I have an enemy, we can't establish intent (may just be crossfire)
		if ( GetEnemy() == NULL )
		{
			// If the player was facing directly at me, or I'm already suspicious, get mad
			if ( HasMemory( bits_MEMORY_SUSPICIOUS ) || IsFacing( inputInfo.GetAttacker(), GetAbsOrigin() ) )
			{
				// Alright, now I'm pissed!
				Speak( BA_MAD );

				Remember( bits_MEMORY_PROVOKED );
				StopFollowing();
			}
			else
			{
				// Hey, be careful with that
				Speak( BA_SHOT );
				Remember( bits_MEMORY_SUSPICIOUS );
			}
		}
		else if ( !(GetEnemy()->IsPlayer()) && m_lifeState == LIFE_ALIVE )
		{
			Speak( BA_SHOT );
		}
	}

	return ret;
}
Example #19
0
bool rvMonsterStroggHover::MarkerPosValid ( void )
{
	//debouncer ftw
	if( markerCheckTime > gameLocal.GetTime() )	{
		return true;
	}

	markerCheckTime = gameLocal.GetTime() + 500 + (gameLocal.random.RandomFloat() * 500);

	trace_t trace;
	gameLocal.TracePoint( this, trace, marker.GetEntity()->GetPhysics()->GetOrigin(), marker.GetEntity()->GetPhysics()->GetOrigin(), GetPhysics()->GetClipMask(), NULL );
	if ( !(trace.c.contents&GetPhysics()->GetClipMask()) )
	{//not in solid
		gameLocal.TracePoint( this, trace, marker.GetEntity()->GetPhysics()->GetOrigin(), GetEnemy()->GetEyePosition(), MASK_SHOT_BOUNDINGBOX, GetEnemy() );
		idActor* enemyAct = NULL;
		rvVehicle* enemyVeh = NULL;
		if ( GetEnemy()->IsType( rvVehicle::GetClassType() ) ) {
			enemyVeh = static_cast<rvVehicle*>(GetEnemy());
		} else if ( GetEnemy()->IsType( idActor::GetClassType() ) ) {
			enemyAct = static_cast<idActor*>(GetEnemy());
		}
		idEntity* hitEnt = gameLocal.entities[trace.c.entityNum];
		idActor* hitAct = NULL;
		if ( hitEnt && hitEnt->IsType( idActor::GetClassType() ) ) {
			hitAct = static_cast<idActor*>(hitEnt);
		}
		if ( trace.fraction >= 1.0f 
			|| (enemyAct && enemyAct->IsInVehicle() && enemyAct->GetVehicleController().GetVehicle() == gameLocal.entities[trace.c.entityNum])
			|| (enemyVeh && hitAct && hitAct->IsInVehicle() && hitAct->GetVehicleController().GetVehicle() == enemyVeh) )
		{//have a clear LOS to enemy
			if ( PointReachableAreaNum( marker.GetEntity()->GetPhysics()->GetOrigin() ) )
			{//valid AAS there...
				return true;
			}
		}
	}
	return false;
}
Example #20
0
//-----------------------------------------------------------------------------
// Purpose: Causes the assassin to prefer to run away, rather than towards her target
//-----------------------------------------------------------------------------
bool CNPC_Assassin::MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost )
{
	if ( GetEnemy() == NULL )
		return true;

	float	multiplier = 1.0f;

	Vector	moveDir = ( vecEnd - vecStart );
	VectorNormalize( moveDir );

	Vector	enemyDir = ( GetEnemy()->GetAbsOrigin() - vecStart );
	VectorNormalize( enemyDir );

	// If we're moving towards our enemy, then the cost is much higher than normal
	if ( DotProduct( enemyDir, moveDir ) > 0.5f )
	{
		multiplier = 16.0f;
	}

	*pCost *= multiplier;

	return ( multiplier != 1 );
}
//------------------------------------------------------------------------------
// Purpose: determines if we can use this behavior currently
// Output : returns true if this behavior is able to run
//------------------------------------------------------------------------------
bool CAI_ASW_PrepareToEngageBehavior::CanSelectSchedule()
{
    if ( !GetOuter()->IsInterruptable() )
        return false;

    if ( GetEnemy() == NULL )
        return false;

    if ( GetEnemy()->Classify() != CLASS_ASW_MARINE )
        return false;

    // don't select this schedule if we're in a target slot and can actually attack
    //CASW_Marine *pMarine = assert_cast<CASW_Marine*>( GetEnemy() );
    //CASW_Alien *pAlien = assert_cast<CASW_Alien*>( GetOuter() );
    //if ( pMarine->IsInTargetSlot( pAlien, pAlien->GetTargetSlotType() ) )
    //return false;

    // TODO: Do we want to grab a target slot here?  This assumes our attack/chase schedules are higher priority than anything else below us...
    //if ( pMarine->OccupyTargetSlot( pAlien, pAlien->GetTargetSlotType() ) )
    //return false;

    return BaseClass::CanSelectSchedule();
}
//-----------------------------------------------------------------------------
// Purpose: override/translate a schedule by type
// Input  : Type - schedule type
// Output : int - translated type
//-----------------------------------------------------------------------------
int CNPC_Bug_Warrior::TranslateSchedule( int scheduleType ) 
{
	if ( scheduleType == SCHED_CHASE_ENEMY ) 
	{
		// Tell my squad that I'm attacking this guy
		if ( m_pSquad )
		{
			m_pSquad->BroadcastInteraction( g_interactionBugSquadAttacking, (void *)GetEnemy(), this );
		}
		return SCHED_WBUG_CHASE_ENEMY;
	}

	return BaseClass::TranslateSchedule(scheduleType);
}
Example #23
0
//-----------------------------------------------------------------------------
// Purpose: 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CAI_AssaultBehavior::CanSelectSchedule()
{
	if ( !GetOuter()->IsInterruptable() )
		return false;

	if ( GetOuter()->HasCondition( COND_RECEIVED_ORDERS ) )
		return false;

	// We're letting other AI run for a little while because the assault AI failed recently.
	if ( m_flTimeDeferScheduleSelection > gpGlobals->curtime )
		return false;

	// No schedule selection if no assault is being conducted.
	if( m_AssaultCue == CUE_NO_ASSAULT )
		return false;

	if ( !m_hAssaultPoint || !m_hRallyPoint )
	{
		Disable();
		return false;
	}

	// Remember when we last saw an enemy
	if ( GetEnemy() )
	{
		m_flLastSawAnEnemyAt = gpGlobals->curtime;
	}

	// If we've seen an enemy in the last few seconds, and we're allowed to divert,
	// let the base AI decide what I should do.
	if ( IsAllowedToDivert() )
	{
		// Return true, but remember that we're actually allowing them to divert
		// This is done because we don't want the assault behaviour to think it's finished with the assault.
		m_bDiverting = true;
	}
	else if ( m_bDiverting )
	{
		// If we were diverting, provoke us to make a new schedule selection
		SetCondition( COND_PROVOKED );

		m_bDiverting = false;
	}

	// If we're diverting, let the base AI decide everything
	if ( m_bDiverting )
		return false;

	return true;
}
//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
bool CAI_ASW_RangedAttackBehavior::FindFiringLocation( )
{
    CBaseEntity *pBestEnt = NULL;
    float flBestDistSq = FLT_MAX;
    AIEnemiesIter_t iter;
    CBaseEntity *pEnemy;

    pEnemy = GetEnemy();

    if ( pEnemy && pEnemy->IsAlive() && GetOuter()->FVisible( pEnemy ) )
    {
        m_hTarget = pEnemy;
        UpdateTargetLocation();
        return true;
    }

    for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) )
    {
        pEnemy = pEMemory->hEnemy;
        if ( !pEnemy || !pEnemy->IsAlive() || !GetOuter()->FVisible( pEnemy ) )
        {
            continue;
        }

        Vector vDelta = GetAbsOrigin() - pEnemy->GetAbsOrigin();

        float flLenSq = vDelta.LengthSqr();
        if ( flLenSq <= flBestDistSq )
        {
            pBestEnt = pEnemy;
            flBestDistSq = flLenSq;
        }
    }

    if ( !pBestEnt )
    {
        // just try shooting at our enemy for now
        if ( pEnemy && pEnemy->IsAlive() )
        {
            UpdateTargetLocation();
            return true;
        }
        return false;
    }

    m_hTarget = pBestEnt;
    GetOuter()->SetEnemy( pBestEnt );
    UpdateTargetLocation();
    return true;
}
/*
================
rvMonsterStroggMarine::CheckAction_SprayAttack
================
*/
bool rvMonsterStroggMarine::CheckAction_SprayAttack ( rvAIAction* action, int animNum )
{
	if ( !enemy.ent || !enemy.fl.inFov ) {
		return false;
	}
	if ( !IsEnemyRecentlyVisible ( ) || enemy.ent->DistanceTo ( enemy.lastKnownPosition ) > 128.0f ) {
		return false;
	}
	if ( GetEnemy()->GetPhysics()->GetLinearVelocity().Compare( vec3_origin ) )
	{//not moving
		return false;
	}
	return true;
}
Example #26
0
void CTibia::ShootMagwall(int nTarget, int nSqm)
{
	SCreature *c = 0;
	switch(nTarget)
	{
	case HotkeyCreature::Self:
		c = (SCreature*)GetPlayer();
		break;
	case HotkeyCreature::Target:
		if(PlayerTarget == 0)
			return;
		c = (SCreature*)GetPlayer(PlayerTarget, true);
		break;
	case HotkeyCreature::Friend:
		c = (SCreature*)GetFriend(100); 
		break;
	case HotkeyCreature::Enemy:
		c = (SCreature*)GetEnemy(100); 
		break;
	}

	SContainerInfo cInfo;
	if(c > 0)
	{
		int x = c->X, y = c->Y;
		switch(c->Direction)
		{
		case Direction::North:
			y = y - nSqm;
			break;
		case Direction::East:
			x = x + nSqm;
			break;
		case Direction::South:
			y = y + nSqm;
			break;
		case Direction::West:
			x = x - nSqm;
			break;
		}
		if(bShootFromClosedBp == true)
		{
			CPacket::UseOnXYZ(Items::MagicwallRune, 0, 0, x, y, c->Z);
		}
		else if(FindItem(Items::MagicwallRune, &cInfo) == true)
		{
			CPacket::UseOnXYZ(Items::MagicwallRune, 0x40 + cInfo.Container, cInfo.Position, x, y, c->Z);
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPC_RocketTurret::SearchThink()
{
	if ( PreThink() || GetEnemy() == NULL )
		return;

	SetSequence ( LookupSequence( "idle" ) );
	UpdateAimPoint();

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

	// Still can't see enemy, zip around frantically
	if ( !m_bHasSightOfEnemy )
	{
		if ( m_flTimeSpentPaused >= m_flPauseLength )
		{
			float flOffsetX = RandomFloat( -5.0f, 5.0f );
			float flOffsetY = RandomFloat( -5.0f, 5.0f );

			if ( fabs(m_flTotalDivergenceX) <= MAX_DIVERGENCE_X || 
				 SignDiffers( m_flTotalDivergenceX, flOffsetX ) )
			{
				m_flTotalDivergenceX += flOffsetX;
				m_vecGoalAngles.x += flOffsetX;
			}

			if ( fabs(m_flTotalDivergenceY) <= MAX_DIVERGENCE_Y ||
				 SignDiffers( m_flTotalDivergenceY, flOffsetY ) )
			{
				m_flTotalDivergenceY += flOffsetY;
				m_vecGoalAngles.y += flOffsetY;
			}

			// Reset pause timer
			m_flTimeSpentPaused = 0.0f;
			m_flPauseLength = RandomFloat( 0.3f, 2.5f );
		}
		m_flTimeSpentPaused += ROCKET_TURRET_THINK_RATE;
	}
	else
	{
		// Found target, go back to following it
		SetThink( &CNPC_RocketTurret::FollowThink );
		SetNextThink( gpGlobals->curtime + ROCKET_TURRET_THINK_RATE );
	}

	// Move beam towards goal angles
	UpdateFacing();
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pTask - 
//-----------------------------------------------------------------------------
void CAI_RappelBehavior::RunTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_RAPPEL:
		{
			// If we don't do this, the beam won't show up sometimes. Ideally, all beams would update their
			// bboxes correctly, but we're close to shipping and we can't change that now.
			if ( m_hLine )
			{
				m_hLine->RelinkBeam();
			}

			if( GetEnemy() )
			{
				// Face the enemy if there's one.
				Vector vecEnemyLKP = GetEnemyLKP();
				GetOuter()->GetMotor()->SetIdealYawToTargetAndUpdate( vecEnemyLKP );
			}

			SetDescentSpeed();
			if( GetOuter()->GetFlags() & FL_ONGROUND )
			{
				CBaseEntity *pGroundEnt = GetOuter()->GetGroundEntity();

				if( pGroundEnt && pGroundEnt->IsPlayer() )
				{
					// try to shove the player in the opposite direction as they are facing (so they'll see me)
					Vector vecForward;
					pGroundEnt->GetVectors( &vecForward, NULL, NULL );
					pGroundEnt->SetAbsVelocity( vecForward * -500 );
					break;
				}

				GetOuter()->m_OnRappelTouchdown.FireOutput( GetOuter(), GetOuter(), 0 );
				GetOuter()->RemoveFlag( FL_FLY );
				
				CutZipline();

				TaskComplete();
			}
		}
		break;

	default:
		BaseClass::RunTask( pTask );
		break;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
Activity CNPC_Monk::NPC_TranslateActivity( Activity eNewActivity )
{
	eNewActivity = BaseClass::NPC_TranslateActivity( eNewActivity );

	if ( (m_NPCState == NPC_STATE_COMBAT || m_NPCState == NPC_STATE_ALERT) )
	{
		bool bGunUp = false;

		bGunUp = (gpGlobals->curtime - m_flLastAttackTime < 4);
		bGunUp = bGunUp || (GetEnemy() && !HasCondition( COND_TOO_FAR_TO_ATTACK ));

		if (bGunUp)
		{
			if ( eNewActivity == ACT_IDLE )
			{
				eNewActivity = ACT_IDLE_ANGRY;
			}
			// keep aiming a little longer than normal since the shot takes so long and there's no good way to do a transitions between movement types :/
			else if ( eNewActivity == ACT_WALK )
			{
				eNewActivity = ACT_WALK_AIM;
			}
			else if ( eNewActivity == ACT_RUN )
			{
				eNewActivity = ACT_RUN_AIM;
			}
		}
	}

	// We need these so that we can pick up the shotgun to throw it in the balcony scene
	if ( eNewActivity == ACT_IDLE_ANGRY_SHOTGUN )
	{
		eNewActivity = ACT_IDLE_ANGRY_SMG1;
	}
	else if ( eNewActivity == ACT_WALK_AIM_SHOTGUN )
	{
		eNewActivity = ACT_WALK_AIM_RIFLE;
	}
	else if ( eNewActivity == ACT_RUN_AIM_SHOTGUN )
	{
		eNewActivity = ACT_RUN_AIM_RIFLE;
	}
	else if ( eNewActivity == ACT_RANGE_ATTACK_SHOTGUN_LOW )
	{
		return ACT_RANGE_ATTACK_SMG1_LOW;
	}

	return eNewActivity;
}
//-----------------------------------------------------------------------------
// Purpose: The turret doesn't run base AI properly, which is a bad decision.
//			As a result, it has to manually find enemies.
//-----------------------------------------------------------------------------
void CNPC_Portal_FloorTurret::HackFindEnemy( void )
{
	// We have to refresh our memories before finding enemies, so
	// dead enemies are cleared out before new ones are added.
	GetEnemies()->RefreshMemories();

	GetSenses()->Look( PORTAL_FLOOR_TURRET_RANGE );
	SetEnemy( BestEnemy() );

	if ( GetEnemy() == NULL )
	{
		// Look through the list of sensed objects for possible targets
		AISightIter_t iter;
		CBaseEntity *pObject;
		CBaseEntity	*pNearest = NULL;
		float flClosestDistSqr = PORTAL_FLOOR_TURRET_RANGE * PORTAL_FLOOR_TURRET_RANGE;

		for ( pObject = GetSenses()->GetFirstSeenEntity( &iter, SEEN_MISC ); pObject; pObject = GetSenses()->GetNextSeenEntity( &iter ) )
		{
			Vector vVelocity;
			pObject->GetVelocity( &vVelocity );

			// Ignore objects going too slowly
			if ( vVelocity.LengthSqr() < m_fMovingTargetThreashold )
				continue;

			float flDistSqr = pObject->WorldSpaceCenter().DistToSqr( GetAbsOrigin() );
			if ( flDistSqr < flClosestDistSqr )
			{
				flClosestDistSqr = flDistSqr;
				pNearest = pObject;
			}
		}

		if ( pNearest )
		{
			SetEnemy( pNearest );
			m_fMovingTargetThreashold += gpGlobals->curtime * 15.0f;
			if ( m_fMovingTargetThreashold > 800.0f )
			{
				m_fMovingTargetThreashold = 800.0f;
			}
		}
	}
	else
	{
		m_fMovingTargetThreashold = 20.0f;
	}
}