Пример #1
0
 public static BlueprintAction[] ActionsForType(Type type)
 {
     if (actionsForType == null)
     {
         actionsForType = new Dictionary <Type, BlueprintAction[]> {
         };
         BlueprintActions.InitializeActions();
     }
     BlueprintAction[] result;
     actionsForType.TryGetValue(type, out result);
     if (result == null)
     {
         var baseType = type.BaseType;
         if (baseType != null)
         {
             result = ActionsForType(baseType);
         }
         if (result == null)
         {
             result = new BlueprintAction[] { };
         }
         actionsForType[type] = result;
     }
     return(result);
 }
Пример #2
0
 public static void BlueprintActionButton(this BlueprintAction action, UnitEntityData unit, BlueprintScriptableObject bp, Action buttonAction, float width)
 {
     if (action != null && action.canPerform(bp, unit))
     {
         UI.ActionButton(action.name, buttonAction, width == 0 ? UI.AutoWidth() : UI.Width(width));
     }
     else
     {
         UI.Space(width + 3);
     }
 }
Пример #3
0
        public static void Register <T>(string name, BlueprintAction <T> .Perform perform, BlueprintAction <T> .CanPerform canPerform = null, bool isRepeatable = false) where T : SimpleBlueprint
        {
            var action = new BlueprintAction <T>(name, perform, canPerform, isRepeatable);
            var type   = action.BlueprintType;

            actionsForType.TryGetValue(type, out var existing);
            existing ??= new BlueprintAction[] { };
            var list = existing.ToList();

            list.Add(action);
            actionsForType[type] = list.ToArray();
        }
Пример #4
0
 public static void Register(params BlueprintAction[] actions)
 {
     foreach (var action in actions)
     {
         var type = action.BlueprintType;
         BlueprintAction[] existing;
         actionsForType.TryGetValue(type, out existing);
         if (existing == null)
         {
             existing = new BlueprintAction[] { };
         }
         var list = existing.ToList();
         list.Add(action);
         actionsForType[type] = list.ToArray();
     }
 }
Пример #5
0
        static public void OnGUI(UnitEntityData ch, List <Spellbook> spellbooks)
        {
            var blueprints = BlueprintBrowser.GetBlueprints();

            if (blueprints == null)
            {
                return;
            }
            OnGUI <Spellbook>("Spellbooks", ch, spellbooks,
                              (sb) => sb.Blueprint,
                              BlueprintExensions.GetBlueprints <BlueprintSpellbook>(),
                              (sb) => sb.Blueprint.GetDisplayName(),
                              (sb) => sb.Blueprint.GetDescription(),
                              null,
                              BlueprintAction.ActionsForType(typeof(BlueprintSpellbook))
                              );
        }
Пример #6
0
        static public void OnGUI(UnitEntityData ch, List <Ability> facts)
        {
            var blueprints = BlueprintBrowser.GetBlueprints();

            if (blueprints == null)
            {
                return;
            }
            OnGUI <Ability>("Abilities", ch, facts,
                            (fact) => fact.Blueprint,
                            BlueprintExensions.GetBlueprints <BlueprintAbility>().Where((bp) => !((BlueprintAbility)bp).IsSpell),
                            (fact) => fact.Name,
                            (fact) => fact.Description,
                            (fact) => fact.GetRank(),
                            BlueprintAction.ActionsForType(typeof(BlueprintAbility))
                            );
        }
Пример #7
0
        static public void OnGUI(UnitEntityData ch, List <Buff> facts)
        {
            var blueprints = BlueprintBrowser.GetBlueprints();

            if (blueprints == null)
            {
                return;
            }
            OnGUI <Buff>("Features", ch, facts,
                         (fact) => fact.Blueprint,
                         BlueprintExensions.GetBlueprints <BlueprintBuff>(),
                         (fact) => fact.Name,
                         (fact) => fact.Description,
                         (fact) => fact.GetRank(),
                         BlueprintAction.ActionsForType(typeof(BlueprintBuff))
                         );
        }
Пример #8
0
        static public void OnGUI(UnitEntityData ch, Spellbook spellbook, int level)
        {
            var spells      = spellbook.GetKnownSpells(level).OrderBy(d => d.Name).ToList();
            var spellbookBP = spellbook.Blueprint;
            var learnable   = spellbookBP.SpellList.GetSpells(level);
            var blueprints  = BlueprintBrowser.GetBlueprints();

            if (blueprints == null)
            {
                return;
            }
            OnGUI <AbilityData>($"Spells.{spellbookBP.Name}", ch, spells,
                                (fact) => fact.Blueprint,
                                learnable,
                                (fact) => fact.Name,
                                (fact) => fact.Description,
                                null,
                                BlueprintAction.ActionsForType(typeof(BlueprintAbility))
                                );
        }
Пример #9
0
        public static void OnGUI(UnitEntityData ch,
                                 IEnumerable <BlueprintScriptableObject> blueprints,
                                 float indent = 0, float remainingWidth = 0,
                                 Func <String, String> titleFormater = null,
                                 NamedTypeFilter typeFilter          = null
                                 )
        {
            if (titleFormater == null)
            {
                titleFormater = (t) => t.orange().bold();
            }
            int index = 0;

            if (needsLayout)
            {
                foreach (BlueprintScriptableObject blueprint in blueprints)
                {
                    var actions = blueprint.GetActions();
                    if (actions.Any(a => a.isRepeatable))
                    {
                        hasRepeatableAction = true;
                    }
                    int actionCount = actions.Sum(action => action.canPerform(blueprint, ch) ? 1 : 0);
                    maxActions = Math.Max(actionCount, maxActions);
                }
                needsLayout = false;
            }
            if (hasRepeatableAction)
            {
                UI.BeginHorizontal();
                UI.Space(553);
                UI.ActionIntTextField(
                    ref repeatCount,
                    "repeatCount",
                    (limit) => { },
                    () => { },
                    UI.Width(160));
                UI.Space(40);
                UI.Label("Parameter".cyan() + ": " + $"{repeatCount}".orange(), UI.ExpandWidth(false));
                repeatCount = Math.Max(1, repeatCount);
                repeatCount = Math.Min(100, repeatCount);
                UI.EndHorizontal();
            }
            UI.Div(indent);
            foreach (BlueprintScriptableObject blueprint in blueprints)
            {
                UI.BeginHorizontal();
                UI.Space(indent);
                var actions = blueprint.GetActions().Where(action => action.canPerform(blueprint, ch)).ToArray();
                var titles  = actions.Select(a => a.name);
                var title   = blueprint.name;
                if (titles.Contains("Remove"))
                {
                    title = title.cyan().bold();
                }
                else
                {
                    title = titleFormater(title);
                }

                UI.Label(title, UI.Width(550 - indent));
                int actionCount = actions != null?actions.Count() : 0;

                for (int ii = 0; ii < maxActions; ii++)
                {
                    if (ii < actionCount)
                    {
                        BlueprintAction action = actions[ii];
                        // TODO -don't show increase or decrease actions until we redo actions into a proper value editor that gives us Add/Remove and numeric item with the ability to show values.  For now users can edit ranks in the Facts Editor
                        if (action.name == "<" || action.name == ">")
                        {
                            UI.Space(164); continue;
                        }
                        var   actionName = action.name;
                        float extraSpace = 0;
                        if (action.isRepeatable)
                        {
                            actionName += (action.isRepeatable ? $" {repeatCount}" : "");
                            extraSpace  = 20 * (float)Math.Ceiling(Math.Log10((double)repeatCount));
                        }
                        UI.ActionButton(actionName, () => { action.action(blueprint, ch, repeatCount); }, UI.Width(160 + extraSpace));
                        UI.Space(10);
                    }
                    else
                    {
                        UI.Space(174);
                    }
                }
                UI.Space(30);
                String typeString = blueprint.GetType().Name;
                if (typeFilter?.collator != null)
                {
                    var collatorString = typeFilter.collator(blueprint);
                    if (!typeString.Contains(collatorString))
                    {
                        typeString += $" : {collatorString}".yellow();
                    }
                }
                Rect rect        = GUILayoutUtility.GetLastRect();
                var  description = blueprint.GetDescription();
                if (description != null && description.Length > 0)
                {
                    description = $"\n{description.green()}";
                }
                else
                {
                    description = "";
                }
                if (settings.showComponents && blueprint.ComponentsArray != null)
                {
                    String componentStr = String.Join <object>(" ", blueprint.ComponentsArray).grey();
                    if (description.Length == 0)
                    {
                        description = componentStr;
                    }
                    else
                    {
                        description = componentStr + description;
                    }
                }
                if (settings.showElements && blueprint.ElementsArray != null)
                {
                    String elementsStr = String.Join <object>(" ", blueprint.ElementsArray).yellow();
                    if (description.Length == 0)
                    {
                        description = elementsStr;
                    }
                    else
                    {
                        description = elementsStr + "\n" + description;
                    }
                }
                if (settings.showAssetIDs)
                {
                    UI.Label(typeString.cyan());
                    GUILayout.TextField(blueprint.AssetGuid, UI.Width(450));
                    UI.EndHorizontal();
                    if (description.Length > 0)
                    {
                        UI.BeginHorizontal();
                        UI.Label("", UI.Width(rect.x));
                        UI.Label(blueprint.GetDescription().green()); //,
                        UI.EndHorizontal();
                    }
                }
                else
                {
                    float width = remainingWidth - rect.xMax;
                    UI.Label(typeString.cyan() + " " + description, UI.Width(800));
                    //UI.Label($"{remainingWidth} - {rect.xMax} = {width}" + typeString + " " + description, UI.Width(800));
                    UI.EndHorizontal();
                }
#if false
                String description = blueprint.GetDescription();
                if (description.Length > 0)
                {
                    UI.BeginHorizontal();
                    UI.Space(684 + maxActions * 154);
                    UI.Label($"{description.green()}");
                    UI.EndHorizontal();
                }
#endif
                UI.Div(indent);
                index++;
            }
        }
Пример #10
0
 public static IEnumerable <BlueprintAction> GetActions(this SimpleBlueprint bp) => BlueprintAction.ActionsForBlueprint(bp);
Пример #11
0
        public static void InitializeActions()
        {
            BlueprintAction.Register(
                new BlueprintAction <BlueprintItem>("Add",
                                                    (bp, ch, n) => Game.Instance.Player.Inventory.Add(bp, n, null),
                                                    null,
                                                    true
                                                    ),
                new BlueprintAction <BlueprintItem>("Remove",
                                                    (bp, ch, n) => Game.Instance.Player.Inventory.Remove(bp, n),
                                                    (bp, ch) => Game.Instance.Player.Inventory.Contains(bp),
                                                    true
                                                    ),
                new BlueprintAction <BlueprintUnit>("Spawn",
                                                    (bp, ch, n) => Actions.SpawnUnit(bp, n),
                                                    null,
                                                    true
                                                    ),
#if false
                new BlueprintAction("Kill", typeof(BlueprintUnit),
                                    (bp, ch) => { Actions.SpawnUnit((BlueprintUnit)bp); }
                                    ),
                new BlueprintAction("Remove", typeof(BlueprintUnit),
                                    (bp, ch) => { CheatsCombat.Kill((BlueprintUnit)bp); },
                                    (bp, ch) => { return(ch.Inventory.Contains((BlueprintUnit)bp)); }
                                    ),
#endif
                new BlueprintAction <BlueprintFeature>("Add",
                                                       (bp, ch, n) => ch.Descriptor.AddFact(bp),
                                                       (bp, ch) => !ch.Progression.Features.HasFact(bp)
                                                       ),
                new BlueprintAction <BlueprintFeature>("Remove",
                                                       (bp, ch, n) => ch.Progression.Features.RemoveFact(bp),
                                                       (bp, ch) => ch.Progression.Features.HasFact(bp)
                                                       ),
                new BlueprintAction <BlueprintFeature>("<",
                                                       (bp, ch, n) => { try { ch.Progression.Features.GetFact(bp).RemoveRank(); } catch (Exception e) { Logger.Log(e); } },
                                                       (bp, ch) => {
                var feature = ch.Progression.Features.GetFact(bp);
                return(feature != null && feature.GetRank() > 1);
            }),
                new BlueprintAction <BlueprintFeature>(">",
                                                       (bp, ch, n) => ch.Progression.Features.GetFact(bp).AddRank(),
                                                       (bp, ch) => {
                var feature = ch.Progression.Features.GetFact(bp);
                return(feature != null && feature.GetRank() < feature.Blueprint.Ranks);
            }),

                // Spellbooks
                new BlueprintAction <BlueprintSpellbook>("Add",
                                                         (bp, ch, n) => { ch.Descriptor.DemandSpellbook(bp.CharacterClass); },
                                                         (bp, ch) => !ch.Descriptor.Spellbooks.Any((sb) => sb.Blueprint == bp)
                                                         ),
                new BlueprintAction <BlueprintSpellbook>("Remove",
                                                         (bp, ch, n) => ch.Descriptor.DeleteSpellbook(bp),
                                                         (bp, ch) => ch.Descriptor.Spellbooks.Any((sb) => sb.Blueprint == bp)
                                                         ),
                new BlueprintAction <BlueprintSpellbook>(">",
                                                         (bp, ch, n) => {
                try {
                    var spellbook = ch.Descriptor.Spellbooks.First((sb) => sb.Blueprint == bp);
                    if (spellbook.IsMythic)
                    {
                        spellbook.AddMythicLevel();
                    }
                    else
                    {
                        spellbook.AddBaseLevel();
                    }
                }
                catch (Exception e) { Logger.Log(e); }
            },
                                                         (bp, ch) => ch.Descriptor.Spellbooks.Any((sb) => sb.Blueprint == bp && sb.CasterLevel < bp.MaxSpellLevel)
                                                         ),

                // Buffs
                new BlueprintAction <BlueprintBuff>("Add",
                                                    (bp, ch, n) => GameHelper.ApplyBuff(ch, bp),
                                                    (bp, ch) => !ch.Descriptor.Buffs.HasFact(bp)
                                                    ),
                new BlueprintAction <BlueprintBuff>("Remove",
                                                    (bp, ch, n) => ch.Descriptor.RemoveFact(bp),
                                                    (bp, ch) => ch.Descriptor.Buffs.HasFact(bp)
                                                    ),
                new BlueprintAction <BlueprintBuff>("<",
                                                    (bp, ch, n) => ch.Descriptor.Buffs.GetFact(bp).RemoveRank(),
                                                    (bp, ch) => {
                var buff = ch.Descriptor.Buffs.GetFact(bp);
                return(buff != null && buff.GetRank() > 1);
            }),
                new BlueprintAction <BlueprintBuff>(">",
                                                    (bp, ch, n) => ch.Descriptor.Buffs.GetFact(bp).AddRank(),
                                                    (bp, ch) => {
                var buff = ch.Descriptor.Buffs.GetFact(bp);
                return(buff != null && buff.GetRank() < buff.Blueprint.Ranks - 1);
            }),

                // Abilities
                new BlueprintAction <BlueprintAbility>("Add",
                                                       (bp, ch, n) => ch.AddAbility(bp),
                                                       (bp, ch) => ch.CanAddAbility(bp)
                                                       ),
                new BlueprintAction <BlueprintAbility>("At Will",
                                                       (bp, ch, n) => ch.AddSpellAsAbility(bp),
                                                       (bp, ch) => ch.CanAddSpellAsAbility(bp)
                                                       ),
                new BlueprintAction <BlueprintAbility>("Remove",
                                                       (bp, ch, n) => ch.RemoveAbility(bp),
                                                       (bp, ch) => ch.HasAbility(bp)
                                                       ),
                // BlueprintActivatableAbility
                new BlueprintAction <BlueprintActivatableAbility>("Add",
                                                                  (bp, ch, n) => ch.Descriptor.AddFact(bp),
                                                                  (bp, ch) => !ch.Descriptor.HasFact(bp)
                                                                  ),
                new BlueprintAction <BlueprintActivatableAbility>("Remove",
                                                                  (bp, ch, n) => ch.Descriptor.RemoveFact(bp),
                                                                  (bp, ch) => ch.Descriptor.HasFact(bp)
                                                                  ),
                // Etudes
                new BlueprintAction <BlueprintEtude>("Start",
                                                     (bp, ch, n) => Game.Instance.Player.EtudesSystem.StartEtude(bp),
                                                     (bp, ch) => Game.Instance.Player.EtudesSystem.EtudeIsNotStarted(bp)
                                                     ),
                new BlueprintAction <BlueprintEtude>("Complete",
                                                     (bp, ch, n) => Game.Instance.Player.EtudesSystem.MarkEtudeCompleted(bp),
                                                     (bp, ch) => !Game.Instance.Player.EtudesSystem.EtudeIsNotStarted(bp) && !Game.Instance.Player.EtudesSystem.EtudeIsCompleted(bp)
                                                     ),
                // Cut Scenes
                new BlueprintAction <Cutscene>("Play",
                                               (bp, ch, n) => {
                Actions.ToggleModWindow();
                CutscenePlayerData cutscenePlayerData = CutscenePlayerData.Queue.FirstOrDefault <CutscenePlayerData>((Func <CutscenePlayerData, bool>)(c => c.PlayActionId == bp.name));
                if (cutscenePlayerData != null)
                {
                    cutscenePlayerData.PreventDestruction = true;
                    cutscenePlayerData.Stop();
                    cutscenePlayerData.PreventDestruction = false;
                }
                var state = Kingmaker.ElementsSystem.ContextData <SpawnedUnitData> .Current?.State;
                CutscenePlayerView.Play(bp, null, true, state).PlayerData.PlayActionId = bp.name;
            }),
                // Teleport
                new BlueprintAction <BlueprintAreaEnterPoint>("Teleport",
                                                              (bp, ch, n) => GameHelper.EnterToArea(bp, AutoSaveMode.None)
                                                              ),
                new BlueprintAction <BlueprintGlobalMap>("Teleport",
                                                         (bp, ch, n) => GameHelper.EnterToArea(bp.GlobalMapEnterPoint, AutoSaveMode.None)
                                                         ),
                //new BlueprintAction<BlueprintAreaPart>("Teleport",
                //    (bp, ch, n) => GameHelper.EnterToArea(bp, AutoSaveMode.None)
                //    ),
                new BlueprintAction <BlueprintArea>("Teleport",
                                                    (area, ch, n) => {
                var areaEnterPoints = BlueprintExensions.BlueprintsOfType <BlueprintAreaEnterPoint>();
                var blueprint       = areaEnterPoints.Where(bp => (bp is BlueprintAreaEnterPoint ep) ? ep.Area == area : false).FirstOrDefault();
                if (blueprint is BlueprintAreaEnterPoint enterPoint)
                {
                    GameHelper.EnterToArea(enterPoint, AutoSaveMode.None);
                }
            }),
Пример #12
0
 public static IEnumerable <BlueprintAction> GetActions(this BlueprintScriptableObject bp)
 {
     return(BlueprintAction.ActionsForBlueprint(bp));
 }
Пример #13
0
        static public void OnGUI <T>(String callerKey,
                                     UnitEntityData unit,
                                     List <T> facts,
                                     Func <T, BlueprintScriptableObject> blueprint,
                                     IEnumerable <BlueprintScriptableObject> blueprints,
                                     Func <T, String> title,
                                     Func <T, String> description          = null,
                                     Func <T, int> value                   = null,
                                     IEnumerable <BlueprintAction> actions = null
                                     )
        {
            bool searchChanged = false;

            if (actions == null)
            {
                actions = new List <BlueprintAction>();
            }
            if (callerKey != prevCallerKey)
            {
                searchChanged = true; showAll = false;
            }
            prevCallerKey = callerKey;
            var mutatorLookup = actions.Distinct().ToDictionary(a => a.name, a => a);

            UI.BeginHorizontal();
            UI.Space(100);
            UI.ActionTextField(ref searchText, "searhText", null, () => { searchChanged = true; }, UI.Width(320));
            UI.Space(25);
            UI.Label("Limit", UI.ExpandWidth(false));
            UI.ActionIntTextField(ref searchLimit, "searchLimit", null, () => { searchChanged = true; }, UI.Width(175));
            if (searchLimit > 1000)
            {
                searchLimit = 1000;
            }
            UI.Space(25);
            UI.Toggle("Show GUIDs", ref Main.settings.showAssetIDs);
            UI.Space(25);
            UI.Toggle("Dividers", ref Main.settings.showDivisions);
            UI.Space(25);
            searchChanged |= UI.DisclosureToggle("Show All".orange().bold(), ref showAll);
            UI.EndHorizontal();
            UI.BeginHorizontal();
            UI.Space(100);
            UI.ActionButton("Search", () => { searchChanged = true; }, UI.AutoWidth());
            UI.Space(25);
            if (matchCount > 0 && searchText.Length > 0)
            {
                String matchesText = "Matches: ".green().bold() + $"{matchCount}".orange().bold();
                if (matchCount > searchLimit)
                {
                    matchesText += " => ".cyan() + $"{searchLimit}".cyan().bold();
                }
                UI.Label(matchesText, UI.ExpandWidth(false));
            }
#if false
            UI.Label("Repeat Count", UI.ExpandWidth(false));
            UI.ActionIntTextField(
                ref repeatCount,
                "repeatCount",
                (limit) => { },
                () => { },
                UI.Width(200));
#endif
            UI.EndHorizontal();

            if (showAll)
            {
                // TODO - do we need this logic or can we make blueprint filtering fast enough to do keys by key searching?
                //if (filteredBPs == null || searchChanged) {
                UpdateSearchResults(searchText, searchLimit, blueprints);
                //}
                BlueprintListUI.OnGUI(unit, filteredBPs, 100);
                return;
            }
            var terms = searchText.Split(' ').Select(s => s.ToLower()).ToHashSet();

            BlueprintAction add      = mutatorLookup.GetValueOrDefault("Add", null);
            BlueprintAction remove   = mutatorLookup.GetValueOrDefault("Remove", null);
            BlueprintAction decrease = mutatorLookup.GetValueOrDefault("<", null);
            BlueprintAction increase = mutatorLookup.GetValueOrDefault(">", null);

            mutatorLookup.Remove("Add");
            mutatorLookup.Remove("Remove");
            mutatorLookup.Remove("<");
            mutatorLookup.Remove(">");

            BlueprintScriptableObject toAdd      = null;
            BlueprintScriptableObject toRemove   = null;
            BlueprintScriptableObject toIncrease = null;
            BlueprintScriptableObject toDecrease = null;
            var toValues = new Dictionary <String, BlueprintScriptableObject>();
            var sorted   = facts.OrderBy((f) => title(f));
            matchCount = 0;
            UI.Div(100);
            foreach (var fact in sorted)
            {
                if (fact == null)
                {
                    continue;
                }
                var    bp        = blueprint(fact);
                String name      = title(fact);
                String nameLower = name.ToLower();
                if (name != null && name.Length > 0 && (searchText.Length == 0 || terms.All(term => nameLower.Contains(term))))
                {
                    matchCount++;
                    UI.BeginHorizontal();
                    UI.Space(100);
                    UI.Label($"{name}".cyan().bold(), UI.Width(400));
                    UI.Space(30);
                    if (value != null)
                    {
                        var v = value(fact);
                        decrease.BlueprintActionButton(unit, bp, () => { toDecrease = bp; }, 50);
                        UI.Space(10f);
                        UI.Label($"{v}".orange().bold(), UI.Width(30));
                        increase.BlueprintActionButton(unit, bp, () => { toIncrease = bp; }, 50);
                    }
#if false
                    UI.Space(30);
                    add.BlueprintActionButton(unit, bp, () => { toAdd = bp; }, 150);
#endif
                    UI.Space(30);
                    remove.BlueprintActionButton(unit, bp, () => { toRemove = bp; }, 150);
#if false
                    foreach (var action in actions)
                    {
                        action.MutatorButton(unit, bp, () => { toValues[action.name] = bp; }, 150);
                    }
#endif
                    if (description != null)
                    {
                        UI.Space(30);
                        var assetID = Main.settings.showAssetIDs ? blueprint(fact).AssetGuid.magenta() + " " : "";
                        UI.Label(assetID + description(fact).green(), UI.AutoWidth());
                    }
                    UI.EndHorizontal();
                    UI.Div(100);
                }
            }
            if (toAdd != null)
            {
                add.action(toAdd, unit, repeatCount); toAdd = null;
            }
            if (toRemove != null)
            {
                remove.action(toRemove, unit, repeatCount); toRemove = null;
            }
            if (toDecrease != null)
            {
                decrease.action(toDecrease, unit, repeatCount); toDecrease = null;
            }
            if (toIncrease != null)
            {
                increase.action(toIncrease, unit, repeatCount); toIncrease = null;
            }
            foreach (var item in toValues)
            {
                var muator = mutatorLookup[item.Key];
                if (muator != null)
                {
                    muator.action(item.Value, unit, repeatCount);
                }
            }
            toValues.Clear();
        }
Пример #14
0
        public static void InitializeActions()
        {
#if false
            var flags = Game.Instance.Player.UnlockableFlags;
            BlueprintAction.Register <BlueprintItem>("Add",
                                                     (bp, ch, n, index) => Game.Instance.Player.Inventory.Add(bp, n), isRepeatable: true);

            BlueprintAction.Register <BlueprintItem>("Remove",
                                                     (bp, ch, n, index) => Game.Instance.Player.Inventory.Remove(bp, n),
                                                     (bp, ch, index) => Game.Instance.Player.Inventory.Contains(bp), true);

            BlueprintAction.Register <BlueprintUnit>("Spawn",
                                                     (bp, ch, n, index) => Actions.SpawnUnit(bp, n), isRepeatable: true);

            BlueprintAction.Register <BlueprintFeature>("Add",
                                                        (bp, ch, n, index) => ch.Descriptor.AddFact(bp),
                                                        (bp, ch, index) => !ch.Progression.Features.HasFact(bp));

            BlueprintAction.Register <BlueprintFeature>("Remove",
                                                        (bp, ch, n, index) => ch.Progression.Features.RemoveFact(bp),
                                                        (bp, ch, index) => ch.Progression.Features.HasFact(bp));

            BlueprintAction.Register <BlueprintParametrizedFeature>("Add",
                                                                    (bp, ch, n, index) => ch?.Descriptor?.AddFact <UnitFact>(bp, null, bp.Items.OrderBy(x => x.Name).ElementAt(BlueprintListUI.ParamSelected[index]).Param),
                                                                    (bp, ch, index) => ch?.Descriptor?.Unit?.Facts?.Get <Feature>(i => i.Blueprint == bp && i.Param == bp.Items.OrderBy(x => x.Name).ElementAt(BlueprintListUI.ParamSelected[index]).Param) == null);

            BlueprintAction.Register <BlueprintParametrizedFeature>("Remove", (bp, ch, n, index) => ch?.Progression?.Features?.RemoveFact(ch.Descriptor?.Unit?.Facts?.Get <Feature>(i => i.Blueprint == bp && i.Param == bp.Items.OrderBy(x => x.Name).ToArray()[BlueprintListUI.ParamSelected[index]].Param)),
                                                                    (bp, ch, index) => ch?.Descriptor?.Unit?.Facts?.Get <Feature>(i => i.Blueprint == bp && i.Param == bp.Items.OrderBy(x => x.Name).ToArray()[BlueprintListUI.ParamSelected[index]].Param) != null);

            BlueprintAction.Register <BlueprintFeature>("<",
                                                        (bp, ch, n, index) => ch.Progression.Features.GetFact(bp)?.RemoveRank(),
                                                        (bp, ch, index) => {
                var feature = ch.Progression.Features.GetFact(bp);
                return(feature?.GetRank() > 1);
            });

            BlueprintAction.Register <BlueprintFeature>(">",
                                                        (bp, ch, n, index) => ch.Progression.Features.GetFact(bp)?.AddRank(),
                                                        (bp, ch, index) => {
                var feature = ch.Progression.Features.GetFact(bp);
                return(feature != null && feature.GetRank() < feature.Blueprint.Ranks);
            });
            //BlueprintAction.Register<BlueprintArchetype>(
            //    "Add",
            //    (bp, ch, n, index) => ch.Progression.AddArchetype(ch.Progression.Classes.First().CharacterClass, bp),
            //    (bp, ch, index) => ch.Progression.CanAddArchetype(ch.Progression.Classes.First().CharacterClass, bp)
            //    );
            //BlueprintAction.Register<BlueprintArchetype>("Remove",
            //    (bp, ch, n, index) => ch.Progression.AddArchetype(ch.Progression.Classes.First().CharacterClass, bp),
            //    (bp, ch, index) => ch.Progression.Classes.First().Archetypes.Contains(bp)
            //    );

            // Spellbooks
            BlueprintAction.Register <BlueprintSpellbook>("Add",
                                                          (bp, ch, n, index) => ch.Descriptor.DemandSpellbook(bp.CharacterClass),
                                                          (bp, ch, index) => ch.Descriptor.Spellbooks.All(sb => sb.Blueprint != bp));

            BlueprintAction.Register <BlueprintSpellbook>("Remove",
                                                          (bp, ch, n, index) => ch.Descriptor.DeleteSpellbook(bp),
                                                          (bp, ch, index) => ch.Descriptor.Spellbooks.Any(sb => sb.Blueprint == bp));

            BlueprintAction.Register <BlueprintSpellbook>(">",
                                                          (bp, ch, n, index) => {
                try {
                    var spellbook = ch.Descriptor.Spellbooks.First(sb => sb.Blueprint == bp);

                    if (spellbook.IsMythic)
                    {
                        spellbook.AddMythicLevel();
                    }
                    else
                    {
                        spellbook.AddBaseLevel();
                    }
                }
                catch (Exception e) { Mod.Error(e); }
            },
                                                          (bp, ch, index) => ch.Descriptor.Spellbooks.Any(sb => sb.Blueprint == bp && sb.CasterLevel < bp.MaxSpellLevel));

            // Buffs
            BlueprintAction.Register <BlueprintBuff>("Add",
                                                     (bp, ch, n, index) => GameHelper.ApplyBuff(ch, bp),
                                                     (bp, ch, index) => !ch.Descriptor.Buffs.HasFact(bp));

            BlueprintAction.Register <BlueprintBuff>("Remove",
                                                     (bp, ch, n, index) => ch.Descriptor.RemoveFact(bp),
                                                     (bp, ch, index) => ch.Descriptor.Buffs.HasFact(bp));

            BlueprintAction.Register <BlueprintBuff>("<",
                                                     (bp, ch, n, index) => ch.Descriptor.Buffs.GetFact(bp)?.RemoveRank(),
                                                     (bp, ch, index) => {
                var buff = ch.Descriptor.Buffs.GetFact(bp);

                return(buff?.GetRank() > 1);
            });

            BlueprintAction.Register <BlueprintBuff>(">",
                                                     (bp, ch, n, index) => ch.Descriptor.Buffs.GetFact(bp)?.AddRank(),
                                                     (bp, ch, index) => {
                var buff = ch.Descriptor.Buffs.GetFact(bp);

                return(buff != null && buff.GetRank() < buff.Blueprint.Ranks - 1);
            });

            // Abilities
            BlueprintAction.Register <BlueprintAbility>("Add",
                                                        (bp, ch, n, index) => ch.AddAbility(bp),
                                                        (bp, ch, index) => ch.CanAddAbility(bp));

            BlueprintAction.Register <BlueprintAbility>("At Will",
                                                        (bp, ch, n, index) => ch.AddSpellAsAbility(bp),
                                                        (bp, ch, index) => ch.CanAddSpellAsAbility(bp));

            BlueprintAction.Register <BlueprintAbility>("Remove",
                                                        (bp, ch, n, index) => ch.RemoveAbility(bp),
                                                        (bp, ch, index) => ch.HasAbility(bp));
            // Ability Resources

            BlueprintAction.Register <BlueprintAbilityResource>("Add",
                                                                (bp, ch, n, index) => ch.Resources.Add(bp, true),
                                                                (bp, ch, index) => !ch.Resources.ContainsResource(bp));

            BlueprintAction.Register <BlueprintAbilityResource>("Remove",
                                                                (bp, ch, n, index) => ch.Resources.Remove(bp),
                                                                (bp, ch, index) => ch.Resources.ContainsResource(bp));

            // Spellbooks


            // BlueprintActivatableAbility
            BlueprintAction.Register <BlueprintActivatableAbility>("Add",
                                                                   (bp, ch, n, index) => ch.Descriptor.AddFact(bp),
                                                                   (bp, ch, index) => !ch.Descriptor.HasFact(bp));

            BlueprintAction.Register <BlueprintActivatableAbility>("Remove",
                                                                   (bp, ch, n, index) => ch.Descriptor.RemoveFact(bp),
                                                                   (bp, ch, index) => ch.Descriptor.HasFact(bp));

            // Quests
            BlueprintAction.Register <BlueprintQuest>("Start",
                                                      (bp, ch, n, index) => Game.Instance.Player.QuestBook.GiveObjective(bp.Objectives.First()),
                                                      (bp, ch, index) => Game.Instance.Player.QuestBook.GetQuest(bp) == null);

            BlueprintAction.Register <BlueprintQuest>("Complete",
                                                      (bp, ch, n, index) => {
                foreach (var objective in bp.Objectives)
                {
                    Game.Instance.Player.QuestBook.CompleteObjective(objective);
                }
            }, (bp, ch, index) => Game.Instance.Player.QuestBook.GetQuest(bp)?.State == QuestState.Started);

            // Quests Objectives
            BlueprintAction.Register <BlueprintQuestObjective>("Start",
                                                               (bp, ch, n, index) => Game.Instance.Player.QuestBook.GiveObjective(bp),
                                                               (bp, ch, index) => Game.Instance.Player.QuestBook.GetQuest(bp.Quest) == null);

            BlueprintAction.Register <BlueprintQuestObjective>("Complete",
                                                               (bp, ch, n, index) => Game.Instance.Player.QuestBook.CompleteObjective(bp),
                                                               (bp, ch, index) => Game.Instance.Player.QuestBook.GetQuest(bp.Quest)?.State == QuestState.Started);

            // Etudes
            BlueprintAction.Register <BlueprintEtude>("Start",
                                                      (bp, ch, n, index) => Game.Instance.Player.EtudesSystem.StartEtude(bp),
                                                      (bp, ch, index) => Game.Instance.Player.EtudesSystem.EtudeIsNotStarted(bp));
            BlueprintAction.Register <BlueprintEtude>("Unstart",
                                                      (bp, ch, n, index) => Game.Instance.Player.EtudesSystem.UnstartEtude(bp),
                                                      (bp, ch, index) => !Game.Instance.Player.EtudesSystem.EtudeIsNotStarted(bp));
            BlueprintAction.Register <BlueprintEtude>("Complete",
                                                      (bp, ch, n, index) => Game.Instance.Player.EtudesSystem.MarkEtudeCompleted(bp),
                                                      (bp, ch, index) => !Game.Instance.Player.EtudesSystem.EtudeIsNotStarted(bp) &&
                                                      !Game.Instance.Player.EtudesSystem.EtudeIsCompleted(bp));
            // Flags
            BlueprintAction.Register <BlueprintUnlockableFlag>("Unlock",
                                                               (bp, ch, n, index) => flags.Unlock(bp),
                                                               (bp, ch, index) => !flags.IsUnlocked(bp));

            BlueprintAction.Register <BlueprintUnlockableFlag>("Lock",
                                                               (bp, ch, n, index) => flags.Lock(bp),
                                                               (bp, ch, index) => flags.IsUnlocked(bp));

            BlueprintAction.Register <BlueprintUnlockableFlag>(">",
                                                               (bp, ch, n, index) => flags.SetFlagValue(bp, flags.GetFlagValue(bp) + n),
                                                               (bp, ch, index) => flags.IsUnlocked(bp));

            BlueprintAction.Register <BlueprintUnlockableFlag>("<",
                                                               (bp, ch, n, index) => flags.SetFlagValue(bp, flags.GetFlagValue(bp) - n),
                                                               (bp, ch, index) => flags.IsUnlocked(bp));

            // Cutscenes
            BlueprintAction.Register <Cutscene>("Play", (bp, ch, n, index) => {
                Actions.ToggleModWindow();
                var cutscenePlayerData = CutscenePlayerData.Queue.FirstOrDefault(c => c.PlayActionId == bp.name);

                if (cutscenePlayerData != null)
                {
                    cutscenePlayerData.PreventDestruction = true;
                    cutscenePlayerData.Stop();
                    cutscenePlayerData.PreventDestruction = false;
                }

                var state = ContextData <SpawnedUnitData> .Current?.State;
                CutscenePlayerView.Play(bp, null, true, state).PlayerData.PlayActionId = bp.name;
            });

            // Teleport
            BlueprintAction.Register <BlueprintAreaEnterPoint>("Teleport", (bp, ch, n, index) => GameHelper.EnterToArea(bp, AutoSaveMode.None));
            BlueprintAction.Register <BlueprintGlobalMap>("Teleport", (bp, ch, n, index) => GameHelper.EnterToArea(bp.GlobalMapEnterPoint, AutoSaveMode.None));

            BlueprintAction.Register <BlueprintArea>("Teleport", (area, ch, n, index) => {
                var areaEnterPoints = BlueprintExensions.BlueprintsOfType <BlueprintAreaEnterPoint>();
                var blueprint       = areaEnterPoints.FirstOrDefault(bp => bp is BlueprintAreaEnterPoint ep && ep.Area == area);

                if (blueprint is BlueprintAreaEnterPoint enterPoint)
                {
                    GameHelper.EnterToArea(enterPoint, AutoSaveMode.None);
                }
            });

            BlueprintAction.Register <BlueprintGlobalMapPoint>("Teleport", (globalMapPoint, ch, n, index) => {
                if (!Teleport.TeleportToGlobalMapPoint(globalMapPoint))
                {
                    Teleport.TeleportToGlobalMap(() => Teleport.TeleportToGlobalMapPoint(globalMapPoint));
                }
            });

            //Army
            BlueprintAction.Register <BlueprintArmyPreset>("Add", (bp, ch, n, l) => {
                Actions.CreateArmy(bp);
            });

            //ArmyGeneral
            BlueprintAction.Register <BlueprintLeaderSkill>("Add",
                                                            (bp, ch, n, l) => Actions.AddSkillToLeader(bp),
                                                            (bp, ch, index) => Actions.LeaderSelected(bp) && !Actions.LeaderHasSkill(bp));

            //ArmyGeneral
            BlueprintAction.Register <BlueprintLeaderSkill>("Remove",
                                                            (bp, ch, n, l) => Actions.RemoveSkillFromLeader(bp),
                                                            (bp, ch, index) => Actions.LeaderSelected(bp) && Actions.LeaderHasSkill(bp));
#endif
        }