You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
13 KiB
C#
305 lines
13 KiB
C#
using MalbersAnimations.Scriptables;
|
|
using UnityEngine;
|
|
|
|
namespace MalbersAnimations.Controller.AI
|
|
{
|
|
|
|
[CreateAssetMenu(menuName = "Malbers Animations/Pluggable AI/Tasks/Play Mode")]
|
|
public class PlayModeTask : MTask
|
|
{
|
|
public override string DisplayName => "Animal/Set|Play Mode";
|
|
|
|
public enum PlayWhen { PlayOnce, PlayForever, Interrupt }
|
|
|
|
[Tooltip("Mode you want to activate when the brain is using this task")]
|
|
public ModeID modeID;
|
|
[Tooltip("Ability ID for the Mode... if is set to -1 it will play a random Ability")]
|
|
public IntReference AbilityID = new IntReference(-99);
|
|
public FloatReference ModePower = new FloatReference();
|
|
[Tooltip("Play the mode only when the animal has arrived to the target")]
|
|
public bool near = false;
|
|
|
|
[Space, Tooltip("Apply the Task to the Animal(Self) or the Target(Target)")]
|
|
public Affected affect = Affected.Self;
|
|
|
|
[Tooltip("Play Once: it will play only at the start of the Task. Play Forever: will play forever using the Cooldown property")]
|
|
public PlayWhen Play = PlayWhen.PlayForever;
|
|
[Tooltip("Time elapsed to Play the Mode again and Again")]
|
|
public FloatReference CoolDown = new FloatReference(2f);
|
|
[Tooltip("Play the Mode if the Animal is Looking at the Target. Avoid playing modes while the target is behind the animal when this value is set to 180")]
|
|
[Range(0f, 360f)]
|
|
public float ModeAngle = 360f;
|
|
|
|
[Tooltip("Align with a Look At towards the Target when Playing a mode")]
|
|
public bool lookAtAlign = false;
|
|
|
|
[Tooltip("When the mode is said to Play Forever, it will ignore the first cooldown")]
|
|
public bool IgnoreFirstCoolDown = true;
|
|
|
|
[Tooltip("Align time to rotate towards the Target")]
|
|
public float alignTime = 0.3f;
|
|
|
|
public override void StartTask(MAnimalBrain brain, int index)
|
|
{
|
|
if (CoolDown <= 0)
|
|
{
|
|
if (Play == PlayWhen.PlayOnce)
|
|
{
|
|
if (near && !brain.AIControl.HasArrived) return; //Dont play if Play on target is true but we are not near the target.
|
|
if (PlayMode(brain))
|
|
{
|
|
brain.TasksVars[index].boolValue = true; //Store on the Bool Variable of the Decision that it has already play the mode
|
|
}
|
|
}
|
|
else if (Play == PlayWhen.Interrupt)
|
|
{
|
|
switch (affect)
|
|
{
|
|
case Affected.Self:
|
|
brain.Animal.Mode_Interrupt();
|
|
break;
|
|
case Affected.Target:
|
|
if (brain.TargetAnimal != null) brain.TargetAnimal.Mode_Interrupt();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void UpdateTask(MAnimalBrain brain, int index)
|
|
{
|
|
if (near && !brain.AIControl.HasArrived)
|
|
{
|
|
// brain.TasksStartTime[index] = Time.time; //Reset the time to the Arrive time
|
|
return; //Dont play if Play on target is true but we are not near the target.
|
|
}
|
|
|
|
|
|
switch (Play)
|
|
{
|
|
case PlayWhen.PlayOnce:
|
|
|
|
if (!brain.TasksVars[index].boolValue) //Means the Mode has not played
|
|
{
|
|
if (MTools.ElapsedTime(brain.TasksStartTime[index], CoolDown) && PlayMode(brain))
|
|
{
|
|
brain.TasksVars[index].boolValue = true; //Set that te mode was Played Once!!
|
|
return; //Skip the code
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
switch (affect)
|
|
{
|
|
case Affected.Self:
|
|
if (!brain.Animal.IsPlayingMode && !brain.Animal.IsPreparingMode) brain.TaskDone(index);
|
|
break;
|
|
case Affected.Target:
|
|
if (brain.TargetAnimal && !brain.TargetAnimal.IsPlayingMode && !brain.TargetAnimal.IsPreparingMode) brain.TaskDone(index);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case PlayWhen.PlayForever:
|
|
|
|
if (!brain.TasksVars[index].boolValue && IgnoreFirstCoolDown) //Means the Mode has not played
|
|
{
|
|
if (PlayMode(brain))
|
|
{
|
|
brain.TasksStartTime[index] = Time.time; // Reset the cooldown timer
|
|
brain.TasksVars[index].boolValue = true; //Set that te mode was Played Once!!
|
|
}
|
|
}
|
|
|
|
if (MTools.ElapsedTime(brain.TasksStartTime[index], CoolDown)) //If the animal is in range of the Target
|
|
{
|
|
if (PlayMode(brain))
|
|
{
|
|
brain.TasksStartTime[index] = Time.time; // Reset the cooldown timer
|
|
}
|
|
}
|
|
break;
|
|
case PlayWhen.Interrupt:
|
|
if (!brain.TasksVars[index].boolValue) //Means the Mode has not played
|
|
{
|
|
if (MTools.ElapsedTime(brain.TasksStartTime[index], CoolDown))
|
|
{
|
|
brain.TasksVars[index].boolValue = true; //Set that te mode was Played Once!!
|
|
|
|
|
|
switch (affect)
|
|
{
|
|
case Affected.Self:
|
|
brain.Animal.Mode_Interrupt();
|
|
break;
|
|
case Affected.Target:
|
|
if (brain.TargetAnimal != null) brain.TargetAnimal.Mode_Interrupt();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
brain.TaskDone(index);
|
|
}
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
private bool PlayMode(MAnimalBrain brain)
|
|
{
|
|
switch (affect)
|
|
{
|
|
case Affected.Self:
|
|
var Direction_to_Target = brain.Target != null ? (brain.Target.position - brain.Eyes.position) : brain.Animal.Forward;
|
|
|
|
var EyesForward = Vector3.ProjectOnPlane(brain.Eyes.forward, brain.Animal.UpVector);
|
|
if (ModeAngle == 360f || Vector3.Dot(Direction_to_Target.normalized, EyesForward) > Mathf.Cos(ModeAngle * 0.5f * Mathf.Deg2Rad)) //Mean is in Range:
|
|
{
|
|
if (brain.Animal.Mode_TryActivate(modeID, AbilityID))
|
|
{
|
|
if (lookAtAlign && brain.Target)
|
|
brain.StartCoroutine(MTools.AlignLookAtTransform(brain.Animal.transform, brain.AIControl.GetTargetPosition(), alignTime));
|
|
|
|
brain.Animal.Mode_SetPower(ModePower);
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
case Affected.Target:
|
|
Direction_to_Target = brain.Eyes.position - brain.Target.position; //Reverse the Direction
|
|
EyesForward = Vector3.ProjectOnPlane(brain.Target.forward, brain.Animal.UpVector);
|
|
|
|
if (ModeAngle == 360f || Vector3.Dot(Direction_to_Target.normalized, EyesForward) > Mathf.Cos(ModeAngle * 0.5f * Mathf.Deg2Rad)) //Mean is in Range:
|
|
{
|
|
if (brain.TargetAnimal && brain.TargetAnimal.Mode_TryActivate(modeID, AbilityID))
|
|
{
|
|
if (lookAtAlign && brain.Target)
|
|
brain.StartCoroutine(MTools.AlignLookAtTransform(brain.TargetAnimal.transform, brain.transform, alignTime));
|
|
|
|
brain.TargetAnimal.Mode_SetPower(ModePower);
|
|
return true;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
public override void DrawGizmos(MAnimalBrain brain)
|
|
{
|
|
var Eyes = brain.Eyes;
|
|
|
|
if (Eyes && brain.Animal && ModeAngle < 360)
|
|
{
|
|
Color c = (Color.green + Color.yellow) / 2;
|
|
c.a = 1f;
|
|
|
|
Vector3 EyesForward = Vector3.ProjectOnPlane(brain.Eyes.forward, brain.Animal.UpVector);
|
|
Vector3 rotatedForward = Quaternion.Euler(0, -ModeAngle * 0.5f, 0) * EyesForward;
|
|
UnityEditor.Handles.color = c;
|
|
UnityEditor.Handles.DrawWireArc(Eyes.position, Vector3.up, rotatedForward, ModeAngle, 2);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void Reset() { Description = "Plays a mode on the Animal(Self or the Target)"; }
|
|
}
|
|
|
|
|
|
|
|
#region Inspector
|
|
|
|
#if UNITY_EDITOR
|
|
[UnityEditor.CustomEditor(typeof(PlayModeTask))]
|
|
public class PlayModeTaksEditor : UnityEditor.Editor
|
|
{
|
|
UnityEditor.SerializedProperty Description, MessageID, CoolDown, modeID, AbilityID, near, affect, ModePower, UpdateInterval,
|
|
Play, ModeAngle, lookAtAlign, WaitForPreviousTask, alignTime, IgnoreFirstCoolDown;
|
|
|
|
private void OnEnable()
|
|
{
|
|
Description = serializedObject.FindProperty("Description");
|
|
MessageID = serializedObject.FindProperty("MessageID");
|
|
ModePower = serializedObject.FindProperty("ModePower");
|
|
modeID = serializedObject.FindProperty("modeID");
|
|
AbilityID = serializedObject.FindProperty("AbilityID");
|
|
near = serializedObject.FindProperty("near");
|
|
affect = serializedObject.FindProperty("affect");
|
|
Play = serializedObject.FindProperty("Play");
|
|
CoolDown = serializedObject.FindProperty("CoolDown");
|
|
ModeAngle = serializedObject.FindProperty("ModeAngle");
|
|
lookAtAlign = serializedObject.FindProperty("lookAtAlign");
|
|
alignTime = serializedObject.FindProperty("alignTime");
|
|
IgnoreFirstCoolDown = serializedObject.FindProperty("IgnoreFirstCoolDown");
|
|
WaitForPreviousTask = serializedObject.FindProperty("WaitForPreviousTask");
|
|
UpdateInterval = serializedObject.FindProperty("UpdateInterval");
|
|
}
|
|
|
|
public override void OnInspectorGUI()
|
|
{
|
|
// base.OnInspectorGUI();
|
|
|
|
serializedObject.Update();
|
|
UnityEditor.EditorGUILayout.PropertyField(Description);
|
|
UnityEditor.EditorGUILayout.PropertyField(MessageID);
|
|
UnityEditor.EditorGUILayout.PropertyField(WaitForPreviousTask);
|
|
UnityEditor.EditorGUILayout.PropertyField(UpdateInterval);
|
|
|
|
UnityEditor.EditorGUILayout.PropertyField(affect);
|
|
UnityEditor.EditorGUILayout.PropertyField(Play, new GUIContent("Action"));
|
|
var playtype = (PlayModeTask.PlayWhen)Play.intValue;
|
|
if (playtype != PlayModeTask.PlayWhen.Interrupt)
|
|
{
|
|
UnityEditor.EditorGUILayout.PropertyField(near);
|
|
|
|
var oldColor = GUI.color;
|
|
GUI.color = modeID.objectReferenceValue == null ? (new Color(1, 0.4f, 0.4f, 1)) : oldColor;
|
|
UnityEditor.EditorGUILayout.PropertyField(modeID);
|
|
GUI.color = oldColor;
|
|
|
|
|
|
UnityEditor.EditorGUILayout.PropertyField(AbilityID);
|
|
UnityEditor.EditorGUILayout.PropertyField(ModePower);
|
|
|
|
|
|
UnityEditor.EditorGUILayout.PropertyField(CoolDown);
|
|
if (Play.intValue == 1 ) UnityEditor.EditorGUILayout.PropertyField(IgnoreFirstCoolDown);
|
|
|
|
UnityEditor.EditorGUILayout.PropertyField(ModeAngle);
|
|
|
|
UnityEditor.EditorGUILayout.BeginHorizontal();
|
|
UnityEditor.EditorGUILayout.PropertyField(lookAtAlign, new GUIContent("Quick Align"));
|
|
|
|
UnityEditor.EditorGUILayout.Space();
|
|
|
|
if (lookAtAlign.boolValue)
|
|
{
|
|
UnityEditor.EditorGUIUtility.labelWidth = 33;
|
|
UnityEditor.EditorGUILayout.PropertyField(alignTime, new GUIContent("Time"));
|
|
UnityEditor.EditorGUIUtility.labelWidth = 0;
|
|
}
|
|
UnityEditor.EditorGUILayout.EndHorizontal();
|
|
}
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
}
|
|
#endif
|
|
#endregion
|
|
}
|