using System.Collections; using System.Collections.Generic; using UnityEngine; public class PirateCommand : MonoBehaviour { [Header("Списки объектов команды")] public List pirates = new(); public List ammoCrates = new(); public List boxingMachines = new(); public PointsManager pointsManager; [Header("Ссылка на вражескую команду")] public EnemyCommand enemyTeam; private void Start() { StartCoroutine(DanceRoutine()); StartCoroutine(BoxingRoutine()); StartCoroutine(ShootingRoutine()); } public void ResetAllPiratesToHome() { foreach (var p in pirates) if (p) p.ResetByIdleHome(); } // ========================================================== // Универсальные методы фильтрации и выбора пиратов // ========================================================== private List GetFreePirates(params System.Type[] busyTypes) { var freePirates = new List(); foreach (var p in pirates) { bool busy = false; foreach (var t in busyTypes) { if (p.IsBusy(t)) { busy = true; break; } } if (!busy) freePirates.Add(p); } return freePirates; } private Pirate GetRandomPirate(List list) { if (list.Count == 0) return null; return list[Random.Range(0, list.Count)]; } // ========================================================== // Стрельба // ========================================================== private IEnumerator ShootingRoutine() { while (true) { float waitTime = Random.Range(5f, 10f); yield return new WaitForSeconds(waitTime); AssignRandomPirateToShoot(); } } public void AssignRandomPirateToShoot() { if (pointsManager == null || enemyTeam == null || enemyTeam.enemies.Count == 0) return; var freePirates = GetFreePirates(typeof(PirateLoader), typeof(PirateDance), typeof(PirateBoxer), typeof(PirateShooter)); Pirate pirate = GetRandomPirate(freePirates); if (pirate == null) return; Transform shootPoint = null; EnemyCombat targetEnemy = null; int attempts = 10; while (attempts-- > 0) { // получаем случайную свободную точку shootPoint = pointsManager.GetRandomFreePoint("shoot", pointsManager.shootPoints); if (shootPoint == null) return; // ищем активного врага, которого видно с этой точки foreach (var enemy in enemyTeam.enemies) { if (enemy != null && enemy.IsActiveTarget() && pointsManager.HasLineOfSight(shootPoint, enemy.transform)) { targetEnemy = enemy; break; } } if (targetEnemy != null) break; // нашли подходящую точку и врага // точка не подходит, освобождаем pointsManager.FreePoint("shoot", shootPoint); shootPoint = null; } if (shootPoint == null || targetEnemy == null) return; pirate.SetBehavior(); if (pirate.CurrentBehavior is PirateShooter shooter) { shooter.ActivateWithTarget(shootPoint, targetEnemy.gameObject, (point) => { pointsManager.FreePoint("shoot", point); }); } } // ========================================================== // Бокс // ========================================================== private IEnumerator BoxingRoutine() { while (true) { float waitTime = Random.Range(10f, 20f); yield return new WaitForSeconds(waitTime); AssignRandomPirateToBox(); } } public void AssignRandomPirateToBox() { if (boxingMachines.Count == 0) return; var freePirates = GetFreePirates(typeof(PirateLoader), typeof(PirateDance), typeof(PirateBoxer), typeof(PirateShooter)); Pirate pirate = GetRandomPirate(freePirates); if (pirate == null) return; BoxingMachine machine = boxingMachines[Random.Range(0, boxingMachines.Count)]; pirate.SetBehavior(); if (pirate.CurrentBehavior is PirateBoxer boxer) { boxer.targetMachine = machine; boxer.Activate(); } } // ========================================================== // Танцы // ========================================================== private IEnumerator DanceRoutine() { while (true) { float waitTime = Random.Range(5f, 15f); yield return new WaitForSeconds(waitTime); AssignRandomPirateToDance(); } } public void AssignRandomPirateToDance() { var freePirates = GetFreePirates(typeof(PirateLoader), typeof(PirateDance), typeof(PirateShooter), typeof(PirateBoxer)); Pirate pirate = GetRandomPirate(freePirates); if (pirate == null) return; // Получаем ближайшую свободную точку для танца Transform dancePoint = pointsManager.GetNearestFreePoint("dance", pointsManager.dancePoints, pirate.transform.position); if (dancePoint == null) return; pirate.SetBehavior(); if (pirate.CurrentBehavior is PirateDance dancer) { // Инициализация точки и колбэка, запускаем Activate уже с нужной точкой dancer.Init(dancePoint, (point) => { pointsManager.FreePoint("dance", point); }); } } // ========================================================== // Загрузка пушек // ========================================================== public Pirate GetNearestIdlePirate(Vector3 position) { Pirate nearest = null; float minDist = float.MaxValue; foreach (var pirate in pirates) { if (pirate.IsBusy()) continue; float dist = Vector3.Distance(pirate.transform.position, position); if (dist < minDist) { minDist = dist; nearest = pirate; } } return nearest; } public AmmoCrate GetNearestCrate(Vector3 position) { AmmoCrate nearest = null; float minDist = float.MaxValue; foreach (var crate in ammoCrates) { float dist = Vector3.Distance(crate.transform.position, position); if (dist < minDist) { minDist = dist; nearest = crate; } } return nearest; } public void AssignPirateToCannon(Cannon cannon) { Pirate pirate = GetNearestIdlePirate(cannon.transform.position); if (pirate == null) return; AmmoCrate crate = GetNearestCrate(cannon.transform.position); if (crate == null) return; Transform approach = crate.GetNearestFreePosition(pirate.transform.position); pirate.SetBehavior(); if (pirate.CurrentBehavior is PirateLoader loader) { loader.ActivateWithTarget(cannon, approach); } } }