diff --git a/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/Assemblies/WulaFallenEmpire.dll index 74c54aec..29cc4e92 100644 Binary files a/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/Defs/ConfigDefs/EventUIConfig.xml b/1.6/Defs/ConfigDefs/EventUIConfig.xml new file mode 100644 index 00000000..a03791be --- /dev/null +++ b/1.6/Defs/ConfigDefs/EventUIConfig.xml @@ -0,0 +1,24 @@ + + + + + Wula_EventUIConfig + + + Small + true + + + + (500, 800) + (260, 130) + (650, 500) + 610 + + + 20 + 20 + + + + diff --git a/1.6/Defs/CustomUIDefs/CustomUI_Example.xml b/1.6/Defs/CustomUIDefs/CustomUI_Example.xml index 26cde88f..7c5ae061 100644 --- a/1.6/Defs/CustomUIDefs/CustomUI_Example.xml +++ b/1.6/Defs/CustomUIDefs/CustomUI_Example.xml @@ -4,7 +4,7 @@ Wula_ExampleUI - + UI/HeroArt/Storytellers/Randy 兰迪·随机 这是一个事件链的开端。选择第一个选项将会打开第二个事件窗口。 diff --git a/Documentation/EventSystem_Documentation.md b/Documentation/EventSystem_Documentation.md index cbf1a381..2613f96d 100644 --- a/Documentation/EventSystem_Documentation.md +++ b/Documentation/EventSystem_Documentation.md @@ -9,10 +9,49 @@ - **`Effect`**: 定义一个选项被点击后执行的具体动作(例如,给予物品、改变关系、打开新窗口等)。 - **`Condition`**: 定义一个选项是否可选的前提条件(例如,需要某个变量达到特定值)。 - **`EventContext`**: 一个全局的静态变量存储系统,允许在不同事件和效果之间传递数据。 +- **`EventUIConfigDef`**: 一个全局的外观和布局配置文件,用于统一管理所有事件窗口的视觉风格。 --- -## 2. 如何创建事件 (`CustomUIDef`) +## 2. 全局UI配置 (`EventUIConfigDef`) + +为了方便统一修改所有事件窗口的外观和布局,系统使用一个单例的 `EventUIConfigDef`。你应该在 `Defs` 文件夹下创建一个XML文件来定义它。 + +**文件示例 (`1.6/Defs/ConfigDefs/EventUIConfig.xml`):** +```xml + + + Wula_EventUIConfig + + + Small + true + UI/Backgrounds/DefaultBG + + + (500, 800) + (260, 130) + (650, 500) + 610 + + + 20 + 20 + + + +``` + +**字段说明:** +- `labelFont`: 事件标题 (`label`) 的字体大小。可选值: `Tiny`, `Small`, `Medium`, `Large`。 +- `drawBorders`: 是否为立绘、名称和描述区域绘制白色边框。 +- `defaultBackgroundImagePath`: 所有事件窗口默认使用的背景图路径。 +- `lihuiSize`, `nameSize`, `textSize`, `optionsWidth`: 定义了UI各部分的基础虚拟尺寸,代码会根据窗口大小按比例缩放它们。 +- `textNameOffset`, `optionsTextOffset`: 定义了各部分之间的垂直间距。 + +--- + +## 3. 如何创建事件 (`CustomUIDef`) 每个事件都是一个 `CustomUIDef`。你需要在一个 `Defs` XML文件中定义它。 @@ -34,15 +73,16 @@ **字段说明:** - `defName`: 事件的唯一ID,用于在代码或其他事件中引用它。 -- `label`: 显示在窗口顶部的标题(当前版本未在UI中显示,但建议填写)。 +- `label`: 显示在窗口左上角的标题。 - `portraitPath`: 立绘的纹理路径(相对于`Resources`或`Textures`目录)。 - `characterName`: 显示在名称框中的文本。 +- `backgroundImagePath`: (可选)为此特定事件指定的背景图路径,它会覆盖 `EventUIConfigDef` 中的默认背景。 - `description`: 显示在描述框中的主要文本。 - `options`: 一个 `
  • ` 列表,定义了所有的交互选项。 --- -## 3. 核心概念:选项 (`CustomUIOption`) +## 4. 核心概念:选项 (`CustomUIOption`) 每个选项都在 `` 列表中的一个 `
  • ` 标签内定义。 @@ -54,13 +94,13 @@ --- -## 4. 核心概念:效果 (`Effect`) +## 5. 核心概念:效果 (`Effect`) 效果定义了“做什么”。每个效果都在 `effects` 列表中的一个 `
  • ` 标签内定义,并且必须有一个 `Class` 属性。 ### 已实现的 `Effect` 列表 -#### 4.1 `Effect_OpenCustomUI` +#### 5.1 `Effect_OpenCustomUI` - **功能**: 打开另一个自定义UI事件窗口。 - **Class**: `WulaFallenEmpire.Effect_OpenCustomUI` - **字段**: @@ -72,7 +112,7 @@
  • ``` -#### 4.2 `Effect_CloseDialog` +#### 5.2 `Effect_CloseDialog` - **功能**: 关闭当前的事件窗口。 - **Class**: `WulaFallenEmpire.Effect_CloseDialog` - **字段**: 无 @@ -81,7 +121,7 @@
  • ``` -#### 4.3 `Effect_ShowMessage` +#### 5.3 `Effect_ShowMessage` - **功能**: 在屏幕左上角显示一条游戏消息。 - **Class**: `WulaFallenEmpire.Effect_ShowMessage` - **字段**: @@ -95,7 +135,7 @@
  • ``` -#### 4.4 `Effect_FireIncident` +#### 5.4 `Effect_FireIncident` - **功能**: 触发一个原版或Mod添加的游戏内事件。 - **Class**: `WulaFallenEmpire.Effect_FireIncident` - **字段**: @@ -107,7 +147,7 @@ ``` -#### 4.5 `Effect_ChangeFactionRelation` +#### 5.5 `Effect_ChangeFactionRelation` - **功能**: 改变与指定派系的好感度。 - **Class**: `WulaFallenEmpire.Effect_ChangeFactionRelation` - **字段**: @@ -121,7 +161,7 @@ ``` -#### 4.6 `Effect_SetVariable` +#### 5.6 `Effect_SetVariable` - **功能**: 在 `EventContext` 中设置或修改一个变量的值。 - **Class**: `WulaFallenEmpire.Effect_SetVariable` - **字段**: @@ -135,15 +175,50 @@ ``` +#### 5.7 `Effect_GiveThing` +- **功能**: 给予玩家一个或多个物品。 +- **Class**: `WulaFallenEmpire.Effect_GiveThing` +- **字段**: + - `thingDef`: (必须) 要给予物品的 `ThingDef` 的 `defName`。 + - `count`: (可选) 给予的数量,默认为 1。 +- **示例**: + ```xml +
  • + Silver + 100 +
  • + ``` + +#### 5.8 `Effect_SpawnPawn` +- **功能**: 在地图上生成一个或多个Pawn,并可选地发送一封信件通知玩家。 +- **Class**: `WulaFallenEmpire.Effect_SpawnPawn` +- **字段**: + - `kindDef`: (必须) 要生成Pawn的 `PawnKindDef` 的 `defName`。 + - `count`: (可选) 生成的数量,默认为 1。 + - `joinPlayerFaction`: (可选) Pawn是否加入玩家派系,默认为 `true`。 + - `letterLabel`: (可选) 通知信件的标题。 + - `letterText`: (可选) 通知信件的内容。 + - `letterDef`: (可选) 通知信件的类型 (例如 `PositiveEvent`, `NegativeEvent`)。默认为 `PositiveEvent`。 +- **示例**: + ```xml +
  • + Colonist + 1 + true + A New Colonist + {PAWN_nameDef} has decided to join your colony. +
  • + ``` + --- -## 5. 核心概念:条件 (`Condition`) +## 6. 核心概念:条件 (`Condition`) 条件定义了选项是否可选的“前提”。每个条件都在 `conditions` 列表中的一个 `
  • ` 标签内定义,并且必须有一个 `Class` 属性。 ### 已实现的 `Condition` 列表 -#### 5.1 `Condition_VariableEquals` +#### 6.1 `Condition_VariableEquals` - **功能**: 检查一个变量是否等于指定的值。 - **Class**: `WulaFallenEmpire.Condition_VariableEquals` - **字段**: @@ -157,7 +232,7 @@
  • ``` -#### 5.2 `Condition_VariableGreaterThan` +#### 6.2 `Condition_VariableGreaterThan` - **功能**: 检查一个变量是否大于指定的值。 - **Class**: `WulaFallenEmpire.Condition_VariableGreaterThan` - **字段**: @@ -173,7 +248,7 @@ --- -## 6. 核心概念:变量系统 (`EventContext`) +## 7. 核心概念:变量系统 (`EventContext`) `EventContext` 是一个全局的静态字典,用于在事件链的不同部分之间传递信息。 @@ -185,7 +260,7 @@ --- -## 7. 完整示例 +## 8. 完整示例 以下是一个演示了事件链、变量和条件的完整示例。 diff --git a/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo b/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo index 653b39b7..9e11ffcd 100644 Binary files a/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo and b/Source/WulaFallenEmpire/.vs/WulaFallenEmpire/v17/.suo differ diff --git a/Source/WulaFallenEmpire/Condition.cs b/Source/WulaFallenEmpire/EventSystem/Condition.cs similarity index 98% rename from Source/WulaFallenEmpire/Condition.cs rename to Source/WulaFallenEmpire/EventSystem/Condition.cs index d898b4cc..0e9e1a7d 100644 --- a/Source/WulaFallenEmpire/Condition.cs +++ b/Source/WulaFallenEmpire/EventSystem/Condition.cs @@ -1,4 +1,5 @@ using Verse; +using RimWorld; namespace WulaFallenEmpire { @@ -61,4 +62,5 @@ namespace WulaFallenEmpire return met; } } + } diff --git a/Source/WulaFallenEmpire/CustomUIDef.cs b/Source/WulaFallenEmpire/EventSystem/CustomUIDef.cs similarity index 87% rename from Source/WulaFallenEmpire/CustomUIDef.cs rename to Source/WulaFallenEmpire/EventSystem/CustomUIDef.cs index 438c69d4..ecfafaf5 100644 --- a/Source/WulaFallenEmpire/CustomUIDef.cs +++ b/Source/WulaFallenEmpire/EventSystem/CustomUIDef.cs @@ -9,6 +9,7 @@ namespace WulaFallenEmpire public string characterName; public new string description; public List options; + public string backgroundImagePath; // Override default background } public class CustomUIOption diff --git a/Source/WulaFallenEmpire/Dialog_CustomDisplay.cs b/Source/WulaFallenEmpire/EventSystem/Dialog_CustomDisplay.cs similarity index 64% rename from Source/WulaFallenEmpire/Dialog_CustomDisplay.cs rename to Source/WulaFallenEmpire/EventSystem/Dialog_CustomDisplay.cs index 21207fdc..49d95f75 100644 --- a/Source/WulaFallenEmpire/Dialog_CustomDisplay.cs +++ b/Source/WulaFallenEmpire/EventSystem/Dialog_CustomDisplay.cs @@ -9,6 +9,20 @@ namespace WulaFallenEmpire { private CustomUIDef def; private Texture2D portrait; + private Texture2D background; + + private static EventUIConfigDef config; + public static EventUIConfigDef Config + { + get + { + if (config == null) + { + config = DefDatabase.GetNamed("Wula_EventUIConfig"); + } + return config; + } + } public override Vector2 InitialSize => new Vector2(1000f, 750f); @@ -25,62 +39,77 @@ namespace WulaFallenEmpire base.PreOpen(); if (!def.portraitPath.NullOrEmpty()) { - this.portrait = ContentFinder.Get(def.portraitPath); + portrait = ContentFinder.Get(def.portraitPath); + } + + string bgPath = !def.backgroundImagePath.NullOrEmpty() ? def.backgroundImagePath : Config.defaultBackgroundImagePath; + if (!bgPath.NullOrEmpty()) + { + background = ContentFinder.Get(bgPath); } } public override void DoWindowContents(Rect inRect) { - // Top-left defName and Label + // 1. Draw Background + if (background != null) + { + GUI.DrawTexture(inRect, background, ScaleMode.ScaleToFit); + } + + // 2. Draw Top-left defName and Label Text.Font = GameFont.Tiny; GUI.color = Color.gray; Widgets.Label(new Rect(5, 5, inRect.width - 10, 20f), def.defName); GUI.color = Color.white; - Text.Font = GameFont.Small; + Text.Font = Config.labelFont; Widgets.Label(new Rect(5, 20f, inRect.width - 10, 30f), def.label); + Text.Font = GameFont.Small; // Reset to default + // 3. Calculate Layout based on ConfigDef + float virtualWidth = Config.lihuiSize.x + Config.textSize.x; + float virtualHeight = Config.lihuiSize.y; - // Define virtual total size from the CSS layout - float virtualWidth = 500f + 650f; // lihui + text - float virtualHeight = 800f; // lihui height - - // Calculate scale to fit the window, maintaining aspect ratio float scaleX = inRect.width / virtualWidth; float scaleY = inRect.height / virtualHeight; - float scale = Mathf.Min(scaleX, scaleY) * 0.95f; // Use 95% of space to leave some margin + float scale = Mathf.Min(scaleX, scaleY) * 0.95f; - // Calculate scaled dimensions - float scaledLihuiWidth = 500f * scale; - float scaledLihuiHeight = 800f * scale; - float scaledNameWidth = 260f * scale; - float scaledNameHeight = 130f * scale; - float scaledTextWidth = 650f * scale; - float scaledTextHeight = 250f * scale; - float scaledOptionsWidth = 610f * scale; + float scaledLihuiWidth = Config.lihuiSize.x * scale; + float scaledLihuiHeight = Config.lihuiSize.y * scale; + float scaledNameWidth = Config.nameSize.x * scale; + float scaledNameHeight = Config.nameSize.y * scale; + float scaledTextWidth = Config.textSize.x * scale; + float scaledTextHeight = Config.textSize.y * scale; + float scaledOptionsWidth = Config.optionsWidth * scale; - // Center the whole content block float totalContentWidth = scaledLihuiWidth + scaledTextWidth; float totalContentHeight = scaledLihuiHeight; float startX = (inRect.width - totalContentWidth) / 2; float startY = (inRect.height - totalContentHeight) / 2; + // 4. Draw UI Elements // lihui (Portrait) Rect lihuiRect = new Rect(startX, startY, scaledLihuiWidth, scaledLihuiHeight); if (portrait != null) { GUI.DrawTexture(lihuiRect, portrait, ScaleMode.ScaleToFit); } - GUI.color = Color.white; - Widgets.DrawBox(lihuiRect); - GUI.color = Color.white; // Reset color - + if (Config.drawBorders) + { + GUI.color = Color.white; + Widgets.DrawBox(lihuiRect); + GUI.color = Color.white; + } // name Rect nameRect = new Rect(lihuiRect.xMax, lihuiRect.y, scaledNameWidth, scaledNameHeight); - GUI.color = Color.white; - Widgets.DrawBox(nameRect); - GUI.color = Color.white; // Reset color + if (Config.drawBorders) + { + GUI.color = Color.white; + Widgets.DrawBox(nameRect); + GUI.color = Color.white; + } Text.Anchor = TextAnchor.MiddleCenter; Text.Font = GameFont.Medium; Widgets.Label(nameRect, def.characterName); @@ -88,15 +117,18 @@ namespace WulaFallenEmpire Text.Anchor = TextAnchor.UpperLeft; // text (Description) - Rect textRect = new Rect(nameRect.x, nameRect.yMax + 20f * scale, scaledTextWidth, scaledTextHeight); - GUI.color = Color.white; - Widgets.DrawBox(textRect); - GUI.color = Color.white; // Reset color + Rect textRect = new Rect(nameRect.x, nameRect.yMax + Config.textNameOffset * scale, scaledTextWidth, scaledTextHeight); + if (Config.drawBorders) + { + GUI.color = Color.white; + Widgets.DrawBox(textRect); + GUI.color = Color.white; + } Rect textInnerRect = textRect.ContractedBy(10f * scale); Widgets.Label(textInnerRect, def.description); // option (Buttons) - Rect optionRect = new Rect(nameRect.x, textRect.yMax + 20f * scale, scaledOptionsWidth, lihuiRect.height - nameRect.height - textRect.height - 40f * scale); + Rect optionRect = new Rect(nameRect.x, textRect.yMax + Config.optionsTextOffset * scale, scaledOptionsWidth, lihuiRect.height - nameRect.height - textRect.height - (Config.textNameOffset + Config.optionsTextOffset) * scale); // No need to draw a box for the options area, the buttons will be listed inside. Listing_Standard listing = new Listing_Standard(); diff --git a/Source/WulaFallenEmpire/Effect.cs b/Source/WulaFallenEmpire/EventSystem/Effect.cs similarity index 63% rename from Source/WulaFallenEmpire/Effect.cs rename to Source/WulaFallenEmpire/EventSystem/Effect.cs index a078daee..78115c8f 100644 --- a/Source/WulaFallenEmpire/Effect.cs +++ b/Source/WulaFallenEmpire/EventSystem/Effect.cs @@ -186,4 +186,86 @@ namespace WulaFallenEmpire } } } + + public class Effect_GiveThing : Effect + { + public ThingDef thingDef; + public int count = 1; + + public override void Execute(Dialog_CustomDisplay dialog) + { + if (thingDef == null) + { + Log.Error("[WulaFallenEmpire] Effect_GiveThing has a null thingDef."); + return; + } + + Map currentMap = Find.CurrentMap; + if (currentMap == null) + { + Log.Error("[WulaFallenEmpire] Effect_GiveThing cannot execute without a current map."); + return; + } + + Thing thing = ThingMaker.MakeThing(thingDef); + thing.stackCount = count; + + IntVec3 dropCenter = DropCellFinder.TradeDropSpot(currentMap); + DropPodUtility.DropThingsNear(dropCenter, currentMap, new List { thing }, 110, false, false, false, false); + + Messages.Message("LetterLabelCargoPodCrash".Translate(), new TargetInfo(dropCenter, currentMap), MessageTypeDefOf.PositiveEvent); + } + } + + public class Effect_SpawnPawn : Effect + { + public PawnKindDef kindDef; + public int count = 1; + public bool joinPlayerFaction = true; + public string letterLabel; + public string letterText; + public LetterDef letterDef; + + public override void Execute(Dialog_CustomDisplay dialog) + { + if (kindDef == null) + { + Log.Error("[WulaFallenEmpire] Effect_SpawnPawn has a null kindDef."); + return; + } + + Map map = Find.CurrentMap; + if (map == null) + { + Log.Error("[WulaFallenEmpire] Effect_SpawnPawn cannot execute without a current map."); + return; + } + + for (int i = 0; i < count; i++) + { + Faction faction = joinPlayerFaction ? Faction.OfPlayer : null; + PawnGenerationRequest request = new PawnGenerationRequest( + kindDef, faction, PawnGenerationContext.NonPlayer, -1, true, false, false, false, + true, 20f, false, true, false, true, true, false, false, false, false, 0f, 0f, null, 1f, + null, null, null, null, null, null, null, null, null, null, null, null, false + ); + Pawn pawn = PawnGenerator.GeneratePawn(request); + + if (!CellFinder.TryFindRandomEdgeCellWith((IntVec3 c) => map.reachability.CanReachColony(c) && !c.Fogged(map), map, CellFinder.EdgeRoadChance_Neutral, out IntVec3 cell)) + { + cell = DropCellFinder.RandomDropSpot(map); + } + + GenSpawn.Spawn(pawn, cell, map, WipeMode.Vanish); + + if (!string.IsNullOrEmpty(letterLabel) && !string.IsNullOrEmpty(letterText)) + { + TaggedString finalLabel = letterLabel.Formatted(pawn.Named("PAWN")).AdjustedFor(pawn); + TaggedString finalText = letterText.Formatted(pawn.Named("PAWN")).AdjustedFor(pawn); + PawnRelationUtility.TryAppendRelationsWithColonistsInfo(ref finalText, ref finalLabel, pawn); + Find.LetterStack.ReceiveLetter(finalLabel, finalText, letterDef ?? LetterDefOf.PositiveEvent, pawn); + } + } + } + } } diff --git a/Source/WulaFallenEmpire/EventContext.cs b/Source/WulaFallenEmpire/EventSystem/EventContext.cs similarity index 100% rename from Source/WulaFallenEmpire/EventContext.cs rename to Source/WulaFallenEmpire/EventSystem/EventContext.cs diff --git a/Source/WulaFallenEmpire/EventSystem/EventUIConfigDef.cs b/Source/WulaFallenEmpire/EventSystem/EventUIConfigDef.cs new file mode 100644 index 00000000..c14a18de --- /dev/null +++ b/Source/WulaFallenEmpire/EventSystem/EventUIConfigDef.cs @@ -0,0 +1,23 @@ +using UnityEngine; +using Verse; + +namespace WulaFallenEmpire +{ + public class EventUIConfigDef : Def + { + // General Style + public GameFont labelFont = GameFont.Small; + public bool drawBorders = true; + public string defaultBackgroundImagePath; + + // Virtual Layout Dimensions + public Vector2 lihuiSize = new Vector2(500f, 800f); + public Vector2 nameSize = new Vector2(260f, 130f); + public Vector2 textSize = new Vector2(650f, 500f); + public float optionsWidth = 610f; + + // Virtual Layout Offsets + public float textNameOffset = 20f; + public float optionsTextOffset = 20f; + } +} diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 9bb016c8..4e55959b 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -102,12 +102,13 @@ - - - - - + + + + + +