# Wula Fallen Empire - 事件系统文档 这是一个用于在RimWorld中创建复杂、带选项的事件和对话框的强大系统。它由两个主要部分组成:**任务事件** 和 **EventDef事件**。 ## 核心概念 - **Effect(效果)**: 一个原子操作,例如生成一个Pawn、给予一个物品、改变派系关系或打开另一个UI。 - **Condition(条件)**: 一个用于决定一个选项是否可用的逻辑检查(例如,检查一个变量的值)。 - **EventContext(事件上下文)**: 一个全局的静态类,用于存储和检索变量,允许在不同的事件和UI之间传递数据。 --- ## 1. 任务事件 (`QuestNode_Root_EventLetter`) 这是通过RimWorld的原版任务系统触发的事件。它会生成一个带有选项的信件。 ### 如何使用 1. 在你的 `QuestScriptDef` 中,使用 `WulaFallenEmpire.QuestNode_Root_EventLetter` 作为根节点。 2. 在XML中定义 `letterLabel`, `letterTitle`, `letterText`。 3. 在 `` 列表中定义多个选项。每个选项都有一个 `label` 和一个或多个 `effects`。 ### 示例 (`QuestScriptDef`) ```xml Wula_ExampleQuestEvent 一个抉择 远方的呼唤 一个来自遥远星系的信号抵达了你们的通讯站。他们似乎想和你们谈谈。
  • Wula_ExampleEvent
  • 你决定无视这个信号。宇宙的寂静再次笼罩着你。 NeutralEvent
  • ``` --- ## 2. EventDef事件 (`Dialog_CustomDisplay`) 这是一个高度可定制的对话框窗口,可以显示角色肖像、背景、文本和多个带条件的选项。 ### 如何使用 1. 创建一个 `EventDef`。 2. 定义 `label`, `characterName`, `portraitPath`, `descriptions` 等。 3. 在 `` 列表中定义选项。每个选项可以有关联的 `effects` 和 `conditions`。 4. 你可以通过 `Effect_OpenCustomUI` 效果来打开这个UI(从任务事件或其他EventDef)。 5. 你也可以通过将 `CompOpenCustomUI` 附加到一个建筑上来从游戏中直接打开它。 ### `EventDef` 参数 - **defName**: (string) Def的唯一标识符。 - **label**: (string) 窗口的标题。 - **characterName**: (string) (可选) 显示在肖像下方的角色名称。 - **portraitPath**: (string) (可选) 角色肖像的纹理路径。 - **backgroundImagePath**: (string) (可选) 对话框的背景图片路径。 - **descriptions**: (List) 一个描述文本列表。 - **descriptionMode**: (enum) (可选) 决定如何从 `descriptions` 列表中选择文本。可以是 `Random` (默认) 或 `Sequential`。 - **conditionalDescriptions**: (List) (可选) 一个条件描述列表,允许你根据特定条件在主描述后附加额外的文本块。 - **options**: (List) 对话框中显示的选项列表。 - **immediateEffects**: (List) (可选) 当对话框打开时立即执行的效果列表。 - **dismissEffects**: (List) (可选) 当对话框关闭时(通过关闭按钮或`Effect_CloseDialog`)执行的效果列表。 - **windowSize**: (Vector2) (可选) 自定义窗口大小。默认为 `(0, 0)`,表示使用默认大小。 - **hiddenWindow**: (bool) (可选) 如果为 `true`,则不会显示窗口。在这种模式下,`immediateEffects` 的内容会在加载时自动合并到 `dismissEffects` 中,然后在事件触发时作为单个效果链统一执行。这对于创建纯粹的后台“效果链”事件非常有用。默认为 `false`。 ### `EventOption` 参数 每个选项 (`
  • ` in ``) 包含以下字段: - **label**: (string) 选项按钮上显示的文本。 - **optionEffects**: (List) 点击该选项时执行的效果列表。 - **conditions**: (List) (可选) 决定该选项是否可用的条件列表。如果条件不满足,选项会变灰。 - **disabledReason**: (string) (可选) 当选项因不满足 `conditions` 而变灰时,鼠标悬停时显示的提示信息。 - **hideWhenDisabled**: (bool) (可选) 如果为 `true`,当 `conditions` 不满足时,该选项将完全隐藏而不是变灰。默认为 `false`。 ### `ConditionalDescription` 参数 每个条件描述 (`
  • ` in ``) 包含以下字段: - **conditions**: (List) 决定此额外描述是否显示的条件列表。 - **text**: (string) 当条件满足时,要附加到主描述文本末尾的字符串。 ### 关于富文本 (Rich Text) 的使用 在所有面向玩家的文本字段中(如 `label`, `descriptions`, `characterName`, `disabledReason` 等),你都可以使用Unity的富文本标签,例如 ``, ``, ``。 **重要提示**: 由于 `<` 和 `>` 是XML的特殊字符,你必须将所有包含富文本标签的字符串包裹在 `` 块中,以避免XML解析错误。 **正确示例:** ```xml ``` **错误示例 (会导致XML解析失败):** ```xml ``` ### `EventDef` 示例 ```xml Wula_ExampleEvent 特使 Textures/Wula/Events/Portraits/Envoy
  • “你好,来自边缘世界的陌生人。我们观察你很久了。你的挣扎……很有趣。”
  • MetTheEnvoy true
  • PlayerMadeChoice false
  • 你没有做出选择就关闭了通讯。
  • “我们是观察者。我们是见证者。现在,我们是你的未来。”
  • 他们似乎对你不够信任。
  • EmpireGoodwill 50
  • IsGenerous true
  • Gold 200
  • Gold 100
  • ``` ### UI 布局配置 (`EventUIConfigDef`) 你可以在 `1.6/Defs/WulaMiscSettingDefs/EventUIConfig.xml` 中调整所有EventDef窗口的默认外观和布局。 --- ## 3. 核心结构: 条件化效果 (`ConditionalEffects`) 所有执行效果的地方 (`immediateEffects`, `dismissEffects`, 以及每个选项的 `optionEffects`) 都是一个 `ConditionalEffects` 块的列表。 这允许你将一组效果与一组条件绑定在一起。 ### `ConditionalEffects` 结构 每个 `
  • ` 代表一个 `ConditionalEffects` 块。它包含两个可选部分: - **``**: 一个条件列表。只有当这里的所有条件都满足时,对应的效果才会执行。如果省略这个部分,效果将总是执行。 - **``**: 一个效果列表。当条件满足时,这些效果会被执行。 ```xml
  • PlayerChoice AcceptedOffer
  • 你接受了提议!
  • Silver 500
  • ``` --- ## 4. 可用的效果 (`Effect`) 这些是可以在 `ConditionalEffects` 块的 `` 列表中使用的类。 ### `Effect_OpenCustomUI` 打开一个指定的 `EventDef`。 - **defName**: (string) 要打开的 `EventDef` 的 `defName`。 ```xml
  • Wula_AnotherEvent
  • ``` ### `Effect_CloseDialog` 关闭当前的EventDef窗口。没有参数。 ```xml
  • ``` ### `Effect_ShowMessage` 在屏幕上显示一条消息。 - **message**: (string) 要显示的消息文本。 - **messageTypeDef**: (MessageTypeDef) 消息的类型 (例如 `PositiveEvent`, `NegativeEvent`, `NeutralEvent`)。默认为 `PositiveEvent`。 ```xml
  • 你获得了一个新的盟友。 PositiveEvent
  • ``` ### `Effect_FireIncident` 触发一个指定的事件。 - **incident**: (IncidentDef) 要触发的事件的 `defName`。 ```xml
  • RaidEnemy
  • ``` ### `Effect_ChangeFactionRelation` 改变玩家与某个派系的关系。 - **faction**: (FactionDef) 目标派系的 `defName`。 - **goodwillChange**: (int) 关系值的变化量(可以是负数)。 ```xml
  • WulaFallenEmpire_Player 15
  • ``` ### `Effect_ChangeFactionRelation_FromVariable` 根据一个变量的值改变派系关系。 - **faction**: (FactionDef) 目标派系的 `defName`。 - **goodwillVariableName**: (string) 存储关系变化值的变量名。 ```xml
  • WulaFallenEmpire_Player ReputationChange
  • ``` ### `Effect_GiveThing` 给玩家一些物品(通过空投)。 - **thingDef**: (ThingDef) 要给予的物品的 `defName`。 - **count**: (int) 给予的数量。默认为 1。 ```xml
  • Plasteel 150
  • ``` ### `Effect_SpawnPawn` 生成一个Pawn。 - **kindDef**: (PawnKindDef) 要生成的Pawn的 `defName`。 - **count**: (int) 生成的数量。默认为 1。 - **joinPlayerFaction**: (bool) 是否加入玩家派系。默认为 `true`。 - **letterLabel**: (string) 可选,生成时附带的信件标题。 - **letterText**: (string) 可选,生成时附带的信件内容。 - **letterDef**: (LetterDef) 可选,信件的类型。 ```xml
  • Colonist 1 true 一个新人加入了! 一个流浪者被你们的善举所吸引,决定加入你们的殖民地。
  • ``` ### `Effect_SpawnPawnAndStore` 生成一个Pawn并将其存储在一个变量中以备后用。 - **kindDef**: (PawnKindDef) 要生成的Pawn的 `defName`。 - **count**: (int) 生成的数量。默认为 1。 - **storeAs**: (string) 用于存储生成Pawn的变量名。如果 `count` 大于1,则存储一个Pawn列表。 ```xml
  • Wula_Elite_Warrior spawnedWarrior
  • ``` ### `Effect_AddQuest` 触发一个新的任务。 - **quest**: (QuestScriptDef) 要开始的任务的 `defName`。 ```xml
  • Wula_AnotherQuest
  • ``` ### `Effect_FinishResearch` 立即完成一个研究项目。 - **research**: (ResearchProjectDef) 要完成的研究的 `defName`。 ```xml
  • MicroelectronicsBasics
  • ``` ### `Effect_TriggerRaid` 触发一次袭击。这个效果有两种模式: 1. **简单模式**: 使用派系默认的袭击队伍。 2. **高级模式**: 使用动态定义的 `pawnGroupMakers` 来生成自定义的袭击队伍。 - **points**: (float) 袭击的点数。 - **faction**: (FactionDef) 袭击者的派系 `defName`。 - **raidStrategy**: (RaidStrategyDef) 袭击策略的 `defName` (例如 `ImmediateAttack`)。 - **raidArrivalMode**: (PawnsArrivalModeDef) 袭击者到达方式的 `defName` (例如 `EdgeWalkIn`)。 - **groupKind**: (PawnGroupKindDef) (高级模式) 定义队伍类型,例如 `Combat` 或 `Trader`。默认为 `Combat`。 - **pawnGroupMakers**: (List) (高级模式) 一个 `PawnGroupMaker` 列表,用于动态定义袭击队伍的构成。 - **letterLabel**: (string) (可选) 自定义袭击信件的标题。如果提供,将覆盖默认的 "Raid" 标题。 - **letterText**: (string) (可选) 自定义袭击信件的内容。如果提供,将覆盖默认的袭击描述文本。 **简单模式示例:** ```xml
  • 500 Pirate ImmediateAttack EdgeWalkIn 侦测到威胁! 我们的传感器侦测到一伙来自 {FACTION_name} 的袭击者!他们看起来充满敌意,正朝着我们的殖民地前进。
  • ``` **高级模式示例:** ```xml
  • 1000 WulaFallenEmpire_Player ImmediateAttack EdgeWalkIn Combat
  • Combat 100 20 20 2 1
  • ``` ### `Effect_SetVariable` **仅在变量尚不存在时**,设置一个 `EventContext` 变量的值。这使得它非常适合用于安全地初始化变量,而不用担心覆盖现有值。 - **name**: (string) 变量名。 - **value**: (string) 变量的初始值。系统会自动尝试将其解析为 `int` 或 `float`,如果失败则作为 `string` 存储。 ```xml
  • MetTheEnvoy true
  • ``` ### `Effect_ModifyVariable` 对一个数字变量进行数学运算或直接赋值。如果变量不存在,会先将其初始化为0,然后再执行操作。 - **name**: (string) 变量名。 - **value**: (float) 用于操作的数值。 - **operation**: (VariableOperation) 操作类型,可以是 `Add`, `Subtract`, `Multiply`, `Divide`, `Set`。 - `Set`: 直接将变量的值设置为 `value`,会覆盖任何现有值。 **加法示例:** ```xml
  • ResourceCount -10 Add
  • ``` **直接设置值示例:** ```xml
  • ResourceCount 100 Set
  • ``` ### `Effect_ClearVariable` 从 `EventContext` 中移除一个变量。 - **name**: (string) 要清除的变量名。 ```xml
  • PlayerChoice
  • ``` ### `Effect_CheckFactionGoodwill` 检查玩家与某个派系的好感度,并将其存储在一个变量中。 - **factionDef**: (FactionDef) 要检查的派系的 `defName`。 - **variableName**: (string) 用于存储好感度数值的变量名。 ```xml
  • Mechanoid MechanoidGoodwill
  • ``` ### `Effect_CallSkyfaller` 在玩家殖民地附近呼叫一个skyfaller。 - **checkClearance**: 确保落点附近X格内净空。 ```xml
  • DropPodIncoming 180 true 4 空投舱已呼叫 轨道空投舱已在途中,预计3秒后抵达。
  • ``` --- ## 4. 可用的条件 (`Condition`) 这些是可以在 `conditions` 列表中使用的类,用于控制选项的可用性。 ### `Condition_VariableEquals` 检查一个变量是否等于一个特定值。 - **name**: (string) 要检查的变量名。 - **value**: (string) 要比较的字面值。 - **valueVariableName**: (string) (可选) 要比较的另一个变量的名称。如果提供此项,则忽略 `value`。 ```xml
  • PlayerChoice AcceptedOffer
  • ``` ### `Condition_VariableNotEqual` 检查一个变量是否 **不等于** 一个特定值。 ```xml
  • QuestStage 3
  • ``` ### `Condition_CompareVariable` (基类) 这是一个抽象基类,不应直接使用。以下所有比较条件(大于、小于等)都继承自这个基类,并共享其参数。 **基类参数:** - **name**: (string) 要检查的变量名。 - **value**: (float) 要比较的字面数值。 - **valueVariableName**: (string) (可选) 要比较的另一个变量的名称。如果提供此项,则会忽略 `value` 字段。 **工作原理:** 当你使用例如 `Condition_VariableGreaterThan` 时,你实际上是在使用一个 `Condition_CompareVariable` 的特定版本。你可以提供 `value` 来与一个固定的数字比较,或者提供 `valueVariableName` 来与另一个变量的值进行比较。 **变量与变量比较示例:** 下面的例子使用了 `Condition_VariableGreaterThanOrEqual`(它是 `Condition_CompareVariable` 的子类),来检查 `PlayerWealth` 变量是否大于或等于 `RequiredWealth` 变量。 ```xml
  • PlayerWealth RequiredWealth
  • ``` ### `Condition_VariableGreaterThan` 检查一个变量是否 **大于** 一个特定值。 ```xml
  • ColonistCount 5
  • ``` ### `Condition_VariableLessThan` 检查一个变量是否 **小于** 一个特定值。 ```xml
  • ThreatPoints 1000
  • ``` ### `Condition_VariableGreaterThanOrEqual` 检查一个变量是否 **大于或等于** 一个特定值。 ```xml
  • EmpireGoodwill 50
  • ``` ### `Condition_VariableLessThanOrEqual` 检查一个变量是否 **小于或等于** 一个特定值。 ```xml
  • YearsPassed 2
  • ``` --- --- ### `Condition_FactionExists` 检查一个派系当前是否存在于游戏中。 - **factionDef**: (FactionDef) 要检查的派系的 `defName`。 ```xml
  • Pirate
  • ```