internal static string ExportCondition(NPC.Conditions.Condition condition, string prefix, int conditionIndex, bool skipLocalization = true)
        {
            StringBuilder result = new StringBuilder();

            result.AppendLine($"{prefix}Condition_{conditionIndex}_Type {condition.Type}");
            foreach (PropertyInfo prop in condition.GetType().GetProperties())
            {
                if (!prop.CanRead || !prop.CanWrite)
                {
                    continue;
                }

                string             propName  = prop.Name;
                SkipFieldAttribute skipPropA = prop.GetCustomAttribute <SkipFieldAttribute>();
                if ((skipLocalization && propName == "Localization") || skipPropA != null)
                {
                    continue;
                }

                object            propValue = prop.GetValue(condition);
                NoValueAttribute  noValueA  = prop.GetCustomAttribute <NoValueAttribute>();
                OptionalAttribute optionalA = prop.GetCustomAttribute <OptionalAttribute>();
                if (skipPropA != null)
                {
                    continue;
                }

                if (noValueA != null)
                {
                    if (propValue.Equals(true))
                    {
                        propValue = "";
                    }
                    else
                    {
                        continue;
                    }
                }

                if (prop.PropertyType.IsNullable())
                {
                    if (propValue == null)
                    {
                        if (optionalA != null)
                        {
                            if (optionalA.DefaultValue == null)
                            {
                                continue;
                            }

                            propValue = optionalA.DefaultValue;
                        }
                    }
                }

                result.AppendLine($"{prefix}Condition_{conditionIndex}_{propName} {propValue}");
            }
            return(result.ToString());
        }
        private static void Export_Characters(IEnumerable <NPCCharacter> characters)
        {
            foreach (NPCCharacter character in characters)
            {
                try
                {
                    Directory.CreateDirectory(dir + $@"Characters\{character.editorName}_{character.id}");
                    using (StreamWriter asset = new StreamWriter(dir + $@"Characters\{character.editorName}_{character.id}\Asset.dat", false, Encoding.UTF8))
                        using (StreamWriter local = new StreamWriter(dir + $@"Characters\{character.editorName}_{character.id}\English.dat", false, Encoding.UTF8))
                        {
                            asset.WriteLine(WaterText);
                            local.WriteLine(WaterText);
                            if (AppConfig.Instance.generateGuids)
                            {
                                asset.WriteLine($"GUID {character.guid}");
                            }

                            asset.WriteLine($"ID {character.id}");
                            asset.WriteLine($"Type NPC");
                            if (character.clothing.Shirt > 0)
                            {
                                asset.WriteLine($"Shirt {character.clothing.Shirt}");
                            }

                            if (character.clothing.Pants > 0)
                            {
                                asset.WriteLine($"Pants {character.clothing.Pants}");
                            }

                            if (character.clothing.Mask > 0)
                            {
                                asset.WriteLine($"Mask {character.clothing.Mask}");
                            }

                            if (character.clothing.Vest > 0)
                            {
                                asset.WriteLine($"Vest {character.clothing.Vest}");
                            }

                            if (character.clothing.Backpack > 0)
                            {
                                asset.WriteLine($"Backpack {character.clothing.Backpack}");
                            }

                            if (character.clothing.Hat > 0)
                            {
                                asset.WriteLine($"Hat {character.clothing.Hat}");
                            }

                            if (character.clothing.Glasses > 0)
                            {
                                asset.WriteLine($"Glasses {character.clothing.Glasses}");
                            }

                            if (!character.christmasClothing.IsEmpty)
                            {
                                asset.WriteLine("Has_Christmas_Outfit True");
                                if (character.christmasClothing.Shirt > 0)
                                {
                                    asset.WriteLine($"Christmas_Shirt {character.christmasClothing.Shirt}");
                                }

                                if (character.christmasClothing.Pants > 0)
                                {
                                    asset.WriteLine($"Christmas_Pants {character.christmasClothing.Pants}");
                                }

                                if (character.christmasClothing.Mask > 0)
                                {
                                    asset.WriteLine($"Christmas_Mask {character.christmasClothing.Mask}");
                                }

                                if (character.christmasClothing.Vest > 0)
                                {
                                    asset.WriteLine($"Christmas_Vest {character.christmasClothing.Vest}");
                                }

                                if (character.christmasClothing.Backpack > 0)
                                {
                                    asset.WriteLine($"Christmas_Backpack {character.christmasClothing.Backpack}");
                                }

                                if (character.christmasClothing.Hat > 0)
                                {
                                    asset.WriteLine($"Christmas_Hat {character.christmasClothing.Hat}");
                                }

                                if (character.christmasClothing.Glasses > 0)
                                {
                                    asset.WriteLine($"Christmas_Glasses {character.christmasClothing.Glasses}");
                                }
                            }

                            if (!character.halloweenClothing.IsEmpty)
                            {
                                asset.WriteLine("Has_Halloween_Outfit True");
                                if (character.halloweenClothing.Shirt > 0)
                                {
                                    asset.WriteLine($"Halloween_Shirt {character.halloweenClothing.Shirt}");
                                }

                                if (character.halloweenClothing.Pants > 0)
                                {
                                    asset.WriteLine($"Halloween_Pants {character.halloweenClothing.Pants}");
                                }

                                if (character.halloweenClothing.Mask > 0)
                                {
                                    asset.WriteLine($"Halloween_Mask {character.halloweenClothing.Mask}");
                                }

                                if (character.halloweenClothing.Vest > 0)
                                {
                                    asset.WriteLine($"Halloween_Vest {character.halloweenClothing.Vest}");
                                }

                                if (character.halloweenClothing.Backpack > 0)
                                {
                                    asset.WriteLine($"Halloween_Backpack {character.halloweenClothing.Backpack}");
                                }

                                if (character.halloweenClothing.Hat > 0)
                                {
                                    asset.WriteLine($"Halloween_Hat {character.halloweenClothing.Hat}");
                                }

                                if (character.halloweenClothing.Glasses > 0)
                                {
                                    asset.WriteLine($"Halloween_Glasses {character.halloweenClothing.Glasses}");
                                }
                            }

                            if (character.equipPrimary > 0)
                            {
                                asset.WriteLine($"Primary {character.equipPrimary}");
                            }

                            if (character.equipSecondary > 0)
                            {
                                asset.WriteLine($"Secondary {character.equipSecondary}");
                            }

                            if (character.equipTertiary > 0)
                            {
                                asset.WriteLine($"Tertiary {character.equipTertiary}");
                            }

                            if (character.equipped != Equip_Type.None)
                            {
                                asset.WriteLine($"Equipped {character.equipped.ToString()}");
                            }

                            asset.WriteLine($"Face {character.face}");
                            asset.WriteLine($"Beard {character.beard}");
                            asset.WriteLine($"Hair {character.haircut}");
                            asset.WriteLine($"Color_Skin {character.skinColor.ToHEX()}");
                            asset.WriteLine($"Color_Hair {character.hairColor.ToHEX()}");
                            asset.WriteLine($"Pose {character.pose.ToString()}");
                            if (character.leftHanded)
                            {
                                asset.WriteLine($"Backward");
                            }

                            if (character.startDialogueId > 0)
                            {
                                asset.WriteLine($"Dialogue {character.startDialogueId}");
                            }

                            if (character.visibilityConditions?.Count() > 0)
                            {
                                int condCount = character.visibilityConditions.Count();
                                asset.WriteLine($"Conditions {condCount}");
                                for (int k = 0; k < condCount; k++)
                                {
                                    NPC.Conditions.Condition cond = character.visibilityConditions.ElementAt(k);

                                    asset.WriteLine(ExportCondition(cond, "", k, true));

                                    if (!string.IsNullOrEmpty(cond.Localization))
                                    {
                                        local.WriteLine($"Condition_{k} {cond.Localization}");
                                    }
                                }
                            }

                            if (!character.poseLean.ApproximateEquals(0))
                            {
                                asset.WriteLine($"Pose_Lean {character.poseLean.ToString(CultureInfo.InvariantCulture)}");
                            }
                            if (!character.posePitch.ApproximateEquals(90))
                            {
                                asset.WriteLine($"Pose_Pitch {character.posePitch.ToString(CultureInfo.InvariantCulture)}");
                            }
                            if (!character.poseHeadOffset.ApproximateEquals(0))
                            {
                                asset.WriteLine($"Pose_Head_Offset {character.poseHeadOffset.ToString(CultureInfo.InvariantCulture)}");
                            }

                            local.WriteLine($"Name {character.editorName}");
                            local.WriteLine($"Character {character.displayName}");
                        }
                }
                catch (Exception ex)
                {
                    App.Logger.LogException($"Can't export character {character.id}", ex: ex);
                    App.NotificationManager.Notify(LocalizationManager.Current.Notification.Translate("Export_Character_Error", character.id));
                }
            }
        }
        private static void Export_Dialogues(IEnumerable <NPCDialogue> dialogues)
        {
            foreach (NPCDialogue dialogue in dialogues)
            {
                try
                {
                    Directory.CreateDirectory(dir + $@"Dialogues\{dialogue.guid}_{dialogue.id}");
                    using (StreamWriter asset = new StreamWriter(dir + $@"Dialogues\{dialogue.guid}_{dialogue.id}\Asset.dat", false, Encoding.UTF8))
                        using (StreamWriter local = new StreamWriter(dir + $@"Dialogues\{dialogue.guid}_{dialogue.id}\English.dat", false, Encoding.UTF8))
                        {
                            asset.WriteLine(WaterText);
                            local.WriteLine(WaterText);
                            if (AppConfig.Instance.generateGuids)
                            {
                                asset.WriteLine($"GUID {dialogue.guid}");
                            }

                            asset.WriteLine($"Type Dialogue");
                            asset.WriteLine($"ID {dialogue.id}");

                            if (dialogue.MessagesAmount > 0)
                            {
                                asset.WriteLine($"Messages {dialogue.MessagesAmount}");
                                for (int k = 0; k < dialogue.MessagesAmount; k++)
                                {
                                    NPCMessage message = dialogue.messages[k];
                                    if (message.PagesAmount > 0)
                                    {
                                        asset.WriteLine($"Message_{k}_Pages {message.PagesAmount}");
                                    }
                                    List <NPCResponse> visibleResponses = dialogue.responses.Where(d => d.VisibleInAll || d.visibleIn.Length <= k || d.visibleIn[k] == 1).ToList();
                                    if (visibleResponses.Count() > 0 && visibleResponses.Count() < dialogue.responses.Count())
                                    {
                                        asset.WriteLine($"Message_{k}_Responses {visibleResponses.Count()}");
                                        int visResCnt = visibleResponses.Count();
                                        for (int c = 0; c < visResCnt; c++)
                                        {
                                            NPCResponse response = visibleResponses[c];
                                            int         id       = dialogue.responses.IndexOf(response);
                                            asset.WriteLine($"Message_{k}_Response_{c} {id}");
                                        }
                                    }
                                    if (message.conditions.Length > 0)
                                    {
                                        asset.WriteLine($"Message_{k}_Conditions {message.conditions.Length}");
                                        for (int c = 0; c < message.conditions.Length; c++)
                                        {
                                            NPC.Conditions.Condition cond = message.conditions[c];

                                            asset.WriteLine(ExportCondition(cond, $"Message_{k}_", c));

                                            if (!string.IsNullOrEmpty(cond.Localization))
                                            {
                                                local.WriteLine($"Message_{k}_Condition_{c} {cond.Localization}");
                                            }
                                        }
                                    }
                                    if (message.rewards.Length > 0)
                                    {
                                        asset.WriteLine($"Message_{k}_Rewards {message.rewards.Length}");
                                        for (int c = 0; c < message.rewards.Length; c++)
                                        {
                                            Reward rew = message.rewards[c];

                                            asset.WriteLine(ExportReward(rew, $"Message_{k}_", c));

                                            if (!string.IsNullOrEmpty(rew.Localization))
                                            {
                                                local.WriteLine($"Message_{k}_Reward_{c} {rew.Localization}");
                                            }
                                        }
                                    }
                                    if (message.prev > 0)
                                    {
                                        asset.WriteLine($"Message_{k}_Prev {message.prev}");
                                    }
                                }
                            }
                            if (dialogue.ResponsesAmount > 0)
                            {
                                asset.WriteLine($"Responses {dialogue.ResponsesAmount}");
                                for (int k = 0; k < dialogue.ResponsesAmount; k++)
                                {
                                    NPCResponse response = dialogue.responses[k];
                                    if (!response.VisibleInAll)
                                    {
                                        asset.WriteLine($"Response_{k}_Messages {response.visibleIn.Count(d => d == 1)}");
                                        for (int c = 0, ind = 0; c < dialogue.MessagesAmount; c++)
                                        {
                                            NPCMessage currentMessage = dialogue.messages[c];
                                            if (response.visibleIn.Length <= c || response.visibleIn[c] == 1)
                                            {
                                                asset.WriteLine($"Response_{k}_Message_{ind++} {dialogue.messages.IndexOf(currentMessage)}");
                                            }
                                        }
                                    }
                                    if (response.openDialogueId > 0)
                                    {
                                        asset.WriteLine($"Response_{k}_Dialogue {response.openDialogueId}");
                                    }

                                    if (response.openQuestId > 0)
                                    {
                                        asset.WriteLine($"Response_{k}_Quest {response.openQuestId}");
                                    }

                                    if (response.openVendorId > 0)
                                    {
                                        asset.WriteLine($"Response_{k}_Vendor {response.openVendorId}");
                                    }

                                    if (response.conditions.Count() > 0)
                                    {
                                        asset.WriteLine($"Response_{k}_Conditions {response.conditions.Count()}");
                                        int cndCnt = response.conditions.Count();
                                        for (int c = 0; c < cndCnt; c++)
                                        {
                                            NPC.Conditions.Condition cond = response.conditions[c];

                                            asset.WriteLine(ExportCondition(cond, $"Response_{k}_", c));

                                            if (!string.IsNullOrEmpty(cond.Localization))
                                            {
                                                local.WriteLine($"Response_{k}_Condition_{c} {cond.Localization}");
                                            }
                                        }
                                    }
                                    if (response.rewards.Count() > 0)
                                    {
                                        asset.WriteLine($"Response_{k}_Rewards {response.rewards.Count()}");
                                        int rwrdCnt = response.rewards.Count();
                                        for (int c = 0; c < rwrdCnt; c++)
                                        {
                                            Reward rew = response.rewards[c];

                                            asset.WriteLine(ExportReward(rew, $"Response_{k}_", c));

                                            if (!string.IsNullOrEmpty(rew.Localization))
                                            {
                                                local.WriteLine($"Response_{k}_Reward_{c} {rew.Localization}");
                                            }
                                        }
                                    }
                                }
                            }
                            for (int k = 0; k < dialogue.MessagesAmount; k++)
                            {
                                for (int c = 0; c < dialogue.messages[k].PagesAmount; c++)
                                {
                                    local.WriteLine($"Message_{k}_Page_{c} {dialogue.messages[k].pages[c]}");
                                }
                            }
                            for (int k = 0; k < dialogue.ResponsesAmount; k++)
                            {
                                local.WriteLine($"Response_{k} {dialogue.responses[k].mainText}");
                            }
                        }
                }
                catch (Exception ex)
                {
                    App.Logger.LogException($"Can't export dialogue {dialogue.id}", ex: ex);
                    App.NotificationManager.Notify(LocalizationManager.Current.Notification.Translate("Export_Dialogue_Error", dialogue.id));
                }
            }
        }