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); }
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); } }
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(); }
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(); } }
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)) ); }
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)) ); }
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)) ); }
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)) ); }
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++; } }
public static IEnumerable <BlueprintAction> GetActions(this SimpleBlueprint bp) => BlueprintAction.ActionsForBlueprint(bp);
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); } }),
public static IEnumerable <BlueprintAction> GetActions(this BlueprintScriptableObject bp) { return(BlueprintAction.ActionsForBlueprint(bp)); }
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(); }
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 }