脚本语法与作用域

脚本基本写法、触发器与效果、this/root/from/prev

基本语法

群星的脚本(Paradox 称为 Clausewitz 脚本)只有几种元素:

Clausewitz 脚本
# 井号后面是注释
key = value                 # 赋值
key = { ... }               # 块
num_communications > 1      # 比较:> < >= <=
is_ai = no                  # 布尔值用 yes / no
name = "country.50.a"       # 字符串,含空格或特殊字符时加引号
value = @tier1unityreward   # @ 开头是脚本变量
  • 缩进和换行没有语法意义,但请保持与原版一致的 Tab 缩进,方便排查括号。
  • 大括号必须配对。少一个 } 会让后面整个文件解析错乱,error.log 里会出现一串看似无关的错误。
  • 键名区分大小写的情况很多,照抄原版最安全。

触发器与效果

脚本里的语句分两类,不能混用:

触发器(trigger)效果(effect)
作用检查条件,返回真/假改变游戏状态
例子is_ai = no、has_country_flag = x、num_communications > 1set_country_flag = x、add_resource = { energy = 100 }
出现的块trigger、limit、potential、allow、pre_triggersimmediate、option、after、effect

触发器块里的多条语句默认是“全部成立”(AND)。逻辑运算用大写:

Clausewitz 脚本
trigger = {
	is_ai = no
	OR = {
		has_country_flag = story1
		num_communications > 1
	}
	NOT = { has_country_flag = starting_event }
	NOR = {
		has_ethic = ethic_gestalt_consciousness
		is_nomadic = yes
	}
}

还有 AND、NAND(AND 取反)、calc_true_if(满足其中若干条)等。

效果里需要条件分支时用 if / else_if / else,条件写在 limit 里:

Clausewitz 脚本
immediate = {
	if = {
		limit = { has_country_flag = story1 }
		country_event = { id = country.1 }
	}
	else = {
		country_event = { id = country.258 days = 180 }
	}
}

(摘自原版 events/country_events_1.txt 的 country.258。)

另外两个常用的效果包装:hidden_effect = { ... } 让里面的效果不显示在提示框里;custom_tooltip = <本地化键> 在提示框里显示一段自定义文字。

作用域(scope)

每条触发器和效果都在某个作用域里执行,也就是“针对哪个对象”:国家、行星、舰队、领袖、星系……例如 add_resource 只能在国家作用域用,is_planet_class 只能在行星作用域用。

切换作用域就是写一个“作用域名 = { }”的块:

Clausewitz 脚本
owner = {                       # 从当前对象切到它的所有者(国家)
	add_resource = { energy = 100 }
}
capital_scope = {               # 从国家切到首都
	save_event_target_as = capital
}

也可以用点号连续切换,例如 root.owner.capital_scope。

注意 4.5 把“殖民地”(colony)作为单独的作用域:capital_scope 的输出是 colony,carrier 从殖民地回到承载它的行星;与之对应,原版大量行星相关事件使用 carrier_event。以 script_documentation\scopes.log 中的 Supported Scopes / Output Scope 为准。

特殊作用域

关键字含义(摘自 4.5 的 scopes.log)
this当前作用域
root这一段脚本最初的作用域,例如 country_event 里的那个国家
prev上一次切换前的作用域;prevprev 再往前一层
from上一个事件的 root,或由 on_action 预设的 FROM;fromfrom 再往前一层

prev 的经典例子:

Clausewitz 脚本
owner = {
	capital_scope = {
		is_owned_by = prev      # prev 指 owner,这条恒为真
	}
}

from 在 on_action 里的含义由该 on_action 决定,原版 common/on_actions/00_on_actions.txt 的注释会写明,例如 on_war_beginning 是 Root = Country、From = War(见 on_actions)。

事件目标

需要在之后的事件里再次引用某个对象时,用 save_event_target_as 保存,用 event_target:名字 取回:

Clausewitz 脚本
capital_scope = { save_event_target_as = capital }
random_system = {
	limit = {
		distance = {
			source = event_target:capital
			use_bypasses = no
			min_jumps = 2
			max_jumps = 6
		}
	}
	save_event_target_as = probe_system_1
}

(改写自原版 country.1 事件。)事件目标在同一条未中断的事件链中有效。

遍历:any / every / random / count

对一组对象做检查或执行效果,用前缀 + 列表名:

前缀类型含义
any_触发器其中任意一个满足条件
count_触发器满足条件的个数
every_效果对每一个满足 limit 的执行
random_效果随机挑一个满足 limit 的执行
ordered_效果按指定排序挑一个执行
Clausewitz 脚本
every_owned_colony = {
	limit = { is_capital = no }
	add_modifier = { modifier = my_mod_bonus days = 360 }
}

注意 4.5 的文档把 every_owned_planet / any_owned_planet 等标记为 “Deprecated; use owned_colony instead”。照抄老教程前,先在 effects.log / triggers.log 里查一下。

下一步:学会本地化,然后写第一个事件。