using System; using System.Collections; using System.Collections.Generic; using System.Linq.Expressions; using System.Security.Cryptography; using UnityEngine; using UnityEngine.UI; using Random = UnityEngine.Random; public class EnemyManager : MonoBehaviour { // Interfaces public GameObject player; public GameObject leftView, rightView, playerLeft, playerRight, playerTop, playerCenter; public CameraMovement cameraMovement; public Vector3 playerPosition; public Vector3 headHeight; public Transform head; public GameManager gameManager; public AudioSource gunshot; public LineRenderer lineRenderer; private TargetDamageable targetDamageable; private LearningEngine learningEngine; private GunHandler gunHandler; public GameObject feet; private GameObject playerFeet; public GameObject gunBarrel; public Image healthBar; // constants set by gamemanager private float minFireRate; private float maxFireRate; public float damage; private float aimModifier; public float health; private float noticeRate; private float speed; // flags private bool firstView; private bool firstDamage; public bool moving; private Vector3 startPoint; private Vector3 moveTo; private Rigidbody rigidbody; private float startTime; private bool readyToMove = false; // trackers private float timeOfEngagementStart; private float timeOfFirstDamage; private float damageDealt; private float timeOfNextShot; private Vector3 playerDirectionAtStart; private Vector3 playerDirectionAtKill; public int id; void Start() { // configure constants gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); gunshot = GetComponent<AudioSource>(); targetDamageable = GetComponent<TargetDamageable>(); lineRenderer = GetComponent<LineRenderer>(); lineRenderer.startColor = Color.white; lineRenderer.endColor = Color.white; lineRenderer.enabled = false; learningEngine = GameObject.Find("GameManager").GetComponent<LearningEngine>(); rigidbody = GetComponent<Rigidbody>(); firstView = true; firstDamage = true; startTime = Time.time; id = Random.Range(0, int.MaxValue); moving = Random.Range(0, 4) == 0; // 25% chance to be moving } // Update is called once per frame void Update() { if (!readyToMove && Time.time - startTime > 0.5f) { readyToMove = true; if (moving) { var pointFound = false; startPoint = transform.position; while (!pointFound) { var relativeChange = new Vector3(Random.Range(-5, 5), 0, Random.Range(-5, 5)); moveTo = startPoint + relativeChange; if (!Physics.Linecast(startPoint, moveTo)) { pointFound = true; } } } } head = transform.Find("headhitbox").transform; headHeight = head.position; if (moving && PlayerPrefs.GetInt("playerTrackingEnabled") == 1 && readyToMove) { rigidbody.position = Vector3.Lerp(startPoint, moveTo, Mathf.PingPong(Time.time, speed)); transform.position = rigidbody.position; } healthBar.fillAmount = (targetDamageable.health / targetDamageable.maxHealth); if (player == null) { player = GameObject.FindGameObjectWithTag("Player"); cameraMovement = player.GetComponentInChildren<CameraMovement>(); gunHandler = player.GetComponentInChildren<GunHandler>(); playerFeet = GameObject.Find("playerFeet"); playerCenter = GameObject.Find("playerCenterView"); playerLeft = GameObject.Find("playerLeftView"); playerRight = GameObject.Find("playerRightView"); playerTop = GameObject.Find("playerTopView"); } playerPosition = player.transform.position; if (CanSeePlayer()) { if (firstView) { timeOfNextShot = Time.time + noticeRate; timeOfEngagementStart = Time.time; firstView = false; learningEngine.StartEngagement(this); learningEngine.ReportAmmo(gunHandler.ammoInClip); learningEngine.ReportHeightDifference(this, playerFeet.transform.position.y - feet.transform.position.y); playerDirectionAtStart = cameraMovement.transform.forward; } if (Time.time > timeOfNextShot) { ShootPlayer(); } } if (!firstView) { // run every time once engagement has started if (targetDamageable.health < 100 && firstDamage) { firstDamage = false; timeOfFirstDamage = Time.time; gameManager.ReportTimeToDamage(timeOfFirstDamage - timeOfEngagementStart, this); } } } public void AddHit() { } public void ReportDeath() { gameManager.ReportHealthLoss(damageDealt, this); gameManager.ReportTimeToKill(Time.time - timeOfEngagementStart, this); // learning engine report crosshair movement playerDirectionAtKill = cameraMovement.transform.forward; var xMovement = Vector3.Angle(new Vector3(playerDirectionAtStart.x, 0, playerDirectionAtStart.z), new Vector3(playerDirectionAtKill.x, 0, playerDirectionAtKill.z)); var yMovement = Vector3.Angle(new Vector3(0, playerDirectionAtStart.y, playerDirectionAtStart.z), new Vector3(0, playerDirectionAtKill.y, playerDirectionAtKill.z)); learningEngine.ReportCrosshairMovement(this, xMovement, yMovement); learningEngine.EndEngagement(this); } bool CanSeePlayer() { var mePositions = new[] {leftView.transform.position, rightView.transform.position}; var playerPositions = new[] {playerCenter.transform.position, playerLeft.transform.position, playerRight.transform.position, playerTop.transform.position}; bool hitPlayer = false; foreach (var mePos in mePositions) { foreach (var playerPos in playerPositions) { if (!Physics.Linecast(mePos, playerPos)) { hitPlayer = true; } } } return hitPlayer; } IEnumerator DrawLine(Vector3 start, Vector3 end) { Color c = lineRenderer.material.color; lineRenderer.SetPosition(0, start); lineRenderer.SetPosition(1, end); lineRenderer.enabled = true; for (float alpha = 1f; alpha >= 0; alpha -= 0.1f) { c.a = alpha; lineRenderer.material.color = c; yield return null; } lineRenderer.enabled = false; } void ShootPlayer() { AudioSource.PlayClipAtPoint(gunshot.clip, transform.position); float spread = aimModifier; Vector3 randomDir = new Vector3(Random.Range(-spread, spread), Random.Range(-spread, spread), Random.Range(-spread, spread)); Vector3 sprayDir = head.TransformVector(randomDir); Vector3 dir = (playerPosition - headHeight).normalized; RaycastHit hit; if (Physics.Raycast(headHeight, dir + sprayDir, out hit)) { StartCoroutine(DrawLine(gunBarrel.transform.position, hit.transform.position)); if (hit.collider.gameObject.CompareTag("Player")) { damageDealt += damage; gameManager.DealDamage((int) damage); learningEngine.ReportDamageSource(this); } } timeOfNextShot = Time.time + minFireRate + Random.Range(0f, maxFireRate); } public void SetConstants() { if (gameManager == null) { gameManager = GameObject.Find("GameManager").GetComponent<GameManager>(); } if (targetDamageable == null) { targetDamageable = GetComponent<TargetDamageable>(); } noticeRate = gameManager.enemyNoticeRate; damage = gameManager.enemyDamage; minFireRate = gameManager.enemyFireRate; aimModifier = gameManager.enemyAimModifier; health = gameManager.enemyHealth; maxFireRate = gameManager.enemyMaxFireRate; targetDamageable.maxHealth = gameManager.enemyHealth; targetDamageable.health = gameManager.enemyHealth; speed = gameManager.enemySpeed; } }