using AIMachineTools; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.AI; public class AIMachine : MonoBehaviour { [HideInInspector] public DisplayLog logD; [HideInInspector] public GameManager gameManager; [HideInInspector] public BotStats botStats; [HideInInspector] public Health enemyHealth; [HideInInspector] public NavMeshAgent thisAgent; [HideInInspector] public BotStateMachine botMachine; [HideInInspector] public LineRenderer laserLine; [HideInInspector] public AudioSource audioS; [HideInInspector] public Animator animator; [HideInInspector] public SoundManager soundMgr; public string displayName; public int followDistance; public int healDistance; public int baseSearchRadius; //base radius without changes private int modifiedSearchRadius; //change from base radius via bot stats private int currentSearchRadius; //actual radius in use public int sentryRadiusIncrease; //amount radius is increased when in sentry state public int baseReinforcementRadius; public int attackDistance; public int retreatRadius; private int reinforcementRadius; public int hitChance; public int critChance; public int heavyHitChance; public int heavyHitModifier; public float fireRate; public float healRate; public float markerDistance; public float moveToDistance; public int turretRotateSpeed; public int barrelMoveSpeed; public int bodyRotateSpeed; public Transform lineOrigin; public Transform barrelEnd; public Transform turretPos; public Transform barrelPos; public Vector3 contactPoint; public Vector3 targetWaypoint; public Vector3 startingPos; public Vector3 agentVelocity; public GameObject marker; public GameObject grenadePrefab; public GameObject areaHealPrefab; public GameObject enemyObject; public GameObject barrelHitTarget; public GameObject playerObject; public GameObject followTarget; public GameObject markerCopy; public GameObject impactObject; public bool canSeeEnemy; public bool onTarget = false; public bool supportBuff = false; public bool removingEnemy = false; public bool disabled = false; public ParticleSystem laserParticles; public Light barrelLight; public List<GameObject> friendlyBots; public List<GameObject> additionalEnemies; public List<GameObject> nearbyFriendlies; public List<GameObject> objectives; public List<Material> lasers = new List<Material>(); private float timeToScan = 0; public int ModifiedSearchRadius { get => modifiedSearchRadius; set => modifiedSearchRadius = value; } public int ReinforcementRadius { get => reinforcementRadius; set => reinforcementRadius = value; } void Start() { foreach (GameObject bot in GameObject.FindGameObjectsWithTag("Target")) { if (bot.GetComponent<Health>() && bot.GetComponent<AIMachine>()) friendlyBots.Add(bot); } friendlyBots.Remove(this.gameObject); friendlyBots.Remove(GameObject.Find("PlayerSphere")); foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Cap Area")) { objectives.Add(obj); } foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Terminal")) { objectives.Add(obj); } botMachine = GetComponent<BotStateMachine>(); thisAgent = GetComponent<NavMeshAgent>(); botStats = GetComponent<BotStats>(); gameManager = GameObject.Find("Persistent Object").GetComponent<GameManager>(); soundMgr = GameObject.Find("Persistent Object").GetComponent<SoundManager>(); logD = GameObject.Find("RunningUI/Text Log/Log Panel/Content").GetComponent<DisplayLog>(); playerObject = GameObject.Find("PlayerSphere"); laserLine = GetComponent<LineRenderer>(); laserLine.enabled = false; audioS = GetComponent<AudioSource>(); startingPos = transform.position; barrelLight = barrelEnd.gameObject.GetComponent<Light>(); animator = GetComponent<Animator>(); barrelLight.enabled = false; if (gameObject.name.Contains("Blue")) displayName = "Blue Bot"; if (gameObject.name.Contains("Green")) displayName = "Green Bot"; if (gameObject.name.Contains("Orange")) displayName = "Orange Bot"; } void Update() { if (botMachine.baseStateName.Contains("Sentry") && currentSearchRadius == modifiedSearchRadius) currentSearchRadius = modifiedSearchRadius + sentryRadiusIncrease; else if (!botMachine.baseStateName.Contains("Sentry") && currentSearchRadius != modifiedSearchRadius) currentSearchRadius = modifiedSearchRadius; if (enemyObject != null) if (enemyObject.activeSelf == false) { enemyObject = null; Debug.Log(displayName + ": Enemy object is not active, removing."); } agentVelocity = thisAgent.velocity; timeToScan += Time.deltaTime; if (timeToScan >= 1.0f) { DrawSearchRays(); DrawBarrelRay(); timeToScan = 0.0f; } KeyCommands(); } private void KeyCommands() { if (Input.GetButtonDown("AI Idle Mode")) { botMachine.ChangeState(IdleState.instance); } if (Input.GetButtonDown("AI Follow Mode")) { followTarget = playerObject; botMachine.ChangeState(FollowState.instance); } if (Input.GetButtonDown("AI Search Mode")) { botMachine.ChangeState(SearchState.instance); } if (Input.GetButtonDown("AI Sentry Mode")) { botMachine.ChangeState(SentryState.instance); } if (Input.GetButtonDown("AI Move To Command")) { botMachine.ChangeState(MoveToState.instance); } } private void DrawSearchRays() { Quaternion startingAngle = Quaternion.AngleAxis(-60, Vector3.up); Quaternion stepAngle = Quaternion.AngleAxis(5, Vector3.up); RaycastHit hit; var angle = transform.rotation * startingAngle; var direction = angle * Vector3.forward; for (var i = 0; i < 72; i++) { if (Physics.Raycast(lineOrigin.transform.position, direction, out hit, currentSearchRadius)) { if (hit.collider.gameObject.CompareTag("Enemy")) { Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.red); canSeeEnemy = true; additionalEnemies.Add(hit.collider.gameObject); additionalEnemies = additionalEnemies.Distinct().ToList(); SetTarget(); break; } else if (hit.collider.gameObject.CompareTag("EnemyStructure")) { Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.green); canSeeEnemy = true; additionalEnemies.Add(hit.collider.gameObject); additionalEnemies = additionalEnemies.Distinct().ToList(); SetTarget(); break; } else if (hit.collider.gameObject.CompareTag("Target")) { Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.blue); nearbyFriendlies.Add(hit.collider.gameObject); nearbyFriendlies = nearbyFriendlies.Distinct().ToList(); } else { Debug.DrawRay(lineOrigin.transform.position, direction * hit.distance, Color.yellow); canSeeEnemy = false; } } else { Debug.DrawRay(lineOrigin.transform.position, direction * currentSearchRadius, Color.white); canSeeEnemy = false; } direction = stepAngle * direction; } for (int i = 0; i < additionalEnemies.Count; i++) { if (Vector3.Distance(transform.position, additionalEnemies[i].transform.position) > currentSearchRadius || additionalEnemies[i].activeSelf == false) additionalEnemies.RemoveAt(i); } for (int i = 0; i < nearbyFriendlies.Count; i++) { if (Vector3.Distance(transform.position, nearbyFriendlies[i].transform.position) > currentSearchRadius || nearbyFriendlies[i].activeSelf == false) nearbyFriendlies.RemoveAt(i); } } public void DrawBarrelRay() { RaycastHit hit; if (Physics.Raycast(barrelEnd.transform.position, barrelEnd.forward, out hit, attackDistance + 10f)) { if (hit.collider.gameObject.CompareTag("Enemy")) { Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * hit.distance, Color.red); barrelHitTarget = hit.collider.gameObject; contactPoint = hit.point; onTarget = true; } else if (hit.collider.gameObject.CompareTag("Target")) { Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * hit.distance, Color.blue); barrelHitTarget = hit.collider.gameObject; contactPoint = hit.point; onTarget = true; } else if (hit.collider.gameObject.CompareTag("EnemyStructure")) { Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * hit.distance, Color.green); barrelHitTarget = hit.collider.gameObject; contactPoint = hit.point; onTarget = true; } else { Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * hit.distance, Color.yellow); barrelHitTarget = null; onTarget = false; } } else { Debug.DrawRay(barrelEnd.transform.position, barrelEnd.forward * attackDistance); barrelHitTarget = null; onTarget = false; } } public void SetTarget() { float minDistance = float.MaxValue; GameObject targetBot = null; if (additionalEnemies.Count > 0) { for (int i = 0; i < additionalEnemies.Count; i++) { if (additionalEnemies[i].activeSelf == false) additionalEnemies.Remove(additionalEnemies[i]); } if (additionalEnemies.Count == 1) { enemyObject = additionalEnemies[0]; enemyHealth = enemyObject.GetComponent<Health>(); } else if (additionalEnemies.Count > 1) //if there is more than 1 enemy { for (int i = 0; i < additionalEnemies.Count; i++) { float thisDistance = Vector3.Distance(transform.position, additionalEnemies[i].transform.position); if (thisDistance < minDistance) { minDistance = thisDistance; targetBot = additionalEnemies[i]; } } enemyObject = targetBot; enemyHealth = enemyObject.GetComponent<Health>(); } } } public void MarkLocation() { RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit)) { markerCopy = Instantiate(marker, hit.point, Quaternion.identity); marker.transform.position = hit.point; } } public void RemoveMarker() { if (markerCopy != null) Destroy(markerCopy); } public void CreateImpactParticles() { Instantiate(impactObject, contactPoint, Quaternion.identity, gameObject.transform.parent); } }