CK3 Mod 开发入门教程:从 Mod 组成开始

2026-05-05 默认分类
  • 12
  • 0
  • 0
CK3 Mod 开发入门教程:从 Mod 组成开始

很多玩家第一次接触《Crusader Kings III》的 Mod 开发时,最容易产生的误解是:Mod 开发是不是必须会编程?是不是要懂 C++、Python、Lua,甚至要能改游戏底层?实际上,对于 CK3 绝大多数常见 Mod 来说,答案是否定的。CK3 的 Mod 开发主要依赖 Paradox 自己的一套脚本体系,开发者通过修改文本文件、定义配置、编写触发条件、效果逻辑、本地化文本和界面资源,就可以改变游戏中的大量内容。CK3 Wiki 也明确提到,CK3 Modding 不要求掌握传统编程语言,大多数内容都可以用普通文本编辑器完成,但它使用的是游戏自己的脚本语言,因此也会受到这套脚本体系本身的限制。

这意味着,CK3 Mod 开发更像是在“阅读并重组游戏规则”,而不是从零写一个游戏。你要做的事情,不是自己造一个王国模拟器,而是在 CK3 已经提供好的框架里,理解游戏文件是如何组织的,理解角色、头衔、事件、决议、互动、特质、法律、政体、文化、宗教、战争、脚本效果这些系统之间如何联动,然后用自己的规则去覆盖、扩展或新增内容。

对于初学者来说,最重要的不是一上来就写复杂事件链,也不是一开始就尝试做大型全转化 Mod,而是先搞清楚一个 CK3 Mod 到底由哪些部分组成,每一类文件负责什么,游戏是如何读取这些文件的,以及当你写错一个括号、一个 key、一个路径、一个本地化编码时,应该从哪里排查问题。

这篇教程会从最基础的 Mod 组成开始讲起。你可以把它看成 CK3 Mod 开发的第一课:先认识门,再走进屋子,最后再开始装修。

一、CK3 Mod 的本质是什么

CK3 的 Mod,本质上是一组放在指定目录下的文件集合。它可以新增游戏内容,也可以修改原版内容,还可以覆盖某些原有规则。小到一个特质、一条本地化文本、一张图标,大到一个完整政体、全新地图、全新宗教体系、全新历史剧本,都属于 Mod 的范畴。

从结构上说,一个 CK3 Mod 通常由两部分组成:一份描述文件,以及一个真正存放 Mod 内容的文件夹。CK3 Wiki 的 Mod structure 页面也说明,每个 Mod 都需要这两部分,并且它们需要位于 CK3 的 mod 目录下,二者之间通过名称和路径进行关联。

描述文件通常叫做 .mod 文件,它告诉启动器和游戏:这个 Mod 叫什么、版本是多少、路径在哪里、支持哪个游戏版本、有哪些标签、是否包含远程上传信息等。真正的 Mod 文件夹则存放你写的所有内容,比如 commoneventslocalizationgfxguihistorymap_data 等目录。

可以用一个非常简单的比喻来理解:.mod 文件像是门牌和身份证,告诉游戏“这里有一个 Mod,它叫这个名字,内容在这个位置”;Mod 文件夹则是真正的房子,里面装着你的脚本、文本、图片、事件和规则。

如果 .mod 文件写错了,游戏可能根本找不到你的 Mod。如果 Mod 文件夹结构写错了,游戏可能能加载 Mod,但不会读取你的内容。如果脚本文件写错了,轻则功能失效,重则游戏报错、闪退或出现大量日志错误。所以 CK3 Mod 开发第一步,不是写功能,而是把结构搭对。

二、Mod 的存放位置

在 Windows 系统中,CK3 的本地 Mod 通常存放在:

文档\Paradox Interactive\Crusader Kings III\mod

也就是常见路径:

C:\Users\你的用户名\Documents\Paradox Interactive\Crusader Kings III\mod

如果你的系统文档目录被 OneDrive 接管,路径可能会变成:

C:\Users\你的用户名\OneDrive\Documents\Paradox Interactive\Crusader Kings III\mod

这里需要特别注意,很多新手 Mod 不生效,不是因为代码写错,而是因为文件放错了地方。尤其是中文 Windows 用户,经常会遇到“文档”目录被 OneDrive 或系统重定向的问题。如果你在一个目录里创建了 Mod,但启动器读取的是另一个目录,那么你改半天也不会生效。

最简单的判断方式是:你打开 Paradox Launcher 创建一个本地 Mod,然后看它自动生成在哪里。以后你所有本地开发的 Mod,都尽量放在这个目录下。

一个标准的 Mod 目录可能长这样:

Crusader Kings III
└── mod
    ├── zhuge_menu.mod
    └── zhuge_menu
        ├── descriptor.mod
        ├── common
        ├── events
        ├── localization
        ├── gfx
        └── gui

这里有两个容易混淆的文件:外面的 zhuge_menu.mod 和里面的 descriptor.mod。外面的 .mod 文件用于让启动器识别 Mod;里面的 descriptor.mod 通常用于记录 Mod 自身的描述信息,在上传到 Steam 创意工坊或 Paradox Mods 时也会用到。二者内容经常相似,但位置不同,作用也不完全一样。

一个简单的外部 .mod 文件可以这样写:

version="1.0"
tags={
    "Gameplay"
    "Utilities"
}
name="Zhuge Game Menu"
supported_version="1.17.*"
path="mod/zhuge_menu"

其中 name 是启动器显示的 Mod 名称,path 是 Mod 文件夹路径,supported_version 是支持的游戏版本。这里的路径要特别小心,大小写、斜杠、文件夹名都不要写错。

很多人喜欢把 Mod 文件夹改成中文名,这并不是绝对不行,但我不建议新手这么做。尤其是涉及上传、压缩、跨平台、Steam、Paradox Launcher、多人游戏时,英文路径更稳定。中文可以放在 name 字段里展示,但文件夹、脚本 key、事件命名空间、变量名,尽量使用英文和下划线。

三、一个 CK3 Mod 通常由哪些部分组成

CK3 的 Mod 内容不是随便堆在文件夹里,而是按照游戏原版的目录结构进行组织。你想改什么,就要把对应类型的文件放到对应目录里。

常见目录包括:

common
events
localization
gfx
gui
history
map_data
music
sound

其中,common 是最核心的脚本规则目录,里面可以放特质、决议、互动、法律、政体、文化、宗教、脚本效果、脚本触发器、修正、头衔规则等内容。events 用来放事件文件。localization 用来放本地化文本,也就是玩家在游戏中看到的中文、英文、俄文等文本。gfx 用来放图标、纹理、肖像相关资源。gui 用来改界面。history 用来改历史开局角色、头衔、文化、宗教、家族等。map_data 则通常用于地图相关内容,比如省份、河流、地形、地图定义等。

如果你只是想做一个简单的功能菜单,通常只需要掌握 commoneventslocalizationgfx 这几个目录。如果你想做一个大型全新剧本,才会大量接触 historymap_data。如果你想做复杂界面,比如自定义窗口、按钮、列表、地图模式,则需要深入 gui

对于新手来说,建议不要一开始就碰地图。CK3 地图开发是一个很深的坑,涉及省份定义、贴图、河流、高度图、地形、头衔、历史、地理区域、寻路等大量内容。刚入门先从特质、决议、互动、事件、本地化开始,会更稳。

四、common 目录:规则的核心仓库

common 是 CK3 Mod 开发中最重要的目录之一。它里面存放的是游戏规则层面的定义。你可以把它理解为“游戏系统配置中心”。

常见子目录包括:

common
├── decisions
├── character_interactions
├── traits
├── modifiers
├── scripted_effects
├── scripted_triggers
├── scripted_values
├── on_action
├── government_types
├── laws
├── religions
├── culture
├── landed_titles
├── dynasty_perks
├── schemes
├── artifacts
└── defines

不同版本和不同 DLC 下,目录可能会有差异,但整体思路基本一致。你要新增一个决议,就去 common/decisions。你要新增一个角色互动,就去 common/character_interactions。你要新增一个特质,就去 common/traits。你要写一段可以重复调用的效果逻辑,就去 common/scripted_effects。你要写一段可以重复判断的条件,就去 common/scripted_triggers

这里要建立一个非常重要的观念:CK3 的脚本不是“从上到下执行所有文件”,而是游戏根据目录和 key 去读取定义。你在 common/traits 中写的内容,会被游戏当作特质定义读取;你在 common/decisions 中写的内容,会被游戏当作决议读取。放错目录,游戏就可能无法按你的预期解析。

比如你写了一个特质:

zhuge_immortal = {
    index = 900001
    icon = zhuge_immortal.dds

    immortal = yes

    prowess = 10
    health = 5

    ai_boldness = 20
    ai_honor = 20
}

这个文件应该放在:

common/traits/

如果你把它放进 events,它不会变成特质。如果你把它放进 localization,那更是离谱,游戏看了都得沉默。CK3 Mod 开发的很多 bug,其实不是逻辑错,而是“东西放错地方”。

五、events 目录:让游戏发生事情

events 目录用来存放事件。事件是 CK3 中最常见、也最强大的内容形式之一。一个事件可以弹出窗口,可以给角色加特质,可以改变关系,可以授予头衔,可以杀死角色,可以触发战争,可以调用其他事件,也可以作为隐藏事件在后台执行一系列逻辑。

CK3 Wiki 的事件教程说明,事件可以写描述文本,也可以引用本地化 key;事件不会无缘无故自动发生,通常需要由决议、角色互动、on_action、故事循环或其他脚本触发。

一个基础事件大概长这样:

namespace = zhuge_tutorial

zhuge_tutorial.0001 = {
    type = character_event
    title = zhuge_tutorial.0001.t
    desc = zhuge_tutorial.0001.desc
    theme = realm

    left_portrait = root

    option = {
        name = zhuge_tutorial.0001.a
        add_prestige = 100
    }
}

这里的 namespace = zhuge_tutorial 很重要。它相当于事件命名空间,用来避免和其他 Mod 或原版事件冲突。事件 ID zhuge_tutorial.0001 就是一个完整事件 key。以后你要触发它,可以写:

trigger_event = zhuge_tutorial.0001

或者:

scope:actor = {
    trigger_event = zhuge_tutorial.0001
}

事件开发中最常见的错误包括:忘记写 namespace、事件 ID 冲突、事件类型写错、作用域不对、本地化 key 缺失、括号没闭合、option 里效果写错、触发事件的对象不是角色。

其中“作用域不对”是 CK3 Mod 开发里最折磨人的问题之一。因为 CK3 脚本里同一个效果写在不同 scope 下,含义可能完全不同。你在角色 scope 下写 add_prestige = 100,意思是给这个角色加威望;但如果当前 scope 不是角色,这条效果就可能无效或报错。

所以写事件时要养成一个习惯:每次写效果前,都先问自己一句——当前 scope 是谁?是角色?是头衔?是宗族?是信仰?是文化?是省份?还是全局?

这句话比很多教程都重要。因为 CK3 的脚本不是看起来像英文就能随便写,它的核心逻辑就是 scope、trigger、effect 三件事。

六、localization 目录:玩家真正看到的文字

localization 目录负责本地化,也就是游戏里显示给玩家看的文字。无论是事件标题、事件描述、按钮名称、特质名称、决议说明、互动提示、修正描述,都需要通过本地化文件显示。

CK3 Wiki 对本地化的定义很直接:Localization 就是玩家在游戏中看到的文本,它被用于事件、UI、提示文本等各类场景。

中文本地化文件通常放在:

localization/simp_chinese/

英文放在:

localization/english/

一个中文本地化文件名可以类似这样:

zhuge_tutorial_l_simp_chinese.yml

文件内容示例:

l_simp_chinese:
 zhuge_tutorial.0001.t: "诸葛的第一课"
 zhuge_tutorial.0001.desc: "你已经成功触发了第一个 CK3 Mod 事件。"
 zhuge_tutorial.0001.a: "很好,继续前进。"

这里有几个硬规则,必须记住。

第一,文件开头必须有语言声明,比如中文是:

l_simp_chinese:

第二,key 前面通常要有一个空格。不要顶格写 key。第三,冒号后面要有空格,再写文本。第四,文本建议用英文双引号包起来,尤其是中文文本、带标点文本、带变量文本时。第五,本地化文件编码要注意,CK3 本地化常见要求是 UTF-8 BOM;社区排错文档也经常强调,本地化文件编码错误会导致文本无法正常读取,VS Code、Sublime Text、Notepad++ 都可以手动保存为 UTF-8 with BOM。

本地化缺失时,游戏里不会显示你想要的中文,而是显示 key 本身,比如:

zhuge_tutorial.0001.t

这说明游戏找不到对应文本。此时先检查文件路径、语言目录、文件名、语言声明、key 是否一致、编码是否正确。

本地化是新手最容易嫌麻烦,但实际上最能提升 Mod 质感的部分。一个功能如果没有清晰文本,玩家会觉得它粗糙;一个功能如果有准确标题、描述、按钮、提示和错误说明,即使功能本身不复杂,也会显得非常专业。

七、gfx 目录:图标和视觉资源

gfx 目录主要放图标、纹理、界面图片、特质图标、决议图标、事件图、物品图等视觉资源。

比如你做一个新特质,需要一个图标。你可能会把图标放在:

gfx/interface/icons/traits/

文件名:

zhuge_immortal.dds

然后在特质定义中引用:

icon = zhuge_immortal.dds

CK3 常用的图片格式是 .dds。如果你使用 PNG,有些场景可以通过 spriteType 或特殊方式引用,但对于特质、图标这类内容,建议尽量参考原版格式。做图标时要注意尺寸、透明通道、压缩格式和路径。

视觉资源的常见问题有:图标黑块、图标不显示、图标显示成紫色或异常纹理、路径写错、文件格式不对、图片没有 alpha 通道、大小不符合预期。

对于初学者来说,不要一开始就纠结图标美术。可以先用原版图标占位,把功能跑通。等逻辑稳定后,再替换自己的图标。开发顺序应该是:先能用,再好看;先稳定,再精修。别一上来就沉迷画图标,最后功能一个没跑通,那就像给空气装修,挺有审美,但没房子。

八、gui 目录:界面修改的入口

gui 目录用于修改或新增界面。它是 CK3 Mod 开发中比较高级的部分。简单功能菜单通常不一定需要改 GUI,因为可以通过角色互动、决议、事件窗口来实现。但是当你想做真正的自定义面板,比如一个独立功能菜单、角色管理列表、王朝管理界面、批量操作窗口,就可能需要接触 GUI。

CK3 的 GUI 文件定义了窗口、按钮、文本、图标、布局、容器、列表等界面元素。它和脚本系统相关,但复杂度更高。GUI 改错可能导致界面错位、按钮无效、游戏报错,甚至影响原版界面。

新手学习 GUI 时,不建议凭空写。最稳的方法是复制原版相近界面,先改名字和少量内容,观察效果,再逐渐扩展。比如你想做一个菜单按钮,可以参考原版决议窗口、角色互动窗口或某些可展开界面。先理解它怎么显示,再决定怎么改。

但如果你的目标只是写教程的第一阶段,GUI 可以先放在后面。因为 CK3 的大部分入门功能,通过 commoneventslocalization 就已经能做出来。

九、history 目录:历史开局数据

history 目录用于定义游戏开局时的历史状态。比如某个角色在 867 年是谁,某个头衔属于谁,某个地区信什么宗教,某个文化在哪里,某个家族有哪些成员,某个角色有什么特质和父母关系,这些都属于历史数据。

如果你想做一个历史人物增强 Mod,比如给某个皇帝添加特质、修改出生日期、调整家族关系,就会用到 history/characters。如果你想改某个王国开局归属,就会用到 history/titles。如果你想改省份文化和宗教,就会用到 history/provinces

但 history 修改有一个特点:它主要影响新开局。已经开始的存档,不一定会因为你改了历史文件而变化。因为存档里已经记录了当前世界状态。很多新手会问:“我改了角色历史文件,为什么旧档没变化?”原因就在这里。历史文件是开局生成世界时用的,不是每次加载存档都重新覆盖一次。

所以如果你要做影响当前存档的功能,通常应该用事件、决议、互动、on_action 或脚本效果来改变,而不是只改 history。

十、map_data 目录:地图开发的深坑

map_data 是地图相关目录。它涉及 CK3 最复杂的 Mod 类型之一。全新地图、地图扩展、新省份、新地形、新河流、新大陆,都可能需要修改这里。

地图 Mod 的门槛高,不是因为概念难,而是因为关联文件太多。你改一个省份,可能要同时处理省份定义、像素颜色、地形、头衔、历史归属、地理区域、男爵领、地图贴图、寻路、河流、气候等。一处不匹配,就可能导致地图报错或游戏崩溃。

因此,本教程不建议初学者第一步就做地图。可以先从“功能型 Mod”开始,等熟悉 CK3 的脚本结构之后,再进入地图开发。

十一、descriptor.mod 和 .mod 文件详解

前面说过,一个 CK3 Mod 通常有外部 .mod 文件和内部 descriptor.mod。现在我们详细讲一下。

外部文件示例:

version="1.0"
tags={
    "Gameplay"
    "Utilities"
}
name="Zhuge Game Menu"
supported_version="1.17.*"
path="mod/zhuge_menu"

内部 descriptor.mod 示例:

version="1.0"
tags={
    "Gameplay"
    "Utilities"
}
name="Zhuge Game Menu"
supported_version="1.17.*"

有些情况下,内部 descriptor.mod 不写 path,外部 .modpath。上传 Steam 后,启动器可能还会生成带 remote_file_id 的字段,用于绑定创意工坊文件。

常见字段含义如下。

name 是 Mod 名称。它可以是英文,也可以是中文。但如果要面向全球用户,建议英文名更稳定,中文名可以放在描述里。

version 是 Mod 版本号。建议不要乱写。可以用 1.01.11.2.3 这种格式。每次大更新最好改版本号,方便玩家判断是否更新。

supported_version 是支持的 CK3 游戏版本。比如:

supported_version="1.17.*"

表示支持 1.17 系列版本。这里不建议过于随意。如果你写得太窄,启动器可能提示版本不兼容;如果你写得太宽,玩家可能在不兼容版本加载后报错。

tags 是标签。常见如:

tags={
    "Gameplay"
    "Utilities"
}

path 是本地 Mod 文件夹路径。这个字段对本地开发很关键。写错路径,Mod 就加载不到。

如果你的 Mod 是本地目录:

path="mod/zhuge_menu"

如果你的 Mod 是压缩包形式,可能会使用:

archive="mod/zhuge_menu.zip"

新手阶段建议使用文件夹形式,不要一开始就压缩。文件夹方便调试,改完就能测试。

十二、CK3 脚本的三大核心:trigger、effect、scope

真正开始写 CK3 Mod 后,你会反复遇到三个词:trigger、effect、scope。

trigger 是条件。它用于判断某件事能不能发生。比如这个角色是不是玩家?有没有某个特质?是不是皇帝?有没有足够金币?是否成年?是否被囚禁?

示例:

is_ai = no
is_adult = yes
has_trait = brave
gold >= 100

effect 是效果。它用于执行某个操作。比如加金币、加特质、触发事件、设置变量、杀死角色、改变信仰、创建头衔等。

示例:

add_gold = 100
add_trait = brave
trigger_event = zhuge_tutorial.0001
set_character_flag = zhuge_test_flag

scope 是作用域。它表示当前操作对象是谁。比如当前是角色、头衔、省份、宗族、文化、信仰、战争、秘密、宝物,等等。

示例:

scope:actor = {
    add_gold = 100
}

scope:recipient = {
    add_trait = brave
}

这里的 scope:actor 通常指发起互动的人,scope:recipient 通常指被互动的人。不同脚本环境下可用 scope 不一样。角色互动里常见 actor 和 recipient;事件里常见 root、scope、saved_scope;决议里常见 root;on_action 里则要看具体 on_action 提供哪些作用域。

CK3 Mod 开发水平的提升,本质上就是越来越熟悉:在什么地方,有哪些 scope;在这些 scope 下,可以写哪些 trigger 和 effect;当 scope 不对时,如何切换到正确对象。

很多新手看到一个效果写法,直接复制到自己的文件里,却发现不生效。原因往往不是效果错,而是原代码所在的 scope 和你当前代码所在的 scope 不一样。比如原代码在角色 scope 下,而你复制到了头衔 scope 下。效果还是那个效果,但对象不对,自然无法执行。

十三、从一个最简单的功能开始:添加金币决议

学习 CK3 Mod,最好的方式不是先背所有目录,而是马上写一个能生效的小功能。我们先写一个最简单的决议:点击后给玩家 1000 金币。

创建文件:

common/decisions/zhuge_tutorial_decisions.txt

写入:

zhuge_add_gold_decision = {
    picture = "gfx/interface/illustrations/decisions/decision_dynasty_house.dds"

    desc = zhuge_add_gold_decision_desc
    selection_tooltip = zhuge_add_gold_decision_tooltip

    is_shown = {
        is_ai = no
    }

    is_valid = {
        always = yes
    }

    effect = {
        add_gold = 1000
    }

    ai_check_interval = 0
}

然后创建中文本地化文件:

localization/simp_chinese/zhuge_tutorial_l_simp_chinese.yml

写入:

l_simp_chinese:
 zhuge_add_gold_decision: "诸葛测试:获得金币"
 zhuge_add_gold_decision_desc: "这是一个用于测试 CK3 Mod 是否正常生效的基础决议。"
 zhuge_add_gold_decision_tooltip: "获得 1000 金币。"
 zhuge_add_gold_decision_confirm: "领取金币"

进入游戏后,如果 Mod 加载正常,你应该能在决议界面看到这个决议。点击后,当前玩家角色获得 1000 金币。

这个例子虽然简单,但它包含了 CK3 Mod 的几个基础逻辑:脚本定义、本地化 key、显示条件、有效条件、执行效果。

这里的 is_shown 决定这个决议是否显示。我们写了:

is_ai = no

表示只有非 AI 角色,也就是玩家角色,才显示这个决议。

is_valid 决定这个决议是否可用。我们写了:

always = yes

表示永远可用。

effect 是点击确认后执行的效果。我们写了:

add_gold = 1000

表示给当前角色加 1000 金币。

ai_check_interval = 0 通常用于让 AI 不检查这个决议。对于玩家专用作弊菜单、工具菜单、调试决议,这个写法很常见。

你可以把这个例子当成第一个测试模板。以后只要新 Mod 不生效,就先写一个简单加金币决议测试。如果这个都不显示,就说明目录、描述文件、本地化或启动器加载有问题,不要急着查复杂逻辑。

十四、角色互动:做功能菜单的常用入口

如果说决议适合放在决议界面,那么角色互动就适合做“点人操作”。比如你点击一个角色,可以给他加特质、收养他、指定继承人、改变宗教文化、强制婚姻、授予修正、触发事件、打开菜单等。

角色互动文件通常放在:

common/character_interactions/

一个简单互动示例:

zhuge_give_gold_interaction = {
    category = interaction_category_friendly
    common_interaction = yes
    interface_priority = 80
    icon = gold

    desc = zhuge_give_gold_interaction_desc

    is_shown = {
        scope:actor = {
            is_ai = no
        }
        NOT = {
            scope:actor = scope:recipient
        }
    }

    auto_accept = yes

    on_accept = {
        scope:recipient = {
            add_gold = 100
        }
    }

    ai_will_do = 0
}

本地化:

l_simp_chinese:
 zhuge_give_gold_interaction: "赠予金币"
 zhuge_give_gold_interaction_desc: "立刻给予该角色 100 金币。"

这个互动的逻辑是:玩家点击另一个角色时,可以看到“赠予金币”互动。点击后对方立刻获得 100 金币。

这里要注意几个关键点。

scope:actor 是发起互动的人,通常是玩家。scope:recipient 是被点击的人,也就是目标角色。

common_interaction = yes 表示这是一个常规互动。auto_accept = yes 表示自动接受,不需要对方同意。ai_will_do = 0 表示 AI 不会主动使用这个互动。

NOT = { scope:actor = scope:recipient } 表示不能对自己使用。如果你允许对自己使用,可以去掉这个限制。

角色互动非常适合做 CK3 功能型 Mod。因为 CK3 是一个高度角色驱动的游戏,大多数操作都可以围绕角色展开。你想改变一个人的命运,就点击他;你想调整一个家族,就从家族成员入手;你想控制继承,就对继承人使用互动;你想管理附庸,就对附庸使用互动。

这也是很多大型功能菜单 Mod 的基础入口。

十五、特质:最容易入门也最容易膨胀的系统

特质是 CK3 最直观的内容之一。玩家能看到,角色能携带,效果能长期生效,还能影响 AI 性格、属性、健康、婚姻、生育、威望、虔诚、好感、继承、战斗、计谋等。

特质文件放在:

common/traits/

一个简单特质示例:

zhuge_mastermind = {
    index = 900100
    icon = zhuge_mastermind.dds

    diplomacy = 5
    martial = 5
    stewardship = 5
    intrigue = 5
    learning = 5
    prowess = 5

    health = 1
    fertility = 0.1

    ai_boldness = 20
    ai_energy = 20
    ai_honor = 10
}

本地化:

l_simp_chinese:
 trait_zhuge_mastermind: "诸葛谋主"
 trait_zhuge_mastermind_desc: "此人深谙权力、战争与人心之道,善于在混乱局势中重塑秩序。"
 trait_zhuge_mastermind_character_desc: "[ROOT.GetCharacter.GetFirstNameNoTooltip]深谙权力、战争与人心之道,善于在混乱局势中重塑秩序。"

注意,特质本地化 key 通常要加 trait_ 前缀。比如特质 key 是:

zhuge_mastermind

那么本地化通常是:

trait_zhuge_mastermind
trait_zhuge_mastermind_desc
trait_zhuge_mastermind_character_desc

特质系统看似简单,但要谨慎。因为特质非常容易堆属性,最后导致游戏平衡崩坏。尤其是大型功能 Mod,如果你给玩家提供大量超强特质,短期很爽,长期可能让游戏失去挑战。

比较成熟的做法是:把特质分为功能型、身份型、剧情型、惩罚型、血脉型、调试型。功能型特质用于实现特殊机制;身份型特质用于标记角色地位;剧情型特质用于增强沉浸;惩罚型特质用于平衡;血脉型特质用于继承和家族塑造;调试型特质只给开发者测试用。

此外,如果特质只是作为脚本标记,不一定非要让玩家看到。有时用 character_flag 或变量会更合适。不要把所有逻辑都塞进特质里,否则角色面板会变成“贴纸收集册”,看着热闹,实际维护会很痛苦。

十六、scripted_effects:把重复逻辑封装起来

当你的 Mod 功能越来越多,你会发现很多逻辑会重复出现。比如给角色加一套属性、清理一批 flag、初始化某个系统、授予某个身份、执行某个惩罚。如果每个地方都复制一遍,后期维护会非常麻烦。

这时候就需要 scripted_effects

文件路径:

common/scripted_effects/

示例:

zhuge_give_basic_rewards_effect = {
    add_gold = 500
    add_prestige = 500
    add_piety = 300
}

以后你在事件、决议、互动里都可以调用:

zhuge_give_basic_rewards_effect = yes

这就像把一段常用操作封装成一个工具。以后你想改奖励数值,只需要改 scripted_effects 里的定义,不用到处找。

对于大型 Mod 来说,scripted_effects 是非常重要的工程化手段。它能让你的代码更清晰,也能降低 bug。比如你有一个“初始化诸葛菜单权限”的逻辑,可以写成:

zhuge_init_menu_permission_effect = {
    set_character_flag = zhuge_menu_enabled
    set_character_flag = zhuge_menu_initialized
}

然后在开局事件、调试决议、角色互动里都调用它。

这样你的逻辑就会变得很整齐:入口可以有多个,但核心效果只有一份。

十七、scripted_triggers:把复杂判断封装起来

和 scripted_effects 对应的是 scripted_triggers。它用于封装条件判断。

文件路径:

common/scripted_triggers/

示例:

zhuge_can_use_menu_trigger = {
    is_ai = no
    has_character_flag = zhuge_menu_enabled
}

以后你可以在互动里写:

is_shown = {
    scope:actor = {
        zhuge_can_use_menu_trigger = yes
    }
}

这比每个互动里都写一遍:

is_ai = no
has_character_flag = zhuge_menu_enabled

要干净得多。

当你的 Mod 有几十个互动、上百个功能时,封装 trigger 的价值会非常明显。比如你可以写:

zhuge_is_valid_target_trigger = {
    exists = this
    is_alive = yes
    NOT = { has_trait = incapable }
}

然后所有需要判断目标是否有效的地方都调用它。

成熟的 CK3 Mod 开发,不是看谁代码写得最多,而是看谁能把重复逻辑整理得最少。你写得越乱,后期越容易被自己背刺。昨天的你写爽了,明天的你就要还债。

十八、on_action:让系统自动响应游戏行为

on_action 是 CK3 中非常强大的机制。它可以让你的 Mod 在某些游戏行为发生时自动触发逻辑,比如角色出生、死亡、继承、结婚、成年、战争结束、每年脉冲、每月脉冲等。

文件路径通常是:

common/on_action/

示例:

zhuge_on_birth = {
    on_birth = {
        events = {
            zhuge_birth_event.0001
        }
    }
}

事件文件:

namespace = zhuge_birth_event

zhuge_birth_event.0001 = {
    type = character_event
    hidden = yes

    trigger = {
        always = yes
    }

    immediate = {
        add_character_flag = zhuge_birth_checked
    }
}

这里的意思是:当角色出生时,触发一个隐藏事件,给出生角色打上一个 flag。

不过 on_action 要谨慎使用。尤其是 yearly、monthly、daily 这类周期性触发,如果逻辑复杂、遍历角色过多,会影响性能。大型 Mod 最容易出问题的地方,不是某个按钮,而是后台自动运行的全局逻辑。

如果你要写周期检测,尽量遵守几个原则。

能不用 daily 就不用 daily。能 quarterly 就别 monthly,能 yearly 就别 quarterly。能只检查玩家相关对象,就不要全世界遍历。能用 flag 标记已处理,就不要反复处理。能用触发事件处理,就不要用全局脉冲扫地图。

CK3 是一个角色数量很多的游戏。一个全局遍历如果写得不克制,加载几年后性能会像封建领主的税收一样,一层一层被吃掉,最后玩家只剩叹气。

十九、变量和 flag:Mod 逻辑的记忆系统

CK3 脚本里常用两种“记忆”方式:flag 和 variable。

flag 可以理解为一个开关或标签。比如:

set_character_flag = zhuge_menu_enabled
has_character_flag = zhuge_menu_enabled
remove_character_flag = zhuge_menu_enabled

它适合记录“有没有”某种状态。比如是否开启菜单、是否已经初始化、是否被排除、是否处理过、是否进入某个剧情。

variable 则适合记录数值。比如:

set_variable = {
    name = zhuge_power_value
    value = 100
}

change_variable = {
    name = zhuge_power_value
    add = 10
}

变量适合记录权力值、贡献值、忠诚度、积分、阶段、次数等。

简单判断用 flag,数值变化用 variable。不要用变量去做所有事情,也不要用 flag 堆出一万个状态。否则后期你自己都不知道哪个 flag 是干什么的。

命名也很关键。建议所有自定义 flag 和 variable 都加统一前缀,比如:

zhuge_menu_enabled
zhuge_auto_exclude_title
zhuge_legitimacy_checked
zhuge_power_value

不要写太通用的名字,比如:

checked
enabled
test
value

这些名字很容易和其他 Mod 或原版逻辑冲突,也不利于排查。

二十、命名规范:防止和别人打架

CK3 Mod 是可以同时加载多个的。玩家可能同时开几十个 Mod。如果你的 key 命名太通用,就很容易和其他 Mod 冲突。

比如你写:

add_gold_decision
test_event.0001
immortal
power_value

这些名字就非常危险。别人也可能这么写。一旦 key 冲突,轻则覆盖,重则报错。

推荐所有内容都使用统一前缀,比如你的 Mod 是诸葛游戏菜单,可以用:

zhuge_
zg_
zhuge_menu_

例如:

zhuge_add_gold_decision
zhuge_menu_open_interaction
zhuge_trait_immortal
zhuge_event.0001
zhuge_can_use_menu_trigger
zhuge_give_reward_effect

事件 namespace 也要独立:

namespace = zhuge_menu
namespace = zhuge_birth
namespace = zhuge_admin

不要用:

namespace = test
namespace = event
namespace = menu

命名规范不是形式主义,而是大型 Mod 生存的基本功。你现在写得随意,后面玩家一反馈“和某某 Mod 冲突”,你就会被迫从几千行代码里找问题。那感觉不叫开发,叫考古。

二十一、覆盖规则:新增和替换不是一回事

CK3 Mod 有两种常见改法:新增内容和覆盖原版内容。

新增内容比较安全。比如新增一个决议、新增一个互动、新增一个特质、新增一个事件,只要 key 不冲突,通常不会影响原版。

覆盖原版内容则更危险。比如你复制原版某个文件,改里面一小段,然后放进自己的 Mod。这样可能会覆盖整个文件,导致其他原版更新内容或其他 Mod 内容失效。CK3 Wiki 的 Modding 页面也专门提到 Mod 加载顺序和覆盖规则,包括完整文件覆盖、单对象覆盖等内容,说明这是 CK3 Mod 兼容性中非常关键的一部分。

举个例子,如果你想改一个原版决议,你复制整个原版 decisions 文件,只改一个决议。这看起来方便,但风险很高。因为这个文件里其他决议也会被你覆盖。如果游戏更新了这些决议,你的 Mod 还停留在旧版本,就可能引发兼容问题。

更稳的方式是尽量新增自己的内容,少直接覆盖原版。如果必须覆盖,要清楚自己覆盖了什么,并在更新游戏版本后检查原版文件变化。

大型功能 Mod 追求兼容性时,通常会尽量减少硬覆盖,多用新增互动、决议、事件、scripted_effect、on_action 等方式实现功能。这样虽然有时绕一点,但更稳。

二十二、调试模式:开发者的眼睛

CK3 Mod 开发离不开调试模式。根据 CK3 Wiki 的建议,可以通过启动参数 -debug_mode -develop 启动游戏,以便使用控制台和开发功能,并帮助重新加载文件。

Steam 设置方式通常是:右键 CK3,选择属性,在启动选项中加入:

-debug_mode -develop

开启调试模式后,你可以看到角色 ID、头衔 ID、调试信息,也可以使用控制台命令测试事件、加特质、切换角色等。

常用测试命令包括:

event zhuge_tutorial.0001

用于触发事件。

add_trait zhuge_mastermind

用于添加特质。

当然,具体命令是否适用,要看当前游戏版本和控制台支持情况。调试模式不是万能的,但没有它,开发效率会大幅下降。

除了游戏内调试,日志文件也非常重要。CK3 的错误日志通常在:

Documents\Paradox Interactive\Crusader Kings III\logs

常见文件包括:

error.log
game.log
debug.log

当你的 Mod 不生效时,不要只盯着游戏界面。先打开 error.log。很多时候,错误已经写得很清楚了,比如某个文件第几行括号错误、某个 key 找不到、某个 effect 不合法、某个 scope 不支持。

会看日志,是 CK3 Mod 开发从“瞎猜”进入“排查”的分水岭。

二十三、最常见的错误和排查方法

CK3 Mod 新手最常见的问题,大致可以分为几类。

第一类是 Mod 不显示。通常检查 .mod 文件路径、Mod 文件夹位置、启动器是否启用、播放集是否正确、路径是否被 OneDrive 重定向。

第二类是 Mod 显示但功能不生效。通常检查目录结构是否正确、文件后缀是否正确、key 是否写错、是否被其他 Mod 覆盖、脚本是否报错。

第三类是文本不显示,只显示 key。通常检查本地化路径、语言目录、yml 文件编码、语言声明、key 是否一致。

第四类是游戏报错或闪退。通常检查括号、重复 key、非法 effect、错误 scope、覆盖原版文件导致冲突。

第五类是图标不显示。通常检查 DDS 格式、路径、文件名、引用方式、贴图大小、透明通道。

第六类是旧档不生效。通常要判断你改的是 history 文件还是运行时脚本。如果是 history,通常只影响新开局。

第七类是和其他 Mod 冲突。通常检查是否覆盖了同一个文件、同一个 key、同一个 GUI、同一个 on_action、同一个原版对象。

排查时不要凭感觉乱改。建议按顺序来:先确认 Mod 加载,再确认最简单功能是否生效,再看日志,再逐个禁用其他 Mod,再缩小问题范围。

一个很实用的方法是“最小化测试”。比如你写了一个复杂互动不生效,不要在原文件里越改越乱。新建一个测试互动,只保留最基础的 is_shownon_accept。如果测试互动能显示,说明 Mod 结构没问题;如果测试互动不显示,说明问题在加载或基础结构;如果测试互动显示但复杂互动不显示,说明问题在条件判断。

开发不是玄学。只要你能把问题拆小,CK3 的大部分错误都能定位。

二十四、从功能菜单角度理解 Mod 结构

如果你要开发一个类似“诸葛游戏菜单”这样的功能型 Mod,推荐的结构可以这样组织:

zhuge_menu
├── descriptor.mod
├── common
│   ├── character_interactions
│   │   └── zhuge_menu_interactions.txt
│   ├── decisions
│   │   └── zhuge_menu_decisions.txt
│   ├── scripted_effects
│   │   └── zhuge_menu_effects.txt
│   ├── scripted_triggers
│   │   └── zhuge_menu_triggers.txt
│   ├── on_action
│   │   └── zhuge_menu_on_actions.txt
│   └── traits
│       └── zhuge_menu_traits.txt
├── events
│   ├── zhuge_menu_events.txt
│   ├── zhuge_admin_events.txt
│   └── zhuge_dynasty_events.txt
├── localization
│   ├── simp_chinese
│   │   └── zhuge_menu_l_simp_chinese.yml
│   └── english
│       └── zhuge_menu_l_english.yml
└── gfx
    └── interface
        └── icons

这种结构的好处是清晰。互动归互动,决议归决议,效果封装归效果封装,条件封装归条件封装,事件按系统拆分,本地化按语言拆分。

当功能越来越多时,不建议把所有内容都塞进一个巨大文件。比如一个 zhuge_all.txt 写几万行,短期省事,长期很痛苦。你要找某个功能时,会像在帝国官僚系统里找一张三年前的公文,理论上存在,实际上没人知道在哪。

更好的方式是按功能模块拆:

zhuge_menu_inheritance_interactions.txt
zhuge_menu_religion_interactions.txt
zhuge_menu_culture_interactions.txt
zhuge_menu_title_interactions.txt
zhuge_menu_artifact_interactions.txt
zhuge_menu_admin_interactions.txt

本地化也可以按模块拆:

zhuge_menu_core_l_simp_chinese.yml
zhuge_menu_inheritance_l_simp_chinese.yml
zhuge_menu_admin_l_simp_chinese.yml

这样后期维护、翻译、多语言扩展都会轻松很多。

二十五、从“按钮”到“系统”:功能设计的层级

很多新手做 Mod,容易停留在“加按钮”的层面。比如加金币按钮、加威望按钮、杀死角色按钮、改宗教按钮。这些功能当然有用,但如果你的目标是做长期受欢迎的大型 Mod,就需要从“按钮集合”升级到“系统设计”。

按钮只是入口。真正重要的是入口背后的规则。

比如“指定继承人”不是一个按钮那么简单。你要考虑:是否允许对非子女使用?是否允许对女性使用?是否受继承法限制?是否需要移除其他继承人的标记?是否会影响玩家体验?是否要给 AI 禁用?是否需要提示当前继承状态?是否需要做兼容处理?

再比如“改变宗教文化”也不是简单写:

set_faith = scope:actor.faith
set_culture = scope:actor.culture

你还要考虑目标是否是领主、是否连同领地一起转换、是否影响封臣、是否影响家族、是否触发通知、是否保留原有身份、是否造成过强效果。

一个好 Mod,不是功能越多越好,而是功能之间有秩序。玩家使用时能理解这个功能会发生什么,功能之间不会互相打架,长期玩也不会让存档变成一团浆糊。

这也是功能型 Mod 和“临时作弊脚本”的区别。

二十六、多语言支持:从一开始就要留好空间

如果你的 Mod 面向全球用户,语言支持非常重要。中文、英文、俄文是 CK3 玩家群体中很常见的语言方向。你后期要扩展更多语言,前期就不要把文本写死在脚本里。

比如事件里不要这样写:

title = "诸葛的事件"
desc = "这是一段描述。"

虽然有些地方可以直接写文本,但不推荐。更好的方式是:

title = zhuge_event.0001.t
desc = zhuge_event.0001.desc

然后在本地化文件里分别提供不同语言:

localization/simp_chinese/
localization/english/
localization/russian/
localization/french/
localization/german/

多语言支持的核心不是翻译,而是结构。只要 key 统一,后期翻译就只是填文本。如果你前期到处硬编码中文,后面想做英文和俄文,就会变成大型灾难现场。

本地化 key 也要规范。比如:

zhuge_menu_open_interaction
zhuge_menu_open_interaction_desc
zhuge_menu_open_interaction_tooltip

不要一会儿叫:

open_menu

一会儿叫:

zg_open_desc

一会儿又叫:

menu_text_1

翻译最怕 key 混乱。key 一乱,多语言维护成本会成倍增加。

二十七、版本更新与长期维护

CK3 会持续更新,原版文件、脚本接口、系统机制、DLC 内容都可能变化。一个 Mod 想长期稳定,就必须做版本维护。

维护的第一步是不要过度覆盖原版文件。覆盖越多,每次版本更新风险越高。

第二步是建立更新记录。比如:

1.0:初始版本,加入基础菜单
1.1:新增继承功能,修复本地化缺失
1.2:适配 CK3 1.17,优化行政体系互动

第三步是保留测试流程。每次更新后,至少测试这些内容:游戏能否启动;Mod 是否能加载;核心菜单是否显示;主要互动是否可用;事件是否能触发;本地化是否正常;旧档是否可用;新开局是否可用;是否有明显 error.log 报错。

第四步是谨慎处理玩家反馈。玩家反馈“崩了”,不一定真是你的 Mod 单独导致。可能是加载顺序、其他 Mod 冲突、旧档残留、游戏版本不对、本地化损坏、订阅下载不完整。你需要让玩家提供:游戏版本、Mod 版本、加载列表、是否新档、是否有报错日志、复现步骤。

第五步是不要为了每个玩家的个别需求无限加功能。功能越多,维护成本越高。成熟 Mod 要有边界。不是所有能做的功能都应该做。

二十八、发布到 Steam 创意工坊前要检查什么

发布前,建议做一次完整检查。

首先,确认 Mod 名称清晰。标题不要过长,也不要全是符号。最好能让玩家一眼看出功能定位。

其次,确认描述清楚。说明 Mod 做什么、不做什么、支持版本、是否兼容成就、是否支持多语言、是否需要 DLC、是否兼容其他 Mod。

CK3 Wiki 提到,自 1.9 补丁后,Mod 不再禁用成就,也不会使铁人存档失效;多人游戏中则要求玩家使用相同 Mod 和相同加载顺序。 这类信息如果写进说明里,可以减少玩家疑问,但也要注意跟随游戏版本变化及时调整。

再次,确认缩略图和展示图。Steam 创意工坊玩家经常先看图,再看介绍。一个清晰截图,比一大段说明更直观。

然后,确认本地化文件完整。至少保证主要语言不缺 key。缺 key 会严重影响观感。

最后,确认上传后自己订阅测试一遍。很多 Mod 本地能用,上传后不能用,原因可能是路径、descriptor、压缩结构、远程文件 ID 或大小写问题。CK3 Wiki 的故障排查中也提到,上传到 Steam 后 Mod 不工作是常见问题之一。

发布不是结束,而是长期维护的开始。玩家订阅越多,你越需要把更新节奏、兼容性和说明文档做好。

二十九、给初学者的学习路线

如果你是第一次做 CK3 Mod,可以按照这个顺序学习。

第一阶段,学会创建 Mod。目标是让启动器能识别你的 Mod,并在游戏中看到一个简单决议。

第二阶段,学会本地化。目标是让你的决议、互动、事件都能显示正确中文和英文。

第三阶段,学会角色互动。目标是点击角色后执行简单效果,比如加金币、加特质、触发事件。

第四阶段,学会事件。目标是做出一个有标题、描述、按钮、选项效果的事件。

第五阶段,学会 scripted_effects 和 scripted_triggers。目标是把重复逻辑封装起来。

第六阶段,学会 on_action。目标是让某些功能自动响应出生、继承、年度脉冲等游戏行为。

第七阶段,学会日志排查。目标是能看懂常见 error.log,不再靠猜。

第八阶段,学会模块化管理。目标是把功能拆成清晰文件,方便长期维护。

第九阶段,学会兼容性设计。目标是减少原版覆盖,降低与其他 Mod 冲突。

第十阶段,再考虑 GUI、地图、历史剧本、全转化这些高级内容。

这个路线看起来长,但每一步都很实用。不要跳着学。CK3 Mod 开发最怕基础不稳就上复杂系统,最后代码越写越多,问题越修越乱。

三十、一个完整入门示例:决议触发事件,再执行效果

最后,我们做一个稍微完整一点的入门示例:玩家点击一个决议,触发事件,事件按钮给予奖励并添加特质。

目录结构:

common/decisions/zhuge_tutorial_decisions.txt
common/traits/zhuge_tutorial_traits.txt
events/zhuge_tutorial_events.txt
localization/simp_chinese/zhuge_tutorial_l_simp_chinese.yml

决议文件:

zhuge_tutorial_start_decision = {
    picture = "gfx/interface/illustrations/decisions/decision_dynasty_house.dds"

    desc = zhuge_tutorial_start_decision_desc
    selection_tooltip = zhuge_tutorial_start_decision_tooltip

    is_shown = {
        is_ai = no
    }

    is_valid = {
        always = yes
    }

    effect = {
        trigger_event = zhuge_tutorial.0001
    }

    ai_check_interval = 0
}

特质文件:

zhuge_tutorial_trait = {
    index = 900200
    icon = education_intrigue_5.dds

    diplomacy = 2
    martial = 2
    stewardship = 2
    intrigue = 2
    learning = 2
    prowess = 2

    ai_boldness = 10
    ai_energy = 10
}

事件文件:

namespace = zhuge_tutorial

zhuge_tutorial.0001 = {
    type = character_event
    title = zhuge_tutorial.0001.t
    desc = zhuge_tutorial.0001.desc
    theme = realm

    left_portrait = root

    option = {
        name = zhuge_tutorial.0001.a
        add_gold = 500
        add_prestige = 300
        add_trait = zhuge_tutorial_trait
    }

    option = {
        name = zhuge_tutorial.0001.b
        add_piety = 300
    }
}

本地化文件:

l_simp_chinese:
 zhuge_tutorial_start_decision: "诸葛教程:开始测试"
 zhuge_tutorial_start_decision_desc: "触发一个简单事件,用于测试决议、事件、特质和本地化是否正常工作。"
 zhuge_tutorial_start_decision_tooltip: "打开诸葛教程测试事件。"
 zhuge_tutorial_start_decision_confirm: "开始测试"

 zhuge_tutorial.0001.t: "诸葛教程事件"
 zhuge_tutorial.0001.desc: "如果你看到了这个事件,说明你的 CK3 Mod 已经成功完成了基础结构、决议、本地化和事件触发。接下来,你可以选择获得世俗奖励,或者获得宗教奖励。"
 zhuge_tutorial.0001.a: "获得世俗奖励"
 zhuge_tutorial.0001.b: "获得宗教奖励"

 trait_zhuge_tutorial_trait: "诸葛学徒"
 trait_zhuge_tutorial_trait_desc: "此人已经迈出了 CK3 Mod 开发的第一步。"
 trait_zhuge_tutorial_trait_character_desc: "[ROOT.GetCharacter.GetFirstNameNoTooltip]已经迈出了 CK3 Mod 开发的第一步。"

这个示例已经覆盖了入门开发的核心链路:决议显示、点击决议、触发事件、事件按钮、执行效果、添加特质、本地化显示。

如果这个示例能正常运行,就说明你已经掌握了 CK3 Mod 开发最基础的骨架。后续无论你做角色管理、王朝系统、行政体系、继承控制、朝贡机制、事件链,都是在这个骨架上继续扩展。