Encounter / Assets / Scripts / ScriptableObjects / SpellSO.cs
SpellSO.cs
Raw
using System.Collections.Generic;
using UnityEngine;
using static SpellSO;

#if UNITY_EDITOR
using UnityEditor;
#endif

[CreateAssetMenu(fileName = "New Spell", menuName = "Config/New Spell")]
public class SpellSO : ScriptableObject
{
    public enum Element
    {
        Normal,
        Fire,
        Water,
        Earth,
        Poison,
        Ice,
        Wind,
        Darkness,
        Light,
        Necro,
        Strange,
        Energy
    }
    public enum SpellEffect
    {
        Damage,
        Debuff,
        Heal,
        Buff,
        Refill,
        Other
    }
    public enum OtherEffects
    {
        ManipulateWeather,
        SummonMinions,
        CureAilments,
        Unique,
        Revive
    }
    public enum SavingThrowFailEffect
    {
        SpellFails,
        HalfSpellValue,
        NoDebuff
    }

    public int ID;
    public string Name;
    [TextArea(3, 12)] public string Description;
    public List<string> HelperEffects;
    public int Mana_Cost;
    public Sprite Spell_Sprite;
    public Element Type = Element.Energy;
    public List<SpellEffect> Effects = new List<SpellEffect>();
    public bool HasSavingThrow;
    [Tooltip("0 - STR | 1 - INT | 2 - CON | 3 - DEX | 4 - CHA | 5 - WIS | 6 - LCK")]
    public Vector2Int SavingThrow;
    public SavingThrowFailEffect FailedThrowEffect;
    
    public bool Can_Choose_Effect;
    public List<Entity.Entities> EntityAffiliations = new List<Entity.Entities>(); 
    public List<int> PathOne    = new List<int>();
    public List<int> PathTwo    = new List<int>();
    public List<int> PathThree  = new List<int>();

    public bool Can_Choose_All_Of_Type;
    public bool Left;
    public bool DebuffLeft;
    public bool BuffLeft;
    public bool Right;
    public bool DebuffRight;
    public bool BuffRight;
    public bool UniqueTargetting;
    public bool Requires_Dice;
    public List<Dice.DiceR> Dice = new List<Dice.DiceR>();

    public List<OtherEffects> EffectsPerformed = new List<OtherEffects>();
    public ClimateManager.Weather WeatherChange;
    public List<GameObject> Minions = new List<GameObject>();

    public enum PossReqs
    {
        Stats,
        Sec_Stats,
        Item,
        Ability
    }
    public bool Has_Requirement;
    public List<PossReqs> Requirements;

    // Stats Fields
    public int Number_Of_Stat_Reqs;
    [Tooltip("0 - STR | 1 - INT | 2 - CON | 3 - DEX | 4 - CHA | 5 - WIS | 6 - LCK")]
    public List<Vector3Int> Stats_List;

    // Secondary Stat Fields
    public int Number_Of_Sec_Stat_Reqs;
    [Tooltip("0 - HP | 1 - MP | 2 - Armor")]
    public List<Vector3Int> Sec_Stats_List;

    // Item Fields
    public bool Requires_Specific;
    public int Number_Of_Items;
    public List<string> Item_List;

    public bool Requires_WType;
    public WeaponSO.Type W_Type;

    public bool Requires_AType;
    public ApparelSO.Type A_Type;

    // Ability Fields
    public int Number_Of_Abs;
    public List<string> Ability_List;

    public int Chance_Of_Modifier;
    public ModifierSO Modifier;

    public int ChanceOfBuffModifier;
    public ModifierSO BuffModifier;
    public int ChanceOfDebuffModifier;
    public ModifierSO DebuffModifier;
}

#if UNITY_EDITOR
[CustomEditor(typeof(SpellSO))]
public class SpellSOEditor : Editor
{
    private SpellSO container;

    private const int Max_Prime_Stat_Reqs = 14;
    private const int Max_Secondary_Stat_Reqs = 6;
    private const int Max_Item_Requirement = 10;
    private const int Max_Ability_Requirement = 10;

    private void OnEnable()
    {
        container = target as SpellSO;
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        EditorGUILayout.LabelField("General Properties", EditorStyles.boldLabel);
        container.ID = EditorGUILayout.IntField("ID", container.ID);
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Name"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Description"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("HelperEffects"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Spell_Sprite"));

        EditorGUILayout.Space(10);
        EditorGUILayout.LabelField("Spell Properties", EditorStyles.boldLabel);
        container.Mana_Cost = EditorGUILayout.IntField("Mana_Cost", container.Mana_Cost);
        EditorGUILayout.PropertyField(serializedObject.FindProperty("HasSavingThrow"));
        
        if (container.HasSavingThrow)
        {
            EditorGUILayout.PropertyField(serializedObject.FindProperty("SavingThrow"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("FailedThrowEffect"));
        }

        EditorGUILayout.PropertyField(serializedObject.FindProperty("Type"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Effects"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Can_Choose_Effect"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Can_Choose_All_Of_Type"));
        EditorGUILayout.PropertyField(serializedObject.FindProperty("UniqueTargetting"));

        if (container.Can_Choose_All_Of_Type)
        {
            EditorGUILayout.PropertyField(serializedObject.FindProperty("Left"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("Right"));
        }

        if (container.Left && container.Right && container.Effects.Contains(SpellEffect.Debuff) && container.Effects.Contains(SpellEffect.Buff))
        {
            EditorGUILayout.PropertyField(serializedObject.FindProperty("DebuffLeft"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("BuffLeft"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("DebuffRight"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("BuffRight"));
        }

        if (container.Can_Choose_Effect)
        {
            EditorGUILayout.PropertyField(serializedObject.FindProperty("EntityAffiliations"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("PathOne"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("PathTwo"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("PathThree"));
        }

        if (!container.Effects.Contains(SpellEffect.Damage) && !container.Effects.Contains(SpellEffect.Heal))
            EditorGUILayout.PropertyField(serializedObject.FindProperty("Requires_Dice"));

        if (container.Effects.Contains(SpellEffect.Damage) || container.Effects.Contains(SpellEffect.Heal) || container.Requires_Dice)
            EditorGUILayout.PropertyField(serializedObject.FindProperty("Dice"));

        if (container.Effects.Contains(SpellEffect.Buff) || container.Effects.Contains(SpellEffect.Debuff))
        {
            if ((container.BuffLeft && container.DebuffRight) || (container.DebuffLeft && container.BuffRight))
            {
                EditorGUILayout.Space(15);
                EditorGUILayout.LabelField("Input Buff and Debuff Modifiers", EditorStyles.boldLabel);
                container.ChanceOfBuffModifier = EditorGUILayout.IntField("Chance (Percent To Occur)", container.ChanceOfBuffModifier);
                EditorGUILayout.PropertyField(serializedObject.FindProperty("BuffModifier"));
                container.ChanceOfDebuffModifier = EditorGUILayout.IntField("Chance (Percent To Occur)", container.ChanceOfDebuffModifier);
                EditorGUILayout.PropertyField(serializedObject.FindProperty("DebuffModifier"));
            }
            else
            {
                EditorGUILayout.Space(15);
                EditorGUILayout.LabelField("Input ModifierSO", EditorStyles.boldLabel);
                container.Chance_Of_Modifier = EditorGUILayout.IntField("Chance (Percent To Occur)", container.Chance_Of_Modifier);
                EditorGUILayout.PropertyField(serializedObject.FindProperty("Modifier"));
            } 
        }

        if (container.Effects.Contains(SpellEffect.Other))
        {
            EditorGUILayout.Space(15);
            EditorGUILayout.LabelField("Integral Effects", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(serializedObject.FindProperty("EffectsPerformed"));
            if (container.EffectsPerformed.Contains(OtherEffects.ManipulateWeather))
                EditorGUILayout.PropertyField(serializedObject.FindProperty("WeatherChange"));
            if (container.EffectsPerformed.Contains(OtherEffects.SummonMinions))
                EditorGUILayout.PropertyField(serializedObject.FindProperty("Minions"));
        }

        EditorGUILayout.Space(10);
        EditorGUILayout.LabelField("Requirement Properties", EditorStyles.boldLabel);
        EditorGUILayout.PropertyField(serializedObject.FindProperty("Has_Requirement"));

        if (container.Has_Requirement)
        {
            EditorGUILayout.PropertyField(serializedObject.FindProperty("Requirements"));

            if (container.Requirements.Contains(PossReqs.Stats))
            {
                EditorGUILayout.Space(10);
                EditorGUILayout.LabelField("Stats Requirements", EditorStyles.boldLabel);

                container.Number_Of_Stat_Reqs = EditorGUILayout.IntField("Number_Of_Stat_Reqs", container.Number_Of_Stat_Reqs);
                container.Number_Of_Stat_Reqs = Mathf.Clamp(container.Number_Of_Stat_Reqs, 0, Max_Prime_Stat_Reqs);
                if (container.Stats_List.Count < container.Number_Of_Stat_Reqs)
                {
                    for (int i = 0; i < container.Number_Of_Stat_Reqs; i++)
                        container.Stats_List.Add(new Vector3Int(0, 0, 0));
                }
                else if (container.Stats_List.Count > container.Number_Of_Stat_Reqs)
                    container.Stats_List.Remove(container.Stats_List[^1]);

                EditorGUILayout.PropertyField(serializedObject.FindProperty("Stats_List"));
            }
            if (container.Requirements.Contains(PossReqs.Sec_Stats))
            {
                EditorGUILayout.Space(10);
                EditorGUILayout.LabelField("Sec Stats Requirements", EditorStyles.boldLabel);

                container.Number_Of_Sec_Stat_Reqs = EditorGUILayout.IntField("Number_Of_Sec_Stat_Reqs", container.Number_Of_Sec_Stat_Reqs);
                container.Number_Of_Sec_Stat_Reqs = Mathf.Clamp(container.Number_Of_Sec_Stat_Reqs, 0, Max_Secondary_Stat_Reqs);
                if (container.Sec_Stats_List.Count < container.Number_Of_Sec_Stat_Reqs)
                {
                    for (int i = 0; i < container.Number_Of_Sec_Stat_Reqs; i++)
                        container.Sec_Stats_List.Add(new Vector3Int(0, 0, 0));
                }
                else if (container.Sec_Stats_List.Count > container.Number_Of_Sec_Stat_Reqs)
                    container.Sec_Stats_List.Remove(container.Sec_Stats_List[^1]);

                EditorGUILayout.PropertyField(serializedObject.FindProperty("Sec_Stats_List"));
            }
            if (container.Requirements.Contains(PossReqs.Item))
            {
                EditorGUILayout.Space(10);
                EditorGUILayout.LabelField("Item Requirements", EditorStyles.boldLabel);

                EditorGUILayout.PropertyField(serializedObject.FindProperty("Requires_Specific"));
                if (container.Requires_Specific)
                {
                    container.Number_Of_Items = EditorGUILayout.IntField("Number_Of_Items", container.Number_Of_Items);
                    container.Number_Of_Items = Mathf.Clamp(container.Number_Of_Items, 0, Max_Item_Requirement);
                    if (container.Item_List.Count < container.Number_Of_Items)
                    {
                        for (int i = 0; i < container.Number_Of_Items; i++)
                            container.Item_List.Add("");
                    }
                    else if (container.Item_List.Count > container.Number_Of_Items && container.Number_Of_Items > 0)
                        container.Item_List.Remove(container.Item_List[^1]);

                    EditorGUILayout.PropertyField(serializedObject.FindProperty("Item_List"));
                }
                EditorGUILayout.Space(5);
                EditorGUILayout.PropertyField(serializedObject.FindProperty("Requires_WType"));
                if (container.Requires_WType)
                {
                    EditorGUILayout.PropertyField(serializedObject.FindProperty("W_Type"));
                }
                EditorGUILayout.Space(5);
                EditorGUILayout.PropertyField(serializedObject.FindProperty("Requires_AType"));
                if (container.Requires_AType)
                {
                    EditorGUILayout.PropertyField(serializedObject.FindProperty("A_Type"));
                }
            }
            if (container.Requirements.Contains(PossReqs.Ability))
            {
                EditorGUILayout.Space(10);
                EditorGUILayout.LabelField("Ability Requirements", EditorStyles.boldLabel);

                container.Number_Of_Abs = EditorGUILayout.IntField("Number of Abilities", container.Number_Of_Abs);
                container.Number_Of_Abs = Mathf.Clamp(container.Number_Of_Abs, 0, Max_Ability_Requirement);

                if (container.Ability_List.Count < container.Number_Of_Abs)
                {
                    for (int i = 0; i < container.Number_Of_Abs; i++)
                        container.Ability_List.Add("");
                }
                else if (container.Ability_List.Count > container.Number_Of_Abs && container.Number_Of_Abs > 0)
                    container.Ability_List.Remove(container.Ability_List[^1]);

                EditorGUILayout.PropertyField(serializedObject.FindProperty("Ability_List"));
            }
        }

        serializedObject.ApplyModifiedProperties();
    }
}
#endif