//========================================================= // start task //========================================================= void CNPC_Stalker::StartTask( const Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_STALKER_SCREAM: { if( gpGlobals->curtime > m_flNextScreamTime ) { EmitSound( "NPC_Stalker.Scream" ); m_flNextScreamTime = gpGlobals->curtime + random->RandomFloat( 10.0, 15.0 ); } TaskComplete(); } case TASK_ANNOUNCE_ATTACK: { // If enemy isn't facing me and I haven't attacked in a while // annouce my attack before I start wailing away CBaseCombatCharacter *pBCC = GetEnemyCombatCharacterPointer(); if (pBCC && (!pBCC->FInViewCone ( this )) && (gpGlobals->curtime - m_flLastAttackTime > 1.0) ) { m_flLastAttackTime = gpGlobals->curtime; // Always play this sound EmitSound( "NPC_Stalker.Scream" ); m_flNextScrambleSoundTime = gpGlobals->curtime + 2; m_flNextBreatheSoundTime = gpGlobals->curtime + 2; // Wait two seconds SetWait( 2.0 ); SetActivity(ACT_IDLE); } break; } case TASK_STALKER_ZIGZAG: break; case TASK_RANGE_ATTACK1: { CBaseEntity *pEnemy = GetEnemy(); if (pEnemy) { m_vLaserTargetPos = GetEnemyLKP() + pEnemy->GetViewOffset(); // Never hit target on first try Vector missPos = m_vLaserTargetPos; if( pEnemy->Classify() == CLASS_BULLSEYE && hl2_episodic.GetBool() ) { missPos.x += 60 + 120*random->RandomInt(-1,1); missPos.y += 60 + 120*random->RandomInt(-1,1); } else { missPos.x += 80*random->RandomInt(-1,1); missPos.y += 80*random->RandomInt(-1,1); } // ---------------------------------------------------------------------- // If target is facing me and not running towards me shoot below his feet // so he can see the laser coming // ---------------------------------------------------------------------- CBaseCombatCharacter *pBCC = ToBaseCombatCharacter(pEnemy); if (pBCC) { Vector targetToMe = (pBCC->GetAbsOrigin() - GetAbsOrigin()); Vector vBCCFacing = pBCC->BodyDirection2D( ); if ((DotProduct(vBCCFacing,targetToMe) < 0) && (pBCC->GetSmoothedVelocity().Length() < 50)) { missPos.z -= 150; } // -------------------------------------------------------- // If facing away or running towards laser, // shoot above target's head // -------------------------------------------------------- else { missPos.z += 60; } } m_vLaserDir = missPos - LaserStartPosition(GetAbsOrigin()); VectorNormalize(m_vLaserDir); } else { TaskFail(FAIL_NO_ENEMY); return; } StartAttackBeam(); SetActivity(ACT_RANGE_ATTACK1); break; } case TASK_GET_PATH_TO_ENEMY_LOS: { if ( GetEnemy() != NULL ) { BaseClass:: StartTask( pTask ); return; } Vector posLos; if (GetTacticalServices()->FindLos(m_vLaserCurPos, m_vLaserCurPos, MIN_STALKER_FIRE_RANGE, MAX_STALKER_FIRE_RANGE, 1.0, &posLos)) { AI_NavGoal_t goal( posLos, ACT_RUN, AIN_HULL_TOLERANCE ); GetNavigator()->SetGoal( goal ); } else { TaskFail(FAIL_NO_SHOOT); } break; } case TASK_FACE_ENEMY: { if ( GetEnemy() != NULL ) { BaseClass:: StartTask( pTask ); return; } GetMotor()->SetIdealYawToTarget( m_vLaserCurPos ); break; } default: BaseClass:: StartTask( pTask ); break; } }
//========================================================= // start task //========================================================= void CNPC_Houndeye::StartTask( const Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_HOUND_GET_PATH_TO_CIRCLE: { if (GetEnemy() == NULL) { TaskFail(FAIL_NO_ENEMY); } else { Vector vTargetPos = GetEnemyLKP(); vTargetPos.z = GetFloorZ(vTargetPos); if (GetNavigator()->SetRadialGoal(vTargetPos, random->RandomInt(50,500), 90, 175, m_bLoopClockwise)) { TaskComplete(); return; } TaskFail(FAIL_NO_ROUTE); } break; } case TASK_HOUND_REVERSE_STRAFE_DIR: { // Try the other direction m_bLoopClockwise = (m_bLoopClockwise) ? false : true; TaskComplete(); break; } // Override to set appropriate distances case TASK_GET_PATH_TO_ENEMY_LOS: { float flMaxRange = HOUNDEYE_MAX_ATTACK_RADIUS * 0.9; float flMinRange = HOUNDEYE_MIN_ATTACK_RADIUS; Vector posLos; bool foundLos = false; if (GetEnemy() != NULL) { foundLos = GetTacticalServices()->FindLos(GetEnemyLKP(),GetEnemy()->EyePosition(), flMinRange, flMaxRange, 0.0, &posLos); } else { TaskFail(FAIL_NO_TARGET); return; } if (foundLos) { GetNavigator()->SetGoal( AI_NavGoal_t( posLos, ACT_RUN, AIN_HULL_TOLERANCE ) ); } else { TaskFail(FAIL_NO_SHOOT); } break; } case TASK_HOUND_FALL_ASLEEP: { m_fAsleep = true; // signal that hound is lying down (must stand again before doing anything else!) TaskComplete( true ); break; } case TASK_HOUND_WAKE_UP: { m_fAsleep = false; // signal that hound is standing again TaskComplete( true ); break; } case TASK_HOUND_OPEN_EYE: { m_fDontBlink = false; // turn blinking back on and that code will automatically open the eye TaskComplete( true ); break; } case TASK_HOUND_CLOSE_EYE: { //<<TEMP>> pev->skin = 0; m_fDontBlink = true; // tell blink code to leave the eye alone. break; } case TASK_HOUND_THREAT_DISPLAY: { SetIdealActivity( ACT_IDLE_ANGRY ); break; } case TASK_HOUND_HOP_BACK: { SetIdealActivity( ACT_LEAP ); break; } case TASK_RANGE_ATTACK1: { SetIdealActivity( ACT_RANGE_ATTACK1 ); break; } default: { BaseClass::StartTask(pTask); break; } } }
void CAI_StandoffBehavior::StartTask( const Task_t *pTask ) { bool fCallBase = false; switch ( pTask->iTask ) { case TASK_RANGE_ATTACK1: { m_ShotRegulator.OnFiredWeapon(); fCallBase = true; break; } case TASK_FIND_COVER_FROM_ENEMY: { StandoffMsg( "TASK_FIND_COVER_FROM_ENEMY\n" ); // If within time window to force change if ( !m_params.fStayAtCover && (!m_TimeForceCoverHint.Expired() || m_RandomCoverChangeTimer.Expired()) ) { m_TimeForceCoverHint.Force(); m_RandomCoverChangeTimer.Set( 8, 16, false ); // @TODO (toml 03-24-03): clean this up be tool-izing base tasks. Right now, this is here to force to not use lateral cover search CBaseEntity *pEntity = GetEnemy(); if ( pEntity == NULL ) { // Find cover from self if no enemy available pEntity = GetOuter(); } CBaseEntity *pLeader = GetPlayerLeader(); if ( pLeader ) { m_PlayerMoveMonitor.SetMark( pLeader, 60 ); } Vector coverPos = vec3_origin; CAI_TacticalServices * pTacticalServices = GetTacticalServices(); const Vector & enemyPos = pEntity->GetAbsOrigin(); Vector enemyEyePos = pEntity->EyePosition(); float coverRadius = GetOuter()->CoverRadius(); const Vector & goalPos = GetStandoffGoalPosition(); bool bTryGoalPosFirst = true; if( pLeader && m_vecStandoffGoalPosition == GOAL_POSITION_INVALID ) { if( random->RandomInt(1, 100) <= 50 ) { // Half the time, if the player is leading, try to find a spot near them bTryGoalPosFirst = false; StandoffMsg( "Not trying goal pos\n" ); } } if( bTryGoalPosFirst ) { // Firstly, try to find cover near the goal position. pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, 0, 15*12, &coverPos ); if ( coverPos == vec3_origin ) pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, 15*12-0.1, 40*12, &coverPos ); StandoffMsg1( "Trying goal pos, %s\n", ( coverPos == vec3_origin ) ? "failed" : "succeeded" ); } if ( coverPos == vec3_origin ) { // Otherwise, find a node near to self StandoffMsg( "Looking for near cover\n" ); if ( !GetTacticalServices()->FindCoverPos( enemyPos, enemyEyePos, 0, coverRadius, &coverPos ) ) { // Try local lateral cover if ( !GetTacticalServices()->FindLateralCover( enemyEyePos, &coverPos ) ) { // At this point, try again ignoring front lines. Any cover probably better than hanging out in the open m_fIgnoreFronts = true; if ( !GetTacticalServices()->FindCoverPos( enemyPos, enemyEyePos, 0, coverRadius, &coverPos ) ) { if ( !GetTacticalServices()->FindLateralCover( enemyEyePos, &coverPos ) ) { Assert( coverPos == vec3_origin ); } } m_fIgnoreFronts = false; } } } if ( coverPos != vec3_origin ) { AI_NavGoal_t goal(GOALTYPE_COVER, coverPos, ACT_RUN, AIN_HULL_TOLERANCE, AIN_DEF_FLAGS); GetNavigator()->SetGoal( goal ); GetOuter()->m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; TaskComplete(); } else TaskFail(FAIL_NO_COVER); } else { fCallBase = true; } break; } default: { fCallBase = true; } } if ( fCallBase ) BaseClass::StartTask( pTask ); }