init 1.1.2

This commit is contained in:
2025-07-20 10:01:29 +08:00
commit 2afbbf9be4
1327 changed files with 1596159 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 29aef27e3ae011743acfde9f7aea8fee
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,115 @@
using UnityEngine;
using UnityEditor;
namespace EmeraldAI.Utility
{
[CustomEditor(typeof(EmeraldGeneralTargetBridge))]
[CanEditMultipleObjects]
public class EmeraldGeneralTargetBridgeEditor : Editor
{
GUIStyle FoldoutStyle;
Texture HealthEditorIcon;
SerializedProperty StartHealthProp, ImmortalProp, OnTakeDamageProp, OnDeathProp, HideSettingsFoldout, HealthSettingsFoldout;
void OnEnable()
{
if (HealthEditorIcon == null) HealthEditorIcon = Resources.Load("Editor Icons/EmeraldHealth") as Texture;
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
StartHealthProp = serializedObject.FindProperty("StartingHealth");
ImmortalProp = serializedObject.FindProperty("Immortal");
OnTakeDamageProp = serializedObject.FindProperty("OnTakeDamage");
OnDeathProp = serializedObject.FindProperty("OnDeath");
HealthSettingsFoldout = serializedObject.FindProperty("HealthSettingsFoldout");
}
public override void OnInspectorGUI()
{
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
EmeraldGeneralTargetBridge self = (EmeraldGeneralTargetBridge)target;
serializedObject.Update();
CustomEditorProperties.BeginScriptHeaderNew("Target Bridge", HealthEditorIcon, new GUIContent(), HideSettingsFoldout);
if (!HideSettingsFoldout.boolValue)
{
EditorGUILayout.Space();
HealthSetting(self);
EditorGUILayout.Space();
}
serializedObject.ApplyModifiedProperties();
CustomEditorProperties.EndScriptHeader();
}
void HealthSetting (EmeraldGeneralTargetBridge self)
{
HealthSettingsFoldout.boolValue = EditorGUILayout.Foldout(HealthSettingsFoldout.boolValue, "Health Settings", true, FoldoutStyle);
if (HealthSettingsFoldout.boolValue)
{
CustomEditorProperties.BeginFoldoutWindowBox();
CustomEditorProperties.TextTitleWithDescription("Faction Settings", "Allows AI to identify this gameobject without having to rely on Unity's Tag system. This means all potential targets can share the same Unity Tag and Unity Layer.", true);
CustomEditorProperties.CustomPropertyField(ImmortalProp, "Immortal", "Controls whether or not an AI is immune to damage and is unkillable.", true);
EditorGUI.BeginDisabledGroup(self.Immortal);
CustomEditorProperties.CustomPropertyField(StartHealthProp, "Start Health", "Controls the health this AI will start with.", true);
CustomEditorProperties.CustomHelpLabelField("Triggers an event when this target is damaged.", false);
EditorGUILayout.PropertyField(OnTakeDamageProp, new GUIContent("On Take Damage Event"));
EditorGUILayout.Space();
//CustomEditorProperties.CustomPropertyField(OnTakeDamageProp, "On Take Damage Event", "Triggers an event when this target is damaged.", true);
CustomEditorProperties.CustomHelpLabelField("Triggers an event when this target is dies.", false);
EditorGUILayout.PropertyField(OnDeathProp, new GUIContent("On Death Event"));
//CustomEditorProperties.CustomPropertyField(OnDeathProp, "On Death Event", "Triggers an event when this target is dies.", true);
EditorGUI.EndDisabledGroup();
DrawHealthBar(self);
EditorGUILayout.Space();
CustomEditorProperties.EndFoldoutWindowBox();
}
}
void DrawHealthBar(EmeraldGeneralTargetBridge self)
{
GUILayout.Space(45);
GUIStyle LabelStyle = new GUIStyle();
LabelStyle.alignment = TextAnchor.MiddleCenter;
LabelStyle.padding.bottom = 4;
LabelStyle.fontStyle = FontStyle.Bold;
LabelStyle.normal.textColor = Color.white;
Rect r = EditorGUILayout.BeginVertical();
GUI.backgroundColor = Color.white;
float CurrentHealth = ((float)self.Health / (float)self.StartHealth);
if (!Application.isPlaying)
{
self.Health = self.StartHealth;
}
if (CurrentHealth <= 0)
{
CurrentHealth = 0;
}
EditorGUI.DrawRect(new Rect(r.x, r.position.y - 39f, ((r.width)), 32), new Color(0.05f, 0.05f, 0.05f, 0.5f)); //Health Bar BG Outline
EditorGUI.DrawRect(new Rect(r.x + 4, r.position.y - 35f, ((r.width - 8)), 24), new Color(0.16f, 0.16f, 0.16f, 1f)); //Health Bar BG
Color HealthBarColor = Color.Lerp(new Color(0.6f, 0.1f, 0.1f, 1f), new Color(0.15f, 0.42f, 0.15f, 1f), CurrentHealth);
EditorGUI.DrawRect(new Rect(r.x + 4, r.position.y - 35f, ((r.width - 8) * CurrentHealth), 24), HealthBarColor); //Health Bar Main
if (CurrentHealth > 0)
{
EditorGUI.LabelField(new Rect(r.x, r.position.y - 35f, (r.width), 26), "Current Health: " + self.Health + "/" + self.StartHealth, LabelStyle);
}
else
{
EditorGUI.LabelField(new Rect(r.x, r.position.y - 35f, (r.width), 26), "Current Health: " + 0 + "/" + self.StartHealth + " (Dead)", LabelStyle);
}
EditorGUILayout.EndVertical();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f2200ad73c77b8418c10a2808a92e67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,91 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEditorInternal;
namespace EmeraldAI.Utility
{
[CustomEditor(typeof(FactionExtension))]
[CanEditMultipleObjects]
public class FactionExtensionEditor : Editor
{
GUIStyle FoldoutStyle;
Texture FactionExtensionEditorIcon;
SerializedProperty CurrentFactionProp, HideSettingsFoldout, FactionFoldout;
void OnEnable()
{
if (FactionExtensionEditorIcon == null) FactionExtensionEditorIcon = Resources.Load("Editor Icons/FactionExtension") as Texture;
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
CurrentFactionProp = serializedObject.FindProperty("CurrentFaction");
FactionFoldout = serializedObject.FindProperty("FactionFoldout");
LoadFactionData();
}
public override void OnInspectorGUI()
{
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
FactionExtension self = (FactionExtension)target;
serializedObject.Update();
CustomEditorProperties.BeginScriptHeaderNew("Faction Extension", FactionExtensionEditorIcon, new GUIContent(), HideSettingsFoldout);
if (!HideSettingsFoldout.boolValue)
{
EditorGUILayout.Space();
FactionSetting(self);
EditorGUILayout.Space();
}
serializedObject.ApplyModifiedProperties();
CustomEditorProperties.EndScriptHeader();
}
void FactionSetting (FactionExtension self)
{
FactionFoldout.boolValue = EditorGUILayout.Foldout(FactionFoldout.boolValue, "Faction Settings", true, FoldoutStyle);
if (FactionFoldout.boolValue)
{
CustomEditorProperties.BeginFoldoutWindowBox();
CustomEditorProperties.TextTitleWithDescription("Faction Settings", "Allows AI to identify this gameobject without having to rely on Unity's Tag system. This means all potential targets can share the same Unity Tag and Unity Layer.", true);
CustomEditorProperties.FactionListEnum(new Rect(), new GUIContent(), CurrentFactionProp, "Faction", FactionExtension.StringFactionList);
CustomEditorProperties.CustomHelpLabelField("This Faction is used to identify this gameobject and is indended to be used on non-AI objects such as players. This is the name that AI will use when " +
"looking for targets.", true);
CustomEditorProperties.CustomHelpLabelField("Factions can be created and removed using the Faction Manager. ", false);
if (GUILayout.Button("Open Faction Manager"))
{
EditorWindow APS = EditorWindow.GetWindow(typeof(EmeraldFactionManager));
APS.minSize = new Vector2(600f, 775f);
}
EditorGUILayout.Space();
CustomEditorProperties.EndFoldoutWindowBox();
}
}
void LoadFactionData()
{
FactionExtension.StringFactionList.Clear();
string path = AssetDatabase.GetAssetPath(Resources.Load("Faction Data"));
EmeraldFactionData FactionData = (EmeraldFactionData)AssetDatabase.LoadAssetAtPath(path, typeof(EmeraldFactionData));
if (FactionData != null)
{
foreach (string s in FactionData.FactionNameList)
{
if (!FactionExtension.StringFactionList.Contains(s) && s != "")
{
FactionExtension.StringFactionList.Add(s);
}
}
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 680006eba67e3cd4ba330ff9d13654be
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,122 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using EmeraldAI.Utility;
namespace EmeraldAI
{
[RequireComponent(typeof(TargetPositionModifier))]
[RequireComponent(typeof(FactionExtension))]
[HelpURL("https://black-horizon-studios.gitbook.io/emerald-ai-wiki/getting-started/setting-up-a-player-with-emerald-ai")]
public class EmeraldGeneralTargetBridge : MonoBehaviour, IDamageable, ICombat
{
public int StartingHealth = 50;
public bool Immortal = false;
public UnityEvent OnTakeDamage;
public UnityEvent OnDeath;
public bool DebugLogDeath = true;
public bool HideSettingsFoldout;
public bool HealthSettingsFoldout = true;
public int StartHealth { get => StartingHealth; set => StartingHealth = value; }
[field: SerializeField] public int Health { get; set; }
[field: SerializeField] public List<string> ActiveEffects { get; set; }
TargetPositionModifier m_TargetPositionModifier;
Collider m_Collider;
void Start()
{
Health = StartingHealth;
m_TargetPositionModifier = GetComponent<TargetPositionModifier>();
m_Collider = GetComponent<Collider>();
}
public void Damage(int DamageAmount, Transform AttackerTransform = null, int RagdollForce = 100, bool CriticalHit = false)
{
DefaultDamage(DamageAmount, AttackerTransform);
//Creates damage text on the target's position, if enabled.
if (CombatTextSystem.Instance != null) CombatTextSystem.Instance.CreateCombatText(DamageAmount, DamagePosition(), CriticalHit, false, false);
}
void OnEnable ()
{
if (Health <= 0) ResetTarget();
}
/// <summary>
/// Used for referencing the damage position for this object when an AI takes damage from external sources.
/// </summary>
public Vector3 DamagePosition()
{
if (m_TargetPositionModifier != null)
return new Vector3(m_TargetPositionModifier.TransformSource.position.x, m_TargetPositionModifier.TransformSource.position.y + m_TargetPositionModifier.PositionModifier, m_TargetPositionModifier.TransformSource.position.z);
else
return transform.position + new Vector3(0, transform.localScale.y / 2, 0);
}
void DefaultDamage(int DamageAmount, Transform Target)
{
if (Immortal) return;
Health -= DamageAmount;
OnTakeDamage.Invoke();
if (Health <= 0)
{
if (DebugLogDeath)
Debug.Log("The Non-AI Target has died.");
if (m_Collider != null) m_Collider.enabled = false;
gameObject.layer = 0;
gameObject.tag = "Untagged";
OnDeath.Invoke();
}
}
/// <summary>
/// Resets this Non-AI target to its default settings before it was killed. This includes health, layer, and tag.
/// </summary>
public void ResetTarget ()
{
Health = StartingHealth;
if (m_Collider != null) m_Collider.enabled = true;
}
public Transform TargetTransform()
{
return transform;
}
/// <summary>
/// Used for detecting when this target is attacking.
/// </summary>
public bool IsAttacking()
{
return false;
}
/// <summary>
/// Used for detecting when this target is blocking.
/// </summary>
public bool IsBlocking()
{
return false;
}
/// <summary>
/// Used for detecting when this target is dodging.
/// </summary>
public bool IsDodging()
{
return false;
}
public void TriggerStun(float StunLength)
{
//Custom trigger mechanics can go here, but are not required
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e37b1db7cc7c630488b168e4a6f9888a
timeCreated: 1541616082
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,136 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using EmeraldAI.Utility;
namespace EmeraldAI
{
[RequireComponent(typeof(TargetPositionModifier))]
[RequireComponent(typeof(FactionExtension))]
public class EmeraldPlayerBridge : MonoBehaviour, IDamageable, ICombat
{
public int StartHealth { get; set; } = 100;
public int Health { get; set; } = 100;
[HideInInspector] public bool Immortal = false;
[Space(5)]
public UnityEvent OnTakeDamage;
public UnityEvent OnDeath;
public List<string> ActiveEffects { get; set; } = new List<string>();
TargetPositionModifier m_TargetPositionModifier;
Collider m_Collider;
bool m_CriticalHit;
public virtual void Awake()
{
m_TargetPositionModifier = GetComponent<TargetPositionModifier>();
m_Collider = GetComponent<Collider>();
}
public virtual void Start()
{
Health = StartHealth;
//You should set your StartHealth and Health variables equal to that of your character controller here.
}
/// <summary>
/// Called internally through the IDamageable interface.
/// </summary>
public void Damage(int DamageAmount, Transform AttackerTransform = null, int RagdollForce = 100, bool CriticalHit = false)
{
m_CriticalHit = CriticalHit;
DamageCharacterController(DamageAmount, AttackerTransform);
}
void OnEnable()
{
if (Health <= 0) ResetTarget();
}
/// <summary>
/// Displays damage text based on the damage passed. This is a separate function so users can used it when need (by passing block, dodge, etc.).
/// </summary>
public virtual void DisplayDamageText(int DamageAmount)
{
//Creates damage text on the target's position, if enabled.
if (CombatTextSystem.Instance != null) CombatTextSystem.Instance.CreateCombatText(DamageAmount, DamagePosition(), m_CriticalHit, false, false);
}
/// <summary>
/// Used for referencing the damage position for this object when an AI takes damage from external sources.
/// </summary>
public Vector3 DamagePosition()
{
if (m_TargetPositionModifier != null)
return new Vector3(m_TargetPositionModifier.TransformSource.position.x, m_TargetPositionModifier.TransformSource.position.y + m_TargetPositionModifier.PositionModifier, m_TargetPositionModifier.TransformSource.position.z);
else
return transform.position + new Vector3(0, transform.localScale.y / 2, 0);
}
public virtual void DamageCharacterController(int DamageAmount, Transform Target)
{
if (Immortal) return;
//The code for damaging your character controller should go here.
OnTakeDamage.Invoke();
//You should set the Health variables equal to that of your character controller after it was damaged here.
if (Health <= 0)
{
//Controls what happens when your player dies.
if (m_Collider != null) m_Collider.enabled = false;
OnDeath.Invoke();
}
}
/// <summary>
/// Resets this Non-AI target to its default settings before it was killed. This includes health, layer, and tag.
/// </summary>
public void ResetTarget()
{
Health = StartHealth;
if (m_Collider != null) m_Collider.enabled = true;
}
public virtual Transform TargetTransform()
{
return transform;
}
/// <summary>
/// Used for detecting when this target is attacking.
/// </summary>
public virtual bool IsAttacking()
{
return false;
}
/// <summary>
/// Used for detecting when this target is blocking.
/// </summary>
public virtual bool IsBlocking()
{
return false;
}
/// <summary>
/// Used for detecting when this target is dodging.
/// </summary>
public virtual bool IsDodging()
{
return false;
}
public virtual void TriggerStun(float StunLength)
{
//Custom trigger mechanics can go here, but are not required
}
}
}
@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3bb7e433f45c63a4c8579e88af63de4a
timeCreated: 1541616082
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace EmeraldAI
{
[HelpURL("https://black-horizon-studios.gitbook.io/emerald-ai-wiki/getting-started/setting-up-a-player-with-emerald-ai")]
public class FactionExtension : MonoBehaviour, IFaction
{
public bool HideSettingsFoldout;
public bool FactionFoldout = true;
[SerializeField] public int CurrentFaction = 0;
[SerializeField] public static List<string> StringFactionList = new List<string>();
public int GetFaction()
{
return CurrentFaction;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e4e984eaf744ac149ba931c82f2a82f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,40 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using EmeraldAI;
public class TestPlayerBridge : EmeraldPlayerBridge
{
public override void Start()
{
//You should set the StartHealth and Health variables equal to that of your character controller here.
}
public override void DamageCharacterController(int DamageAmount, Transform Target)
{
//The code for damaging your character controller should go here.
}
public override bool IsAttacking()
{
//Used for detecting when this target is attacking.
return false;
}
public override bool IsBlocking()
{
//Used for detecting when this target is blocking.
return false;
}
public override bool IsDodging()
{
//Used for detecting when this target is dodging.
return false;
}
public override void TriggerStun(float StunLength)
{
//Custom trigger mechanics can go here, but are not required
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8c67e5d17fd531d4e846ad1b2ef99265
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: