diff --git a/.github/workflows/Build Mod on PR.yml b/.github/workflows/Build Mod on PR.yml
index 4cb250614..4b964d24a 100644
--- a/.github/workflows/Build Mod on PR.yml
+++ b/.github/workflows/Build Mod on PR.yml
@@ -18,7 +18,7 @@ jobs:
GAME_NAME: Wrath
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_NAME: ${{ github.repository_owner }}
- PACKAGE_OWNER: xADDBx
+ PACKAGE_OWNER: cabarius
BRANCH_REF: ${{ github.event.pull_request.head.sha }}
- name: Upload build artifacts
@@ -29,11 +29,11 @@ jobs:
- name: Remove Test Label
if: always()
- shell: pwsh
+ shell: bash
run: |
- $headers = @{
- Accept = 'application/vnd.github.v3+json'
- Authorization = "token ${{ secrets.GITHUB_TOKEN }}"
- }
- $url = "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/labels/safe%20to%20test"
- Invoke-RestMethod -Uri $url -Method Delete -Headers $headers
\ No newline at end of file
+ curl --silent --fail-with-body \
+ -X DELETE \
+ -H "Accept: application/vnd.github+json" \
+ -H "Authorization: Bearer ${{ secrets.WRITE_PR_TOKEN }}" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ 'https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/labels/safe%20to%20test'
diff --git a/.github/workflows/Build Mod on Push.yml b/.github/workflows/Build Mod on Push.yml
index 6cc80d042..5fa344dcc 100644
--- a/.github/workflows/Build Mod on Push.yml
+++ b/.github/workflows/Build Mod on Push.yml
@@ -17,7 +17,7 @@ jobs:
GAME_NAME: Wrath
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_NAME: ${{ github.repository_owner }}
- PACKAGE_OWNER: xADDBx
+ PACKAGE_OWNER: cabarius
- name: Upload build artifacts
uses: actions/upload-artifact@v4
diff --git a/.github/workflows/Create Release for new Tag.yml b/.github/workflows/Create Release for new Tag.yml
index a0791f10e..36e8da2b0 100644
--- a/.github/workflows/Create Release for new Tag.yml
+++ b/.github/workflows/Create Release for new Tag.yml
@@ -21,7 +21,7 @@ jobs:
GAME_NAME: Wrath
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_NAME: ${{ github.repository_owner }}
- PACKAGE_OWNER: xADDBx
+ PACKAGE_OWNER: cabarius
- name: Upload build artifacts
uses: actions/upload-artifact@v4
diff --git a/ToyBox/Incompatibilities.json b/ToyBox/Incompatibilities.json
new file mode 100644
index 000000000..b9d1a3320
--- /dev/null
+++ b/ToyBox/Incompatibilities.json
@@ -0,0 +1,3 @@
+[
+ [ "1.5.12", "2.3.0bb" ]
+]
diff --git a/ToyBox/Info.json b/ToyBox/Info.json
index 45e486b7c..865edd04d 100644
--- a/ToyBox/Info.json
+++ b/ToyBox/Info.json
@@ -2,7 +2,7 @@
"Id": "0ToyBox0",
"DisplayName": "ToyBox",
"Author": "Narria",
- "Version": "1.5.18",
+ "Version": "1.5.24",
"ManagerVersion": "0.27.11",
"Requirements": [],
"AssemblyName": "ToyBox.dll",
diff --git a/ToyBox/Localization/Wrath/en.json b/ToyBox/Localization/Wrath/en.json
index 141f89f7b..027ad6105 100644
--- a/ToyBox/Localization/Wrath/en.json
+++ b/ToyBox/Localization/Wrath/en.json
@@ -1,6 +1,6 @@
{
"LanguageCode": "en",
- "Version": "1.5.12",
+ "Version": "1.5.23",
"Contributors": "The ToyBox Team",
"HomePage": "https://github.com/cabarius/ToyBox/",
"Strings": {
@@ -32,6 +32,7 @@
"Allow any gender for any Romance": "Allow any gender for any Romance",
"Allow multiple romances at the same time": "Allow multiple romances at the same time",
"creation of new characters\nNote: This value applies to all saves and in the main menu": "creation of new characters\nNote: This value applies to all saves and in the main menu",
+ "Makes the thumbs up/down in disappear in selections": "Makes the thumbs up/down in disappear in selections",
"Some responses such as comments about your mythic powers will always choose the first one by default. This allows the game to mix things up a bit\nWarning: this will introduce randomness to NPC responses to you in general and may lead to surprising or even wild outcomes": "Some responses such as comments about your mythic powers will always choose the first one by default. This allows the game to mix things up a bit\nWarning: this will introduce randomness to NPC responses to you in general and may lead to surprising or even wild outcomes",
"Tells the game to reset the in game UI. Warning Using this in dialog or the book will dismiss that dialog which may break progress so use with care": "Tells the game to reset the in game UI. Warning Using this in dialog or the book will dismiss that dialog which may break progress so use with care",
"The following modifiers all work on chance = chance (1 + modifier) so a value of -1 means the chance is 0, 0 is chance cost and 2 increases it 3x": "The following modifiers all work on chance = chance (1 + modifier) so a value of -1 means the chance is 0, 0 is chance cost and 2 increases it 3x",
@@ -455,6 +456,7 @@
"Ignore Class Restrictions": "Ignore Class Restrictions",
"ignore Equipment Restrictions": "ignore Equipment Restrictions",
"Ignore Event Solution Restrictions": "Ignore Event Solution Restrictions",
+ "Ignore Feature Recommendations": "Ignore Feature Recommendations",
"Ignore Feature Restrictions": "Ignore Feature Restrictions",
"Ignore Forbidden Archetypes": "Ignore Forbidden Archetypes",
"Ignore Pet Sizes For Mounting": "Ignore Pet Sizes For Mounting",
diff --git a/ToyBox/ReadMe.md b/ToyBox/ReadMe.md
index 63e9cdb72..a3fa7e6b2 100644
--- a/ToyBox/ReadMe.md
+++ b/ToyBox/ReadMe.md
@@ -36,11 +36,32 @@
your save before using. Remember that "with great power comes great responsibility"
* **Quest Resolution**: this allows you to view your active quests and advance them as needed to work around bugs or
skip quests you don't want to do. Be warned this may break your game progression if used carelessly.
+
+### Toybox Wrath - Ver 1.5.24 (built for 2.3.2c)
+* (***CascadingDragon***) Add new feature, Toggle Feature Recommendations. This will turn off the thumbs up/down in the Feature Selections on Level Up (Toggle found in Level Up tab, under Ignore Feature Restrictions)
+
+### ToyBox Wrath - Ver 1.5.23 (built for 2.3.2c)
+* (***CascadingDragon***) Fix Ignore Feature Prerequisites When Choosing Class (now it now longer allows taking feats you shouldn't be able too).
+
+### ToyBox Wrath - Ver 1.5.22 (built for 2.3.2c)
+* (***ADDB***) Add feature under Party => Stats to turn on/off AI control of specific characters.
+* (***CascadingDragon***) Fix Roll 10 Initiative.
+
+### ToyBox Wrath - Ver 1.5.21 (built for 2.3.2c)
+* (***ADDB***) Add incompatibility checker! From now on ToyBox will send a web request to check whether the current mod version has known incompatibilities with the current game version. This is done for cases where the mod still loads after updates, but causes issues in the background (i.e. enemies only having 1 HP). If it detects incompatibilities it will stop loading.
+
+### ToyBox Wrath - Ver 1.5.20 (built for 2.3.2c)
+* (***ADDB***) Maybe Party tab shows more features now? (Especially Parameterized stuff and such?).
+* (***CascadingDragon***) Fix Merging Manually Added Mythic Spell Books.
+
+### ToyBox Wrath - Ver 1.5.19 (built for 2.3.2c)
+* (***ADDB***) Maybe Fixed Remote Companions Dialog causing companions to talk about other companions you might've never even joined you.
+* (***ADDB***) My Magus changes broke some abilities (like Charge) if the feature is enabled. This should be fixed now.
### ToyBox Wrath - Ver 1.5.18 (built for 2.3.1e)
* (***ADDB***) Fix the Magus: Allow Spell Combat for dual wielding.
* (***ADDB***) Maybe added setting to forcefully disable all tutorials.
-* (***ADDB***) Fix MysticalMayhem breaking Search 'n Pick. Is this mod even working correctly currently?
+* (***ADDB***) Fix MysticalMayhem breaking Search 'n Pick. Is this mod even working correctly currently?.
* (***Delth***) Add toggle to remove read-onlyness from etudes.
### ToyBox Wrath - Ver 1.5.15 (built for 2.3.1e)
diff --git a/ToyBox/Repository.json b/ToyBox/Repository.json
index 973731604..ae8050ea7 100644
--- a/ToyBox/Repository.json
+++ b/ToyBox/Repository.json
@@ -2,7 +2,7 @@
"Releases": [
{
"Id": "0ToyBox0",
- "Version": "1.5.18"
+ "Version": "1.5.22"
}
]
}
\ No newline at end of file
diff --git a/ToyBox/ToyBox.csproj b/ToyBox/ToyBox.csproj
index 64a2c53da..4d311b674 100644
--- a/ToyBox/ToyBox.csproj
+++ b/ToyBox/ToyBox.csproj
@@ -7,7 +7,7 @@
ToyBox
Properties
Library
- 1.5.18
+ 1.5.24
true
512
latest
diff --git a/ToyBox/classes/Infrastructure/CasterHelpers.cs b/ToyBox/classes/Infrastructure/CasterHelpers.cs
index 289eea228..3daec3526 100644
--- a/ToyBox/classes/Infrastructure/CasterHelpers.cs
+++ b/ToyBox/classes/Infrastructure/CasterHelpers.cs
@@ -1,4 +1,4 @@
-using Kingmaker.Blueprints;
+using Kingmaker.Blueprints;
using Kingmaker.Blueprints.Classes;
using Kingmaker.Blueprints.Root;
using Kingmaker.EntitySystem.Entities;
@@ -246,25 +246,29 @@ public static int GetActualSpellsLearned(Spellbook spellbook, int level, List MergableClasses(this UnitEntityData unit) {
+ public static IEnumerable MergableClasses(this UnitEntityData unit) {
var spellbookCandidates = unit.Spellbooks
.Where(sb => sb.IsStandaloneMythic && sb.Blueprint.CharacterClass != null)
.Select(sb => sb.Blueprint).ToHashSet();
+ /* Dragon's comment on this. Why are we looking for the Mythic class here? It means you can't merge mythic spellbooks that are added via Toybox
+ * Or any other method that wouldn't add the Mythic class
+ * Looks like maybe for localized name, but... then it's not that functional
+ */
//Mod.Log($"{unit.CharacterName} - spellbookCandidates: {string.Join(", ", spellbookCandidates.Select(sb => sb.DisplayName))}");
- var classCandidates = unit.Progression.Classes
- .Where(cl => cl.Spellbook != null && spellbookCandidates.Contains(cl.Spellbook));
+ //var classCandidates = unit.Progression.Classes
+ // .Where(cl => cl.Spellbook != null && spellbookCandidates.Contains(cl.Spellbook));
//Mod.Log($"{unit.CharacterName} - classCandidates: {string.Join(", ", classCandidates.Select(cl => cl.CharacterClass.Name))}");
- return classCandidates;
+ return spellbookCandidates;
}
- public static void MergeMythicSpellbook(this Spellbook targetSpellbook, ClassData fromClass) {
+ public static void MergeMythicSpellbook(this Spellbook targetSpellbook, BlueprintSpellbook fromClass) {
var unit = targetSpellbook.Owner;
- var oldMythicSpellbookBp = fromClass?.Spellbook;
+ var oldMythicSpellbookBp = fromClass;
if (fromClass == null || oldMythicSpellbookBp == null || !oldMythicSpellbookBp.IsMythic) {
Mod.Warn("Can't merge because you don't have a mythic class / mythic spellbook!");
return;
}
- fromClass.Spellbook = targetSpellbook.Blueprint;
+ //fromClass.Spellbook = targetSpellbook.Blueprint;
targetSpellbook.m_Type = SpellbookType.Mythic;
targetSpellbook.AddSpecialList(oldMythicSpellbookBp.MythicSpellList);
for (var i = targetSpellbook.MythicLevel; i < unit.Progression.MythicLevel; i++) {
diff --git a/ToyBox/classes/MainUI/Browser/FactsEditor.cs b/ToyBox/classes/MainUI/Browser/FactsEditor.cs
index cd7e7e6c1..a755bcbf1 100644
--- a/ToyBox/classes/MainUI/Browser/FactsEditor.cs
+++ b/ToyBox/classes/MainUI/Browser/FactsEditor.cs
@@ -354,10 +354,7 @@ public static List OnGUI- (UnitEntityData ch, Browser {
- var types = fact.GroupBy(f => f.Blueprint.GetType()).Select(g => g.FirstOrDefault().Blueprint.GetType());
- return GetBlueprints()?.Where(bp => types.Contains(bp.GetType()));
- },
+ GetBlueprints,
(feature) => (Definition)feature.Blueprint,
(blueprint) => $"{GetSearchKey(blueprint)}" + (Settings.searchDescriptions ? $"{blueprint.Description}" : ""),
blueprint => new[] { GetSortKey(blueprint) },
diff --git a/ToyBox/classes/MainUI/DiceRollsGUI.cs b/ToyBox/classes/MainUI/DiceRollsGUI.cs
index 8d1f6a07a..e971dc430 100644
--- a/ToyBox/classes/MainUI/DiceRollsGUI.cs
+++ b/ToyBox/classes/MainUI/DiceRollsGUI.cs
@@ -18,7 +18,7 @@ public static void OnGUI() {
() => EnumGrid("Never Roll 20".localize(), ref Settings.neverRoll20, AutoWidth()),
() => EnumGrid("Never Roll 1".localize(), ref Settings.neverRoll1, AutoWidth()),
() => EnumGrid("Initiative: Always Roll 20".localize(), ref Settings.roll20Initiative, AutoWidth()),
- () => EnumGrid("Initiative: Always Roll 10".localize(), ref Settings.roll20Initiative, AutoWidth()),
+ () => EnumGrid("Initiative: Always Roll 10".localize(), ref Settings.roll10Initiative, AutoWidth()),
() => EnumGrid("Initiative: Always Roll 1".localize(), ref Settings.roll1Initiative, AutoWidth()),
() => EnumGrid("Non Combat: Take 20".localize(), ref Settings.alwaysRoll20OutOfCombat, AutoWidth()),
() => EnumGrid("Non Combat: Roll at least 10".localize(), ref Settings.rollAtLeast10OutOfCombat, AutoWidth()),
@@ -29,4 +29,4 @@ public static void OnGUI() {
);
}
}
-}
\ No newline at end of file
+}
diff --git a/ToyBox/classes/MainUI/LevelUp.cs b/ToyBox/classes/MainUI/LevelUp.cs
index ae52c9d21..34dfdbd26 100644
--- a/ToyBox/classes/MainUI/LevelUp.cs
+++ b/ToyBox/classes/MainUI/LevelUp.cs
@@ -84,6 +84,11 @@ public static void OnGUI() {
Space(25);
Label(("Experimental".cyan() + ": lets you select any feat ignoring prerequisites.".green()).localize());
},
+ () => {
+ Toggle("Ignore Feature Recommendations".localize(), ref Settings.toggleFeatureRecommendations);
+ Space(25);
+ Label(("Makes the thumbs up/down in disappear in selections".green()).localize());
+ },
() => Toggle("Allow Companions to Take Mythic Classes".localize(), ref Settings.toggleAllowCompanionsToBecomeMythic),
() => Toggle("Allow Pets to Take Mythic Classes".localize(), ref Settings.toggleAllowMythicPets),
() => Toggle("Ignore Prerequisites When Choosing A Feat".localize(), ref Settings.toggleFeaturesIgnorePrerequisites),
diff --git a/ToyBox/classes/MainUI/Main.cs b/ToyBox/classes/MainUI/Main.cs
index b5dcf9034..064f6e389 100644
--- a/ToyBox/classes/MainUI/Main.cs
+++ b/ToyBox/classes/MainUI/Main.cs
@@ -24,12 +24,14 @@
using Kingmaker.UI.Common;
using Newtonsoft.Json;
using ToyBox.Multiclass;
+using System.Net;
namespace ToyBox {
#if DEBUG
[EnableReloading]
#endif
internal static class Main {
+ internal const string LinkToIncompatibilitiesFile = "https://raw.githubusercontent.com/xADDBx/ToyBox-Wrath/main/ToyBox/Incompatibilities.json";
internal static Harmony HarmonyInstance;
public static readonly LogChannel logger = LogChannelFactory.GetOrCreate("Respec");
private static string _modId;
@@ -78,6 +80,10 @@ public static void SetNeedsResetGameUI() {
public static List Objects;
private static bool Load(UnityModManager.ModEntry modEntry) {
try {
+ if (!IsGameVersionSupported(modEntry.Version, modEntry.Logger)) {
+ modEntry.Logger.Log("Fatal! The current Game Version has known incompatabilities with your current ToyBox version! Please Update.");
+ return false;
+ }
#if DEBUG
modEntry.OnUnload = OnUnload;
#endif
@@ -380,5 +386,46 @@ private static void OnUpdate(UnityModManager.ModEntry modEntry, float z) {
Teleport.TeleportParty();
}
}
+ public static bool IsGameVersionSupported(Version modVersion, UnityModManager.ModEntry.ModLogger logger) {
+ try {
+ using var web = new WebClient();
+ var raw = web.DownloadString(LinkToIncompatibilitiesFile);
+ var definition = new[] { new[] { "", "" } };
+ var versions = JsonConvert.DeserializeAnonymousType(raw, definition);
+ var currentOrNewer = versions.FirstOrDefault(v => new Version(v[0]) >= modVersion);
+ if (currentOrNewer == null) return true;
+ return new Version(GetNumifiedVersion(currentOrNewer[1])) > new Version(GetNumifiedVersion(GameVersion.GetVersion()));
+ } catch (Exception ex) {
+ logger.Log(ex.ToString());
+ }
+ return true;
+ }
+ public static string GetNumifiedVersion(string version) {
+ var comps = version.Split('.');
+ var newComps = new List();
+ foreach (var comp in comps) {
+ uint num = 0;
+ foreach (var c in comp) {
+ uint newNum = num;
+ try {
+ checked {
+ if (uint.TryParse(c.ToString(), out var n)) {
+ newNum = newNum * 10u + n;
+ } else {
+ int signedCharNumber = char.ToUpper(c) - ' ';
+ uint unsignedCharNumber = (uint)Math.Max(0, Math.Min(signedCharNumber, 99));
+ newNum = newNum * 100u + unsignedCharNumber;
+ }
+ num = newNum;
+ }
+ } catch (OverflowException) {
+ logger.Log($"Encountered uint overflow while parsing version component {comp}, continuing with {num}");
+ break;
+ }
+ }
+ newComps.Add(num.ToString());
+ }
+ return string.Join(".", newComps);
+ }
}
}
\ No newline at end of file
diff --git a/ToyBox/classes/MainUI/PartyEditor/SpellsEditor.cs b/ToyBox/classes/MainUI/PartyEditor/SpellsEditor.cs
index a726f7364..29599454c 100644
--- a/ToyBox/classes/MainUI/PartyEditor/SpellsEditor.cs
+++ b/ToyBox/classes/MainUI/PartyEditor/SpellsEditor.cs
@@ -1,4 +1,4 @@
-using Kingmaker.Blueprints;
+using Kingmaker.Blueprints;
using Kingmaker.EntitySystem.Entities;
using Kingmaker.UnitLogic;
using Kingmaker.UnitLogic.Abilities;
@@ -45,7 +45,7 @@ public static List OnSpellsGUI(UnitEntityData ch, List spellb
25.space();
foreach (var cl in mergeableClasses) {
var sb = spellbook;
- ActionButton(cl.CharacterClass.LocalizedName.ToString(), () => sb.MergeMythicSpellbook(cl));
+ ActionButton(cl.GetDisplayName(), () => sb.MergeMythicSpellbook(cl));
15.space();
}
25.space();
diff --git a/ToyBox/classes/MainUI/PartyEditor/StatsEditor.cs b/ToyBox/classes/MainUI/PartyEditor/StatsEditor.cs
index 3cee77770..73c1b0786 100644
--- a/ToyBox/classes/MainUI/PartyEditor/StatsEditor.cs
+++ b/ToyBox/classes/MainUI/PartyEditor/StatsEditor.cs
@@ -341,6 +341,30 @@ public static List OnStatsGUI(UnitEntityData ch) {
}
}
}
+ using (HorizontalScope()) {
+ Space(100);
+ if (!Main.Settings.perSave.doOverrideEnableAiForCompanions.TryGetValue(ch.UniqueId, out var valuePair)) {
+ valuePair = new(false, false);
+ }
+ var temp = valuePair.Item1;
+ if (Toggle("Override AI Control Behaviour".localize(), ref temp)) {
+ if (temp) {
+ Main.Settings.perSave.doOverrideEnableAiForCompanions[ch.UniqueId] = new(temp, valuePair.Item2);
+ Settings.SavePerSaveSettings();
+ } else {
+ Main.Settings.perSave.doOverrideEnableAiForCompanions.Remove(ch.UniqueId);
+ Settings.SavePerSaveSettings();
+ }
+ }
+ if (temp) {
+ Space(50);
+ var temp2 = valuePair.Item2;
+ if (Toggle("Make Character AI Controlled".localize(), ref temp2)) {
+ Main.Settings.perSave.doOverrideEnableAiForCompanions[ch.UniqueId] = new(temp, temp2);
+ Settings.SavePerSaveSettings();
+ }
+ }
+ }
}
if (ch.Descriptor().Progression.GetCurrentMythicClass()?.CharacterClass.Name == "Swarm That Walks") {
UnitPartLocustSwarm SwarmPart = null;
diff --git a/ToyBox/classes/Models/Settings.cs b/ToyBox/classes/Models/Settings.cs
index cb8e7567e..8aa0d02a8 100644
--- a/ToyBox/classes/Models/Settings.cs
+++ b/ToyBox/classes/Models/Settings.cs
@@ -37,6 +37,10 @@ public class PerSaveSettings : EntityPart {
// This is the override setting for the character Descriptor size modifier
[JsonProperty]
public Dictionary characterSizeModifier = new();
+ // Dictionary> doOverrideEnableAiForCompanions = new();
// This is the override setting for the Army Recruitment Growth Modifier
[JsonProperty]
@@ -318,6 +322,7 @@ public PerSaveSettings perSave {
public bool toggleContinousLevelCap = false;
public bool toggleExponentialLevelCap = false;
public bool toggleFeatureMultiplierCompanions = false;
+ public bool toggleFeatureRecommendations = false;
// Multipliers
public int featsMultiplier = 1;
diff --git a/ToyBox/classes/MonkeyPatchin/BagOfPatches/Dialog.cs b/ToyBox/classes/MonkeyPatchin/BagOfPatches/Dialog.cs
index efc59d4a0..233af5c77 100644
--- a/ToyBox/classes/MonkeyPatchin/BagOfPatches/Dialog.cs
+++ b/ToyBox/classes/MonkeyPatchin/BagOfPatches/Dialog.cs
@@ -59,15 +59,28 @@ internal static class Dialog {
public static class CompanionInParty_CheckCondition_Patch {
public static void Postfix(CompanionInParty __instance, ref bool __result) {
if (__instance.Not) return; // We only want this patch to run for conditions requiring the character to be in the party so if it is for the inverse we bail. Example of this comes up with Lann and Wenduag in the final scene of the Prologue Labyrinth
+ // We don't want to match when the game only checks for Ex companions since this is basically a check for companions which left the party then
+ // Example is 6aeb6812dcc1464a9b087786556c9b18 which checks whether Pascal left as a companion. Really weird design from Owlcat right there.
+ if (__instance.MatchWhenEx && !__instance.MatchWhenActive && !__instance.MatchWhenDetached && !__instance.MatchWhenRemote) return;
if (SecretCompanions.Contains(__instance.companion.AssetGuid.ToString())) return;
if (ProblemCues.Contains(__instance.Owner.AssetGuid.ToString())) return;
- if (settings.toggleRemoteCompanionDialog) {
- if (__instance.Owner is BlueprintCue cueBP) {
- Mod.Debug($"overiding {cueBP.name} Companion {__instance.companion.name} In Party to true");
- __result = true;
- }
- if (__instance.Owner is BlueprintCue etudeBP) {
+ UnitPartCompanion unitPartCompanion = null;
+ try {
+ unitPartCompanion = Game.Instance.Player.AllCharacters.FirstOrDefault(unit => unit.Blueprint == __instance.companion).Parts.Get();
+ } catch (NullReferenceException ex) {
+ Mod.Trace(ex.ToString());
+ }
+ if (unitPartCompanion != null) {
+ if (settings.toggleRemoteCompanionDialog && unitPartCompanion.State != CompanionState.None) {
+ if ((settings.toggleExCompanionDialog && unitPartCompanion.State == CompanionState.ExCompanion) || unitPartCompanion.State != CompanionState.ExCompanion) {
+ if (__instance.Owner is BlueprintCue cueBP) {
+ Mod.Debug($"overiding {cueBP.name} Companion {__instance.companion.name} In Party to true");
+ __result = true;
+ }
+ if (__instance.Owner is BlueprintCue etudeBP) {
+ }
+ }
}
}
}
diff --git a/ToyBox/classes/MonkeyPatchin/BagOfPatches/LevelUpPatchesWrath.cs b/ToyBox/classes/MonkeyPatchin/BagOfPatches/LevelUpPatchesWrath.cs
index 3620a6e5d..3ca964aa2 100644
--- a/ToyBox/classes/MonkeyPatchin/BagOfPatches/LevelUpPatchesWrath.cs
+++ b/ToyBox/classes/MonkeyPatchin/BagOfPatches/LevelUpPatchesWrath.cs
@@ -1,4 +1,4 @@
-// borrowed shamelessly and enhanced from Bag of Tricks https://www.nexusmods.com/pathfinderkingmaker/mods/26, which is under the MIT License
+// borrowed shamelessly and enhanced from Bag of Tricks https://www.nexusmods.com/pathfinderkingmaker/mods/26, which is under the MIT License
using HarmonyLib;
using JetBrains.Annotations;
@@ -34,6 +34,8 @@
using Kingmaker.EntitySystem.Entities;
using Owlcat.Runtime.Core.Logging;
using Kingmaker.UI.MVVM._VM.CharGen.Phases.Alignment;
+using Kingmaker.Designers.Mechanics.Recommendations;
+using Kingmaker.UI.LevelUp;
namespace ToyBox.BagOfPatches {
internal static class LevelUp {
@@ -487,12 +489,30 @@ public static bool Prefix(CharGenClassSelectorItemVM __instance, ref BlueprintRa
}
}
+ [HarmonyPatch(typeof(BlueprintCharacterClass))]
+ private static class BlueprintCharacterClass_Patch {
+ [HarmonyPatch(nameof(BlueprintCharacterClass.MeetsPrerequisites)), HarmonyPostfix]
+ public static void MeetsPrerequisites_Patch(ref bool __result, BlueprintCharacterClass __instance) {
+ if (settings.toggleIgnoreFeaturePrerequisitesWhenChoosingClass && !__instance.IsMythic) {
+ __result = true;
+ }
+ }
+ }
+
+ [HarmonyPatch(typeof(BlueprintArchetype))]
+ private static class BlueprintArchetype_Patch {
+ [HarmonyPatch(nameof(BlueprintArchetype.MeetsPrerequisites)), HarmonyPostfix]
+ public static void MeetsPrerequisites_Patch(ref bool __result, BlueprintArchetype __instance) {
+ if (settings.toggleIgnoreFeaturePrerequisitesWhenChoosingClass )
+ __result = true;
+ }
+ }
- [HarmonyPatch(typeof(PrerequisiteFeature))]
+ /*[HarmonyPatch(typeof(PrerequisiteFeature))]
public static class PrerequisiteFeature_CheckInternal_Patch {
[HarmonyPostfix]
[HarmonyPatch(nameof(PrerequisiteFeature.CheckInternal))]
- public static void PostfixCheckInternal([NotNull] UnitDescriptor unit, ref bool __result) {
+ public static void PostfixCheckInternal(UnitDescriptor unit, ref bool __result, PrerequisiteFeature __instance) {
if (!unit.IsPartyOrPet()) {
return;
}
@@ -513,7 +533,7 @@ public static void PostfixConsiderFulfilled([NotNull] UnitDescriptor unit, ref b
__result = true;
}
}
- }
+ }*/
[HarmonyPatch(typeof(CharGenAlignmentPhaseVM), nameof(CharGenAlignmentPhaseVM.SelectionStateIsCompleted))]
public static class CharGenAlignmentPhaseVM_SelectionStateIsCompleted_Patch {
@@ -791,5 +811,122 @@ private static void ExecuteByMultiplier(int multiplier, Action run = null) {
}
}
#endif
+ [HarmonyPatch(typeof(RecommendationHasFeature))]
+ public static class RecommendHasFeature_Patch {
+ [HarmonyPatch(nameof(RecommendationHasFeature.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationAccomplishedSneakAttacker))]
+ public static class RecommendationAccomplishedSneakAttacker_Patch {
+ [HarmonyPatch(nameof(RecommendationAccomplishedSneakAttacker.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationBaseAttackPart))]
+ public static class RecommendationBaseAttackPart_Patch {
+ [HarmonyPatch(nameof(RecommendationBaseAttackPart.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationCompanionBoon))]
+ public static class RecommendationCompanionBoon_Patch {
+ [HarmonyPatch(nameof(RecommendationCompanionBoon.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationForWeaponCategory))]
+ public static class RecommendationForWeaponCategory_Patch {
+ [HarmonyPatch(nameof(RecommendationForWeaponCategory.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationHasClasses))]
+ public static class RecommendationHasClasses_Patch {
+ [HarmonyPatch(nameof(RecommendationHasClasses.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationNoFeatFromGroup))]
+ public static class RecommendationNoFeatFromGroup_Patch {
+ [HarmonyPatch(nameof(RecommendationNoFeatFromGroup.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationRequiresSpellbook))]
+ public static class RecommendationRequiresSpellbook_Patch {
+ [HarmonyPatch(nameof(RecommendationRequiresSpellbook.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationRequiresSpellbookSource))]
+ public static class RecommendationRequiresSpellbookSource_Patch {
+ [HarmonyPatch(nameof(RecommendationRequiresSpellbookSource.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationStatComparison))]
+ public static class RecommendationStatComparison_Patch {
+ [HarmonyPatch(nameof(RecommendationStatComparison.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationStatMiminum))]
+ public static class RecommendationStatMiminum_Patch {
+ [HarmonyPatch(nameof(RecommendationStatMiminum.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationWeaponSubcategoryFocus))]
+ public static class RecommendationWeaponSubcategoryFocus_Patch {
+ [HarmonyPatch(nameof(RecommendationWeaponSubcategoryFocus.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
+ [HarmonyPatch(typeof(RecommendationWeaponTypeFocus))]
+ public static class RecommendationWeaponTypeFocus_Patch {
+ [HarmonyPatch(nameof(RecommendationWeaponTypeFocus.GetPriority)), HarmonyPostfix]
+ public static void GetPriority_Patch(ref RecommendationPriority __result) {
+ if (settings.toggleFeatureRecommendations) {
+ __result = RecommendationPriority.Same;
+ }
+ }
+ }
}
}
diff --git a/ToyBox/classes/MonkeyPatchin/BagOfPatches/TweaksWrath.cs b/ToyBox/classes/MonkeyPatchin/BagOfPatches/TweaksWrath.cs
index aa5ba0c4e..cd4f8abe1 100644
--- a/ToyBox/classes/MonkeyPatchin/BagOfPatches/TweaksWrath.cs
+++ b/ToyBox/classes/MonkeyPatchin/BagOfPatches/TweaksWrath.cs
@@ -81,6 +81,20 @@ internal static partial class Tweaks {
// private static bool CanCopySpell([NotNull] BlueprintAbility spell, [NotNull] Spellbook spellbook) => spellbook.Blueprint.CanCopyScrolls && !spellbook.IsKnown(spell) && spellbook.Blueprint.SpellList.Contains(spell);
+
+ [HarmonyPatch(typeof(UnitEntityData))]
+ private static class UnitEntityData_Patch {
+ [HarmonyPatch(nameof(UnitEntityData.IsDirectlyControllable), MethodType.Getter)]
+ [HarmonyPostfix]
+ private static void IsDirectlyControllable(UnitEntityData __instance, ref bool __result) {
+ if (__instance == null) return;
+ if (Main.Settings.perSave.doOverrideEnableAiForCompanions.TryGetValue(__instance.UniqueId, out var maybeOverride)) {
+ if (maybeOverride.Item1) {
+ __result = !maybeOverride.Item2;
+ }
+ }
+ }
+ }
[HarmonyPatch(typeof(CopyScroll), nameof(CopyScroll.CanCopySpell))]
[HarmonyPatch(new Type[] { typeof(BlueprintAbility), typeof(Spellbook) })]
public static class CopyScroll_CanCopySpell_Patch {
@@ -603,9 +617,14 @@ public static void CanUseSpellCombat(ref bool __result, UnitPartMagus __instance
}
}
[HarmonyPatch(nameof(UnitPartMagus.IsSpellFromMagusSpellList)), HarmonyFinalizer]
- public static Exception IsSpellFromMagusSpellList(ref bool __result, UnitPartMagus __instance) {
+ public static Exception IsSpellFromMagusSpellList(ref bool __result, UnitPartMagus __instance, AbilityData spell) {
if (Settings.toggleAlwaysAllowSpellCombat && __instance.Owner != null && __instance.Owner.IsPartyOrPet()) {
- __result = true;
+ try {
+ bool flag = (bool)__instance.WandWielder && spell.SourceItemUsableBlueprint != null && spell.SourceItemUsableBlueprint?.Type == UsableItemType.Wand;
+ __result = spell.IsInSpellList(__instance.Spellbook?.Blueprint?.SpellList) || (__instance.Spellbook?.IsKnown(spell?.Blueprint) ?? false) || flag;
+ } catch {
+ __result = spell.Range == AbilityRange.Touch && spell.Spellbook != null;
+ }
}
return null;
}