bool CASW_BaseAI_Senses::WaitingUntilSeen( CBaseEntity *pSightEnt ) { if ( GetOuter()->GetSpawnFlags() & SF_NPC_WAIT_TILL_SEEN ) { // asw, wake up if marines see us (not players) if ( pSightEnt && pSightEnt->Classify() == CLASS_ASW_MARINE ) { CBaseCombatCharacter *pBCC = dynamic_cast<CBaseCombatCharacter*>( pSightEnt ); Vector zero = Vector(0,0,0); // don't link this client in the list if the npc is wait till seen and the player isn't facing the npc if (// && pPlayer->FVisible( GetOuter() ) pBCC->FInViewCone( GetOuter() ) && FBoxVisible( pSightEnt, static_cast<CBaseEntity*>(GetOuter()), zero ) ) { // marine sees us, become normal now. GetOuter()->RemoveSpawnFlags( SF_NPC_WAIT_TILL_SEEN ); return false; } } return true; } return false; }
//========================================================= // RunTask //========================================================= void CNPC_Stalker::RunTask( const Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_ANNOUNCE_ATTACK: { // Stop waiting if enemy facing me or lost enemy CBaseCombatCharacter* pBCC = GetEnemyCombatCharacterPointer(); if (!pBCC || pBCC->FInViewCone( this )) { TaskComplete(); } if ( IsWaitFinished() ) { TaskComplete(); } break; } case TASK_STALKER_ZIGZAG : { if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) { TaskComplete(); GetNavigator()->StopMoving(); // Stop moving } else if (!GetNavigator()->IsGoalActive()) { SetIdealActivity( GetStoppedActivity() ); } else if (ValidateNavGoal()) { SetIdealActivity( GetNavigator()->GetMovementActivity() ); AddZigZagToPath(); } break; } case TASK_RANGE_ATTACK1: UpdateAttackBeam(); if ( !TaskIsRunning() || HasCondition( COND_TASK_FAILED )) { KillAttackBeam(); } break; case TASK_FACE_ENEMY: { if ( GetEnemy() != NULL ) { BaseClass:: RunTask( pTask ); return; } GetMotor()->SetIdealYawToTargetAndUpdate( m_vLaserCurPos ); if ( FacingIdeal() ) { TaskComplete(); } break; } default: { BaseClass::RunTask( pTask ); break; } } }
//========================================================= // 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; } }