int CNPC_Vortigaunt::TranslateSchedule( int scheduleType ) { //Oops can't get to my enemy. if ( scheduleType == SCHED_CHASE_ENEMY_FAILED ) { return SCHED_ESTABLISH_LINE_OF_FIRE; } switch ( scheduleType ) { case SCHED_FAIL: if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) { return ( SCHED_MELEE_ATTACK1 ); } break; case SCHED_RANGE_ATTACK1: { //Adrian - HACK HACK! This should've been done up there ^^^^ if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) { return ( SCHED_MELEE_ATTACK1 ); } return SCHED_VORTIGAUNT_ATTACK; } break; } return BaseClass::TranslateSchedule( scheduleType ); }
//--------------------------------------------------------- //--------------------------------------------------------- int CNPC_Roller::SelectSchedule ( void ) { if( m_fHACKJustSpawned ) { m_fHACKJustSpawned = false; return SCHED_ROLLER_WAIT_FOR_PHYSICS; } switch( m_NPCState ) { case NPC_STATE_COMBAT: if( HasCondition( COND_ROLLER_PHYSICS ) ) { return SCHED_ROLLER_WAIT_FOR_PHYSICS; } break; default: if( HasCondition( COND_ROLLER_PHYSICS ) ) { return SCHED_ROLLER_WAIT_FOR_PHYSICS; } return SCHED_IDLE_STAND; break; } return SCHED_IDLE_STAND; }
//------------------------------------------------------------------------------ // Purpose: routine called to select what schedule we want to run // Output : returns the schedule id of the schedule we want to run //------------------------------------------------------------------------------ int CAI_ASW_ShieldBehavior::SelectSchedule() { if ( !HasCondition( COND_CAN_MELEE_ATTACK2 ) ) { return SCHED_SHIELD_LOWER; } if ( GetBehaviorParam( m_StatusParm ) == 0 ) { return SCHED_SHIELD_PREPARE; } else { return SCHED_SHIELD_MAINTAIN; } #if 0 if ( m_bShieldLowering == true ) { return SCHED_SHIELD_LOWER; } if ( GetBehaviorParam( m_StatusParm ) == 0 ) { return SCHED_SHIELD_PREPARE; } if ( HasCondition( COND_SHIELD_CAN_FLICK ) ) { return SCHED_SHIELD_FLICK; } return SCHED_SHIELD_MAINTAIN; #endif }
int CNPC_Hydra::SelectSchedule () { switch ( m_NPCState ) { case NPC_STATE_IDLE: { SetState( NPC_STATE_ALERT ); return SCHED_HYDRA_DEPLOY; } break; case NPC_STATE_ALERT: { return SCHED_HYDRA_STAB; } break; case NPC_STATE_COMBAT: { if (HasCondition( COND_HYDRA_SNAGGED )) { return SCHED_HYDRA_PULLBACK; } else if (HasCondition( COND_HYDRA_OVERSTRETCH )) { return SCHED_HYDRA_STAB; } return SCHED_HYDRA_STAB; } break; } return BaseClass::SelectSchedule(); }
// note: mostly copied from shover parent (no clean way to call up and extend), with the jump part added int CASW_Alien_Jumper::SelectCombatSchedule( void ) { //Physics target if ( HasCondition( COND_ALIEN_SHOVER_PHYSICS_TARGET ) ) { //Msg("Alien shoving physics object from selectcombatschedule\n"); return SCHED_ALIEN_SHOVER_PHYSICS_ATTACK; } // Attack if we can if ( HasCondition(COND_CAN_MELEE_ATTACK1) ) return SCHED_MELEE_ATTACK1; // See if we can bash what's in our way, or roar if ( HasCondition( COND_ENEMY_UNREACHABLE ) ) { int iUnreach = SelectUnreachableSchedule(); if (iUnreach != -1) return iUnreach; } // Try to jump if ( HasCondition( COND_ASW_ALIEN_CAN_JUMP ) ) return SCHED_ASW_ALIEN_JUMP; return BaseClass::BaseClass::SelectSchedule(); }
//================================================================================ //================================================================================ float CHuntEnemySchedule::GetDesire() const { if ( !GetMemory() || !GetLocomotion() ) return BOT_DESIRE_NONE; if ( !GetDecision()->CanHuntThreat() ) return BOT_DESIRE_NONE; CEntityMemory *memory = GetBot()->GetPrimaryThreat(); if ( memory == NULL ) return BOT_DESIRE_NONE; // We have no vision of the enemy if ( HasCondition( BCOND_ENEMY_LOST ) ) { // But we have a vision of his last position and we are close if ( HasCondition( BCOND_ENEMY_LAST_POSITION_VISIBLE ) && (HasCondition( BCOND_ENEMY_TOO_NEAR ) || HasCondition( BCOND_ENEMY_NEAR )) ) return BOT_DESIRE_NONE; return 0.65f; } // We do not have direct vision to the enemy (a person, window, etc.) if ( HasCondition( BCOND_ENEMY_OCCLUDED ) ) return 0.65f; // We do not have range of attack if ( HasCondition( BCOND_TOO_FAR_TO_ATTACK ) ) return 0.38f; return BOT_DESIRE_NONE; }
NPC_STATE CNPC_Cremator::SelectIdealState( void ) { switch( m_NPCState ) { case NPC_STATE_COMBAT: { if ( GetEnemy() == NULL ) { if ( !HasCondition( COND_ENEMY_DEAD ) ) { SetCondition( COND_ENEMY_DEAD ); // TODO: patrolling } return NPC_STATE_ALERT; } else if ( HasCondition( COND_ENEMY_DEAD ) ) { //AnnounceEnemyKill(GetEnemy()); } } default: { return BaseClass::SelectIdealState(); } } return GetIdealState(); }
int CAI_StandoffBehavior::SelectScheduleUpdateWeapon( void ) { // Check if need to reload if ( HasCondition ( COND_NO_PRIMARY_AMMO ) || HasCondition ( COND_LOW_PRIMARY_AMMO )) { if ( m_params.fCoverOnReload ) return SCHED_HIDE_AND_RELOAD; else return SCHED_RELOAD; } // Otherwise, update planned shots to fire before taking cover again if ( HasCondition( COND_LIGHT_DAMAGE ) ) { // if hurt: int iPercent = random->RandomInt(0,99); if ( iPercent <= m_params.oddsCover && GetEnemy() != NULL ) { SetReuseCurrentCover(); m_ShotRegulator.SetShots( ( m_ShotRegulator.GetShots() > 1 ) ? 1 : 0 ); } } m_ShotRegulator.Update(); return SCHED_NONE; }
int CAI_StandoffBehavior::SelectScheduleUpdateWeapon( void ) { // Check if need to reload if ( HasCondition ( COND_NO_PRIMARY_AMMO ) || HasCondition ( COND_LOW_PRIMARY_AMMO )) { StandoffMsg( "Out of ammo, reloading\n" ); if ( m_params.fCoverOnReload ) { GetOuter()->SpeakSentence( STANDOFF_SENTENCE_OUT_OF_AMMO ); return SCHED_HIDE_AND_RELOAD; } return SCHED_RELOAD; } // Otherwise, update planned shots to fire before taking cover again if ( HasCondition( COND_LIGHT_DAMAGE ) ) { // if hurt: int iPercent = random->RandomInt(0,99); if ( iPercent <= m_params.oddsCover && GetEnemy() != NULL ) { SetReuseCurrentCover(); StandoffMsg( "Hurt, firing one more shot before cover\n" ); if ( !GetOuter()->GetShotRegulator()->IsInRestInterval() ) { GetOuter()->GetShotRegulator()->SetBurstShotsRemaining( 1 ); } } } return SCHED_NONE; }
//--------------------------------------------------------- //--------------------------------------------------------- void CNPC_GroundTurret::GatherConditions() { if( !IsEnabled() ) { return; } if( !IsOpen() && !UTIL_FindClientInPVS( edict() ) ) { return; } // Throw away old enemies so the turret can retire AIEnemiesIter_t iter; for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) { if( pEMemory->timeLastSeen < gpGlobals->curtime - GROUNDTURRET_RETIRE_TIME ) { pEMemory->hEnemy = NULL; } } BaseClass::GatherConditions(); if( GetEnemy() && HasCondition(COND_SEE_ENEMY) ) { m_flTimeLastSawEnemy = gpGlobals->curtime; } else { if( gpGlobals->curtime - m_flTimeLastSawEnemy >= GROUNDTURRET_RETIRE_TIME ) { m_OnAreaClear.FireOutput(this, this); m_flTimeLastSawEnemy = FLT_MAX; return; } } if( HasCondition( COND_SEE_ENEMY ) ) { m_bSeeEnemy = true; } else { m_bSeeEnemy = false; } if( GetEnemy() && m_bSeeEnemy && IsEnabled() ) { if( m_flTimeNextShoot < gpGlobals->curtime ) { Shoot(); } } }
bool CAI_LeadBehavior::CanSelectSchedule() { if ( !AI_GetSinglePlayer() || AI_GetSinglePlayer()->IsDead() ) return false; bool fAttacked = ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ); bool fNonCombat = ( GetNpcState() == NPC_STATE_IDLE || GetNpcState() == NPC_STATE_ALERT ); return ( !fAttacked && (fNonCombat || m_args.bLeadDuringCombat) && HasGoal() ); }
//----------------------------------------------------------------------------- // Purpose: // Input : &vecTarget - // Output : float //----------------------------------------------------------------------------- float CNPC_Bug_Warrior::CalcIdealYaw( const Vector &vecTarget ) { //If we can see our enemy but not reach them, face them always if ( ( GetEnemy() != NULL ) && ( HasCondition( COND_SEE_ENEMY ) && HasCondition( COND_ENEMY_UNREACHABLE ) ) ) { return UTIL_VecToYaw ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ); } return BaseClass::CalcIdealYaw( vecTarget ); }
bool CNPC_Tentacle::HeardAnything( void ) { if ( HasCondition( COND_HEAR_DANGER ) || // I remove a bunch of sounds from here on purpose. Talk to me if you're changing this!(sjb) HasCondition( COND_HEAR_COMBAT ) || HasCondition( COND_HEAR_WORLD ) || HasCondition( COND_HEAR_PLAYER ) ) return true; return false; }
//----------------------------------------------------------------------------- // Purpose: Move the zombie to the vehicle //----------------------------------------------------------------------------- int CAI_PassengerBehaviorZombie::SelectSchedule( void ) { // See if our enemy got out if ( GetOuter()->GetEnemy() != NULL && EnemyInVehicle() == false ) { if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) { // Exit the vehicle SetCondition( COND_PASSENGER_EXITING ); } else if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE ) { // Our target has left the vehicle and we're outside as well, so give up Disable(); return BaseClass::SelectSchedule(); } } // Entering schedule if ( HasCondition( COND_PASSENGER_ENTERING ) ) { ClearCondition( COND_PASSENGER_ENTERING ); return SCHED_PASSENGER_ZOMBIE_ENTER_VEHICLE; } // Exiting schedule if ( HasCondition( COND_PASSENGER_EXITING ) ) { ClearCondition( COND_PASSENGER_EXITING ); return SCHED_PASSENGER_ZOMBIE_EXIT_VEHICLE; } // Select different schedules based on our state PassengerState_e nState = GetPassengerState(); int nNewSchedule = SCHED_NONE; if ( nState == PASSENGER_STATE_INSIDE ) { nNewSchedule = SelectInsideSchedule(); if ( nNewSchedule != SCHED_NONE ) return nNewSchedule; } else if ( nState == PASSENGER_STATE_OUTSIDE ) { nNewSchedule = SelectOutsideSchedule(); if ( nNewSchedule != SCHED_NONE ) return nNewSchedule; } // Worst case he just stands here Assert(0); return SCHED_IDLE_STAND; }
//========================================================= // CheckRangeAttack1 // // !!!LATER - we may want to load balance this. Several // tracelines are done, so we may not want to do this every // server frame. Definitely not while firing. //========================================================= int CNPC_AlienGrunt::RangeAttack1Conditions ( float flDot, float flDist ) { if ( gpGlobals->curtime < m_flNextHornetAttackCheck ) { if ( HasCondition( COND_SEE_ENEMY ) ) { if ( m_fCanHornetAttack == true ) { return COND_CAN_RANGE_ATTACK1; } else { return COND_NONE; } } else return COND_NONE; } if ( flDist < AGRUNT_MELEE_DIST ) return COND_NONE; if ( flDist > 1024 ) return COND_NONE; if ( flDot < 0.5 ) return COND_NONE; if ( HasCondition( COND_SEE_ENEMY ) ) { trace_t tr; Vector vecArmPos; QAngle angArmDir; // verify that a shot fired from the gun will hit the enemy before the world. // !!!LATER - we may wish to do something different for projectile weapons as opposed to instant-hit GetAttachment( "0", vecArmPos, angArmDir ); UTIL_TraceLine( vecArmPos, GetEnemy()->BodyTarget( vecArmPos ), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr); if ( tr.fraction == 1.0 || tr.m_pEnt == GetEnemy() ) { m_flNextHornetAttackCheck = gpGlobals->curtime + random->RandomFloat( 2, 5 ); m_fCanHornetAttack = true; return COND_CAN_RANGE_ATTACK1; } } m_flNextHornetAttackCheck = gpGlobals->curtime + 0.2;// don't check for half second if this check wasn't successful m_fCanHornetAttack = false; return COND_NONE; }
void CNPC_Stalker::AddZigZagToPath(void) { // If already on a detour don't add a zigzag if (GetNavigator()->GetCurWaypointFlags() & bits_WP_TO_DETOUR) { return; } // If enemy isn't facing me or occluded, don't add a zigzag if (HasCondition(COND_ENEMY_OCCLUDED) || !HasCondition ( COND_ENEMY_FACING_ME )) { return; } Vector waypointPos = GetNavigator()->GetCurWaypointPos(); Vector waypointDir = (waypointPos - GetAbsOrigin()); // If the distance to the next node is greater than ZIG_ZAG_SIZE // then add a random zig/zag to the path if (waypointDir.LengthSqr() > ZIG_ZAG_SIZE) { // Pick a random distance for the zigzag (less that sqrt(ZIG_ZAG_SIZE) float distance = random->RandomFloat( 30, 60 ); // Get me a vector orthogonal to the direction of motion VectorNormalize( waypointDir ); Vector vDirUp(0,0,1); Vector vDir; CrossProduct( waypointDir, vDirUp, vDir); // Pick a random direction (left/right) for the zigzag if (random->RandomInt(0,1)) { vDir = -1 * vDir; } // Get zigzag position in direction of target waypoint Vector zigZagPos = GetAbsOrigin() + waypointDir * 60; // Now offset zigZagPos = zigZagPos + (vDir * distance); // Now make sure that we can still get to the zigzag position and the waypoint AIMoveTrace_t moveTrace1, moveTrace2; GetMoveProbe()->MoveLimit( NAV_GROUND, GetAbsOrigin(), zigZagPos, GetAITraceMask(), NULL, &moveTrace1); GetMoveProbe()->MoveLimit( NAV_GROUND, zigZagPos, waypointPos, GetAITraceMask(), NULL, &moveTrace2); if ( !IsMoveBlocked( moveTrace1 ) && !IsMoveBlocked( moveTrace2 ) ) { GetNavigator()->PrependWaypoint( zigZagPos, NAV_GROUND, bits_WP_TO_DETOUR ); } } }
//------------------------------------------------------------------------------ // Purpose: routine called to select what schedule we want to run // Output : returns the schedule id of the schedule we want to run //------------------------------------------------------------------------------ int CAI_ASW_HealOtherBehavior::SelectSchedule() { if ( HasCondition( COND_HEAL_OTHER_NOT_HAS_TARGET ) || HasCondition( COND_HEAL_OTHER_HAS_FULL_HEALTH ) || HasCondition( COND_HEAL_OTHER_NOT_TARGET_IN_RANGE ) || HasCondition( COND_HEAL_OTHER_TARGET_CHANGED ) ) { return SCHED_HEAL_OTHER_MOVE_TO_CANDIDATE; } else { return SCHED_HEAL_WAIT; } // return BaseClass::SelectSchedule(); }
//----------------------------------------------------------------------------- // Purpose: // // // Output : //----------------------------------------------------------------------------- int CNPC_RollerDozer::SelectSchedule ( void ) { if( HasCondition( COND_ROLLERDOZER_FOUND_DEBRIS ) ) { return SCHED_ROLLERDOZER_CLEAR_DEBRIS; } if( HasCondition( COND_ROLLER_PHYSICS ) ) { m_hDebris = NULL; } return BaseClass::SelectSchedule(); }
//------------------------------------------------------------------------------ // Purpose: determines if we can use this behavior currently // Output : returns true if this behavior is able to run //------------------------------------------------------------------------------ bool CAI_ASW_RetreatBehavior::CanSelectSchedule() { if ( !GetOuter()->IsInterruptable() ) { return false; } if ( !HasCondition( COND_LIGHT_DAMAGE ) && !HasCondition( COND_HEAVY_DAMAGE ) ) { return false; } return BaseClass::CanSelectSchedule(); }
int CNPC_SO_BaseZombie::SelectAlertSchedule() { // Improve zombies' perception of their surroundings // http://developer.valvesoftware.com/wiki/AI_Perception_Behavior_Enhancement if ( HasCondition ( COND_HEAR_DANGER ) || HasCondition ( COND_HEAR_PLAYER ) || HasCondition ( COND_HEAR_WORLD ) || HasCondition ( COND_HEAR_BULLET_IMPACT ) || HasCondition ( COND_HEAR_COMBAT ) ) { return SCHED_INVESTIGATE_SOUND; } return BaseClass::SelectAlertSchedule(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CNPC_VehicleDriver::SelectSchedule( void ) { // Vehicle driver hangs in the air inside the vehicle, so we never need to fall to ground ClearCondition( COND_FLOATING_OFF_GROUND ); if ( HasSpawnFlags(SF_VEHICLEDRIVER_INACTIVE) ) { SetState( NPC_STATE_IDLE ); return SCHED_VEHICLEDRIVER_INACTIVE; } if ( GetGoalEnt() ) return SCHED_VEHICLEDRIVER_DRIVE_PATH; switch ( m_NPCState ) { case NPC_STATE_IDLE: break; case NPC_STATE_ALERT: break; case NPC_STATE_COMBAT: { if ( HasCondition(COND_NEW_ENEMY) || HasCondition( COND_ENEMY_DEAD ) ) return BaseClass::SelectSchedule(); if ( HasCondition(COND_SEE_ENEMY) ) { // we can see the enemy if ( HasCondition(COND_CAN_RANGE_ATTACK2) ) return SCHED_RANGE_ATTACK2; if ( HasCondition(COND_CAN_RANGE_ATTACK1) ) return SCHED_RANGE_ATTACK1; // What to do here? Not necessarily easy to face enemy. //if ( HasCondition(COND_NOT_FACING_ATTACK) ) //return SCHED_COMBAT_FACE; } // We can see him, but can't shoot him. Just wait and hope he comes closer. return SCHED_VEHICLEDRIVER_COMBAT_WAIT; } break; } return BaseClass::SelectSchedule(); }
//========================================================= // CheckRangeAttack2 - toss grenade is enemy gets in the way and is too close. //========================================================= int CNPC_HAssassin::RangeAttack2Conditions ( float flDot, float flDist ) { m_fThrowGrenade = false; if ( !FBitSet ( GetEnemy()->GetFlags(), FL_ONGROUND ) ) { // don't throw grenades at anything that isn't on the ground! return COND_NONE; } // don't get grenade happy unless the player starts to piss you off if ( m_iFrustration <= 2) return COND_NONE; if ( m_flNextGrenadeCheck < gpGlobals->curtime && !HasCondition( COND_ENEMY_OCCLUDED ) && flDist <= 512 ) { Vector vTossPos; QAngle vAngles; GetAttachment( "grenadehand", vTossPos, vAngles ); Vector vecToss = VecCheckThrow( this, vTossPos, GetEnemy()->WorldSpaceCenter(), flDist, 0.5 ); // use dist as speed to get there in 1 second if ( vecToss != vec3_origin ) { m_vecTossVelocity = vecToss; // throw a hand grenade m_fThrowGrenade = TRUE; return COND_CAN_RANGE_ATTACK2; } } return COND_NONE; }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CRebelZombie::IsHeavyDamage( const CTakeDamageInfo &info ) { #ifdef HL2_EPISODIC if ( info.GetDamageType() & DMG_BUCKSHOT ) { if ( info.GetDamage() > (m_iMaxHealth/3) ) return true; } // Randomly treat all damage as heavy if ( info.GetDamageType() & (DMG_BULLET | DMG_BUCKSHOT) ) { // Don't randomly flinch if I'm melee attacking if ( !HasCondition(COND_CAN_MELEE_ATTACK1) && (RandomFloat() > 0.5) ) { // Randomly forget I've flinched, so that I'll be forced to play a big flinch // If this doesn't happen, it means I may not fully flinch if I recently flinched if ( RandomFloat() > 0.75 ) { Forget(bits_MEMORY_FLINCHED); } return true; } } #endif // HL2_EPISODIC return BaseClass::IsHeavyDamage(info); }
int CRebelZombie::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) { if ( HasCondition( COND_BLOCKED_BY_DOOR ) && m_hBlockingDoor != NULL ) { ClearCondition( COND_BLOCKED_BY_DOOR ); if ( m_NextTimeToStartDoorBash.Expired() && failedSchedule != SCHED_ZOMBIE_BASH_DOOR ) return SCHED_ZOMBIE_BASH_DOOR; m_hBlockingDoor = NULL; } if ( failedSchedule != SCHED_ZOMBIE_CHARGE_ENEMY && IsPathTaskFailure( taskFailCode ) && random->RandomInt( 1, 100 ) < 50 ) { return SCHED_ZOMBIE_CHARGE_ENEMY; } if ( failedSchedule != SCHED_ZOMBIE_WANDER_ANGRILY && ( failedSchedule == SCHED_TAKE_COVER_FROM_ENEMY || failedSchedule == SCHED_CHASE_ENEMY_FAILED ) ) { return SCHED_ZOMBIE_WANDER_ANGRILY; } return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); }
// Выбор скина для глаз крематора в зависимости от обстановки (уместно сравнить с Большими Папочками в Bioshock). В настоящее время не работает. void CNPC_Cremator::SelectSkin( void ) // doesn't quite work, it can turn eyes red ("combat" skin) when combating an enemy, but will not return to calm/alert skin when an enemy is dead { if(m_NPCState == NPC_STATE_COMBAT) { m_nSkin = 3; if ( HasCondition( COND_ENEMY_DEAD ) ) { m_nSkin = 0; } if ( GetEnemy() == NULL ) { m_nSkin = 1; } } if(m_NPCState == NPC_STATE_ALERT) { m_nSkin = 3; if ( GetEnemy() == NULL ) { m_nSkin = 1; } } if(m_NPCState == NPC_STATE_NONE) { m_nSkin = 1; } }
//========================================================= // MeleeAttack2Conditions - bullsquid is a big guy, so has a longer // melee range than most monsters. This is the bite attack. // this attack will not be performed if the tailwhip attack // is valid. //========================================================= int CNPC_Bullsquid::MeleeAttack2Conditions( float flDot, float flDist ) { if ( flDist <= 85 && flDot >= 0.7 && !HasCondition( COND_CAN_MELEE_ATTACK1 ) ) // The player & bullsquid can be as much as their bboxes return ( COND_CAN_MELEE_ATTACK2 ); return( COND_NONE ); }
int CNPC_APCDriver::RangeAttack2Conditions( float flDot, float flDist ) { if ( HasSpawnFlags(SF_APCDRIVER_NO_ROCKET_ATTACK) ) return COND_NONE; if ( m_hAPC->m_lifeState != LIFE_ALIVE ) return COND_NONE; if ( IsBeingCarried() || m_bFiringDisabled ) return COND_NONE; if ( !HasCondition( COND_SEE_ENEMY ) ) return COND_NONE; // Vehicle not ready to fire again yet? if ( m_pVehicleInterface->Weapon_SecondaryCanFireAt() > gpGlobals->curtime + 0.1f ) return COND_NONE; float flMinDist, flMaxDist; m_pVehicleInterface->Weapon_SecondaryRanges( &flMinDist, &flMaxDist ); if (flDist < flMinDist) return COND_NONE; if (flDist > flMaxDist) return COND_NONE; return COND_CAN_RANGE_ATTACK2; }
void CASW_Parasite::GatherEnemyConditions( CBaseEntity *pEnemy ) { // Do the base class BaseClass::GatherEnemyConditions( pEnemy ); // If we're not already too far away, check again //TODO: Check to make sure we don't already have a condition set that removes the need for this if ( HasCondition( COND_ENEMY_UNREACHABLE ) == false ) { Vector predPosition; UTIL_PredictedPosition( GetEnemy(), 1.0f, &predPosition ); Vector predDir = ( predPosition - GetAbsOrigin() ); float predLength = VectorNormalize( predDir ); // See if we'll be outside our effective target range if ( predLength > 2000 ) // m_flEludeDistance { Vector predVelDir = ( predPosition - GetEnemy()->GetAbsOrigin() ); float predSpeed = VectorNormalize( predVelDir ); // See if the enemy is moving mostly away from us if ( ( predSpeed > 512.0f ) && ( DotProduct( predVelDir, predDir ) > 0.0f ) ) { // Mark the enemy as eluded and burrow away ClearEnemyMemory(); SetEnemy( NULL ); SetIdealState( NPC_STATE_ALERT ); SetCondition( COND_ENEMY_UNREACHABLE ); } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_Assassin::GatherEnemyConditions( CBaseEntity *pEnemy ) { ClearCondition( COND_ASSASSIN_ENEMY_TARGETTING_ME ); BaseClass::GatherEnemyConditions( pEnemy ); // See if we're being targetted specifically if ( HasCondition( COND_ENEMY_FACING_ME ) ) { Vector enemyDir = GetAbsOrigin() - pEnemy->GetAbsOrigin(); VectorNormalize( enemyDir ); Vector enemyBodyDir; CBasePlayer *pPlayer = ToBasePlayer( pEnemy ); if ( pPlayer != NULL ) { enemyBodyDir = pPlayer->BodyDirection3D(); } else { AngleVectors( pEnemy->GetAbsAngles(), &enemyBodyDir ); } float enemyDot = DotProduct( enemyBodyDir, enemyDir ); //FIXME: Need to refine this a bit if ( enemyDot > 0.97f ) { SetCondition( COND_ASSASSIN_ENEMY_TARGETTING_ME ); } } }
//----------------------------------------------------------------------------- // Purpose: Translate base schedules into overridden forms //----------------------------------------------------------------------------- int CAI_BehaviorAlyxInjured::TranslateSchedule( int scheduleType ) { switch( scheduleType ) { case SCHED_RUN_FROM_ENEMY: case SCHED_RUN_FROM_ENEMY_MOB: { // Get under cover if we're able to if ( ShouldRunToCover() ) return SCHED_INJURED_RUN_FROM_ENEMY; // Run to our follow goal if we're too far away from it if ( ShouldRunToFollowGoal() ) return SCHED_FOLLOW; // Cower if surrounded if ( HasCondition( COND_INJURED_OVERWHELMED ) ) return SCHED_INJURED_COWER; // Face our enemies return SCHED_INJURED_FEAR_FACE; } break; case SCHED_RUN_FROM_ENEMY_FALLBACK: return SCHED_INJURED_COWER; break; } return BaseClass::TranslateSchedule( scheduleType ); }