diff --git a/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/Assemblies/WulaFallenEmpire.dll
index 8bb5a621..d62c5b8b 100644
Binary files a/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/Assemblies/WulaFallenEmpire.dll differ
diff --git a/1.6/Defs/CustomUIDefs/CustomUI_Example.xml b/1.6/Defs/CustomUIDefs/CustomUI_Example.xml
new file mode 100644
index 00000000..cb2b8e41
--- /dev/null
+++ b/1.6/Defs/CustomUIDefs/CustomUI_Example.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+ Wula_ExampleUI
+
+ UI/HeroArt/Storytellers/Randy
+ 兰迪·随机
+ 这是一个事件链的开端。选择第一个选项将会打开第二个事件窗口。
+
+
+
+
+
+ 你选择继续...
+ PositiveEvent
+
+
+ Wula_ExampleUI_Next
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Wula_ExampleUI_Next
+
+ UI/HeroArt/Storytellers/Cassandra
+ 卡桑德拉·经典
+ 这是事件链的第二部分。你已经从第一个窗口来到了这里。
+
+
+
+
+
+ 事件链已完成!一位流浪者加入了你的殖民地。
+
+
+ WandererJoin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo b/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo
index 5da9f907..a8a344fa 100644
Binary files a/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo and b/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo differ
diff --git a/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/DocumentLayout.json b/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/DocumentLayout.json
index 07f9c84d..9877f5de 100644
--- a/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/DocumentLayout.json
+++ b/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/DocumentLayout.json
@@ -2,6 +2,10 @@
"Version": 1,
"WorkspaceRootPath": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\",
"Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\3516260226\\source\\wulafallenempire\\debugactions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:debugactions.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
{
"AbsoluteMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\3516260226\\source\\wulafallenempire\\mentalstate_brokenpersonality.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{F5AE8C3B-0221-4C16-A128-9A62D521A8FF}|WulaFallenEmpire.csproj|solutionrelative:mentalstate_brokenpersonality.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
@@ -67,19 +71,32 @@
{
"$type": "Document",
"DocumentIndex": 0,
+ "Title": "DebugActions.cs",
+ "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\DebugActions.cs",
+ "RelativeDocumentMoniker": "DebugActions.cs",
+ "ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\DebugActions.cs",
+ "RelativeToolTip": "DebugActions.cs",
+ "ViewState": "AQIAAAAAAAAAAAAAAAAAAAkAAAAAAAAA",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-07-27T07:57:05.014Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
"Title": "MentalState_BrokenPersonality.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\MentalState_BrokenPersonality.cs",
"RelativeDocumentMoniker": "MentalState_BrokenPersonality.cs",
"ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\MentalState_BrokenPersonality.cs",
"RelativeToolTip": "MentalState_BrokenPersonality.cs",
- "ViewState": "AQIAADMAAAAAAAAAAAAlwEsAAAAjAAAA",
+ "ViewState": "AQIAABMAAAAAAAAAAAAAwEsAAAAjAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-07-25T13:51:03.13Z",
"EditorCaption": ""
},
{
"$type": "Document",
- "DocumentIndex": 1,
+ "DocumentIndex": 2,
"Title": "Recipe_AdministerWulaMechRepairKit.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\Recipe_AdministerWulaMechRepairKit.cs",
"RelativeDocumentMoniker": "Recipe_AdministerWulaMechRepairKit.cs",
@@ -91,7 +108,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 2,
+ "DocumentIndex": 3,
"Title": "WorkGiver_Warden_DeliverEnergy.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\WorkGiver_Warden_DeliverEnergy.cs",
"RelativeDocumentMoniker": "WorkGiver_Warden_DeliverEnergy.cs",
@@ -103,7 +120,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 3,
+ "DocumentIndex": 4,
"Title": "WorkGiverDefExtension_FeedWula.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\WorkGiverDefExtension_FeedWula.cs",
"RelativeDocumentMoniker": "WorkGiverDefExtension_FeedWula.cs",
@@ -115,7 +132,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 4,
+ "DocumentIndex": 5,
"Title": "CompApparelInterceptor.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\CompApparelInterceptor.cs",
"RelativeDocumentMoniker": "CompApparelInterceptor.cs",
@@ -127,7 +144,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 5,
+ "DocumentIndex": 6,
"Title": "Projectile_Launch_Patch.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\HarmonyPatches\\Projectile_Launch_Patch.cs",
"RelativeDocumentMoniker": "HarmonyPatches\\Projectile_Launch_Patch.cs",
@@ -139,7 +156,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 7,
+ "DocumentIndex": 8,
"Title": "IngestPatch.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\IngestPatch.cs",
"RelativeDocumentMoniker": "IngestPatch.cs",
@@ -151,7 +168,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 6,
+ "DocumentIndex": 7,
"Title": "CompUseEffect_WulaSkillTrainer.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\CompUseEffect_WulaSkillTrainer.cs",
"RelativeDocumentMoniker": "CompUseEffect_WulaSkillTrainer.cs",
@@ -163,7 +180,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 8,
+ "DocumentIndex": 9,
"Title": "Building_Wula_DarkEnergy_Engine.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\Building_Wula_DarkEnergy_Engine.cs",
"RelativeDocumentMoniker": "Building_Wula_DarkEnergy_Engine.cs",
@@ -175,7 +192,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 9,
+ "DocumentIndex": 10,
"Title": "HediffComp_RegenerateBackstory.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\HediffComp_RegenerateBackstory.cs",
"RelativeDocumentMoniker": "HediffComp_RegenerateBackstory.cs",
@@ -187,7 +204,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 10,
+ "DocumentIndex": 11,
"Title": "WulaFallenEmpireMod.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\WulaFallenEmpireMod.cs",
"RelativeDocumentMoniker": "WulaFallenEmpireMod.cs",
@@ -199,7 +216,7 @@
},
{
"$type": "Document",
- "DocumentIndex": 11,
+ "DocumentIndex": 12,
"Title": "MechanitorPatch.cs",
"DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\3516260226\\Source\\WulaFallenEmpire\\MechanitorPatch.cs",
"RelativeDocumentMoniker": "MechanitorPatch.cs",
diff --git a/Source/WulaFallenEmpire/CustomUIDef.cs b/Source/WulaFallenEmpire/CustomUIDef.cs
new file mode 100644
index 00000000..cfe71551
--- /dev/null
+++ b/Source/WulaFallenEmpire/CustomUIDef.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class CustomUIDef : Def
+ {
+ public string portraitPath;
+ public string characterName;
+ public new string description;
+ public List options;
+ }
+
+ public class CustomUIOption
+ {
+ public string label;
+ public List effects;
+ }
+}
diff --git a/Source/WulaFallenEmpire/DebugActions.cs b/Source/WulaFallenEmpire/DebugActions.cs
new file mode 100644
index 00000000..cec64aa5
--- /dev/null
+++ b/Source/WulaFallenEmpire/DebugActions.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using Verse;
+using RimWorld;
+using LudeonTK;
+
+namespace WulaFallenEmpire
+{
+ public static class WulaDebugActions
+ {
+ [DebugAction("Wula Fallen Empire", "Open Custom UI...", actionType = DebugActionType.ToolMap, allowedGameStates = AllowedGameStates.Playing)]
+ private static void OpenCustomUI()
+ {
+ List list = new List();
+ foreach (CustomUIDef localDef in DefDatabase.AllDefs)
+ {
+ // Capture the local variable for the lambda
+ CustomUIDef currentDef = localDef;
+ list.Add(new DebugMenuOption(currentDef.defName, DebugMenuOptionMode.Action, delegate
+ {
+ Find.WindowStack.Add(new Dialog_CustomDisplay(currentDef));
+ }));
+ }
+ Find.WindowStack.Add(new Dialog_DebugOptionListLister(list));
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Dialog_CustomDisplay.cs b/Source/WulaFallenEmpire/Dialog_CustomDisplay.cs
new file mode 100644
index 00000000..d1487557
--- /dev/null
+++ b/Source/WulaFallenEmpire/Dialog_CustomDisplay.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using Verse;
+
+namespace WulaFallenEmpire
+{
+ public class Dialog_CustomDisplay : Window
+ {
+ private CustomUIDef def;
+ private Texture2D portrait;
+
+ public override Vector2 InitialSize => new Vector2(1000f, 750f);
+
+ public Dialog_CustomDisplay(CustomUIDef def)
+ {
+ this.def = def;
+ this.forcePause = true;
+ this.absorbInputAroundWindow = true;
+ this.doCloseX = true; // Add a close button to the window
+ }
+
+ public override void PreOpen()
+ {
+ base.PreOpen();
+ if (!def.portraitPath.NullOrEmpty())
+ {
+ this.portrait = ContentFinder.Get(def.portraitPath);
+ }
+ }
+
+ public override void DoWindowContents(Rect inRect)
+ {
+ // Top-left defName
+ Text.Font = GameFont.Tiny;
+ GUI.color = Color.gray;
+ Widgets.Label(new Rect(0, 0, inRect.width, 30f), def.defName);
+ GUI.color = Color.white;
+ Text.Font = GameFont.Small;
+
+ // Scaling factor to fit the new window size while maintaining layout proportions.
+ float scale = 0.65f;
+
+ // The original CSS was based on a large canvas. We create a virtual canvas inside our window.
+ // Center the main content block.
+ float contentWidth = 1200f * scale;
+ float contentHeight = 1100f * scale;
+ Rect contentRect = new Rect((inRect.width - contentWidth) / 2, (inRect.height - contentHeight) / 2, contentWidth, contentHeight);
+
+ // All original positions are now relative to this contentRect and scaled.
+ Rect mainBodySRect = new Rect(contentRect.x + 200f * scale, contentRect.y + 400f * scale, 1050f * scale, 1000f * scale);
+
+ // lihui (Portrait)
+ Rect lihuiRect = new Rect(mainBodySRect.x - 150f * scale, mainBodySRect.y - 200f * scale, 500f * scale, 800f * scale);
+ if (portrait != null)
+ {
+ GUI.DrawTexture(lihuiRect, portrait, ScaleMode.ScaleToFit);
+ }
+ GUI.color = Color.white;
+ Widgets.DrawBox(lihuiRect);
+ GUI.color = Color.white; // Reset color
+
+
+ // name
+ Rect nameRect = new Rect(lihuiRect.xMax, mainBodySRect.y - 30f * scale, 260f * scale, 130f * scale);
+ GUI.color = Color.white;
+ Widgets.DrawBox(nameRect);
+ GUI.color = Color.white; // Reset color
+ Text.Anchor = TextAnchor.MiddleCenter;
+ Text.Font = GameFont.Medium;
+ Widgets.Label(nameRect, def.characterName);
+ Text.Font = GameFont.Small;
+ Text.Anchor = TextAnchor.UpperLeft;
+
+ // text (Description)
+ Rect textRect = new Rect(nameRect.x, nameRect.yMax + 50f * scale, 650f * scale, 250f * scale);
+ GUI.color = Color.white;
+ Widgets.DrawBox(textRect);
+ GUI.color = Color.white; // Reset color
+ Rect textInnerRect = textRect.ContractedBy(10f * scale);
+ Widgets.Label(textInnerRect, def.description);
+
+ // option (Buttons)
+ Rect optionRect = new Rect(nameRect.x, textRect.yMax, 610f * scale, 300f * scale);
+ // No need to draw a box for the options area, the buttons will be listed inside.
+
+ Listing_Standard listing = new Listing_Standard();
+ listing.Begin(optionRect.ContractedBy(10f * scale));
+ if (def.options != null)
+ {
+ foreach (var option in def.options)
+ {
+ if (listing.ButtonText(option.label))
+ {
+ HandleAction(option.effects);
+ }
+ }
+ }
+ listing.End();
+ }
+
+ private void HandleAction(List effects)
+ {
+ if (effects.NullOrEmpty())
+ {
+ return;
+ }
+
+ foreach (var effect in effects)
+ {
+ effect.Execute(this);
+ }
+ }
+ }
+}
diff --git a/Source/WulaFallenEmpire/Effect.cs b/Source/WulaFallenEmpire/Effect.cs
new file mode 100644
index 00000000..a1fe47e3
--- /dev/null
+++ b/Source/WulaFallenEmpire/Effect.cs
@@ -0,0 +1,90 @@
+using Verse;
+using RimWorld;
+
+namespace WulaFallenEmpire
+{
+ public abstract class Effect
+ {
+ public abstract void Execute(Dialog_CustomDisplay dialog);
+ }
+
+ public class Effect_OpenCustomUI : Effect
+ {
+ public string defName;
+
+ public override void Execute(Dialog_CustomDisplay dialog)
+ {
+ CustomUIDef nextDef = DefDatabase.GetNamed(defName);
+ if (nextDef != null)
+ {
+ Find.WindowStack.Add(new Dialog_CustomDisplay(nextDef));
+ }
+ else
+ {
+ Log.Error($"[WulaFallenEmpire] Effect_OpenCustomUI could not find CustomUIDef named '{defName}'");
+ }
+ }
+ }
+
+ public class Effect_CloseDialog : Effect
+ {
+ public override void Execute(Dialog_CustomDisplay dialog)
+ {
+ dialog.Close();
+ }
+ }
+
+ public class Effect_ShowMessage : Effect
+ {
+ public string message;
+ public MessageTypeDef messageTypeDef;
+
+ public override void Execute(Dialog_CustomDisplay dialog)
+ {
+ if (messageTypeDef == null)
+ {
+ messageTypeDef = MessageTypeDefOf.PositiveEvent;
+ }
+ Messages.Message(message, messageTypeDef);
+ }
+ }
+
+ public class Effect_FireIncident : Effect
+ {
+ public IncidentDef incident;
+
+ public override void Execute(Dialog_CustomDisplay dialog)
+ {
+ if (incident == null)
+ {
+ Log.Error("[WulaFallenEmpire] Effect_FireIncident has a null incident Def.");
+ return;
+ }
+
+ IncidentParms parms = new IncidentParms
+ {
+ target = Find.CurrentMap,
+ forced = true
+ };
+
+ if (!incident.Worker.TryExecute(parms))
+ {
+ Log.Error($"[WulaFallenEmpire] Could not fire incident {incident.defName}");
+ }
+ }
+ }
+
+ public class Effect_ChangeFactionRelation : Effect
+ {
+ public FactionDef faction;
+ public int goodwillChange;
+
+ public override void Execute(Dialog_CustomDisplay dialog)
+ {
+ if (faction == null)
+ {
+ Log.Error("[WulaFallenEmpire] Effect_ChangeFactionRelation has a null faction Def.");
+ return;
+ }
+
+ Faction.OfPlayer.TryAffectGoodwillWith(faction, goodwillChange, canSendMessage: true, canSendHostilityLetter: true, reason: HistoryEventDefOf.QuestGoodwill, lookTarget: null);
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
index 87de747e..b0cbd491 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
+++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj
@@ -102,6 +102,10 @@
+
+
+
+
diff --git a/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs b/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs
index cb6a4608..a7d7479d 100644
--- a/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs
+++ b/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs
@@ -1,6 +1,7 @@
using System;
using System.Reflection;
using HarmonyLib;
+using UnityEngine;
using Verse;
namespace WulaFallenEmpire
@@ -16,5 +17,6 @@ namespace WulaFallenEmpire
Log.Message("[WulaFallenEmpire] Harmony patches applied.");
}
+
}
}