init
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9a48ee69236a0b49bd29d3a1a8e4519
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e82d99fedd324bb89f27581e90b12ace
|
||||
timeCreated: 1709163553
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e8e769129ee4c1b9adaf2335158ae9b
|
||||
timeCreated: 1709165760
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Schema;
|
||||
using Sirenix.Utilities;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Dict.Ability;
|
||||
using VOID.Generic.Util;
|
||||
using VOID.ScriptableObjects.Abilities;
|
||||
using Action = Schema.Action;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Gets ability by selected filters from this unit and save it as blackboard variable")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class GetAbility : Action
|
||||
{
|
||||
private enum SearchType
|
||||
{
|
||||
First,
|
||||
Random,
|
||||
LeastExpensive,
|
||||
MostExpensive,
|
||||
GreatestRange
|
||||
}
|
||||
|
||||
private enum AbilityPurposeType
|
||||
{
|
||||
Any,
|
||||
All
|
||||
}
|
||||
|
||||
[SerializeField] private bool includeBasicAttack;
|
||||
[SerializeField] private BlackboardEntrySelector<float> atLeastRange;
|
||||
[SerializeField] private AbilityPurposeType abilityPurposeType;
|
||||
[SerializeField] private AbilityPurposeFlag abilityPurpose;
|
||||
[SerializeField] private SearchType searchBy;
|
||||
[SerializeField, WriteOnly, Space(15)] private BlackboardEntrySelector<BasicAbility> saveTo;
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var thisUnit = ((UnitObjectSchemaAgent)agent).unit;
|
||||
var allAbilities = thisUnit.unitAbilityBook.abilities.ToList();
|
||||
|
||||
// Unit dont have any abilities
|
||||
if (allAbilities.IsNullOrEmpty()) return NodeStatus.Failure;
|
||||
|
||||
if (includeBasicAttack) allAbilities.Add(thisUnit.unitAbilityBook.attackAbility);
|
||||
|
||||
// Filter by range required
|
||||
allAbilities = allAbilities.Where(ability => ability.range >= atLeastRange.value).ToList();
|
||||
|
||||
// Filter by wanted purpose
|
||||
allAbilities = allAbilities.Where(ability =>
|
||||
{
|
||||
switch (abilityPurposeType)
|
||||
{
|
||||
case AbilityPurposeType.All when (ability.abilityPurpose & abilityPurpose) == abilityPurpose:
|
||||
case AbilityPurposeType.Any when (ability.abilityPurpose & abilityPurpose) != AbilityPurposeFlag.None:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}).ToList();
|
||||
|
||||
// Getting final ability and saving it
|
||||
saveTo.value = searchBy switch
|
||||
{
|
||||
SearchType.First => allAbilities.FirstOrDefault(),
|
||||
SearchType.Random => RandomUtil.RandomElement(allAbilities),
|
||||
SearchType.LeastExpensive => allAbilities.Aggregate(allAbilities.First(),
|
||||
(a1, a2) => a2.actionPointCost > a1.actionPointCost ? a1 : a2),
|
||||
SearchType.MostExpensive => allAbilities.Aggregate(allAbilities.First(),
|
||||
(a1, a2) => a2.actionPointCost <= a1.actionPointCost ? a1 : a2),
|
||||
SearchType.GreatestRange => allAbilities.Aggregate(allAbilities.First(),
|
||||
(a1, a2) => a2.range <= a1.range ? a1 : a2),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
if (!saveTo.value) return NodeStatus.Failure;
|
||||
|
||||
return NodeStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0912de9aef0840feb6e15e730b800677
|
||||
timeCreated: 1709738283
|
||||
@@ -0,0 +1,23 @@
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.ScriptableObjects.Abilities;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Gets basic attack ability from this unit and save it as blackboard variable")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class GetAttackAbility : Action
|
||||
{
|
||||
[SerializeField, WriteOnly] public BlackboardEntrySelector<BasicAbility> _saveTo;
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var thisUnit = ((UnitObjectSchemaAgent)agent).unit;
|
||||
|
||||
_saveTo.value = thisUnit.unitAbilityBook.attackAbility;
|
||||
if (!_saveTo.value) return NodeStatus.Failure;
|
||||
|
||||
return NodeStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60fa739b5d604f3b9e0a0155377b4692
|
||||
timeCreated: 1710064236
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using Schema;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Util;
|
||||
using Action = Schema.Action;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Gets distance between ThisUnit and target position or unit, minus radius of both of units")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class GetDistanceTo : Action
|
||||
{
|
||||
private enum DistanceFrom
|
||||
{
|
||||
Current,
|
||||
Another
|
||||
}
|
||||
|
||||
private enum DistanceTo
|
||||
{
|
||||
Position,
|
||||
Unit
|
||||
}
|
||||
|
||||
[SerializeField] private DistanceFrom _distanceFrom;
|
||||
[SerializeField, ShowIf(nameof(_distanceFrom), DistanceFrom.Another)] private BlackboardEntrySelector<Vector3> _position;
|
||||
[SerializeField, Space(15)] private DistanceTo _distanceTo;
|
||||
[SerializeField, ShowIf(nameof(_distanceTo), DistanceTo.Position)] private BlackboardEntrySelector<Vector3> _toPosition;
|
||||
[SerializeField, ShowIf(nameof(_distanceTo), DistanceTo.Unit)] private BlackboardEntrySelector<UnitObject> _toUnit;
|
||||
|
||||
[WriteOnly, SerializeField, Space(15)] private BlackboardEntrySelector<float> _saveTo;
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
var thisUnit = unitAgent.unit;
|
||||
|
||||
_saveTo.value = (_distanceFrom, _distanceTo) switch
|
||||
{
|
||||
(DistanceFrom.Current, DistanceTo.Position) => RangeUtil.GetDistance(thisUnit, _toPosition.value),
|
||||
(DistanceFrom.Current, DistanceTo.Unit) => RangeUtil.GetDistance(thisUnit, _toUnit.value),
|
||||
(DistanceFrom.Another, DistanceTo.Position) => RangeUtil.GetDistance(_toPosition.value, _position.value) - thisUnit.basicData.radius,
|
||||
(DistanceFrom.Another, DistanceTo.Unit) => RangeUtil.GetDistance(_toUnit.value, _position.value) - thisUnit.basicData.radius,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
return NodeStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3deac86e81441299d91ee926c0015af
|
||||
timeCreated: 1726666687
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Util;
|
||||
using Action = Schema.Action;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Gets point where ThisUnit can go with current MovementPoints towards given destination point")]
|
||||
[Category(SchemaCategory.CombatThisUnit)]
|
||||
public class GetReachablePosition : Action
|
||||
{
|
||||
private enum DestinationType
|
||||
{
|
||||
Position,
|
||||
Unit
|
||||
}
|
||||
|
||||
[SerializeField] private DestinationType _destinationType;
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _toUnit;
|
||||
[SerializeField] private BlackboardEntrySelector<Vector3> _toPosition;
|
||||
[SerializeField, WriteOnly, Space(15)] private BlackboardEntrySelector<Vector3> _saveTo;
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var thisUnit = ((UnitObjectSchemaAgent)agent).unit;
|
||||
if (!thisUnit.basicState.turnManager) return NodeStatus.Failure;
|
||||
|
||||
// Whole path to destination
|
||||
var path = _destinationType switch
|
||||
{
|
||||
DestinationType.Position => GetPathToPosition(thisUnit),
|
||||
DestinationType.Unit => GetPathToUnit(thisUnit),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
var movePoints = thisUnit.unitData.currentResources.movePoints;
|
||||
|
||||
// Path can't be calculated
|
||||
if (thisUnit.unitNavAgent.GetPath().status is NavMeshPathStatus.PathInvalid) return NodeStatus.Failure;
|
||||
|
||||
// Reachable path (within move points range) and its last possible point
|
||||
NavMeshPathUtil.SplitPath(path.ToArray(), movePoints, out var reachablePath, out _);
|
||||
_saveTo.value = reachablePath.Last();
|
||||
|
||||
return NodeStatus.Success;
|
||||
}
|
||||
|
||||
private List<Vector3> GetPathToPosition(UnitObject thisUnit)
|
||||
{
|
||||
thisUnit.unitNavAgent.CalculatePathTo(_toPosition.value);
|
||||
return thisUnit.unitNavAgent.GetCorrectedPath();
|
||||
}
|
||||
|
||||
private List<Vector3> GetPathToUnit(UnitObject thisUnit)
|
||||
{
|
||||
thisUnit.unitNavAgent.CalculatePathTo(_toUnit.value);
|
||||
return thisUnit.unitNavAgent.GetCorrectedPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74aab9b029674f94ac8347a3683ca308
|
||||
timeCreated: 1726254338
|
||||
@@ -0,0 +1,19 @@
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Gets this unit and save it as blackboard variable")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class GetThisUnit : Action
|
||||
{
|
||||
[SerializeField, WriteOnly] public BlackboardEntrySelector<UnitObject> _saveTo;
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
_saveTo.value = ((UnitObjectSchemaAgent)agent).unit;
|
||||
return NodeStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a40ad4564276481f831e44fd55979d34
|
||||
timeCreated: 1709499899
|
||||
@@ -0,0 +1,178 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a79026c80b3d42cc922bba86f43a82bb
|
||||
timeCreated: 1709555651
|
||||
@@ -0,0 +1,22 @@
|
||||
using Schema;
|
||||
using VOID.Generic.Objects.Unit.Actions;
|
||||
using VOID.Generic.Objects.Unit.Actions.Exceptions;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Starts turn based fight")]
|
||||
[Category(SchemaCategory.CombatThisUnit)]
|
||||
public class UnitEndTurn : Action
|
||||
{
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
if (!unitAgent.unit || !unitAgent.unit.basicState.turnManager || !unitAgent.unit.unitState.isSelfTurn)
|
||||
return NodeStatus.Failure;
|
||||
|
||||
unitAgent.unit.OrderInstantly(new EndTurnAction(unitAgent.unit));
|
||||
|
||||
return NodeStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb47dac215e44eae810d2d4d1537bff5
|
||||
timeCreated: 1709573630
|
||||
@@ -0,0 +1,93 @@
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Objects.Unit.Actions;
|
||||
using VOID.Generic.Objects.Unit.Events;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("This unit will move to given point")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class UnitMoveTo : Action
|
||||
{
|
||||
private class UnitMoveToMemory
|
||||
{
|
||||
public SchemaUnitEventWrapper<MoveEvent, UnitMoveToMemory> onMoveEnd;
|
||||
public bool isMoving;
|
||||
public bool isFinished;
|
||||
}
|
||||
|
||||
private enum MoveToType
|
||||
{
|
||||
Position,
|
||||
Unit
|
||||
}
|
||||
|
||||
[SerializeField] private MoveToType _moveTo;
|
||||
[SerializeField] private BlackboardEntrySelector<Transform> _moveToPosition;
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _moveToUnit;
|
||||
[SerializeField, Space(15)] private BlackboardEntrySelector<float> _range;
|
||||
|
||||
public override void OnNodeEnter(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitMoveToMemory)nodeMemory;
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
|
||||
memory.onMoveEnd = new SchemaUnitEventWrapper<MoveEvent, UnitMoveToMemory>(
|
||||
unitAgent.unit.unitEvents.onMoveEnd, OnMoveEnd, unitAgent, memory);
|
||||
memory.onMoveEnd.On();
|
||||
memory.isMoving = false;
|
||||
memory.isFinished = false;
|
||||
}
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitMoveToMemory)nodeMemory;
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
|
||||
// moveTo target not defined
|
||||
if (_moveTo is MoveToType.Unit && !_moveToUnit.value) return NodeStatus.Failure;
|
||||
if (_moveTo is MoveToType.Position && !_moveToPosition.value) return NodeStatus.Failure;
|
||||
|
||||
// unit reached target - end MoveTo with success
|
||||
if (memory.isFinished) return NodeStatus.Success;
|
||||
|
||||
// not started moving yet - start moving for this unit
|
||||
if (!memory.isMoving)
|
||||
{
|
||||
memory.isMoving = true;
|
||||
memory.isFinished = false;
|
||||
unitAgent.unit.OrderStop();
|
||||
if (_moveTo is MoveToType.Position)
|
||||
unitAgent.unit.Order(new MoveAction(unitAgent.unit, _moveToPosition.value.position, _range.value));
|
||||
if (_moveTo is MoveToType.Unit)
|
||||
unitAgent.unit.Order(new MoveAction(unitAgent.unit, _moveToUnit.value, _range.value));
|
||||
}
|
||||
|
||||
// If somehow this unit don't have anything in current action (something aborted that??)
|
||||
// Then end with failure whole MoveTo
|
||||
if (unitAgent.unit.unitActionQueue.actionCurrent == null)
|
||||
return NodeStatus.Failure;
|
||||
|
||||
// moving
|
||||
return NodeStatus.Running;
|
||||
}
|
||||
|
||||
public override void OnNodeExit(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitMoveToMemory)nodeMemory;
|
||||
memory.onMoveEnd.Off();
|
||||
}
|
||||
|
||||
public override void OnNodeAbort(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitMoveToMemory)nodeMemory;
|
||||
memory.onMoveEnd.Off();
|
||||
}
|
||||
|
||||
private void OnMoveEnd(MoveEvent moveEvent, UnitMoveToMemory memory, UnitObjectSchemaAgent agent)
|
||||
{
|
||||
memory.isFinished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 624124ec53d149399992419f68d2a199
|
||||
timeCreated: 1709562199
|
||||
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit.Actions;
|
||||
using VOID.Generic.Objects.Unit.Events;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("This unit will patrol between given points")]
|
||||
[Category(SchemaCategory.RealtimeThisUnit)]
|
||||
public class UnitPatrol : Action
|
||||
{
|
||||
private class UnitPatrolMemory
|
||||
{
|
||||
public SchemaUnitEventWrapper<MoveEvent, UnitPatrolMemory> onMoveEnd;
|
||||
public int nextStop = - 1;
|
||||
public bool isMoving = false;
|
||||
}
|
||||
|
||||
public override void OnNodeEnter(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitPatrolMemory)nodeMemory;
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
var patrolPoints = unitAgent.unitAI.patrol;
|
||||
var closestDistance = float.MaxValue;
|
||||
|
||||
for (var index = 0; index < patrolPoints.Count; index++)
|
||||
{
|
||||
var distance = Vector3.Distance(unitAgent.unit.transform.position, patrolPoints[index].position);
|
||||
if (distance >= closestDistance) continue;
|
||||
closestDistance = distance;
|
||||
memory.nextStop = index;
|
||||
}
|
||||
|
||||
memory.onMoveEnd = new SchemaUnitEventWrapper<MoveEvent, UnitPatrolMemory>(
|
||||
unitAgent.unit.unitEvents.onMoveEnd, OnMoveEnd, unitAgent, memory);
|
||||
memory.onMoveEnd.On();
|
||||
}
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitPatrolMemory)nodeMemory;
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
|
||||
if (memory.nextStop == - 1) return NodeStatus.Failure;
|
||||
if (memory.isMoving) return NodeStatus.Running;
|
||||
|
||||
// Get next patrol points in order to check
|
||||
var orderedPatrolPoints = new List<Transform>();
|
||||
orderedPatrolPoints.AddRange(unitAgent.unitAI.patrol.Skip(memory.nextStop+1));
|
||||
orderedPatrolPoints.AddRange(unitAgent.unitAI.patrol.Take(memory.nextStop+1));
|
||||
|
||||
// Find next valid patrol point and order move to it
|
||||
foreach (var point in orderedPatrolPoints)
|
||||
{
|
||||
var moveAction = new MoveAction(unitAgent.unit, point.position);
|
||||
if (moveAction.CanDoItBoolean() == false) continue;
|
||||
unitAgent.unit.Order(moveAction);
|
||||
memory.isMoving = true;
|
||||
return NodeStatus.Running;
|
||||
}
|
||||
|
||||
// Next point cant be found - error!
|
||||
return NodeStatus.Failure;
|
||||
}
|
||||
|
||||
public override void OnNodeExit(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitPatrolMemory)nodeMemory;
|
||||
memory.onMoveEnd.Off();
|
||||
memory.isMoving = false;
|
||||
}
|
||||
|
||||
public override void OnNodeAbort(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitPatrolMemory)nodeMemory;
|
||||
memory.onMoveEnd.Off();
|
||||
memory.isMoving = false;
|
||||
}
|
||||
|
||||
private void OnMoveEnd(MoveEvent moveEvent, UnitPatrolMemory memory, UnitObjectSchemaAgent agent)
|
||||
{
|
||||
memory.nextStop = (memory.nextStop + 1) % agent.unitAI.patrol.Count;
|
||||
memory.isMoving = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a11564bc03bb4a52a083e28d35d798cf
|
||||
timeCreated: 1709223806
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using Schema;
|
||||
using VOID.Generic.Dict;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Turn;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Starts turn based fight")]
|
||||
[Category(SchemaCategory.RealtimeThisUnit)]
|
||||
public class UnitStartFight : Action
|
||||
{
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
var hostileUnits = unitAgent.unit.unitSenses.GetUnitsInSightByAttitude(AttitudeType.Hostile);
|
||||
if (hostileUnits.Count == 0) return NodeStatus.Failure;
|
||||
var units = new List<UnitObject>();
|
||||
units.Add(unitAgent.unit);
|
||||
units.AddRange(hostileUnits);
|
||||
TurnManager.BuildGameObject(units);
|
||||
return NodeStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62ecce8528974c928665fff4143169dd
|
||||
timeCreated: 1709379357
|
||||
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Dict;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Objects.Unit.Actions;
|
||||
using VOID.Generic.Objects.Unit.Events;
|
||||
using VOID.ScriptableObjects.Abilities;
|
||||
using Action = Schema.Action;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Actions
|
||||
{
|
||||
[Description("Order this unit to use selected ability")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class UnitUseAbility : Action
|
||||
{
|
||||
private class UnitUseAbilityMemory
|
||||
{
|
||||
public SchemaUnitEventWrapper<AnimationGenericEvent, UnitUseAbilityMemory> onCastAnimationEnd;
|
||||
public bool isRunning;
|
||||
public bool isFinished;
|
||||
}
|
||||
|
||||
private enum TargetType
|
||||
{
|
||||
Position,
|
||||
Unit
|
||||
}
|
||||
|
||||
[SerializeField] private BlackboardEntrySelector<BasicAbility> _ability;
|
||||
[SerializeField, Space(15)] private TargetType _targetType;
|
||||
[SerializeField] private BlackboardEntrySelector<Transform> _position;
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _unit;
|
||||
|
||||
public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitUseAbilityMemory)nodeMemory;
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
var thisUnit = unitAgent.unit;
|
||||
|
||||
// Ability not selected
|
||||
if (!_ability.value) return NodeStatus.Failure;
|
||||
|
||||
// Whenever is during casting or already done that
|
||||
if (memory.isFinished) return NodeStatus.Success;
|
||||
if (memory.isRunning) return NodeStatus.Running;
|
||||
|
||||
// Targets not selected
|
||||
if (_targetType == TargetType.Position && !_position.value) return NodeStatus.Failure;
|
||||
if (_targetType == TargetType.Unit && !_unit.value) return NodeStatus.Failure;
|
||||
|
||||
AbilityAction abilityAction;
|
||||
if (_targetType is TargetType.Position)
|
||||
{
|
||||
// TODO: for now if ability needs multiple targets all will be identical
|
||||
var targets = Enumerable.Repeat(_position.value.position, _ability.value.castUsages).ToArray();
|
||||
abilityAction = new AbilityAction(thisUnit, _ability.value, targets);
|
||||
}
|
||||
else if (_targetType is TargetType.Unit)
|
||||
{
|
||||
// TODO: for now if ability needs multiple targets all will be identical
|
||||
var targets = Enumerable.Repeat(_unit.value, _ability.value.castUsages).ToArray();
|
||||
abilityAction = new AbilityAction(thisUnit, _ability.value, targets);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
// Check if that action can be done
|
||||
if (!abilityAction.CanDoItBoolean()) return NodeStatus.Failure;
|
||||
|
||||
// Listen to end of abilisty casting animation
|
||||
memory.onCastAnimationEnd?.Off();
|
||||
memory.onCastAnimationEnd = new SchemaUnitEventWrapper<AnimationGenericEvent, UnitUseAbilityMemory>(
|
||||
thisUnit.unitEvents.onAnimation[AnimationType.Ability].onEnd, OnAbilityCastEnd, unitAgent, memory);
|
||||
memory.onCastAnimationEnd.On();
|
||||
|
||||
// Everything seems ok - order unit to do that action
|
||||
thisUnit.OrderStop();
|
||||
thisUnit.Order(abilityAction);
|
||||
memory.isRunning = true;
|
||||
|
||||
return NodeStatus.Running;
|
||||
}
|
||||
|
||||
public override void OnNodeExit(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitUseAbilityMemory)nodeMemory;
|
||||
memory.onCastAnimationEnd?.Off();
|
||||
memory.isFinished = false;
|
||||
memory.isRunning = false;
|
||||
}
|
||||
|
||||
public override void OnNodeAbort(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var memory = (UnitUseAbilityMemory)nodeMemory;
|
||||
memory.onCastAnimationEnd?.Off();
|
||||
memory.isFinished = false;
|
||||
memory.isRunning = false;
|
||||
}
|
||||
|
||||
private void OnAbilityCastEnd(AnimationGenericEvent abilityCastEvent, UnitUseAbilityMemory memory,
|
||||
UnitObjectSchemaAgent agent)
|
||||
{
|
||||
memory.isFinished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45d528d62fdb41c7b539945d8d9f39be
|
||||
timeCreated: 1709821286
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a75df9d1888e48babf6ec8f326d7d85a
|
||||
timeCreated: 1709166099
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using Sirenix.Utilities;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
using VOID.Generic.Util;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.AnyUnit)]
|
||||
public class CanUnitMoveTo : Conditional
|
||||
{
|
||||
private enum MoveToType
|
||||
{
|
||||
Position,
|
||||
Unit
|
||||
}
|
||||
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _unit;
|
||||
[SerializeField, Space(15)] private MoveToType _moveTo;
|
||||
[SerializeField] private BlackboardEntrySelector<Transform> _moveToPosition;
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _moveToUnit;
|
||||
[SerializeField, Space(15)] private BlackboardEntrySelector<float> _range;
|
||||
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
var unitAgent = (UnitObjectSchemaAgent)agent;
|
||||
|
||||
switch (_moveTo)
|
||||
{
|
||||
case MoveToType.Position:
|
||||
_unit.value.unitNavAgent.CalculatePathTo(_moveToPosition.value.position,
|
||||
_range.value + unitAgent.unit.basicData.radius);
|
||||
break;
|
||||
case MoveToType.Unit:
|
||||
_unit.value.unitNavAgent.CalculatePathTo(_moveToUnit.value.transform.position,
|
||||
_range.value + unitAgent.unit.basicData.radius + _moveToUnit.value.basicData.radius);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
var path = _unit.value.unitNavAgent.GetCorrectedPath();
|
||||
|
||||
// If somehow path isnt calculated - cant move
|
||||
if (path.IsNullOrEmpty()) return false;
|
||||
|
||||
// Out of combat - costless move
|
||||
if (!_unit.value.basicState.turnManager) return true;
|
||||
|
||||
// Calculate move cost when in turn combat
|
||||
var cost = NavMeshPathUtil.CalculatePathCost(path);
|
||||
return _unit.value.unitData.currentResources.movePoints >= cost;
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append($"If <color=red>{_unit.name}</color> can move to ");
|
||||
if (_moveTo is MoveToType.Position) sb.Append($"<color=red>{_moveToPosition.name}</color>");
|
||||
if (_moveTo is MoveToType.Unit) sb.Append($"<color=red>{_moveToUnit.name}</color>");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3b68fb79d3b4f19bee514ad03229447
|
||||
timeCreated: 1709732599
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Dict;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.AnyUnit)]
|
||||
public class IsBasicResource : Conditional
|
||||
{
|
||||
private enum ComparisonType
|
||||
{
|
||||
Greater,
|
||||
Less
|
||||
}
|
||||
|
||||
private enum ValueType
|
||||
{
|
||||
Value,
|
||||
Percent
|
||||
}
|
||||
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _unit;
|
||||
[SerializeField, Space(15)] private BasicResourceType _resourceType;
|
||||
[SerializeField] private ComparisonType _comparisonType;
|
||||
[SerializeField, ShowIf(nameof(_compareBy), ValueType.Value)] private BlackboardEntrySelector<int> _value = new(1);
|
||||
[SerializeField, ShowIf(nameof(_compareBy), ValueType.Percent)] private BlackboardEntrySelector<int> _percent = new(50);
|
||||
[SerializeField] private ValueType _compareBy;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
_percent.inspectorValue = Mathf.Min(Mathf.Max(_percent.inspectorValue, 0), 100);
|
||||
_value.inspectorValue = Mathf.Max(_value.inspectorValue, 0);
|
||||
}
|
||||
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
return _compareBy switch
|
||||
{
|
||||
ValueType.Percent => CompareByPercent(),
|
||||
ValueType.Value => CompareByValue(),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private bool CompareByValue()
|
||||
{
|
||||
var currentResource = _unit.value.basicData.currentResources.Get(_resourceType);
|
||||
|
||||
return _comparisonType switch
|
||||
{
|
||||
ComparisonType.Greater => currentResource > _value.value,
|
||||
ComparisonType.Less => currentResource < _value.value,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private bool CompareByPercent()
|
||||
{
|
||||
var currentResource = _unit.value.basicData.currentResources.Get(_resourceType);
|
||||
var maxResource = _unit.value.basicData.maxResources.Get(_resourceType);
|
||||
var currentPercent = currentResource / maxResource * 100;
|
||||
|
||||
return _comparisonType switch
|
||||
{
|
||||
ComparisonType.Greater => currentPercent > _percent.value,
|
||||
ComparisonType.Less => currentPercent < _percent.value,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append(
|
||||
$"If <color=red>{_unit.name}</color> {nameof(UnitObjectData)}'s <color=red>{_resourceType}</color>");
|
||||
sb.Append(_comparisonType == ComparisonType.Greater ? " > " : " < ");
|
||||
if (_compareBy is ValueType.Percent) sb.Append($"<color=red>{_percent.name}</color>%");
|
||||
if (_compareBy is ValueType.Value) sb.Append($"<color=red>{_value.name}</color>");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1245ec365cb943c6acc3d9e85330d07a
|
||||
timeCreated: 1709501957
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class IsPatrolDefined : Conditional
|
||||
{
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
return (agent as UnitObjectSchemaAgent)?.unitAI.patrol.Count > 1;
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append($"<color=red>{nameof(UnitObjectSenses)}</color> has at least two <color=red>patrol</color> points");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74564f3f9d4b467bb3e954c5a84cf780
|
||||
timeCreated: 1709383094
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.AnyUnit)]
|
||||
public class IsUnitDead : Conditional
|
||||
{
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _unit;
|
||||
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
return _unit.value && _unit.value.basicState.isDead;
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append($"If <color=red>{_unit.name}</color> is dead");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba8914a1869a4e06aebdeebf2ec743cd
|
||||
timeCreated: 1710974135
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Dict;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class IsUnitInSight : Conditional
|
||||
{
|
||||
[SerializeField] private AttitudeType _attitudeType;
|
||||
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
return (agent as UnitObjectSchemaAgent)?.unit.unitSenses.GetUnitsInSightByAttitude(_attitudeType).Count > 0;
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append(
|
||||
$"<color=red>{nameof(UnitObjectSenses)}</color> has at least one <color=red>{_attitudeType}</color> in range");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6eed700ee23b489189517c4ae32e687a
|
||||
timeCreated: 1709382718
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.ThisUnit)]
|
||||
public class IsUnitObjectSchema : Conditional
|
||||
{
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
return agent is UnitObjectSchemaAgent unitAgent && unitAgent.unit;
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append($"If this is <color=red>{nameof(UnitObject)}</color>'s schema");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b727768fcf6433687f118b54fe16e53
|
||||
timeCreated: 1709203631
|
||||
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Dict;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.AnyUnit)]
|
||||
public class IsUnitResource : Conditional
|
||||
{
|
||||
private enum ComparisonType
|
||||
{
|
||||
Greater,
|
||||
Less
|
||||
}
|
||||
|
||||
private enum ValueType
|
||||
{
|
||||
Value,
|
||||
Percent
|
||||
}
|
||||
|
||||
[SerializeField] private BlackboardEntrySelector<UnitObject> _unit;
|
||||
[SerializeField, Space(15)] private UnitResourceType _resourceType;
|
||||
[SerializeField] private ComparisonType _comparisonType;
|
||||
[SerializeField, ShowIf(nameof(_compareBy), ValueType.Value)] private BlackboardEntrySelector<int> _value = new(1);
|
||||
[SerializeField, ShowIf(nameof(_compareBy), ValueType.Value)] private BlackboardEntrySelector<int> _percent = new(50);
|
||||
[SerializeField] private ValueType _compareBy;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
_percent.inspectorValue = Mathf.Min(Mathf.Max(_percent.inspectorValue, 0), 100);
|
||||
_value.inspectorValue = Mathf.Max(_value.inspectorValue, 0);
|
||||
}
|
||||
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
return _compareBy switch
|
||||
{
|
||||
ValueType.Percent => CompareByPercent(),
|
||||
ValueType.Value => CompareByValue(),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private bool CompareByValue()
|
||||
{
|
||||
var currentResource = _unit.value.unitData.currentResources.Get(_resourceType);
|
||||
|
||||
return _comparisonType switch
|
||||
{
|
||||
ComparisonType.Greater => currentResource > _value.value,
|
||||
ComparisonType.Less => currentResource < _value.value,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private bool CompareByPercent()
|
||||
{
|
||||
var currentResource = _unit.value.unitData.currentResources.Get(_resourceType);
|
||||
var maxResource = _unit.value.unitData.maxResources.Get(_resourceType);
|
||||
var currentPercent = currentResource / maxResource * 100;
|
||||
|
||||
return _comparisonType switch
|
||||
{
|
||||
ComparisonType.Greater => currentPercent > _percent.value,
|
||||
ComparisonType.Less => currentPercent < _percent.value,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append(
|
||||
$"If <color=red>{_unit.name}</color> {nameof(UnitObjectData)}'s <color=red>{_resourceType}</color>");
|
||||
sb.Append(_comparisonType == ComparisonType.Greater ? " > " : " < ");
|
||||
if (_compareBy is ValueType.Percent) sb.Append($"<color=red>{_percent.name}</color>%");
|
||||
if (_compareBy is ValueType.Value) sb.Append($"<color=red>{_value.name}</color>");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9851bd79142742a4a00ffe81f4cf8385
|
||||
timeCreated: 1709492242
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.Text;
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Conditionals
|
||||
{
|
||||
[DarkIcon("Conditionals/d_IsNull")]
|
||||
[LightIcon("Conditionals/IsNull")]
|
||||
[Category(SchemaCategory.CombatAnyUnit)]
|
||||
public class IsUnitTurn : Conditional
|
||||
{
|
||||
[SerializeField] public BlackboardEntrySelector<UnitObject> _unit;
|
||||
|
||||
public override bool Evaluate(object nodeMemory, SchemaAgent agent)
|
||||
{
|
||||
return _unit.value && _unit.value.basicState.turnManager && _unit.value.unitState.isSelfTurn;
|
||||
}
|
||||
|
||||
public override GUIContent GetConditionalContent()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (invert) sb.Append("<color=red>NOT</color> ");
|
||||
sb.Append($"If its <color=red>{_unit.name}</color>'s turn");
|
||||
return new GUIContent(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da0d9e0133ee4779bc1daea1bb680d25
|
||||
timeCreated: 1709565723
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace VOID.Generic.AI.Schema
|
||||
{
|
||||
public static class SchemaCategory
|
||||
{
|
||||
private const string VoidCategory = "VOID RPG / ";
|
||||
public const string CombatAnyUnit = VoidCategory + "Combat only / Any Unit";
|
||||
public const string RealtimeAnyUnit = VoidCategory + "Realtime only / Any Unit";
|
||||
public const string CombatThisUnit = VoidCategory + "Combat only / This Unit";
|
||||
public const string RealtimeThisUnit = VoidCategory + "Realtime only / This Unit";
|
||||
public const string AnyUnit = VoidCategory + "Any Unit";
|
||||
public const string ThisUnit = VoidCategory + "This Unit";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33bca9a6c7ab4879a2e5a29f53b78b41
|
||||
timeCreated: 1709820395
|
||||
@@ -0,0 +1,31 @@
|
||||
using UnityEngine.Events;
|
||||
using VOID.Generic.Objects.Abstract.Events;
|
||||
|
||||
namespace VOID.Generic.AI.Schema
|
||||
{
|
||||
public class SchemaUnitEventWrapper<TUnitEvent, TMemory> where TUnitEvent : AbstractEvent
|
||||
{
|
||||
private UnityEvent<TUnitEvent> _listener;
|
||||
private UnityAction<TUnitEvent> _action;
|
||||
|
||||
public SchemaUnitEventWrapper(
|
||||
UnityEvent<TUnitEvent> addListenerTo,
|
||||
UnityAction<TUnitEvent, TMemory, UnitObjectSchemaAgent> action,
|
||||
UnitObjectSchemaAgent agent,
|
||||
TMemory memory)
|
||||
{
|
||||
_listener = addListenerTo;
|
||||
_action = t1 => action.Invoke(t1, memory, agent);
|
||||
}
|
||||
|
||||
public void On()
|
||||
{
|
||||
_listener.AddListener(_action);
|
||||
}
|
||||
|
||||
public void Off()
|
||||
{
|
||||
_listener.RemoveListener(_action);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80f30b03c1f0439fbefcc92e468b592b
|
||||
timeCreated: 1709228750
|
||||
@@ -0,0 +1,11 @@
|
||||
using Schema;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema
|
||||
{
|
||||
public class UnitObjectSchemaAgent : SchemaAgent
|
||||
{
|
||||
public UnitObject unit;
|
||||
public UnitAI unitAI;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6adfb8fe7d19483aa20b5a2d03709433
|
||||
timeCreated: 1709501103
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2b2f0e2aece4ae684c4e3e19189ef70
|
||||
timeCreated: 1709163584
|
||||
@@ -0,0 +1,19 @@
|
||||
using Schema;
|
||||
using VOID.ScriptableObjects.Abilities;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Variables
|
||||
{
|
||||
[Color("#b07219")]
|
||||
[Name(nameof(BasicAbility))]
|
||||
[UseExternalTypeDefinition(typeof(BasicAbility))]
|
||||
[IncludePaths(
|
||||
"actionPointCost",
|
||||
"movePointCost",
|
||||
"isRanged",
|
||||
"range",
|
||||
"castUsages"
|
||||
)]
|
||||
public class AbilityVariable : EntryType
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9715994280f4de0b20ae8cc047a02e3
|
||||
timeCreated: 1709730991
|
||||
@@ -0,0 +1,30 @@
|
||||
using Schema;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.Objects.Abstract;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Variables
|
||||
{
|
||||
[Color("#b07219")]
|
||||
[Name(nameof(AbstractObject))]
|
||||
[UseExternalTypeDefinition(typeof(AbstractObject))]
|
||||
[ExcludePaths(
|
||||
"gameObject",
|
||||
"transform",
|
||||
"transform.position",
|
||||
"basicData.currentResources.health",
|
||||
"basicData.resistances.physicalResistance",
|
||||
"basicData.resistances.magicalResistance",
|
||||
"basicData.resistances.fireResistance",
|
||||
"basicData.resistances.waterResistance",
|
||||
"basicData.resistances.earthResistance",
|
||||
"basicData.resistances.airResistance",
|
||||
"basicData.resistances.poisonResistance",
|
||||
"basicData.resistances.lightResistance",
|
||||
"basicData.resistances.darkResistance",
|
||||
"basicData.resistances.healResistance"
|
||||
)]
|
||||
[ExcludeTypes(typeof(Matrix4x4))]
|
||||
public class AbstractObjectVariable : EntryType
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4c4f14007c8494fa0d8743dffa15a98
|
||||
timeCreated: 1709564147
|
||||
@@ -0,0 +1,30 @@
|
||||
using Schema;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI.Schema.Variables
|
||||
{
|
||||
[Color("#b07219")]
|
||||
[Name(nameof(UnitObject))]
|
||||
[UseExternalTypeDefinition(typeof(UnitObject))]
|
||||
[IncludePaths(
|
||||
"gameObject",
|
||||
"transform",
|
||||
"transform.position",
|
||||
"basicData.currentResources.health",
|
||||
"basicData.resistances.physicalResistance",
|
||||
"basicData.resistances.magicalResistance",
|
||||
"basicData.resistances.fireResistance",
|
||||
"basicData.resistances.waterResistance",
|
||||
"basicData.resistances.earthResistance",
|
||||
"basicData.resistances.airResistance",
|
||||
"basicData.resistances.poisonResistance",
|
||||
"basicData.resistances.lightResistance",
|
||||
"basicData.resistances.darkResistance",
|
||||
"basicData.resistances.healResistance",
|
||||
"unitData.level",
|
||||
"unitData.exp"
|
||||
)]
|
||||
public class UnitObjectVariable : EntryType
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a55139c845b4f4284fc7d276794d548
|
||||
timeCreated: 1709163608
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Collections.Generic;
|
||||
using Schema;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using VOID.Generic.AI.Schema;
|
||||
using VOID.Generic.Objects.Abstract.Events;
|
||||
using VOID.Generic.Objects.Unit;
|
||||
|
||||
namespace VOID.Generic.AI
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public class UnitAI : MonoBehaviour
|
||||
{
|
||||
private UnitObject _unit;
|
||||
private UnitObjectSchemaAgent _schemaAgent;
|
||||
|
||||
[Title("AI Schemas")]
|
||||
[DisableOnPlay, SerializeField, Required] private Graph _passiveSchema;
|
||||
[DisableOnPlay, SerializeField, Required] private Graph _combatSchema;
|
||||
|
||||
[Title("Variables for schemas")]
|
||||
public List<Transform> patrol;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
enabled = false;
|
||||
|
||||
if (!_passiveSchema || !_combatSchema)
|
||||
{
|
||||
Debug.LogError("Both AI schemas are REQUIRED!");
|
||||
return;
|
||||
}
|
||||
|
||||
_unit = GetComponent<UnitObject>();
|
||||
if (!_unit)
|
||||
{
|
||||
Debug.LogError("Found no UnitObject!");
|
||||
return;
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
|
||||
// Disable AI when unit is dead or enable when revived
|
||||
_unit.basicEvents.onDeathAfter.AddListener(OnDeathAfter);
|
||||
_unit.basicEvents.onRevive.AddListener(OnRevive);
|
||||
|
||||
// Change AI schemas between passive and combat
|
||||
_unit.basicEvents.onTurnQueueEnter.AddListener(OnTurnQueueEnter);
|
||||
_unit.basicEvents.onTurnQueueLeave.AddListener(OnTurnQueueLeave);
|
||||
|
||||
_schemaAgent = gameObject.AddComponent<UnitObjectSchemaAgent>();
|
||||
_schemaAgent.hideFlags = HideFlags.NotEditable;
|
||||
_schemaAgent.unit = _unit;
|
||||
_schemaAgent.unitAI = this;
|
||||
_schemaAgent.ChangeSchema(_passiveSchema);
|
||||
}
|
||||
|
||||
private void OnTurnQueueEnter(TurnEvent turnEvent)
|
||||
{
|
||||
_schemaAgent.ChangeSchema(_combatSchema);
|
||||
}
|
||||
|
||||
private void OnTurnQueueLeave(TurnEvent turnEvent)
|
||||
{
|
||||
_schemaAgent.ChangeSchema(_passiveSchema);
|
||||
}
|
||||
|
||||
private void OnDeathAfter(DeathEvent deathEvent) {
|
||||
_schemaAgent.enabled = false;
|
||||
}
|
||||
|
||||
private void OnRevive(ReviveEvent reviveEvent) {
|
||||
_schemaAgent.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2d54cbb701447989de500c51c021077
|
||||
timeCreated: 1725642293
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18a9023d69624afb95176a1cf8e8b811
|
||||
timeCreated: 1668882343
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VOID.Generic.AreaOfEffect
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class AbstractAreaOfEffect
|
||||
{
|
||||
[SerializeField] private bool fixedRotation;
|
||||
[SerializeField] [MinValue(-180), MaxValue(180)] private float offsetRotation;
|
||||
|
||||
/// <summary>
|
||||
/// Calculates final rotation that include AOE offset rotation and/or fixed rotation.
|
||||
/// </summary>
|
||||
/// <param name="from">Position on AOE collider</param>
|
||||
/// <param name="to">Position where AOE collider should look</param>
|
||||
/// <returns>Quaternion to put into tranform.rotation</returns>
|
||||
public Quaternion GetRotation(Vector3 from, Vector3 to)
|
||||
{
|
||||
// Ignore look angle, we use only offset rotation
|
||||
if (fixedRotation) return Quaternion.Euler(new Vector3(0, offsetRotation, 0));
|
||||
|
||||
// Include offset rotation into look rotation
|
||||
var directionNormalized = (new Vector2(to.x, to.z) - new Vector2(from.x, from.z)).normalized;
|
||||
var lookAngleY = Vector2.SignedAngle(Vector2.up, directionNormalized) * -1;
|
||||
return Quaternion.Euler(new Vector3(0, lookAngleY + offsetRotation, 0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns mesh of this area of effect.
|
||||
/// </summary>
|
||||
public abstract Mesh GetMesh();
|
||||
|
||||
/// <summary>
|
||||
/// Adds prepared collider to given GameObject.
|
||||
/// </summary>
|
||||
public abstract Collider AddCollider(GameObject gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4df7809a77e042a9966ae305d6e915a6
|
||||
timeCreated: 1668882573
|
||||
@@ -0,0 +1,100 @@
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VOID.Generic.AreaOfEffect
|
||||
{
|
||||
[TypeRegistryItem("Cone")]
|
||||
public class ConeAreaOfEffect : AbstractAreaOfEffect
|
||||
{
|
||||
[SerializeField, Required, MinValue(0.5), MaxValue(10)]
|
||||
private float length;
|
||||
[SerializeField, Required, MinValue(10), MaxValue(350)]
|
||||
private float degree;
|
||||
|
||||
public override Mesh GetMesh()
|
||||
{
|
||||
var mesh = GenerateConeMesh();
|
||||
mesh.vertices = mesh.vertices.Select(vertex => Vector3.Scale(vertex, new Vector3(length, 1, length))).ToArray();
|
||||
return mesh;
|
||||
}
|
||||
|
||||
public override Collider AddCollider(GameObject gameObject)
|
||||
{
|
||||
var collider = gameObject.AddComponent<MeshCollider>();
|
||||
collider.sharedMesh = GetMesh();
|
||||
collider.convex = true;
|
||||
collider.isTrigger = true;
|
||||
|
||||
return collider;
|
||||
}
|
||||
|
||||
private Mesh GenerateConeMesh()
|
||||
{
|
||||
var sections = Mathf.FloorToInt(degree / 10);
|
||||
var mesh = new Mesh();
|
||||
|
||||
var vertices = new Vector3[4 + sections * 2];
|
||||
var uv = new Vector2[vertices.Length];
|
||||
var triangles = new int[(4 + sections * 4) * 3];
|
||||
|
||||
var currentAngle = -sections * 10 / 2;
|
||||
var vertexIndex = 0;
|
||||
var triangleIndex = 0;
|
||||
|
||||
vertices[0] = new Vector3(0,-0.5f,0);
|
||||
vertices[1] = new Vector3(0,0.5f,0);
|
||||
vertices[2] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), -0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));
|
||||
vertices[3] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), 0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));
|
||||
|
||||
triangles[0] = 0;
|
||||
triangles[1] = 3;
|
||||
triangles[2] = 1;
|
||||
triangles[3] = 0;
|
||||
triangles[4] = 2;
|
||||
triangles[5] = 3;
|
||||
|
||||
for (var i = 0; i < sections; i++)
|
||||
{
|
||||
|
||||
vertexIndex = 4 + i*2;
|
||||
triangleIndex = (2 + i*4) * 3;
|
||||
currentAngle += 10;
|
||||
|
||||
vertices[vertexIndex+0] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), -0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));
|
||||
vertices[vertexIndex+1] = new Vector3(Mathf.Sin(Mathf.Deg2Rad * currentAngle), 0.5f, Mathf.Cos(Mathf.Deg2Rad * currentAngle));
|
||||
|
||||
triangles[triangleIndex+0] = 0;
|
||||
triangles[triangleIndex+1] = vertexIndex;
|
||||
triangles[triangleIndex+2] = vertexIndex-2;
|
||||
|
||||
triangles[triangleIndex+3] = 1;
|
||||
triangles[triangleIndex+4] = vertexIndex-1;
|
||||
triangles[triangleIndex+5] = vertexIndex+1;
|
||||
|
||||
triangles[triangleIndex+6] = vertexIndex-2;
|
||||
triangles[triangleIndex+7] = vertexIndex;
|
||||
triangles[triangleIndex+8] = vertexIndex-1;
|
||||
|
||||
triangles[triangleIndex+9] = vertexIndex;
|
||||
triangles[triangleIndex+10] = vertexIndex+1;
|
||||
triangles[triangleIndex+11] = vertexIndex-1;
|
||||
}
|
||||
|
||||
triangleIndex += 12;
|
||||
triangles[triangleIndex+0] = 0;
|
||||
triangles[triangleIndex+1] = vertexIndex+1;
|
||||
triangles[triangleIndex+2] = vertexIndex;
|
||||
|
||||
triangles[triangleIndex+3] = 0;
|
||||
triangles[triangleIndex+4] = 1;
|
||||
triangles[triangleIndex+5] = vertexIndex+1;
|
||||
|
||||
mesh.vertices = vertices;
|
||||
mesh.uv = uv;
|
||||
mesh.triangles = triangles;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 520c8333284d4e80ad52f6f52c6bed9f
|
||||
timeCreated: 1668886267
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VOID.Generic.AreaOfEffect
|
||||
{
|
||||
[TypeRegistryItem("Line")]
|
||||
public class LineAreaOfEffect : AbstractAreaOfEffect
|
||||
{
|
||||
[SerializeField, Required, MinValue(0.5), MaxValue(10)]
|
||||
private float length;
|
||||
[SerializeField, Required, MinValue(0.1), MaxValue(1)]
|
||||
private float width;
|
||||
|
||||
public override Mesh GetMesh()
|
||||
{
|
||||
var scale = new Vector3(width, 1, length);
|
||||
var cubeMesh = Resources.GetBuiltinResource<Mesh>("Cube.fbx");
|
||||
|
||||
var mesh = new Mesh();
|
||||
mesh.vertices = cubeMesh.vertices.Select(vertex => Vector3.Scale(vertex, scale)).ToArray();
|
||||
mesh.triangles = cubeMesh.triangles;
|
||||
mesh.uv = cubeMesh.uv;
|
||||
mesh.normals = cubeMesh.normals;
|
||||
mesh.colors = cubeMesh.colors;
|
||||
mesh.tangents = cubeMesh.tangents;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
public override Collider AddCollider(GameObject gameObject)
|
||||
{
|
||||
var collider = gameObject.AddComponent<BoxCollider>();
|
||||
collider.isTrigger = true;
|
||||
collider.size = new Vector3(width, 1, length);
|
||||
collider.center = new Vector3(0, 0, length/2);
|
||||
|
||||
return collider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09edcf0819c940c9bf301b7cec804652
|
||||
timeCreated: 1668886161
|
||||
@@ -0,0 +1,19 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VOID.Generic.AreaOfEffect
|
||||
{
|
||||
[TypeRegistryItem("None")]
|
||||
public class NoneAreaOfEffect : AbstractAreaOfEffect
|
||||
{
|
||||
public override Mesh GetMesh()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override Collider AddCollider(GameObject gameObject)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 296c84aa02c94e42b05c9fe8fa167c6a
|
||||
timeCreated: 1723994170
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VOID.Generic.AreaOfEffect
|
||||
{
|
||||
[TypeRegistryItem("Point")]
|
||||
public class PointAreaOfEffect : AbstractAreaOfEffect
|
||||
{
|
||||
public override Mesh GetMesh()
|
||||
{
|
||||
var sphereMesh = Resources.GetBuiltinResource<Mesh>("Sphere.fbx");
|
||||
|
||||
var mesh = new Mesh();
|
||||
mesh.vertices = sphereMesh.vertices.Select(vertex => vertex * 0.1f).ToArray();
|
||||
mesh.triangles = sphereMesh.triangles;
|
||||
mesh.uv = sphereMesh.uv;
|
||||
mesh.normals = sphereMesh.normals;
|
||||
mesh.colors = sphereMesh.colors;
|
||||
mesh.tangents = sphereMesh.tangents;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
public override Collider AddCollider(GameObject gameObject)
|
||||
{
|
||||
var collider = gameObject.AddComponent<SphereCollider>();
|
||||
collider.isTrigger = true;
|
||||
collider.radius = 0.05f;
|
||||
|
||||
return collider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c184340780c04acd8a4b77a992cfa0d5
|
||||
timeCreated: 1668886062
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Linq;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VOID.Generic.AreaOfEffect
|
||||
{
|
||||
[TypeRegistryItem("Sphere")]
|
||||
public class SphereAreaOfEffect : AbstractAreaOfEffect
|
||||
{
|
||||
[SerializeField, Required, MinValue(0.5)]
|
||||
private float radius;
|
||||
|
||||
public override Mesh GetMesh()
|
||||
{
|
||||
var sphereMesh = Resources.GetBuiltinResource<Mesh>("Cylinder.fbx");
|
||||
|
||||
var mesh = new Mesh();
|
||||
mesh.vertices = sphereMesh.vertices.Select(vertex => vertex * radius).ToArray();
|
||||
mesh.triangles = sphereMesh.triangles;
|
||||
mesh.uv = sphereMesh.uv;
|
||||
mesh.normals = sphereMesh.normals;
|
||||
mesh.colors = sphereMesh.colors;
|
||||
mesh.tangents = sphereMesh.tangents;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
public override Collider AddCollider(GameObject gameObject)
|
||||
{
|
||||
var collider = gameObject.AddComponent<SphereCollider>();
|
||||
collider.isTrigger = true;
|
||||
collider.radius = radius;
|
||||
|
||||
return collider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afb5127c03e442a693e9ae8065efc8b7
|
||||
timeCreated: 1668886391
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3402e0e5e8b443fbcf6efcfda99b79c
|
||||
timeCreated: 1675371332
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f31597e216b4550b09c18de2e95f2d1
|
||||
timeCreated: 1675891233
|
||||
@@ -0,0 +1,15 @@
|
||||
using Sirenix.OdinInspector;
|
||||
|
||||
namespace VOID.Generic.Dict.Ability
|
||||
{
|
||||
[InfoBox(
|
||||
"Defines if player will be assisted with aiming:\n" +
|
||||
"<u><b>" + nameof(None) + "</b></u> nothing will change\n" +
|
||||
"<u><b>" + nameof(Directional) + "</b></u> changes target to farthest point in selected direction"
|
||||
)]
|
||||
public enum AbilityAimingCorrectionType
|
||||
{
|
||||
None,
|
||||
Directional,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee72266c891d48c98224fab00ac02b23
|
||||
timeCreated: 1733843075
|
||||
@@ -0,0 +1,15 @@
|
||||
using Sirenix.OdinInspector;
|
||||
|
||||
namespace VOID.Generic.Dict.Ability
|
||||
{
|
||||
[InfoBox("Define how ability gets targets from player or AI:\n" +
|
||||
"<u><b>" + nameof(Blank) + "</b></u> there is no aiming and no targets\n" +
|
||||
"<u><b>" + nameof(Self) + "</b></u> targeting self with only one projectile\n" +
|
||||
"<u><b>" + nameof(Target) + "</b></u> manually selecting target(s) needed, before firing")]
|
||||
public enum AbilityAimingType
|
||||
{
|
||||
Blank,
|
||||
Self,
|
||||
Target,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b2571b2c5b9432e9823da2fe8a17167
|
||||
timeCreated: 1675891471
|
||||
@@ -0,0 +1,18 @@
|
||||
using Sirenix.OdinInspector;
|
||||
|
||||
namespace VOID.Generic.Dict.Ability
|
||||
{
|
||||
[InfoBox("Define how ability is casted by unit:\n" +
|
||||
"<u><b>" + nameof(Instant) + "</b></u> casting and ability animations skipped, instantly fires\n" +
|
||||
"<u><b>" + nameof(InstantCasting) + "</b></u> casting animation skipped and start ability animation, then fires\n" +
|
||||
"<u><b>" + nameof(Casted) + "</b></u> starts casting animation and shoot projectile(s)\n" +
|
||||
"<u><b>" + nameof(Channel) + "</b></u> starts looped casting animation, shoot projectile(s)" +
|
||||
"and animation ends when all projectiles finish")]
|
||||
public enum AbilityCastingType
|
||||
{
|
||||
Instant,
|
||||
InstantCasting,
|
||||
Casted,
|
||||
Channel,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6efeff194e294c74ada4bae8523b910f
|
||||
timeCreated: 1675892484
|
||||
@@ -0,0 +1,16 @@
|
||||
using Sirenix.OdinInspector;
|
||||
|
||||
namespace VOID.Generic.Dict.Ability
|
||||
{
|
||||
[InfoBox("Define moment when effects apply to caster:\n" +
|
||||
"<u><b>" + nameof(None) + "</b></u> will never apply effects to caster\n" +
|
||||
"<u><b>" + nameof(AfterCast) + "</b></u> after ability successfully cast\n" +
|
||||
"<u><b>" + nameof(AfterEnd) + "</b></u> after ability animation end" +
|
||||
"and animation ends when all projectiles finish")]
|
||||
public enum AbilityExecutionMoment
|
||||
{
|
||||
None,
|
||||
AfterCast,
|
||||
AfterEnd
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4834a8992964154b471fb88dc35fa60
|
||||
timeCreated: 1719249326
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace VOID.Generic.Dict.Ability
|
||||
{
|
||||
[Flags]
|
||||
public enum AbilityPurposeFlag
|
||||
{
|
||||
None = 0,
|
||||
Damage = 1 << 0,
|
||||
Buff = 1 << 1,
|
||||
Debuff = 1 << 2,
|
||||
Mobility = 1 << 3,
|
||||
Heal = 1 << 4,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65b55f6110344a1ab2fd0317abc15c06
|
||||
timeCreated: 1726671937
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum AccessoryType
|
||||
{
|
||||
Ring,
|
||||
Necklace
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23983ab8393e4c909d3e29979655b873
|
||||
timeCreated: 1705006309
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum AnimationType
|
||||
{
|
||||
// Use,
|
||||
// Talk,
|
||||
// Take,
|
||||
// Inspect,
|
||||
Casting,
|
||||
Ability,
|
||||
Traverse,
|
||||
Death
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 001031de5f494ecbb81c9b0af54f7035
|
||||
timeCreated: 1686509529
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum AreaConnectionType
|
||||
{
|
||||
None,
|
||||
Inner,
|
||||
Tunnel,
|
||||
Whole,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d38543a4a0a64d73afdb1ac9fc68b45c
|
||||
timeCreated: 1706478382
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum ArmorSubType
|
||||
{
|
||||
Light,
|
||||
Medium,
|
||||
Heavy,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14f456af555442dd9bf04093305147a5
|
||||
timeCreated: 1705100835
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum ArmorType
|
||||
{
|
||||
Armor,
|
||||
Belt,
|
||||
Boots,
|
||||
Gloves,
|
||||
Helmet,
|
||||
Pants,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9822d956fd8545a3be27d400761e7573
|
||||
timeCreated: 1705006358
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum AttitudeType
|
||||
{
|
||||
Hostile,
|
||||
Cautious,
|
||||
Neutral,
|
||||
Friendly,
|
||||
Companion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 579e1337c7324c19bb5eb81876007168
|
||||
timeCreated: 1708428031
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum BasicResourceType
|
||||
{
|
||||
Health,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 050b1c4adee848edb5f96bde1efd6f79
|
||||
timeCreated: 1674674346
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum DamageType
|
||||
{
|
||||
Physical,
|
||||
Magical,
|
||||
Fire,
|
||||
Water,
|
||||
Earth,
|
||||
Air,
|
||||
Poison,
|
||||
Light,
|
||||
Dark,
|
||||
Heal
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8fa5e2948ccb44d189117e4c6f670b34
|
||||
timeCreated: 1675371152
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace VOID.Generic.Dict
|
||||
{
|
||||
public enum Direction2D
|
||||
{
|
||||
Forward,
|
||||
Right,
|
||||
Back,
|
||||
Left
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24d0b232789c4297874ef7e1635977a9
|
||||
timeCreated: 1706994305
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user