Files
VOIDRPG/Assets/90 - Scripts/Generic/AI/Schema/Actions/GetUnit.cs
T
2026-07-09 21:33:33 +02:00

178 lines
6.9 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Schema;
using UnityEngine;
using UnityEngine.AI;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Util;
namespace VOID.Generic.AI.Schema.Actions
{
[Description("Gets unit by selected filters and save it as blackboard variable")]
[Category(SchemaCategory.CombatThisUnit)]
public class GetUnit : Action
{
private enum UnitType
{
Any,
Enemy,
Neutral,
Friendly
}
private enum SearchType
{
ClosestByDistance,
FarthestByDistance,
Random,
LeastHp,
MostHp,
ClosestByPath,
FarthestByPath
}
[SerializeField] private UnitType _findUnitBy;
[SerializeField] private SearchType _searchBy;
[SerializeField, Space(15)] private BlackboardEntrySelector<UnitObject> _saveTo;
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
{
var thisUnit = ((UnitObjectSchemaAgent)agent).unit;
if (!thisUnit.basicState.turnManager) return NodeStatus.Failure;
// Get all participants in combat except current unit
var allUnits = thisUnit.basicState.turnManager.allUnitsInQueue.Where(otherUnit => otherUnit != thisUnit)
.ToList();
// Filter by UnitType
if (_findUnitBy is UnitType.Enemy) allUnits = GetEnemy(thisUnit, allUnits);
if (_findUnitBy is UnitType.Neutral) allUnits = GetNeutral(thisUnit, allUnits);
if (_findUnitBy is UnitType.Friendly) allUnits = GetFriendly(thisUnit, allUnits);
// Filter by SearchType
if (_searchBy is SearchType.ClosestByDistance) _saveTo.value = GetClosestByDistance(thisUnit, allUnits);
if (_searchBy is SearchType.FarthestByDistance) _saveTo.value = GetFarthestByDistance(thisUnit, allUnits);
if (_searchBy is SearchType.Random) _saveTo.value = RandomUtil.RandomElement(allUnits);
if (_searchBy is SearchType.LeastHp) _saveTo.value = GetByLeastHp(allUnits);
if (_searchBy is SearchType.MostHp) _saveTo.value = GetByMostHp(allUnits);
if (_searchBy is SearchType.ClosestByPath) _saveTo.value = GetClosestByPath(thisUnit, allUnits);
if (_searchBy is SearchType.FarthestByPath) _saveTo.value = GetFarthestByPath(thisUnit, allUnits);
// Could not find anything
if (!_saveTo.value) return NodeStatus.Failure;
return NodeStatus.Success;
}
private List<UnitObject> GetEnemy(UnitObject thisUnit, List<UnitObject> units)
{
return units.Where(otherUnit => thisUnit.unitAttitude.GetAttitudeWith(otherUnit) < AttitudeType.Neutral)
.ToList();
}
private List<UnitObject> GetNeutral(UnitObject thisUnit, List<UnitObject> units)
{
return units.Where(otherUnit => thisUnit.unitAttitude.GetAttitudeWith(otherUnit) == AttitudeType.Neutral)
.ToList();
}
private List<UnitObject> GetFriendly(UnitObject thisUnit, List<UnitObject> units)
{
return units.Where(otherUnit => thisUnit.unitAttitude.GetAttitudeWith(otherUnit) > AttitudeType.Neutral)
.ToList();
}
private UnitObject GetClosestByDistance(UnitObject thisUnit, List<UnitObject> units)
{
var closestDistance = float.MaxValue;
var closestUnit = (UnitObject)null;
units.ForEach(otherUnit =>
{
var distance = RangeUtil.GetDistance(thisUnit, otherUnit);
if (distance >= closestDistance) return;
closestDistance = distance;
closestUnit = otherUnit;
});
return closestUnit;
}
private UnitObject GetFarthestByDistance(UnitObject thisUnit, List<UnitObject> units)
{
var farthestDistance = float.MinValue;
var farthestUnit = (UnitObject)null;
units.ForEach(otherUnit =>
{
var distance = RangeUtil.GetDistance(thisUnit, otherUnit);
if (distance <= farthestDistance) return;
farthestDistance = distance;
farthestUnit = otherUnit;
});
return farthestUnit;
}
private UnitObject GetClosestByPath(UnitObject thisUnit, List<UnitObject> units)
{
var closestPathLength = float.MaxValue;
var closestUnit = (UnitObject)null;
units.ForEach(otherUnit =>
{
thisUnit.unitNavAgent.CalculatePathTo(otherUnit.transform.position);
var path = thisUnit.unitNavAgent.GetPath();
var pathLength = NavMeshPathUtil.GetPathLength(path);
if (path.status is not NavMeshPathStatus.PathInvalid)
pathLength += Vector3.Distance(path.corners.Last(), otherUnit.transform.position);
if (pathLength >= closestPathLength) return;
closestPathLength = pathLength;
closestUnit = otherUnit;
});
return closestUnit;
}
private UnitObject GetFarthestByPath(UnitObject thisUnit, List<UnitObject> units)
{
var farthestPathLength = float.MinValue;
var farthestUnit = (UnitObject)null;
units.ForEach(otherUnit =>
{
thisUnit.unitNavAgent.CalculatePathTo(otherUnit.transform.position);
var path = thisUnit.unitNavAgent.GetPath();
var pathLength = NavMeshPathUtil.GetPathLength(path);
if (path.status is not NavMeshPathStatus.PathInvalid)
pathLength += Vector3.Distance(path.corners.Last(), otherUnit.transform.position);
if (pathLength <= farthestPathLength) return;
farthestPathLength = pathLength;
farthestUnit = otherUnit;
});
return farthestUnit;
}
private UnitObject GetByLeastHp(List<UnitObject> units)
{
var leastHp = float.MinValue;
var leastHpUnit = (UnitObject)null;
units.ForEach(otherUnit =>
{
var hp = otherUnit.basicData.currentResources.health;
if (hp >= leastHp) return;
leastHp = hp;
leastHpUnit = otherUnit;
});
return leastHpUnit;
}
private UnitObject GetByMostHp(List<UnitObject> units)
{
var mostHp = float.MaxValue;
var mostHpUnit = (UnitObject)null;
units.ForEach(otherUnit =>
{
var hp = otherUnit.basicData.currentResources.health;
if (hp <= mostHp) return;
mostHp = hp;
mostHpUnit = otherUnit;
});
return mostHpUnit;
}
}
}