public override IEnumerator InState(EnemyAIMachine owner) { while (owner.botMachine.currentState == EnemyMoveToState.instance) { if (!owner.disabled) { if (RotateBody(owner, owner.objective.transform.position)) { owner.thisAgent.SetDestination(owner.objective.transform.position); Debug.DrawLine(owner.transform.position, owner.objective.transform.position); if (Vector3.Distance(owner.transform.position, owner.objective.transform.position) <= owner.followDistance) { //go to the defend state Debug.Log("Objective in range, going to defend state"); owner.botMachine.ChangeState(EnemyDefendState.instance); yield break; } } if (owner.canSeeEnemy && owner.enemyObject != null) //if an enemy is found, go to the chase state { owner.botMachine.ChangeState(EnemyChaseState.instance); yield break; } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return(null); } }
private void MoveTurret(EnemyAIMachine _owner) //called to move the bots turret so that it faces the target { //declare variables that will be used to determine how to move the turret Vector3 hitPos = _owner.enemyObject.GetComponentInChildren <HighlightObject>().transform.position; Quaternion hitRot = Quaternion.LookRotation(hitPos - _owner.transform.position); Quaternion turretRot = Quaternion.LookRotation(hitPos - _owner.turretPos.transform.position); if (Vector3.Angle(_owner.turretPos.transform.forward, _owner.enemyObject.transform.position - _owner.turretPos.transform.position) > 5) //rotate the turret until it is facing within 5 degrees of the enemy { //rotate the turret over time to the enemy _owner.turretPos.transform.rotation = Quaternion.RotateTowards(_owner.turretPos.transform.rotation, turretRot, Time.deltaTime * _owner.turretRotateSpeed); //set the turrets y euler angle so that it only moves on that transform _owner.turretPos.transform.localEulerAngles = new Vector3(0, _owner.turretPos.transform.localEulerAngles.y, 0); } //rotate the barrel over time to the enemy _owner.barrelPos.transform.rotation = Quaternion.RotateTowards(_owner.barrelPos.transform.rotation, turretRot, Time.deltaTime * _owner.barrelMoveSpeed); //set the barrels y euler angle so that it only moves on that transform if (_owner.turretBot) { _owner.barrelPos.transform.localEulerAngles = new Vector3(_owner.barrelPos.transform.localEulerAngles.x, 0, 0); } else { _owner.barrelPos.transform.localEulerAngles = new Vector3(0, _owner.barrelPos.transform.localEulerAngles.y, 0); } }
public override IEnumerator InState(EnemyAIMachine owner) { while (owner.botMachine.currentState == EnemyTurretSearchState.instance) { if (!owner.disabled) { owner.GetComponent <Animator>().enabled = true; if (owner.canSeeEnemy && owner.enemyObject != null) { owner.botMachine.ChangeState(EnemyAttackState.instance); yield break; } else { owner.canSeeEnemy = false; } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return(null); } }
public Vector3 MoveWaypoint(EnemyAIMachine _owner) //generate a position within the search radius { RaycastHit hit; NavMeshHit NH; Vector3 point = _owner.transform.position + Random.insideUnitSphere * _owner.searchRadius; //create a point on the navmesh NavMesh.SamplePosition(point, out NH, _owner.searchRadius, NavMesh.AllAreas); //create a position to give to the NH var if (Physics.Raycast(_owner.lineOrigin.transform.position, NH.position - _owner.transform.position, out hit, _owner.searchRadius)) //draw a ray from this bot to the point at the same length as the distance from the bot to the point { //if the ray hits any object, get a new point and redo the raycast until the cast is false do { point = _owner.transform.position + Random.insideUnitSphere * _owner.searchRadius; NavMesh.SamplePosition(point, out NH, _owner.searchRadius, NavMesh.AllAreas); }while (Physics.Raycast(_owner.lineOrigin.transform.position, NH.position - _owner.transform.position, out hit, _owner.searchRadius)); } //show rays from the bots position to the point Debug.DrawLine(_owner.gameObject.transform.position, NH.position, Color.cyan, 5); Debug.DrawRay(_owner.lineOrigin.transform.position, NH.position - _owner.transform.position, Color.magenta, 5); return(NH.position); }
public override IEnumerator InState(EnemyAIMachine owner) //because of the checks done before coming to this state, there will always be a bot in range to retreat to { Vector3 destination = owner.transform.position; for (int i = 0; i < owner.movingBotsOnly.Count; i++) //for all moving bots, check if any of them are close enough to retreat to { if (Vector3.Distance(owner.movingBotsOnly[i].transform.position, owner.transform.position) <= owner.retreatRadius && Vector3.Distance(owner.movingBotsOnly[i].transform.position, owner.transform.position) >= 50) { destination = owner.movingBotsOnly[i].transform.position; break; } } owner.logD.RecieveLog(owner.displayName + " is attempting to retreat!"); //generate a log stating that the bot is retreating while (owner.botMachine.currentState == EnemyRetreatState.instance) //called from bots in the attack state when they are outnumbered { if (!owner.disabled) { if (RotateBody(owner, destination)) { owner.thisAgent.SetDestination(destination); //set the destination for the agent to the destination variable that was generated before entering the while loop Debug.DrawLine(owner.transform.position, destination, Color.green); //draw a debug line that shows the destination the bot should retreat to if (Vector3.Distance(owner.transform.position, destination) <= 5) //if the distance between the bot and the destination is less than 5, change to the search state { owner.canSeeEnemy = false; owner.enemyObject = null; owner.health = null; owner.additionalEnemies.Clear(); //clear the bots list of enemies if (owner.insideNormalSearch) { owner.botMachine.ChangeState(EnemySearchState.instance); } else if (owner.insideDefend) { owner.botMachine.ChangeState(EnemyMoveToState.instance); } else if (owner.insidePartner) { owner.botMachine.ChangeState(EnemyPartnerState.instance); } } } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return(null); } }
public override IEnumerator InState(EnemyAIMachine owner) { while (owner.botMachine.currentState == EnemyChaseState.instance) { if (!owner.disabled) { if (owner.enemyObject == null) //if the enemy is gone, go back to search { owner.health = null; if (owner.insideNormalSearch) { owner.botMachine.ChangeState(EnemySearchState.instance); } else if (owner.insideDefend) { owner.botMachine.ChangeState(EnemyMoveToState.instance); } else if (owner.insidePartner) { owner.botMachine.ChangeState(EnemyPartnerState.instance); } yield break; } if (owner.enemyObject != null) //if the enemy is still around, go after it { if (RotateBody(owner, owner.enemyObject.transform.position)) //if the bot is rotated towards the enemy, start moving { owner.thisAgent.SetDestination(owner.enemyObject.transform.position); if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= owner.attackDistance && owner.canSeeEnemy) //if the enemy is in attack range and is visible, attack it { owner.botMachine.ChangeState(EnemyAttackState.instance); yield break; } } if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= owner.attackDistance && owner.canSeeEnemy) //if the enemy is in range and visible but the bot is not rotated, just attack it { owner.botMachine.ChangeState(EnemyAttackState.instance); yield break; } } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return(null); } }
public override IEnumerator InState(EnemyAIMachine owner) { Vector3 point = MoveWaypoint(owner); float waitTime = 3f; float elapsedTime = 0f; while (owner.botMachine.currentState == EnemySearchState.instance) { if (!owner.disabled) { //before setting the destination, have the bot rotate to face the point if (RotateBody(owner, point)) { owner.thisAgent.SetDestination(point); //set the bots destination to the generated point if (Vector3.Distance(owner.gameObject.transform.position, point) <= 5) //if the bot gets within 5 units of a destination, stop and wait { owner.thisAgent.SetDestination(owner.gameObject.transform.position); //set destination to itself elapsedTime += Time.deltaTime; //track time if (elapsedTime >= waitTime) //if the elapsed time goes over the wait time, generate a new waypoint { elapsedTime = 0f; point = MoveWaypoint(owner); } } } if (owner.canSeeEnemy && owner.enemyObject != null) //if an enemy is found, go to the chase state { owner.botMachine.ChangeState(EnemyChaseState.instance); yield break; } else { owner.canSeeEnemy = false; } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return(null); } }
private bool RotateBody(EnemyAIMachine _owner, Vector3 navPoint) //called to have the bot rotate to face the waypoint before navigating to it { //declare variables that will be used to determine how to move the bot Quaternion targetRot = Quaternion.LookRotation(navPoint - _owner.transform.position); //rotate the bot over time to face the enemy _owner.transform.rotation = Quaternion.RotateTowards(_owner.transform.rotation, targetRot, Time.deltaTime * _owner.bodyRotateSpeed); //set the bots y euler angle so that it only moves on that transform _owner.transform.localEulerAngles = new Vector3(0, _owner.transform.localEulerAngles.y, 0); if (Vector3.Angle(_owner.transform.forward, navPoint - _owner.transform.position) < 10) { return(true); } else { return(false); } }
public override IEnumerator InState(EnemyAIMachine owner) { float timeWaitingToShoot = 0; bool movingCloserToEnemy = false; while (owner.botMachine.currentState == EnemyAttackState.instance) { if (!owner.disabled) { if (owner.enemyObject == null) { owner.canSeeEnemy = false; owner.health = null; if (!owner.insideTurret) { owner.botMachine.ChangeState(EnemyChaseState.instance); } else { owner.botMachine.ChangeState(EnemyTurretSearchState.instance); } yield break; } if (owner.enemyObject != null) { if (owner.turretBot == false && movingCloserToEnemy == false) { owner.thisAgent.SetDestination(owner.transform.position); } else { owner.GetComponent <Animator>().enabled = false; } //before firing check if there are too many enemies and if the bot should change to the retreat state if (owner.additionalEnemies.Count >= 2 && owner.friendlyBots.Count <= 1 && !owner.turretBot) { for (int i = 0; i < owner.movingBotsOnly.Count; i++) //for all moving bots, check if any of them are close enough to retreat to { if (Vector3.Distance(owner.movingBotsOnly[i].transform.position, owner.transform.position) <= owner.retreatRadius && Vector3.Distance(owner.movingBotsOnly[i].transform.position, owner.transform.position) >= 50) { owner.botMachine.ChangeState(EnemyRetreatState.instance); yield break; } } } int numberOfBotsCalled = 0; for (int i = 0; i < owner.movingBotsOnly.Count; i++) //if there are any friendly bots within the reinforcementRadius, give them this bots target { if (Vector3.Distance(owner.transform.position, owner.movingBotsOnly[i].transform.position) <= owner.reinforcementRadius) { if (owner.movingBotsOnly[i].GetComponent <EnemyAIMachine>().enemyObject == null) //if the current bot doesnt already have a target, set it { owner.movingBotsOnly[i].GetComponent <EnemyAIMachine>().enemyObject = owner.enemyObject; numberOfBotsCalled++; } } } if (numberOfBotsCalled != 0) { owner.logD.RecieveLog(owner.displayName + " called " + numberOfBotsCalled + " bot(s) for help!"); numberOfBotsCalled = 0; } if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= owner.attackDistance && owner.canSeeEnemy) { MoveTurret(owner); timeWaitingToShoot += Time.deltaTime; if (timeWaitingToShoot >= 5f) { owner.thisAgent.SetDestination(owner.enemyObject.transform.position); movingCloserToEnemy = true; if (Vector3.Distance(owner.transform.position, owner.enemyObject.transform.position) <= 20) { owner.thisAgent.SetDestination(owner.transform.position); movingCloserToEnemy = false; } } //after calling the MoveTurret method, wait for the onTarget bool to be true if (owner.onTarget == true) { timeWaitingToShoot = 0; owner.laserLine.SetPosition(0, owner.barrelEnd.position); owner.laserLine.SetPosition(1, owner.contactPoint); owner.laserLine.enabled = true; owner.audioS.PlayOneShot(owner.GetComponent <MultipleAudioClips>().clips[1]); yield return(new WaitForSeconds(0.5f)); owner.laserLine.enabled = false; Shoot(owner); bool removing = false; for (int i = 0; i < owner.friendlyBots.Count; i++) //if any of the bots are already removing an enemy, dont do anything { if (owner.friendlyBots[i].GetComponent <EnemyAIMachine>().removingEnemy == true) { removing = true; break; } } if (removing == false) { if (owner.enemyObject != null) { if (owner.health.health <= 0) { owner.removingEnemy = true; OnEnemyDeath(owner); } } } } } else { if (!owner.insideTurret) { owner.botMachine.ChangeState(EnemyChaseState.instance); } else { owner.botMachine.ChangeState(EnemyTurretSearchState.instance); } yield break; } } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return(null); } }
private void OnEnemyDeath(EnemyAIMachine _owner) { var tempEnemyHolder = _owner.enemyObject; _owner.enemyObject.SetActive(false); _owner.enemyObject = null; _owner.health = null; _owner.canSeeEnemy = false; if (tempEnemyHolder.GetComponent <StructureInfo>()) //check what type of enemy was killed and put out the correct logs { _owner.logD.RecieveLog(tempEnemyHolder.GetComponent <StructureInfo>().displayName + " has died", Color.red); } else { if (tempEnemyHolder.GetComponent <Health>().HP == null) //if the enemy target has no text variable, it is an ally (protect mode unit) { _owner.logD.RecieveLog(tempEnemyHolder.GetComponent <AIAllyMachine>().displayName + " has died", Color.red); } else { tempEnemyHolder.GetComponent <Health>().HP.text = "Dead"; if (tempEnemyHolder.GetComponent <AIMachine>() != null) { _owner.logD.RecieveLog(tempEnemyHolder.GetComponent <AIMachine>().displayName + " has died", Color.red); } else { _owner.logD.RecieveLog(_owner.displayName + ": lead bot has died", Color.red); } } } for (int i = 0; i < _owner.friendlyBots.Count; i++) //after the enemy is dead, check other friendly bots for the same target, remove it, then send them to an appropriate state { EnemyAIMachine targetBot = null; targetBot = _owner.friendlyBots[i].GetComponent <EnemyAIMachine>(); if (targetBot.enemyObject == tempEnemyHolder) { targetBot.enemyObject = null; targetBot.health = null; targetBot.canSeeEnemy = false; var currentState = targetBot.botMachine.currentState; if (currentState == EnemyAttackState.instance && !_owner.turretBot) { targetBot.botMachine.ChangeState(EnemyChaseState.instance); } else if (currentState == EnemyAttackState.instance && _owner.turretBot) { targetBot.botMachine.ChangeState(EnemyTurretSearchState.instance); } } } _owner.removingEnemy = false; }
private void Shoot(EnemyAIMachine _owner) { int randomHitChance = Random.Range(0, 100); int randomCritChance = Random.Range(0, 100); if (!_owner.enemyObject.GetComponent <StructureInfo>()) { int modifiedHitChance = 0; modifiedHitChance = _owner.enemyObject.GetComponent <BotStats>().ModifyEnemyHitChance(_owner.hitChance); //call to the enemys bot stats script to change the hit chance based on thier lucky stat if (randomHitChance <= modifiedHitChance && _owner.enemyObject != null) { _owner.audioS.PlayOneShot(_owner.enemyObject.GetComponent <MultipleAudioClips>().clips[0]); int damageAmt = 0; if (randomCritChance <= _owner.critChance) { _owner.health.HealthReduce(2); //reduces health of target, health script grabbed in update of EnemyAIMachine damageAmt = 2; } else { _owner.health.HealthReduce(); damageAmt = 1; } if (_owner.enemyObject.GetComponent <AIMachine>() != null) //if the enemy is an player controlled AI { _owner.logD.RecieveLog(_owner.displayName + ": " + _owner.enemyObject.GetComponent <AIMachine>().displayName + " takes " + damageAmt + " damage"); if (_owner.enemyObject.GetComponent <AIMachine>().enemyObject == null) //if the enemy doesnt already have a target, set it to this bot { _owner.enemyObject.GetComponent <AIMachine>().enemyObject = _owner.gameObject; _owner.enemyObject.GetComponent <AIMachine>().canSeeEnemy = true; } } else if (_owner.enemyObject.GetComponent <AIAllyMachine>()) //if the enemy is an Ally AI { _owner.logD.RecieveLog(_owner.displayName + ": Ally bot takes " + damageAmt + " damage"); if (_owner.enemyObject.GetComponent <AIAllyMachine>().enemyObject == null) //if the enemy doesnt already have a target, set it to this bot { _owner.enemyObject.GetComponent <AIAllyMachine>().enemyObject = _owner.gameObject; _owner.enemyObject.GetComponent <AIAllyMachine>().canSeeEnemy = true; } } else //if the enemy is the player { _owner.logD.RecieveLog(_owner.displayName + ": lead bot takes " + damageAmt + " damage"); } } else { _owner.logD.RecieveLog(_owner.displayName + " missed their shot."); } } else { if (randomHitChance <= _owner.hitChance && _owner.enemyObject != null) { _owner.audioS.PlayOneShot(_owner.enemyObject.GetComponent <MultipleAudioClips>().clips[0]); int damageAmt = 0; if (randomCritChance <= _owner.critChance) { _owner.health.HealthReduce(2); damageAmt = 2; } else { _owner.health.HealthReduce(); damageAmt = 1; } _owner.logD.RecieveLog(_owner.displayName + ": " + _owner.enemyObject.GetComponent <StructureInfo>().displayName + "takes " + damageAmt + " damage"); } } }
public abstract IEnumerator InState(EnemyAIMachine owner);
public void Start() { owner = GetComponent <EnemyAIMachine>(); currentState = null; }
public override IEnumerator InState(EnemyAIMachine owner) //no errors but not all leaders get followers and some bots wont move after spawning { bool followTargetFound = false; GameObject followTarget = null; while (owner.botMachine.currentState == EnemyPartnerState.instance) { if (!owner.disabled) { if (!followTargetFound) //check if the target has been found before entering the loop { //check each bot for open slots and then set them as the follow target for (int i = 0; i < owner.movingBotsOnly.Count; i++) { var targetBot = owner.movingBotsOnly[i].GetComponent <EnemyAIMachine>(); if (targetBot.leader == true) //check if the bot is a leader { if (targetBot.partnerBot == null) //if the first partner slot is empty, fill it and then break out of the for loop { targetBot.partnerBot = owner.gameObject; followTarget = owner.movingBotsOnly[i]; followTargetFound = true; break; } if (targetBot.partnerBot1 == null) //if the second partner slot is empty, fill it and then break out of the loop { targetBot.partnerBot1 = owner.gameObject; followTarget = owner.movingBotsOnly[i]; followTargetFound = true; break; } } } if (!followTargetFound || followTarget == null || !followTarget.activeSelf) //if a follow target is not found after checking each bot, revert to regular searching { followTarget = null; followTargetFound = false; owner.insidePartner = false; owner.insideNormalSearch = true; owner.botMachine.ChangeState(EnemySearchState.instance); } } if (followTargetFound == true && followTarget != null && followTarget.activeSelf) //check if the target exists and is active { if (RotateBody(owner, followTarget.transform.position)) { owner.thisAgent.SetDestination(followTarget.transform.position); //if the bot is too close to the target, stop where you are if (Vector3.Distance(owner.transform.position, followTarget.transform.position) <= owner.followDistance) { owner.thisAgent.SetDestination(owner.transform.position); } } //if the bot finds an enemy while following, chase it if (owner.canSeeEnemy && owner.enemyObject != null) { //enter the partner chase state owner.botMachine.ChangeState(EnemyChaseState.instance); } } if (followTarget == null || followTargetFound == false || !followTarget.activeSelf) //if the target is null or inactive, reset the variables { followTarget = null; followTargetFound = false; owner.insidePartner = false; owner.insideNormalSearch = true; owner.botMachine.ChangeState(EnemySearchState.instance); } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return(null); } }
void Shoot() //draw a ray out from the player and damage the enemy { RaycastHit hit; //if the ray hits something when firing in a straight line if (Physics.Raycast(barrelEnd.position, barrelEnd.forward, out hit) && animator.GetBool("Firing") == false) { //set the laser line to end whereever the laser hits laserLine.SetPosition(0, barrelEnd.position); laserLine.SetPosition(1, hit.point); animator.SetBool("Firing", true); laserLine.enabled = true; audioS.PlayOneShot(GetComponent <MultipleAudioClips>().clips[1]); if (hit.collider.gameObject.CompareTag("Enemy")) { EnemyAIMachine enemyHit = hit.collider.gameObject.GetComponent <EnemyAIMachine>(); Health enemyHP = hit.collider.gameObject.GetComponent <Health>(); int randCritChance = Random.Range(0, 100); int randHeavyHitChance = Random.Range(0, 100); if (randCritChance <= critChance) { int hitDamage = 2; if (randHeavyHitChance <= heavyHitChance) { hitDamage += heavyHitModifier; } enemyHP.HealthReduce(hitDamage); displayLog.RecieveLog(enemyHit.displayName + " takes " + hitDamage + " Damage, CRITICAL!!!!"); } else { int hitDamage = 1; if (randHeavyHitChance <= heavyHitChance) { hitDamage += heavyHitModifier; } enemyHP.HealthReduce(hitDamage); displayLog.RecieveLog(enemyHit.displayName + " takes " + hitDamage + " Damage"); } hit.collider.gameObject.GetComponent <AudioSource>().PlayOneShot(hit.collider.gameObject.GetComponent <MultipleAudioClips>().clips[0]); enemyHit.enemyObject = gameObject; enemyHit.canSeeEnemy = true; if (enemyHP.health <= 0) { gameManager.OnKill(enemyHit.gameObject); displayLog.RecieveLog(enemyHit.displayName + " was destroyed", Color.red); botStats.KillExpIncrease(hit.collider.gameObject); hit.collider.gameObject.SetActive(false); } } else if (hit.collider.gameObject.CompareTag("EnemyStructure")) { StructureInfo enemyHit = hit.collider.gameObject.GetComponent <StructureInfo>(); Health enemyHP = hit.collider.gameObject.GetComponent <Health>(); int randCritChance = Random.Range(0, 100); int randHeavyHitChance = Random.Range(0, 100); if (randCritChance <= critChance) { int hitDamage = 2; if (randHeavyHitChance <= heavyHitChance) { hitDamage += heavyHitModifier; } enemyHP.HealthReduce(hitDamage); displayLog.RecieveLog(enemyHit.displayName + " takes " + hitDamage + " Damage, CRITICAL!!!!"); } else { int hitDamage = 1; if (randHeavyHitChance <= heavyHitChance) { hitDamage += heavyHitModifier; } enemyHP.HealthReduce(hitDamage); displayLog.RecieveLog(enemyHit.displayName + " takes " + hitDamage + " Damage"); } hit.collider.gameObject.GetComponent <AudioSource>().PlayOneShot(hit.collider.gameObject.GetComponent <MultipleAudioClips>().clips[0]); if (enemyHP.health <= 0) { gameManager.OnKill(enemyHit.gameObject); displayLog.RecieveLog(enemyHit.displayName + " was destroyed", Color.red); botStats.KillExpIncrease(hit.collider.gameObject); hit.collider.gameObject.SetActive(false); } } } }