public EngageTargetBehavior(String thisID, String targetID, WaypointSequence relativeLoiterPattern, Boolean returnAfter) { m_engagementState = EngagementState.Tracking; m_thisID = thisID; m_targetID = targetID; m_relativeLoiterPattern = relativeLoiterPattern; m_absoluteLoiterPattern = null; m_destWaypoint = null; m_attackEndTime = 0; m_attackInProcess = false; m_attackIsWeapon = false; m_originalLocation = null; m_returnAfter = returnAfter; }
public void AttackSucceeded(SimulationEvent ev) { String attacker = ((StringValue)ev["ObjectID"]).value; String target = ((StringValue)ev["TargetID"]).value; String newState = ((StringValue)ev["NewState"]).value; if (m_attackInProcess) { if (target == m_targetID) { ResetAttack(); if (m_returnAfter) { m_engagementState = EngagementState.Returning; m_dddServer.SendMoveObjectRequest(m_thisID, m_originalLocation, 1); } else { m_done = true; } } } }
public void Start(DDDServerConnection serverConnection, DMView dmView) { m_dmView = dmView; m_dddServer = serverConnection; SimObject me = dmView.AllObjects[m_thisID]; LocationValue myLocation = me.Location; SimObject track = dmView.AllObjects[m_targetID]; LocationValue trackLocation = track.Location; m_originalLocation = myLocation; //m_trackTarget = ShouldTrack(serverConnection, dmView); m_engagementState = EngagementState.Tracking; //if (m_trackTarget) //{ // serverConnection.SendMoveObjectRequest(m_thisID, trackLocation, 1); //} //else //{ // StartLoiter(serverConnection, dmView); //} }
public void Update(DDDServerConnection serverConnection, DMView dmView) { if (m_done) { return; } SimObject me = dmView.AllObjects[m_thisID]; LocationValue myLocation = me.Location; SimObject track = dmView.AllObjects[m_targetID]; LocationValue trackLocation = track.Location; m_absoluteLoiterPattern = m_relativeLoiterPattern.ToAbsolute(trackLocation); switch (m_engagementState) { case EngagementState.Tracking: if (ShouldTrack(serverConnection, dmView)) { serverConnection.SendMoveObjectRequest(m_thisID, trackLocation, 1); } else { m_engagementState = EngagementState.Attacking; StartLoiter(serverConnection, dmView); } break; case EngagementState.Attacking: ContinueLoiter(serverConnection, dmView); if (!m_attackInProcess) // start the attack { // start with weapons if (me.DockedWeapons.Count > 0) { m_attackWeaponID = me.DockedWeapons[0]; serverConnection.SendWeaponLaunchRequest(m_thisID, m_attackWeaponID, m_targetID); m_attackEndTime = dmView.SimTime + 12000; // give a two minute time window to start, AttackUpdate will modify this m_attackInProcess = true; m_attackIsWeapon = true; } else // use native capabilities { // figure out capability/vulnerability match up String cap = DetermineCapability(me.CapabilityList, track.VulnerabilityList); if (cap != String.Empty) { serverConnection.SendAttackObjectRequest(m_thisID, m_targetID, cap); m_attackInProcess = true; m_attackIsWeapon = false; m_attackEndTime = dmView.SimTime + 12000; } else // I don't have the right capabilities, finish up { ResetAttack(); if (m_returnAfter) { m_engagementState = EngagementState.Returning; m_dddServer.SendMoveObjectRequest(m_thisID, m_originalLocation, 1); } else { m_done = true; } } } } else // check to see if the attack was succesful { // if we are still in attack mode 2 seconds after attack was supposed to end // start another attack if (dmView.SimTime > m_attackEndTime + 2000) { ResetAttack(); } } break; case EngagementState.Returning: if (BehaviorHelper.Distance(myLocation, m_originalLocation) < 1) { m_done = true; } break; } }
IEnumerator FightingLogicController() { allowedToStartEngagementCoroutine = false; //if we are currently free, determine what type of situation we are in and react to it if(engagementStatus == EngagementState.free || engagementStatus == EngagementState.cover) { //the situation that we are stationary and probably in cover, come out, try to shoot the player and then go to the next cover if(movement.velocity.magnitude > -0.1f && movement.velocity.magnitude < 0.1f) { engagementStatus = EngagementState.busy; if(debug) { Debug.Log("Engage: Started computing best location"); } Vector3 attackPosition = movement.FindClosestHalfCover(); //movement.Defreeze(); //now lets move to that position movement.SetNewDestination(attackPosition); //go in to crouching if(allowCrouching == true) { crouching = true; } if(debug) { Debug.Log("Engage: Moving to attack position: " + attackPosition); } //wait till we get to the cover TEST_IF_AT_HALF_COVER: if(Vector3.Distance(transform.position, coverManager.coverPostion) > 2f ) { yield return new WaitForFixedUpdate(); goto TEST_IF_AT_HALF_COVER; } else { if(debug) { Debug.LogError("We're in cover; face enemy"); } //face the general direction of the enemy movement.SetNewDestination( transform.position + ( sightManager.lastSeenLocation - transform.position).normalized * 1.1f); } //lets wait a random number of seconds while we're attacking the enemy yield return new WaitForSeconds(Random.Range(minCoverTime/2f, maxCoverTime/2f)); if(debug) { Debug.Log("Engage: Deciding what to do"); } //stand up crouching = false; //if we heard a bullet, go to cover, or else come closer to the last spotted area, or if the fight instict kicks in, STORM! if(earsManager.canHearTarget2 == true) { movement.SetNewDestination(coverManager.coverPostion); engagementStatus = EngagementState.cover; if(debug) { Debug.Log("Engage: Going back to cover"); } } else { movement.SetNewDestination(sightManager.lastSeenLocation); engagementStatus = EngagementState.free; if(debug) { Debug.Log("Engage: Going back to cover/checking what happened"); } } } } allowedToStartEngagementCoroutine = true; }
void Update() { //check whether we're allowed to think if(allowedToThink == false) { return; } //check whether we have to use basic level if( onlyBasicFunctionality == true ) { goto BASIC_FUNCTION; } //setup multiple weapons correctly MultipleWeaponsConfigure(); //update some variables enemyIsInUnobstructedView = CheckIfFree( sightManager.objectToSeek ); if(distanceToEnemy < 1.5f) { enemyIsInUnobstructedView = true; } //anti-bottlenecking procedure lastFiredEngagement += 1f; enemyDistanceCheckFrame += 1f; if(enemyDistanceCheckFrame > enemyDistanceCheckFrameBarrier) { enemyDistanceCheckFrame = 0f; if(sightManager.objectToSeek != null) { distanceToEnemy = earsManager.CalculatePathLength(sightManager.objectToSeek.transform.position); //coverManager.FindCoverPostion( sightManager.eyeLevel, false ); } } //patrol part if(currentState == CurrentState.patrol) { //disable crouching if(crouching == true) { crouching = false; } //internal clock ticks += 1f; if(ticks > tickBarrier) { //if we need to check for updated position ticks = 0f; //set our new waypoint if(patrolM != null) { movement.SetNewDestination(patrolM.nextDestination); } if(patrolManager.GetComponent<LocationManager>() != null) { movement.SetNewDestination(patrolManager.GetComponent<LocationManager>().nextDestination); } if(debug) { Debug.Log("Going to next waypoint"); } } } //if we suddenly hear/see player and we are in patrol and we are not engaging/stepping down if((currentState == CurrentState.patrol || currentState == CurrentState.chase || (currentState == CurrentState.investigate && ticksInvestigate > ticksInvestigateBarrier)) && engage == "") { //if we can hear the target if(earsManager.canHearTarget == true) { //investigate what we heard there movement.SetNewDestination(earsManager.lastHeardPosition); //set the correct state currentState = CurrentState.chase; //we heard last lastSeen = false; if(debug) { Debug.Log("Chase using ears"); } } //if we saw the target, investigate if(sightManager.canSeeObject == true) { //investigate what we saw there movement.SetNewDestination(sightManager.lastSeenLocation); //set the correct state currentState = CurrentState.chase; //we saw last lastSeen = true; if(debug) { Debug.Log("Chase using eyes"); } } //if we heard a bullet if(earsManager.canHearTarget2 == true) { if(debug) { Debug.Log("Chase where we heard bullet."); } //investigate what we heard from the area where the bullet originated movement.SetNewDestination( earsManager.lastHeardPositionSecondary ); //set the correct state currentState = CurrentState.chase; //we heard last lastSeen = false; } } //if we were chasing him but lose sight/hearing of him, change to investigate if(currentState == CurrentState.chase && earsManager.canHearTarget == false && sightManager.canSeeObject == false && earsManager.canHearTarget2 == false) { //change to investigate currentState = CurrentState.investigate; StartCoroutine( StartInvestigationCountdown() ); crouching = false; if(debug) { Debug.Log("Going from chase to investigate, because we can't locate enemy."); } } //if we're investigating and we're past the barrier if(currentState == CurrentState.investigate && ticksInvestigate > ticksInvestigateBarrier) { //lets go to the last seen location if we last saw the player, else to last heard location if(lastSeen == true) { if(debug) { Debug.Log("New last seen pos"); } ticksInvestigate = 0f; movement.SetNewDestination(sightManager.lastSeenLocation); } else { if(debug) { Debug.Log("New last heard pos"); } ticksInvestigate = 0f; if( earsManager.lastHeardPosition != Vector3.zero ) { movement.SetNewDestination( earsManager.lastHeardPosition); } else { movement.SetNewDestination( earsManager.lastHeardPositionSecondary); } } } ticksInvestigate += 1f; //once we see the player //if we suddenly hear/see player and we are in patrol/chase/investigate if(currentState == CurrentState.patrol || currentState == CurrentState.chase || currentState == CurrentState.investigate) { //if we can see the target if(sightManager.canSeeObject == true) { gameObject.AddComponent( FindCorrectVisualCheckString() ); //check if we should enage or not SendMessage("VisualCheck"); //start again for reset, so that if the player does act in the rules of engagement, we wont miss it StartCoroutine("ResetEngagement"); if(alreadyEngaged == false) { //if we have yet engaged the player once if(engage == "engage") { //if we should engage currentState = CurrentState.engage; EngageShooting(); //go in shock to higher the reaction time StartCoroutine("Shock"); //say that we've already engaged the player alreadyEngaged = true; if(debug) { Debug.Log("We see enemy, engage!"); } } else { //else we step down and go back to patroling currentState = CurrentState.patrol; if(debug) { Debug.Log("Step down."); } } } else { //if we have engaged the player already, ATTACK! currentState = CurrentState.engage; EngageShooting(); if(debug) { Debug.Log("We see enemy again! Attack!"); } } } } //if we're in cover and suddenly see the player if(currentState == CurrentState.cover && movement.velocity.magnitude < 0.2f && enemyIsInUnobstructedView == true) { //go to engage currentState = CurrentState.engage; //reset previous variables engagementStatus = EngagementState.free; //start engagement cycle EngageShooting(); } //what to do if we directly see the player and we are engaging it if(meleeAttackUsed != 2 && sightManager.canSeeObject == true && sightManager.canSeeObjectFromWeapon == true && currentState == CurrentState.engage && currentlyInShock == false) { //shoot ActualShoot(); //stay on the spot if we have ammo if( weaponController.weaponHoldingObject != null && weaponController.weaponHoldingObject.GetComponent<AIWeaponSelected>().reloading == false) { if(debug) { Debug.Log("Frozen: We see enemy and are engaged"); } movement.Freeze(); } else { //run to cover if we're reloading movement.Defreeze(); coverManager.FindCoverPostion( sightManager.eyeLevel, false ); movement.SetNewDestination( coverManager.coverPostion ); currentState = CurrentState.cover; StartCoroutine( ComeOutOfCover() ); if(debug) { Debug.Log("We're reloading, run for cover!"); } } //if we're too close, try switching weapons or get back if( meleeAttackUsed == 0 && sightManager.objectToSeek != null && Vector3.Distance( transform.position, sightManager.objectToSeek.transform.position) < (meleeAttackDistance + 1.5f) ) { //find a weapon melee int newWeaponIndex = FindMeleeWeapon(); if(newWeaponIndex != -1) { //create new weapon and set it up correctly GameObject newWeapon = Instantiate( otherWeapons[newWeaponIndex] ) as GameObject; newWeapon.SetActive( true); newWeapon.transform.parent = weaponController.weaponHoldingLocation; newWeapon.transform.position = weaponController.weaponHoldingObject.transform.position; newWeapon.transform.rotation = weaponController.weaponHoldingObject.transform.rotation; //switch it for the previous GameObject prevWeapon = weaponController.weaponHoldingObject; weaponController.weaponHoldingObject = newWeapon; prevWeapon.SetActive(false); } else { //get to a cover currentState = CurrentState.cover; movement.Defreeze(); coverManager.FindCoverPostion( sightManager.eyeLevel, false ); movement.SetNewDestination( coverManager.coverPostion ); StartCoroutine( ComeOutOfCover() ); if(debug) { Debug.Log("Engagement: Too close to enemy. Getting to cover.", transform); } } } } //if we get shot whilst we are engaged if(currentState == CurrentState.engage && hit == true) { //test our chance for either fight or flight if(FightOrFlight() == false) { //we should search for cover coverManager.FindCoverPostion( sightManager.eyeLevel, false ); //change current state currentState = CurrentState.cover; //then go there movement.SetNewDestination(coverManager.coverPostion); //reset the cycle StartCoroutine( ComeOutOfCover() ); if(debug) { Debug.Log("Cover"); } } else { //else, ignore the pain and CHARGE! hit = false; //move towards where we think the player is movement.SetNewDestination(sightManager.lastSeenLocation); //audio if(audioControl != null) { audioControl.PlaySound( ShooterAIAudioOptions.Charge ); } if(debug) { Debug.Log("Charge"); } } } //if we lose sight of the player whilst we are in engagement mode if(currentState == CurrentState.engage && sightManager.canSeeObject == false) { ticksPlayerNotSeen += 1f; } //reset clock if we see the player again if(sightManager.canSeeObject == true && ticksPlayerNotSeen > 0f) { ticksPlayerNotSeen = 0; } //if we dont see the player for a specific amount of time if(currentState == CurrentState.engage && ticksPlayerNotSeen > timeBarrierEngageToInvestigate) { //go into investigative mode currentState = CurrentState.investigate; engagementStatus = EngagementState.free; StartCoroutine( StartInvestigationCountdown() ); crouching = false; if(debug) { Debug.Log("Go into investigation mode"); } } //this part is for when the ai runs out of ammo, it will take a chance to run and melee the enemy else go into cover if(currentState == CurrentState.engage && weaponController.amountOfAmmo <= 0f && engagementStatus == EngagementState.free) { if(FightOrFlight()) { movement.SetNewDestination(sightManager.lastSeenLocation); andrenaline += 2f; engagementStatus = EngagementState.busy; } else { currentState = CurrentState.cover; //then go to the cover coverManager.FindCoverPostion( sightManager.eyeLevel, false ); movement.SetNewDestination(coverManager.coverPostion); StartCoroutine( ComeOutOfCover() ); } } //this is the part that is used for the most basic function, without turning off the brain completely BASIC_FUNCTION: //this is the fight logic managing code if(currentState == CurrentState.engage) { //choose the correct type of fight logic, based on distance to us or availability of object, BUT we can't be only melee attack if(sightManager.objectToSeek != null && distanceToEnemy > distanceToStopWalking && meleeAttackUsed != 2) { DuringEngagement(); } else { //if we're either to far for melee or not using melee at all if((sightManager.objectToSeek != null && distanceToEnemy > meleeAttackDistance && meleeAttackUsed == 1) || (meleeAttackUsed == 0 && sightManager.objectToSeek != null && distanceToEnemy < meleeAttackDistance ) ) { //choose the close range fighting logic CloseRangeFightLogic(); } } if( (sightManager.objectToSeek != null && distanceToEnemy > meleeAttackDistance && meleeAttackUsed == 2) || (sightManager.objectToSeek != null && distanceToEnemy < meleeAttackDistance && meleeAttackUsed == 1)) { MeleeFightLogic(); } } //control the speed SpeedControl(); //the ai searches for cover once every number of seconds FindCover(); //sight control SightControl(); //crouching control if(allowCrouching == true) { ControlCrouching(); } //this has to be last, so that the preseration logic always kicks in SelfPreservation(); //take care of all emotions EmotionsControl(); //this script does ik head stuff //if we're engaged, then look at where we're aiming, else just look forward if(weaponController.weaponHoldingObject != null && currentState == CurrentState.engage /*&& Vector3.Distance( transform.position, weaponController.debugAimingPos) > 1.5f && sightManager.canSeeObject == true */) { if(weaponController.debugAimingPos != Vector3.zero) { animationManager.GetComponent<HandIK>().headShouldLook = true; animationManager.GetComponent<HandIK>().headLook = weaponController.debugAimingPos; } else { animationManager.GetComponent<HandIK>().headShouldLook = true; animationManager.GetComponent<HandIK>().headLook = sightManager.lastSeenLocation + enemyHeight; } } else { animationManager.GetComponent<HandIK>().headShouldLook = false; } //max weapon turn angle stuff, to make it more nice looking if(turnToEnemyWeaponAngle == true && currentState == CurrentState.engage) { movement.SetNewDestination(transform.position - (transform.position - sightManager.lastSeenLocation).normalized); } }
//come out of cover public IEnumerator ComeOutOfCover() { //crouch if(allowCrouching) { crouching = true; } //wait till we get to the cover TEST_IF_AT_COVER: if(Vector3.Distance(transform.position, coverManager.coverPostion) > 2f ) { yield return new WaitForFixedUpdate(); goto TEST_IF_AT_COVER; } else { if(debug) { Debug.LogError("We're in cover; face enemy"); } //face the general direction of the enemy movement.SetNewDestination( transform.position + ( sightManager.lastSeenLocation - transform.position).normalized * 1.1f); } //wait random amount of seconds yield return new WaitForSeconds(Random.Range(minCoverTime, maxCoverTime)); //reset hit hit = false; //go back to engage currentState = CurrentState.engage; engagementStatus = EngagementState.free; //move towards where we think the player is movement.SetNewDestination(sightManager.lastSeenLocation); if(debug) { Debug.Log("Come out of cover"); } }
void Awake() { //set the caches correctly weaponController = GetComponent<AIWeaponController>(); movementManager = GetComponent<AIMovementSwitcher>(); coverManager = GetComponent<SearchCover>(); sightManager = sight.GetComponent<Sight>(); earsManager = ears.GetComponent<Auditory>(); patrolM = patrolManager.GetComponent<PatrolManager>(); //at the start the current state is patroling currentState = CurrentState.patrol; //and the engagment is set to free engagementStatus = EngagementState.free; //some variables that we will later use for reference initFreezeTime = freezeTime; initShockTime = shockTime; initFOV = sightManager.fieldOfView; initChanceForFight = chanceForFight; initFear = fear; audioControl = GetComponent<ShooterAIAudioControl>(); if(GetComponent<NavMeshAgent>() != null) { initHeight = GetComponent<NavMeshAgent>().height; } initYScale = GetComponentInChildren<HealthManager>().gameObject.transform.localScale.y; movement = movementManager; //anti-bottlenecking procedure enemyDistanceCheckFrameBarrier += Random.Range(-30f, 30f); //find the health manager automatically healthManager = GetComponentInChildren<HealthManager>().gameObject; //setup multiple weapons correctly otherWeapons.Add( weaponController.weaponHoldingObject ); otherWeaponsMelee.Add( meleeAttackUsed ); }