using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.AI; public class Virus : MonoBehaviour { private Item item; private NavMeshAgent nav; void Awake() { item = GetComponentInChildren<Item>(); nav = GetComponentInChildren<NavMeshAgent>(); nav.isStopped = true; repathTimer = new SimpleTimer(); attackTween = new SimpleTween(); attackTimer = new SimpleTimer(); } // Start is called before the first frame update void Start() { } void StartLocal() { PathToPlayer(); } private float pathTime; private Player targetPlayer; private SimpleTimer repathTimer; private SimpleTween attackTween; private SimpleTimer attackTimer; private void PathToPlayer() { List<Player> players = new List<Player>(); List<float> weights = new List<float>(); foreach (Player p in FindObjectsOfType<Player>()) { players.Add(p); float dist = (p.transform.position - transform.position).magnitude; weights.Add(30 - dist); } if (players.Count == 0) { repathTimer.Start(3, PathToPlayer); } float total = weights.Sum(); targetPlayer = null; float rand = UnityEngine.Random.Range(0, total); float sum = 0; for (int i = 0; i < players.Count; i++) { sum += weights[i]; if (rand < sum || i == players.Count - 1) { targetPlayer = players[i]; break; } } if (targetPlayer != null) { nav.stoppingDistance = AttackMaxDist * 0.8f; pathTime = Time.realtimeSinceStartup; nav.isStopped = false; nav.destination = TargetBasePos; } } public void StopPathing() { nav.isStopped = true; } public bool IsPathFinished() { if (!nav.pathPending) { if (nav.remainingDistance <= nav.stoppingDistance) { if (!nav.hasPath || nav.velocity.sqrMagnitude == 0f) { return true; } } } return false; } public Vector3 TargetBasePos { get { if (targetPlayer == null) return new Vector3(); return targetPlayer.transform.position + Vector3.down * targetPlayer.BottomOffset; } } public float DistToTarget { get { if (targetPlayer == null) return 99999; return (TargetBasePos - transform.position).magnitude; } } public float AttackMaxDist = 1.3f; public float RepathTime = 1.3f; // Update is called once per frame void Update() { if (item != null && item.IsLocal && !nav.isStopped) { if (IsPathFinished()) { if (DistToTarget > AttackMaxDist) { nav.destination = TargetBasePos; } else { StopPathing(); AttackTarget(); } } else if (targetPlayer == null) { StopPathing(); targetPlayer = null; PathToPlayer(); } else if (Time.realtimeSinceStartup > pathTime + RepathTime && DistToTarget > 2) { nav.destination = TargetBasePos; } } } void OnDestroy() { attackTween.Stop(); repathTimer.Stop(); attackTimer.Stop(); } public float AttackTime = 0.2f; public float AttackDistMult = 1.3f; public float Damage = 0.4f; private void AttackTarget() { Vector3 startPos = transform.position; Vector3 delta = TargetBasePos - startPos; delta *= AttackDistMult; attackTween.Init(v => transform.position = startPos + delta * v, SimpleTween.QuadEaseOut, 0, 1, AttackTime); attackTween.OnFinish = FinishedAttack; attackTimer.Start(AttackTime / AttackDistMult, DamageTarget); } public float AttackWait = 0.8f; private void FinishedAttack() { if (targetPlayer != null && DistToTarget <= AttackMaxDist) { attackTimer.Start(AttackWait, CheckAttackTarget); } else { targetPlayer = null; PathToPlayer(); } } private void CheckAttackTarget() { if (targetPlayer != null && DistToTarget <= AttackMaxDist) { AttackTarget(); } else { targetPlayer = null; PathToPlayer(); } } private void DamageTarget() { if (targetPlayer != null) { Item playerItem = targetPlayer.GetComponentInChildren<Item>(); if (playerItem != null && item != null && item.GetNetHost() != null) { item.GetNetHost().SendItemCommand(playerItem.Key, "TakeDamage", new Dictionary<string, object> { { "damage", Damage } }); } } } }