From cbf50a9a3b107fae2eea82d26f546a7cbff4e5f7 Mon Sep 17 00:00:00 2001 From: Canon Date: Sat, 28 Feb 2026 14:01:02 +0800 Subject: [PATCH] RoyalTitleUtility Display Patches --- .../RoyalTitleUtility_Branching_Patches.cs | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 Source/FCPTools/FalloutCore/Factions/Harmony/RoyalTitleUtility_Branching_Patches.cs diff --git a/Source/FCPTools/FalloutCore/Factions/Harmony/RoyalTitleUtility_Branching_Patches.cs b/Source/FCPTools/FalloutCore/Factions/Harmony/RoyalTitleUtility_Branching_Patches.cs new file mode 100644 index 0000000..ad6eea0 --- /dev/null +++ b/Source/FCPTools/FalloutCore/Factions/Harmony/RoyalTitleUtility_Branching_Patches.cs @@ -0,0 +1,96 @@ +using HarmonyLib; +using Verse; +// ReSharper disable InconsistentNaming + +namespace FCP.Factions; + +[HarmonyPatch(typeof(RoyalTitleUtility))] +public static class RoyalTitleUtility_Branching_Patches +{ + [HarmonyPrefix, HarmonyPatch(nameof(RoyalTitleUtility.GetTitleProgressionInfo))] + public static bool GetTitleProgressionInfo_Prefix(Faction faction, Pawn pawn, ref string __result) + { + List awardableTitles = faction.def.RoyalTitlesAwardableInSeniorityOrderForReading; + + // Check if any awardable title has branching + bool hasBranching = false; + foreach (RoyalTitleDef title in awardableTitles) + { + if (title.GetModExtension() != null) + { + hasBranching = true; + break; + } + } + + if (!hasBranching) + return true; // use the original, then. + + List unbranchedTitles = []; + Dictionary> branchedTitles = []; + + foreach (RoyalTitleDef title in awardableTitles) + { + var ext = title.GetModExtension(); + if (ext == null) + { + unbranchedTitles.Add(title); + } + else + { + // titles with the extension get sorted, keyed by branch. + // ensure each branch gets its own list created on first encounter and is added to it afterwards + if (!branchedTitles.TryGetValue(ext.branchDef, out List list)) + { + list = []; + branchedTitles[ext.branchDef] = list; + } + list.Add(title); + } + } + + TaggedString result = "RoyalTitleTooltipTitlesEarnable".Translate(faction.Named("FACTION")) + ":"; + + // Shared progression + int sharedCost = 0; + foreach (RoyalTitleDef title in unbranchedTitles) + { + sharedCost += title.favorCost; + result += FormatTitleLine(title, pawn, sharedCost, faction); + } + + // Per-branch progression + foreach ((TitleBranchDef branch, List titles) in branchedTitles) + { + result += "\n\n " + branch.LabelCap + ":"; + int branchCost = sharedCost; + foreach (RoyalTitleDef title in titles) + { + branchCost += title.favorCost; + result += FormatTitleLine(title, pawn, branchCost, faction); + } + } + + // Non-awardable titles, filtered to only show branchless or matching branches + List nonAwardable = faction.def.RoyalTitlesAllInSeniorityOrderForReading + .Where(def => !def.Awardable) + .ToList(); + + result += "\n\n" + "RoyalTitleTooltipTitlesNonEarnable".Translate(faction.Named("FACTION")) + ":"; + foreach (RoyalTitleDef title in nonAwardable) + { + result += "\n - " + title.GetLabelCapForBothGenders(); + } + + __result = result.Resolve(); + return false; + } + + private static string FormatTitleLine(RoyalTitleDef title, Pawn pawn, int totalCost, Faction faction) + { + string label = pawn != null ? title.GetLabelCapFor(pawn) : title.GetLabelCapForBothGenders(); + return "\n - " + label + ": " + + "RoyalTitleTooltipRoyalFavorAmount".Translate(title.favorCost, faction.def.royalFavorLabel) + + " (" + "RoyalTitleTooltipRoyalFavorTotal".Translate(totalCost.ToString()) + ")"; + } +}