178 lines
6.9 KiB
C#
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;
|
|
}
|
|
}
|
|
} |