事件(Events)

事件文件的结构、命名空间、事件类型、触发方式与选项

事件是什么

事件是群星脚本里最常用的“执行单元”:弹窗剧情、异常点结果、隐藏的后台逻辑,几乎都是事件。事件文件放在模组的 events\ 文件夹,扩展名 .txt。原版的 events\ 下有约 170 个文件,可以随时打开参考。

一个完整的例子

下面是一个仿照原版 events/country_events_1.txt 写的国家事件:

Clausewitz 脚本
namespace = mymod

# 来自深空的信号
country_event = {
	id = mymod.1
	title = mymod.1.name
	desc = mymod.1.desc
	picture = GFX_evt_satellite_in_orbit
	show_sound = event_sensor_ping

	is_triggered_only = yes

	trigger = {
		is_ai = no
		NOT = { has_country_flag = mymod_signal_seen }
	}

	immediate = {
		set_country_flag = mymod_signal_seen
	}

	option = {
		name = mymod.1.a
		add_resource = { energy = 100 }
	}
	option = {
		name = mymod.1.b
		add_resource = { minerals = 100 }
	}
}

对应的本地化(见本地化):

本地化 YML
l_simp_chinese:
 mymod.1.name: "来自深空的信号"
 mymod.1.desc: "传感器捕捉到了一段规律的信号。"
 mymod.1.a: "把它卖给能源公司。"
 mymod.1.b: "拆了接收器换矿物。"

命名空间与 ID

文件开头的 namespace = mymod 声明命名空间,之后的事件 ID 写成 命名空间.数字,如 mymod.1、mymod.100。原版就是这么做的:events/country_events_1.txt 开头是 namespace = country,事件 ID 为 country.1、country.50。

  • 命名空间请用模组专属的前缀,避免和原版或其他模组撞 ID。
  • 本地化键习惯用 <ID>.name、<ID>.desc、<ID>.a、<ID>.b。
  • 实测 4.5.2 中 events 是 FIOS:两个文件定义同一个 ID 时,按文件名排序先读的生效,后读的报 an event with id [xxx] already exists!。想覆盖原版事件,要么让你的文件名排在原版文件前面,要么整文件覆盖。详见加载顺序与覆盖规则。

事件类型

事件块的名字决定事件的作用域(root 是什么)。按原版 4.5 的使用次数,常见的有:

类型root原版中的用量
country_event国家约 5200 个
carrier_event承载殖民地的行星(4.5 行星类事件的主力)约 1100 个
ship_event舰船约 1000 个
fleet_event舰队约 900 个
situation_event局势约 700 个
event无作用域(全局)约 140 个
observer_event观察者约 90 个
leader_event领袖约 70 个
system_event星系约 70 个
planet_event、colony_event、starbase_event、pop_group_event对应对象各十几个

此外还有 first_contact_event、espionage_operation_event、astral_rift_event、agreement_event 等专用类型。

常用字段

字段说明
id事件 ID
title / desc / picture弹窗的标题、正文、配图。desc 也可以写成带 trigger 的块,按条件显示不同文字(原版 country.50 就这么做)
show_sound弹出时的音效
location点击事件可跳转到的位置,如 ROOT、FROM.fleet
hide_window = yes不弹窗,只执行效果。原版有约 2800 个隐藏事件,多用于后台逻辑
is_triggered_only = yes只在被调用时触发,不会自己发生
trigger触发条件(触发器块)。被调用时也会检查
pre_triggers更快的预筛条件,用于行星、星系、领袖等事件,见 events/000_added_pre_triggers_to_planet_events.txt
mean_time_to_happen让事件按平均间隔自行发生,如 months = 40
fire_only_once = yes一局游戏只触发一次
immediate事件一触发就执行的效果,在玩家看到弹窗之前
option选项,至少写一个 name
after玩家选完任一选项之后执行的效果

事件怎样被触发

1. 由效果调用(最常用)。 原版约 9500 处 is_triggered_only = yes,绝大多数事件都是被别的脚本调用的:

Clausewitz 脚本
country_event = { id = mymod.1 }
country_event = { id = mymod.2 days = 30 random = 10 }

days 是延迟天数,random 是额外的随机延迟上限。country_event、ship_event 等效果还支持 scopes = { from = ... },用来指定被调用事件的 FROM(以 effects.log 中各效果的说明为准)。

2. 由 on_action 触发。 游戏在特定时刻(开局、每月、殖民完成、战争开始……)会触发 on_action,把你的事件挂上去即可,见 on_actions。

3. 按 MTTH 自行发生。 写 mean_time_to_happen 而不写 is_triggered_only。原版只有约 140 个这样的事件;能用 on_action 解决的,优先用 on_action。

4. 控制台调试。 event mymod.1 直接触发,见调试。

选项

Clausewitz 脚本
option = {
	name = country.50.b
	add_monthly_resource_mult = {
		resource = unity
		value = @tier1unityreward
		min = @tier1unitymin
		max = @tier1unitymax
	}
	hidden_effect = {
		end_event_chain = "survey_habitable_worlds_chain"
	}
}

(摘自原版 country.50。)选项里直接写效果;不想让玩家在提示框里看到的部分放进 hidden_effect,只想展示说明而不执行时可以用 tooltip = { ... }。

提示 隐藏事件也常写一个 option,不过真正的逻辑通常放在 immediate 里——它在事件触发的瞬间执行,不依赖玩家点击。

写事件时的检查清单

  1. 文件开头有 namespace,ID 前缀与之一致。
  2. 被调用的事件写了 is_triggered_only = yes。
  3. 所有 title、desc、name 都有对应的本地化键,且 .yml 带 BOM。
  4. 用 event <ID> 在控制台测一遍,再看 error.log。