#nullable enable
namespace TagFighter
{
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public interface IAreaOfEffect
{
public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin, EffectTarget effectTarget);
public IAreaOfEffect ShallowCopy();
}
[Serializable]
public class SingleTarget : IAreaOfEffect
{
public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin, EffectTarget effectTarget) {
return new Transform[] { effectTarget.Transform };
}
public IAreaOfEffect ShallowCopy() {
return (IAreaOfEffect)MemberwiseClone();
}
}
[Serializable]
public class CircleArea : IAreaOfEffect
{
public float Radius;
public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin, EffectTarget effectTarget) {
var origin = effectOrigin.Transform;
var hits = Physics.SphereCastAll(origin.position, Radius, origin.forward, 0, LayerMaskExtensions.GetUnitsLayerMask());
return hits.Select(x => x.transform);
}
public IAreaOfEffect ShallowCopy() {
return (IAreaOfEffect)MemberwiseClone();
}
}
[Serializable]
public class ConeArea : IAreaOfEffect
{
public float Radius;
[Range(0f, 360f)]
public float Angle;
public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin, EffectTarget effectTarget) {
var origin = effectOrigin.Transform;
var direction = (effectTarget.Transform.position - origin.position).normalized;
// Its problematic to cast a real cone, so we cast the sphere and later
// calculate if the potential target is within the cone.
var possibleHits = Physics.SphereCastAll(origin.position, Radius, origin.forward, 0, LayerMaskExtensions.GetUnitsLayerMask());
if (possibleHits.Length == 0) {
return Enumerable.Empty<Transform>();
}
foreach (var h in possibleHits) {
Debug.Log($"ConeArea:GetAffectedUnits possbile hit: {h.transform.gameObject}");
}
var hits = possibleHits.Where(h => {
var targetDir = (h.transform.position - origin.position).normalized;
var targetAngle = Math.Abs(Vector3.Angle(targetDir, direction));
Debug.Log($"ConeArea:GetAffectedUnits target: {h.transform.gameObject} angle: {targetAngle}");
return targetAngle <= Angle / 2;
});
foreach (var h in hits) {
Debug.Log($"ConeArea:GetAffectedUnits hit: {h.transform.gameObject}");
}
return hits.Select(x => x.transform);
}
public IAreaOfEffect ShallowCopy() {
return (IAreaOfEffect)MemberwiseClone();
}
}
[Serializable]
public class PathArea : IAreaOfEffect
{
public float Width;
public float Length;
public IEnumerable<Transform> GetAffectedUnits(EffectOrigin effectOrigin, EffectTarget effectTarget) {
var origin = effectOrigin.Transform;
var direction = (effectTarget.Transform.position - origin.position).normalized;
// Get potential collisions
var hits = Physics.BoxCastAll(origin.position, new Vector3(Width / 2, 0, 0), direction, origin.rotation, Length, LayerMaskExtensions.GetUnitsLayerMask());
foreach (var h in hits) {
Debug.Log($"PathArea:GetAffectedUnits hit: {h.transform.gameObject} Location: {h.transform.position}");
}
return hits.Select(x => x.transform);
}
public IAreaOfEffect ShallowCopy() {
return (IAreaOfEffect)MemberwiseClone();
}
}
}