// Gets called each time the mind is thinking void SearchingState::Think( idAI *owner ) { UpdateAlertLevel(); // Ensure we are in the correct alert level if( !CheckAlertLevel( owner ) ) { return; } // grayman #3063 - move up so it gets done each time, // regardless of what state the hiding spot search is in. // Let the AI check its senses owner->PerformVisualScan(); if( owner->GetMoveType() == MOVETYPE_SIT || owner->GetMoveType() == MOVETYPE_SLEEP || owner->GetMoveType() == MOVETYPE_SIT_DOWN || owner->GetMoveType() == MOVETYPE_LAY_DOWN ) { owner->GetUp(); return; } Memory &memory = owner->GetMemory(); owner->MarkEventAsSearched( memory.currentSearchEventID ); // grayman #3424 // grayman #3520 - look at alert spots if( owner->m_lookAtAlertSpot ) { owner->m_lookAtAlertSpot = false; idVec3 alertSpot = owner->m_lookAtPos; if( alertSpot.x != idMath::INFINITY ) { // grayman #3438 if( !owner->CheckFOV( alertSpot ) ) { // Search spot is not within FOV, turn towards the position owner->TurnToward( alertSpot ); owner->Event_LookAtPosition( alertSpot, 2.0f ); } else { owner->Event_LookAtPosition( alertSpot, 2.0f ); } } owner->m_lookAtPos = idVec3( idMath::INFINITY, idMath::INFINITY, idMath::INFINITY ); } // grayman #3200 - if asked to restart the hiding spot search, don't continue with the current hiding spot search if( memory.restartSearchForHidingSpots ) { // We should restart the search (probably due to a new incoming stimulus) // Setup a new hiding spot search StartNewHidingSpotSearch( owner ); } else if( !memory.hidingSpotSearchDone ) { // Do we have an ongoing hiding spot search? // Let the hiding spot search do its task PerformHidingSpotSearch( owner ); // Let the AI check its senses // owner->PerformVisualScan(); // grayman #3063 - moved to front /* // angua: commented this out, problems with getting up from sitting idStr waitState(owner->WaitState()); if (waitState.IsEmpty()) { // Waitstate is not matching, this means that the animation // can be started. owner->SetAnimState(ANIMCHANNEL_TORSO, "Torso_LookAround", 5); //owner->SetAnimState(ANIMCHANNEL_LEGS, "Legs_LookAround", 5); // Set the waitstate, this gets cleared by // the script function when the animation is done. owner->SetWaitState("look_around"); } */ } // Is a hiding spot search in progress? else if( !memory.hidingSpotInvestigationInProgress ) { // Spot search and investigation done, what next? // Have run out of hiding spots? if( memory.noMoreHidingSpots ) { if( gameLocal.time >= memory.nextTime2GenRandomSpot ) { memory.nextTime2GenRandomSpot = gameLocal.time + DELAY_RANDOM_SPOT_GEN * ( 1 + ( gameLocal.random.RandomFloat() - 0.5 ) / 3 ); // grayman #2422 // Generate a random search point, but make sure it's inside an AAS area // and that it's also inside the search volume. idVec3 p; // random point int areaNum; // p's area number idVec3 searchSize = owner->m_searchLimits.GetSize(); idVec3 searchCenter = owner->m_searchLimits.GetCenter(); //gameRenderWorld->DebugBox(colorWhite, idBox(owner->m_searchLimits), MS2SEC(memory.nextTime2GenRandomSpot - gameLocal.time)); bool validPoint = false; for( int i = 0 ; i < 6 ; i++ ) { p = searchCenter; p.x += gameLocal.random.RandomFloat() * ( searchSize.x ) - searchSize.x / 2; p.y += gameLocal.random.RandomFloat() * ( searchSize.y ) - searchSize.y / 2; p.z += gameLocal.random.RandomFloat() * ( searchSize.z ) - searchSize.z / 2; //p.z += gameLocal.random.RandomFloat()*(searchSize.z/2) - searchSize.z/4; areaNum = owner->PointReachableAreaNum( p ); if( areaNum == 0 ) { //gameRenderWorld->DebugArrow(colorRed, owner->GetEyePosition(), p, 1, MS2SEC(memory.nextTime2GenRandomSpot - gameLocal.time)); continue; } owner->GetAAS()->PushPointIntoAreaNum( areaNum, p ); // if this point is outside this area, it will be moved to one of the area's edges if( !owner->m_searchLimits.ContainsPoint( p ) ) { //gameRenderWorld->DebugArrow(colorPink, owner->GetEyePosition(), p, 1, MS2SEC(memory.nextTime2GenRandomSpot - gameLocal.time)); continue; } //gameRenderWorld->DebugArrow(colorGreen, owner->GetEyePosition(), p, 1, MS2SEC(memory.nextTime2GenRandomSpot - gameLocal.time)); validPoint = true; break; } if( validPoint ) { // grayman #2422 - the point chosen memory.currentSearchSpot = p; // Choose to investigate spots closely on a random basis // grayman #2801 - and only if you weren't hit by a projectile memory.investigateStimulusLocationClosely = ( ( gameLocal.random.RandomFloat() < 0.3f ) && ( memory.alertType != EAlertTypeHitByProjectile ) ); owner->actionSubsystem->PushTask( TaskPtr( InvestigateSpotTask::CreateInstance() ) ); //gameRenderWorld->DebugArrow(colorGreen, owner->GetEyePosition(), memory.currentSearchSpot, 1, 500); // Set the flag to TRUE, so that the sensory scan can be performed memory.hidingSpotInvestigationInProgress = true; } if( !validPoint ) { // no valid random point found // Stop moving, the algorithm will choose another spot the next round owner->StopMove( MOVE_STATUS_DONE ); memory.StopReacting(); // grayman #3559 // grayman #2422 - at least turn toward and look at the last invalid point some of the time // grayman #3492 - do it every time //if ( gameLocal.random.RandomFloat() < 0.5 ) //{ p.z += 60; // look up a bit, to simulate searching for the player's head if( !owner->CheckFOV( p ) ) { owner->TurnToward( p ); } owner->Event_LookAtPosition( p, MS2SEC( memory.nextTime2GenRandomSpot - gameLocal.time + 100 ) ); //gameRenderWorld->DebugArrow(colorPink, owner->GetEyePosition(), p, 1, MS2SEC(memory.nextTime2GenRandomSpot - gameLocal.time + 100)); //} } } } // We should have more hiding spots, try to get the next one else if( !ChooseNextHidingSpotToSearch( owner ) ) { // No more hiding spots to search DM_LOG( LC_AI, LT_INFO )LOGSTRING( "No more hiding spots!\r" ); // Stop moving, the algorithm will choose another spot the next round owner->StopMove( MOVE_STATUS_DONE ); memory.StopReacting(); // grayman #3559 } else { // ChooseNextHidingSpot returned TRUE, so we have memory.currentSearchSpot set //gameRenderWorld->DebugArrow(colorBlue, owner->GetEyePosition(), memory.currentSearchSpot, 1, 2000); // Delegate the spot investigation to a new task, this will take the correct action. owner->actionSubsystem->PushTask( InvestigateSpotTask::CreateInstance() ); // Prevent falling into the same hole twice memory.hidingSpotInvestigationInProgress = true; } } /* grayman #3200 - moved up else if (memory.restartSearchForHidingSpots) { // We should restart the search (probably due to a new incoming stimulus) // Setup a new hiding spot search StartNewHidingSpotSearch(owner); } else // grayman #3063 - moved to front { // Move to Hiding spot is ongoing, do additional sensory tasks here // Let the AI check its senses owner->PerformVisualScan(); } */ }
void SearchingState::Init( idAI *owner ) { // Init base class first State::Init( owner ); DM_LOG( LC_AI, LT_INFO )LOGSTRING( "SearchingState initialised.\r" ); assert( owner ); // Ensure we are in the correct alert level if( !CheckAlertLevel( owner ) ) { return; } if( owner->GetMoveType() == MOVETYPE_SIT || owner->GetMoveType() == MOVETYPE_SLEEP ) { owner->GetUp(); } // Shortcut reference Memory &memory = owner->GetMemory(); float alertTime = owner->atime3 + owner->atime3_fuzzyness * ( gameLocal.random.RandomFloat() - 0.5 ); _alertLevelDecreaseRate = ( owner->thresh_4 - owner->thresh_3 ) / alertTime; if( owner->AlertIndexIncreased() || memory.mandatory ) { // grayman #3331 // Setup a new hiding spot search StartNewHidingSpotSearch( owner ); } if( owner->AlertIndexIncreased() ) { // grayman #3423 - when the alert level is ascending, kill the repeated bark task owner->commSubsystem->ClearTasks(); // Play bark if alert level is ascending // grayman #3496 - enough time passed since last alert bark? if( gameLocal.time >= memory.lastTimeAlertBark + MIN_TIME_BETWEEN_ALERT_BARKS ) { idStr bark; if( ( memory.alertedDueToCommunication == false ) && ( ( memory.alertType == EAlertTypeSuspicious ) || ( memory.alertType == EAlertTypeEnemy ) ) ) { bool friendsNear = ( ( MS2SEC( gameLocal.time - memory.lastTimeFriendlyAISeen ) ) <= MAX_FRIEND_SIGHTING_SECONDS_FOR_ACCOMPANIED_ALERT_BARK ); if( ( memory.alertClass == EAlertVisual_1 ) || ( memory.alertClass == EAlertVisual_2 ) || // grayman #2603, #3424 // (memory.alertClass == EAlertVisual_3) ) || // grayman #3472 - no longer needed ( memory.alertClass == EAlertVisual_4 ) ) { // grayman #3498 if( friendsNear ) { bark = "snd_alert3sc"; } else { bark = "snd_alert3s"; } } else if( memory.alertClass == EAlertAudio ) { if( friendsNear ) { bark = "snd_alert3hc"; } else { bark = "snd_alert3h"; } } else if( friendsNear ) { bark = "snd_alert3c"; } else { bark = "snd_alert3"; } // Allocate a SingleBarkTask, set the sound and enqueue it owner->commSubsystem->AddCommTask( CommunicationTaskPtr( new SingleBarkTask( bark ) ) ); memory.lastTimeAlertBark = gameLocal.time; // grayman #3496 if( cv_ai_debug_transition_barks.GetBool() ) { gameLocal.Printf( "%d: %s rises to Searching state, barks '%s'\n", gameLocal.time, owner->GetName(), bark.c_str() ); } } } else { if( cv_ai_debug_transition_barks.GetBool() ) { gameLocal.Printf( "%d: %s rises to Searching state, can't bark 'snd_alert3{s/sc/h/hc/c}' yet\n", gameLocal.time, owner->GetName() ); } } } else if( memory.alertType == EAlertTypeEnemy ) { // reduce the alert type, so we can react to other alert types (such as a dead person) memory.alertType = EAlertTypeSuspicious; } // grayman #3472 - When ascending, set up a repeated bark if( owner->AlertIndexIncreased() ) { owner->commSubsystem->AddSilence( 5000 + gameLocal.random.RandomInt( 3000 ) ); // grayman #3424 // This will hold the message to be delivered with the bark CommMessagePtr message( new CommMessage( CommMessage::DetectedEnemy_CommType, owner, NULL,// from this AI to anyone NULL, idVec3( idMath::INFINITY, idMath::INFINITY, idMath::INFINITY ), 0 ) ); int minTime = SEC2MS( owner->spawnArgs.GetFloat( "searchbark_delay_min", "10" ) ); int maxTime = SEC2MS( owner->spawnArgs.GetFloat( "searchbark_delay_max", "15" ) ); owner->commSubsystem->AddCommTask( CommunicationTaskPtr( new RepeatedBarkTask( "snd_state3", minTime, maxTime, message ) ) ); } else { // descending // Allow repeated barks from Agitated Searching to continue. } if( !owner->HasSeenEvidence() ) { owner->SheathWeapon(); owner->UpdateAttachmentContents( false ); } else { // Let the AI update their weapons (make them solid) owner->UpdateAttachmentContents( true ); } }
void AgitatedSearchingState::Init(idAI* owner) { // Init base class first (note: we're not calling SearchingState::Init() on purpose here) State::Init(owner); DM_LOG(LC_AI, LT_INFO)LOGSTRING("AgitatedSearchingState initialised.\r"); assert(owner); // Shortcut reference Memory& memory = owner->GetMemory(); memory.leaveAlertState = false; // Ensure we are in the correct alert level if ( !CheckAlertLevel(owner) ) { return; } // grayman #3496 - note that we spent time in Agitated Search memory.agitatedSearched = true; CalculateAlertDecreaseRate(owner); if (owner->GetMoveType() == MOVETYPE_SIT || owner->GetMoveType() == MOVETYPE_SLEEP) { owner->GetUp(); } // Set up a new hiding spot search if not already assigned to one if (owner->m_searchID <= 0) { if (!StartNewHidingSpotSearch(owner)) // grayman #3857 - AI gets his assignment { // grayman - this section can't run because it causes // the stealth score to rise dramatically during player sightings //owner->SetAlertLevel(owner->thresh_3 - 0.1); // failed to create a search, so drop down to Suspicious mode //owner->GetMind()->EndState(); //return; } } // kill the repeated and single bark tasks owner->commSubsystem->ClearTasks(); // grayman #3182 memory.repeatedBarkState = ERBS_NULL; // grayman #3857 if (owner->AlertIndexIncreased()) { // grayman #3496 - enough time passed since last alert bark? // grayman #3857 - enough time passed since last visual stim bark? if ( ( gameLocal.time >= memory.lastTimeAlertBark + MIN_TIME_BETWEEN_ALERT_BARKS ) && ( gameLocal.time >= memory.lastTimeVisualStimBark + MIN_TIME_BETWEEN_ALERT_BARKS ) ) { idStr soundName = ""; if ( ( memory.alertedDueToCommunication == false ) && ( ( memory.alertType == EAlertTypeSuspicious ) || ( memory.alertType == EAlertTypeEnemy ) || ( memory.alertType == EAlertTypeFailedKO ) ) ) { if (owner->HasSeenEvidence()) { soundName = "snd_alert4"; } else { soundName = "snd_alert4NoEvidence"; } CommMessagePtr message = CommMessagePtr(new CommMessage( CommMessage::DetectedSomethingSuspicious_CommType, owner, NULL, // from this AI to anyone NULL, memory.alertPos, memory.currentSearchEventID // grayman #3438 )); owner->commSubsystem->AddCommTask(CommunicationTaskPtr(new SingleBarkTask(soundName,message))); memory.lastTimeAlertBark = gameLocal.time; // grayman #3496 if (cv_ai_debug_transition_barks.GetBool()) { gameLocal.Printf("%d: %s rises to Agitated Searching state, barks '%s'\n",gameLocal.time,owner->GetName(),soundName.c_str()); } } else if ( memory.respondingToSomethingSuspiciousMsg ) // grayman #3857 { soundName = "snd_helpSearch"; // Allocate a SingleBarkTask, set the sound and enqueue it owner->commSubsystem->AddCommTask(CommunicationTaskPtr(new SingleBarkTask(soundName))); memory.lastTimeAlertBark = gameLocal.time; // grayman #3496 if (cv_ai_debug_transition_barks.GetBool()) { gameLocal.Printf("%d: %s rises to Searching state, barks '%s'\n",gameLocal.time,owner->GetName(),soundName.c_str()); } } } else { if (cv_ai_debug_transition_barks.GetBool()) { gameLocal.Printf("%d: %s rises to Agitated Searching state, can't bark 'snd_alert4{NoEvidence}' yet\n",gameLocal.time,owner->GetName()); } } } owner->commSubsystem->AddSilence(5000 + gameLocal.random.RandomInt(3000)); // grayman #3424 SetRepeatedBark(owner); // grayman #3857 DrawWeapon(owner); // grayman #3507 // Let the AI update their weapons (make them solid) owner->UpdateAttachmentContents(true); // grayman #3857 - no idle search anims in this state owner->actionSubsystem->ClearTasks(); }