using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; public class SkinlessMonsterComponent : MonoBehaviour { [SerializeField] private NavMeshAgent agent; [SerializeField] private SkinlessMonsterAnimator animator; private bool inDamageRange = false; private bool inDamageMargin = false; private bool atTarget = false; [SerializeField] private float atTargetDistance = 2; private TargetInformation target; [SerializeField] private float health = 2f; private bool isAlive = true; private Vector3 oppositeVector; private PlayerComponent player; private float distanceToPlayer; private FlareRegister flareRegister; [SerializeField] [Tooltip("This is the angle of visibility the enemy has")] private float visibilityConeLimit = 90f; [SerializeField] private float bulletSoundRange = 15f; private GameObject targetObject; [SerializeField] private float newTargetCooldown = 5f; private float timeSinceTarget = 0f; private InGameManager manager; private bool prePauseStoppedState = false; private void Awake() { //Find active player rn. PlayerComponent[] players = GameObject.FindObjectsOfType(); foreach (PlayerComponent p in players) { if (p.isActiveAndEnabled) { player = p; } } manager = GameObject.FindObjectOfType(); } private void Start() { flareRegister = GameObject.FindObjectOfType(); if (targetObject == null) targetObject = new GameObject(); targetObject.name = "Enemy Target"; if(player == null) { player = GameObject.FindObjectOfType(); } } void HandleTargetOperations() { //Update booleans for movement float distToTarget = Vector3.Distance(target.target.transform.position, agent.transform.position); atTarget = atTargetDistance >= distToTarget; if (target.hasDamageRange) { inDamageRange = target.damageRange <= distToTarget; inDamageMargin = target.damageMargin + target.damageRange <= distToTarget; } else { inDamageRange = false; inDamageMargin = false; } //Perform actions. if (target.runTowards) { if (inDamageRange) { //Damage is being dealt animator.InLight(); //Deal Damage health -= Time.deltaTime; if (health < 0 && this.isAlive) { this.Kill(); } } else if (inDamageMargin) { //Effective stop agent.SetDestination(transform.position); animator.StopMoving(); } else { if (atTarget) { //Effective stop agent.SetDestination(transform.position); animator.StopMoving(); if (target.isHostile) { animator.Attack(); animator.SetAttackType(Random.Range(0, 0)); } } else { agent.SetDestination(target.target.transform.position); animator.StartMoving(); animator.NotInLight(); } } } else { //Run away logic if (atTarget || distToTarget < 3) { animator.StopMoving(); } else { Ray r = new Ray(); r.origin = transform.position; r.direction = oppositeVector; RaycastHit hit; if (Physics.Raycast(r, out hit)) { animator.StartMoving(); agent.SetDestination(hit.point); } else { agent.SetDestination(transform.position + oppositeVector * 100); agent.isStopped = false; } } } if (atTarget&&target.isHostile) { SlowLookAt(target.target.transform.position-transform.position); } } void SlowLookAt(Vector3 targetVector,float animatedRotationSpeed=1f) { Vector3 relativePos = targetVector; Quaternion toRotation = Quaternion.LookRotation(relativePos); transform.rotation = Quaternion.Lerp(transform.rotation, toRotation, animatedRotationSpeed * Time.deltaTime); } void CheckForAOERanges() { foreach(BulletComponent bullet in flareRegister.bullets) { float dist = Vector3.Distance(bullet.transform.position, transform.position); if (dist <= bullet.DamageRange) { this.health = 0; this.Kill(true); } } foreach(FlareBeacon beacon in flareRegister.beacons) { float dist = Vector3.Distance(beacon.transform.position, transform.position); if (dist <= beacon.Range) { this.health = 0f; } } if (this.health <= 0) { this.Kill(); } } public bool isPlayerVisible(bool withAngle) { Ray r = new Ray(); r.origin = transform.position; r.direction = player.transform.position - transform.position; Vector3 toPosition = (player.transform.position - transform.position).normalized; float angleToPosition = Vector3.Angle(transform.forward, toPosition); RaycastHit hit; if(Physics.Raycast(r, out hit)) { GameObject hitObject = hit.transform.gameObject; if (hitObject.GetComponent() != null) { //hit player return angleToPosition <= this.visibilityConeLimit||!withAngle; }else if (hitObject.GetComponentInParent() != null) { //also hit player return angleToPosition <= this.visibilityConeLimit||!withAngle; } } return false; } void SetLiveTargeting() { if (!isAlive) { //this.targetObject.transform.position = transform.position; this.Stop(); } distanceToPlayer = Vector3.Distance(this.transform.position, player.transform.position); //print("Dist Comparison "+distanceToPlayer.ToString()+" Noise:"+player.NoiseManager.NoiseDistance); bool isPlayerVisible = this.isPlayerVisible(true); //check if player is heard or player line of sight if (distanceToPlayer <= player.NoiseManager.NoiseDistance||isPlayerVisible) { //check that nothing in between if (this.isPlayerVisible(false)) { this.Target(player.gameObject, true); } } else { if (this.timeSinceTarget < this.newTargetCooldown) { //no further targeting //Stop(); return; } BulletComponent closestBullet = null; float closestDistance = Mathf.Infinity; foreach(BulletComponent bullet in this.flareRegister.bullets) { float bDist = Vector3.Distance(bullet.transform.position, transform.position); if (closestBullet==null||(bDist< bulletSoundRange&&bDist /// Runs away from object. A minimum range is specified where it no longer takes damage, and a minimum margin is /// speicifed where it can stop running. /// /// /// /// public void RunAwayFrom(GameObject obj,float minRange,float minMargin) { if(target== null ||target.target != obj) { //target = new TargetInformation(obj, false, true, minRange, minMargin, false); target = new TargetInformation(); target.target = obj; target.isHostile = false; target.hasDamageRange = true; target.damageRange = minRange; target.damageMargin = minMargin; target.runTowards = false; oppositeVector = -(target.target.transform.position - transform.position).normalized; timeSinceTarget = 0; } } public void Stop() { target = new TargetInformation(); target.target = this.gameObject; target.isHostile = false; target.hasDamageRange = false; target.runTowards = true; } public void Kill(bool fast=false) { if (this.isAlive) { this.animator.Kill(fast); this.isAlive = false; agent.isStopped = true; } } private void OnTriggerEnter(Collider other) { if (other.gameObject.GetComponent() != null) { this.health -= other.gameObject.GetComponent().DamageMagnitude; } } } class TargetInformation { public GameObject target; public bool isHostile; public bool hasDamageRange; public float damageRange; public float damageMargin; public bool runTowards; }