public static bool Compare <T>(T a, T b, Logic_Type logic) where T : IComparable
        {
            switch (logic)
            {
            case Logic_Type.Equal:
                return(a.CompareTo(b) == 0);

            case Logic_Type.Greater_Than:
                return(a.CompareTo(b) > 0);

            case Logic_Type.Greater_Than_Or_Equal_To:
                return(a.CompareTo(b) >= 0);

            case Logic_Type.Less_Than:
                return(a.CompareTo(b) < 0);

            case Logic_Type.Less_Than_Or_Equal_To:
                return(a.CompareTo(b) <= 0);

            case Logic_Type.Not_Equal:
                return(a.CompareTo(b) != 0);

            default: throw new Exception("Invalid logic");
            }
        }
        private Condition[] ParseConditions(string prefix, string postfix = "Condition_")
        {
            Condition[] c = new Condition[asset.ReadByte(prefix + "Conditions")];

            int    num = 0;
            string text;

            while (true)
            {
                if (num >= c.Length)
                {
                    return(c);
                }

                text = $"{prefix}{postfix}{num}_Type";
                if (!asset.Has(text))
                {
                    break;
                }

                Condition_Type type        = asset.ReadEnum(text, Condition_Type.None);
                string         desc        = local?.ReadString($"{prefix}{postfix}{num}");
                bool           needToReset = asset.Has($"{prefix}{postfix}{num}_Reset");
                Logic_Type     logic       = asset.ReadEnum($"{prefix}{postfix}{num}_Logic", Logic_Type.Equal);
                string         tp          = $"{prefix}{postfix}{num}_";
                switch (type)
                {
                case Condition_Type.Kills_Tree:
                    c[num] = new ConditionKillsTree()
                    {
                        ID    = asset.ReadUInt16(tp + "ID"),
                        Tree  = asset.ReadString(tp + "Tree"),
                        Value = asset.ReadInt16(tp + "Value")
                    };
                    break;

                case Condition_Type.Currency:
                    c[num] = new ConditionCurrency()
                    {
                        GUID  = asset.ReadString(tp + "GUID"),
                        Logic = logic,
                        Value = asset.ReadUInt32(tp + "Value")
                    };
                    break;

                case Condition_Type.Experience:
                    c[num] = new ConditionExperience()
                    {
                        Logic = logic,
                        Value = asset.ReadUInt32(tp + "Value")
                    };
                    break;

                case Condition_Type.Reputation:
                    c[num] = new ConditionReputation()
                    {
                        Logic = logic,
                        Value = asset.ReadInt32(tp + "Value")
                    };
                    break;

                case Condition_Type.Flag_Bool:
                    c[num] = new ConditionFlagBool()
                    {
                        Logic       = logic,
                        Allow_Unset = asset.Has(tp + "Allow_Unset"),
                        ID          = asset.ReadUInt16(tp + "ID"),
                        Value       = asset.ReadBoolean(tp + "Value")
                    };
                    break;

                case Condition_Type.Flag_Short:
                    c[num] = new ConditionFlagShort()
                    {
                        Logic       = logic,
                        Allow_Unset = asset.Has(tp + "Allow_Unset"),
                        ID          = asset.ReadUInt16(tp + "ID"),
                        Value       = asset.ReadInt16(tp + "Value")
                    };
                    break;

                case Condition_Type.Quest:
                    c[num] = new ConditionQuest()
                    {
                        Logic      = logic,
                        ID         = asset.ReadUInt16(tp + "ID"),
                        Status     = asset.ReadEnum <Quest_Status>(tp + "Status"),
                        Ignore_NPC = asset.Has(tp + "Ignore_NPC")
                    };
                    break;

                case Condition_Type.Skillset:
                    c[num] = new ConditionSkillset()
                    {
                        Logic = logic,
                        Value = asset.ReadEnum <ESkillset>(tp + "Value")
                    };
                    break;

                case Condition_Type.Item:
                    c[num] = new ConditionItem()
                    {
                        ID     = asset.ReadUInt16(tp + "ID"),
                        Amount = asset.ReadUInt16(tp + "Amount")
                    };
                    break;

                case Condition_Type.Kills_Zombie:
                    c[num] = new ConditionKillsZombie()
                    {
                        ID             = asset.ReadUInt16(tp + "ID"),
                        Nav            = asset.ReadByte(tp + "Nav"),
                        Spawn          = asset.Has(tp + "Spawn"),
                        Spawn_Quantity = asset.Has(tp + "Spawn_Quantity") ? asset.ReadInt32(tp + "Spawn_Quantity") : 1,
                        Value          = asset.ReadInt16(tp + "Value"),
                        Radius         = asset.ReadSingle(tp + "Radius", 512f),
                        Zombie         = asset.ReadEnum <Zombie_Type>(tp + "Zombie")
                    };
                    break;

                case Condition_Type.Kills_Horde:
                    c[num] = new ConditionKillsHorde()
                    {
                        ID    = asset.ReadUInt16(tp + "ID"),
                        Nav   = asset.ReadByte(tp + "Nav"),
                        Value = asset.ReadInt16(tp + "Value")
                    };
                    break;

                case Condition_Type.Kills_Animal:
                    c[num] = new ConditionKillsAnimal()
                    {
                        Animal = asset.ReadUInt16(tp + "Animal"),
                        ID     = asset.ReadUInt16(tp + "ID"),
                        Value  = asset.ReadInt16(tp + "Value")
                    };
                    break;

                case Condition_Type.Compare_Flags:
                    c[num] = new ConditionCompareFlags()
                    {
                        Allow_A_Unset = asset.Has(tp + "Allow_A_Unset"),
                        Allow_B_Unset = asset.Has(tp + "Allow_B_Unset"),
                        A_ID          = asset.ReadUInt16(tp + "A_ID"),
                        B_ID          = asset.ReadUInt16(tp + "B_ID"),
                        Logic         = logic
                    };
                    break;

                case Condition_Type.Time_Of_Day:
                    c[num] = new ConditionTimeOfDay()
                    {
                        Logic  = logic,
                        Second = asset.ReadInt32(tp + "Second")
                    };
                    break;

                case Condition_Type.Player_Life_Health:
                    c[num] = new ConditionPlayerLifeHealth()
                    {
                        Logic = logic,
                        Value = asset.ReadInt32(tp + "Value")
                    };
                    break;

                case Condition_Type.Player_Life_Food:
                    c[num] = new ConditionPlayerLifeFood()
                    {
                        Logic = logic,
                        Value = asset.ReadInt32(tp + "Value")
                    };
                    break;

                case Condition_Type.Player_Life_Water:
                    c[num] = new ConditionPlayerLifeWater()
                    {
                        Logic = logic,
                        Value = asset.ReadInt32(tp + "Value")
                    };
                    break;

                case Condition_Type.Player_Life_Virus:
                    c[num] = new ConditionPlayerLifeVirus()
                    {
                        Logic = logic,
                        Value = asset.ReadInt32(tp + "Value")
                    };
                    break;

                case Condition_Type.Holiday:
                    c[num] = new ConditionHoliday()
                    {
                        Value = asset.ReadEnum <ENPCHoliday>(tp + "Value")
                    };
                    break;

                case Condition_Type.Kills_Player:
                    c[num] = new ConditionKillsPlayer()
                    {
                        ID    = asset.ReadUInt16(tp + "ID"),
                        Value = asset.ReadInt16(tp + "Value")
                    };
                    break;

                case Condition_Type.Kills_Object:
                    c[num] = new ConditionKillsObject()
                    {
                        ID     = asset.ReadUInt16(tp + "ID"),
                        Nav    = asset.ReadByte(tp + "Nav"),
                        Object = asset.ReadString(tp + "Object") ?? "",
                        Value  = asset.ReadInt16(tp + "Value")
                    };
                    break;

                case Condition_Type.Weather_Blend_Alpha:
                    c[num] = new ConditionWeatherBlendAlpha()
                    {
                        GUID  = asset.ReadString(tp + "GUID"),
                        Value = asset.ReadSingle(tp + "Value")
                    };
                    break;

                case Condition_Type.Weather_Status:
                    c[num] = new ConditionWeatherStatus()
                    {
                        GUID  = asset.ReadString(tp + "GUID"),
                        Value = asset.ReadEnum(tp + "Value", ENPCWeatherStatus.Active)
                    };
                    break;
                }
                c[num].Localization = desc ?? "";
                c[num].Reset        = needToReset;
                num++;
            }
            return(c);
        }