on_actions

在开局、每月、殖民、开战等时刻自动触发你的事件

什么是 on_action

on_action 是游戏在某个时刻自动“广播”的钩子:开局、每月、每年、勘测行星、殖民完成、战争开始……每个 on_action 下挂着一串事件,时刻一到就逐个尝试触发。原版定义在 common/on_actions/ 下,99_README_ON_ACTIONS.txt 是官方说明。

按 README 的描述,每次 on_action 触发时:

  • events = { } 里的每一个事件都会检查各自的 trigger,成立的全部触发;
  • random_events = { } 里先排除条件不成立的,再按权重随机挑一个触发。
Clausewitz 脚本
on_action_name = {
	events = {
		# 每次都可能触发
	}
	random_events = {
		200 = 0             # 权重 200:什么都不触发
		10 = event_name.01
		10 = event_name.02
	}
}

给 on_action 挂上自己的事件

不要复制原版的 00_on_actions.txt(那会变成整文件覆盖,原版更新后你的模组就会吞掉新内容)。新建一个带自己前缀的文件,只写你要加的事件:

Clausewitz 脚本
# common/on_actions/mymod_on_actions.txt

on_yearly_pulse_country = {
	events = {
		mymod.10
	}
}

同名 on_action 的内容会被合并,而不是覆盖:原版挂在 on_yearly_pulse_country 上的事件照常运行,你的 mymod.10 也会加进去。

对应的事件需要写 is_triggered_only = yes,并用 trigger 把范围缩小:

Clausewitz 脚本
country_event = {
	id = mymod.10
	hide_window = yes
	is_triggered_only = yes

	trigger = {
		is_ai = no
		has_country_flag = mymod_enabled
	}

	immediate = {
		add_resource = { unity = 50 }
	}
}

原版的 on_action 分布在 common/on_actions/ 的三个文件里:00_on_actions.txt(绝大多数)、01_planet_destruction.txt 和 02_component_on_actions.txt。想找某个时刻有没有现成的钩子,直接在这几个文件里搜关键词,再读它上方的注释。

提示 验证挂载是否成功的最快办法:在事件的 immediate 里写一行 log = "mymod.10 fired",跑一个月或一年后去 game.log 里找这行字(见调试)。没有输出时,先检查事件的 trigger,再检查 on_action 的名字是否拼错——拼错的名字会被当成一个新的自定义 on_action,永远不会被游戏触发。

作用域:看原版注释

每个 on_action 的 root 和 from 是什么,原版在 common/on_actions/00_on_actions.txt 里用注释写明了。几个例子:

on_action原版注释
on_game_start开局时触发,无作用域
on_monthly_pulse、on_yearly_pulseNo scope, like on_game_start
on_monthly_pulse_country、on_yearly_pulse_countrythis = country
on_entering_systemScope = Ship、From = System、FromFrom = Country
on_planet_surveyedRoot = Planet、From = Country、FromFrom 为勘测舰队(如果有)
on_colonizedScope = Carrier
on_war_beginningRoot = Country、From = War,对战争中的每个国家各执行一次

所以挂到 on_war_beginning 上的应该是 country_event,事件里可以用 from 取到这场战争;挂到无作用域的 on_monthly_pulse 上的则应是不带作用域的 event。

提示 原版注释还会提醒用法,例如 on_entering_system 旁写着“通常更适合用 on_entering_system_first_time 或 on_entering_system_fleet”。动手前先读注释。

性能

on_monthly_pulse_country 这类脉冲每月对每个国家都触发一次,挂在上面的事件条件会被频繁检查。几条原则:

  1. trigger 里把最便宜、最能排除的条件放前面,例如 is_ai = no、has_country_flag。
  2. 行星、星系、星港、领袖类事件用 pre_triggers 做快速预筛,README 专门推荐了这一点,写法见原版 events/000_added_pre_triggers_to_planet_events.txt:
Clausewitz 脚本
pre_triggers = {
	has_owner = yes
	is_ai = no
}
  1. 能挂年脉冲的就不挂月脉冲。

random_events 的权重修正

random_events 里的数字是固定权重,不支持条件修正。README 给出的办法是在事件本身写 weight_multiplier:

Clausewitz 脚本
weight_multiplier = {
	factor = 1
	modifier = {
		factor = 2
		has_country_flag = mymod_lucky
	}
}

自定义 on_action

你也可以发明自己的 on_action,然后用 fire_on_action 效果手动触发,方便多个模组往同一个钩子里挂事件:

Clausewitz 脚本
# common/on_actions/mymod_on_actions.txt
mymod_on_signal_decoded = {
	events = {
		mymod.20
	}
}
Clausewitz 脚本
# 某个事件的 immediate 或 option 里
fire_on_action = {
	on_action = mymod_on_signal_decoded
	scopes = { from = root }
}

scopes 用来指定被触发事件的 from、fromfrom 等,格式见 effects.log 中 fire_on_action 的说明(fire_on_action = { on_action = <string> scopes = { from = X fromfrom = Y } })。