sea-battle/Assets/Scripts/Pirate/PirateCommand.cs
2026-01-09 08:45:22 +03:00

264 lines
7.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PirateCommand : MonoBehaviour
{
[Header("Ñïèñêè îáúåêòîâ êîìàíäû")]
public List<Pirate> pirates = new();
public List<AmmoCrate> ammoCrates = new();
public List<BoxingMachine> 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<Pirate> GetFreePirates(params System.Type[] busyTypes)
{
var freePirates = new List<Pirate>();
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<Pirate> 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<PirateShooter>();
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<PirateBoxer>();
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<PirateDance>();
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<PirateLoader>()) 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<PirateLoader>();
if (pirate.CurrentBehavior is PirateLoader loader)
{
loader.ActivateWithTarget(cannon, approach);
}
}
}