//========================================================= // 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; } }