变量、脚本值与脚本化本地化

运行时变量的读写与运算,script_values 的公式写法与参数,以及 scripted_loc 的 defined_text

本篇讲三样“动态”的东西:

手段位置用来做什么
变量存在游戏对象上(存档里)记住一个会变化的数:计数器、累计值、上次的结果
脚本值(script value)common/script_values/一个按公式现算的数,不存储
脚本化本地化common/scripted_loc/按条件挑选一段文本,供本地化里的 [...] 调用

@ 开头的脚本变量是常量,属于另一回事,见脚本化触发器、效果、变量与 inline_script。

原版对变量最完整的说明在 events/000_how_to_use_variables_in_script.txt,脚本值的说明在 common/script_values/00_script_values.txt 开头。

变量

变量是挂在某个作用域上的有名数字。几乎所有作用域都能存变量:国家、行星、舰船、领袖、物种、星系、战争、联邦……(effects.log 中 set_variable 的 Supported Scopes 列出了全部)。

注意 effects.log 特别说明:殖民地(colony)作用域不存变量,在殖民地上读写变量实际访问的是它所在的星球。

设置与修改

Clausewitz 脚本
set_variable = { which = mymod_signals value = 0 }
change_variable = { which = mymod_signals value = 1 }
multiply_variable = { which = mymod_signals value = 2 }
clear_variable = mymod_signals

value 可以是数字、另一个变量、作用域.变量,或 trigger:<触发器>。此外还有 subtract_variable、divide_variable、modulo_variable,以及取整用的 round_variable、floor_variable、ceiling_variable、round_variable_to_closest。

从游戏状态导出数值到变量:

效果导出什么
export_trigger_value_to_variable一个数值型触发器的值;带 { } 的触发器用 parameters = { } 传参
export_modifier_to_variable作用在该作用域上的某个修正的总和
export_resource_income_to_variable / export_resource_stockpile_to_variable国家某资源的月收入 / 库存
get_galaxy_setup_value银河设置选项
Clausewitz 脚本
export_trigger_value_to_variable = {
	trigger = has_resource
	parameters = { resource = energy }
	variable = mymod_energy_now
}

检查

Clausewitz 脚本
is_variable_set = mymod_signals
check_variable = { which = mymod_signals value >= 3 }

读取一个没设置过的变量会出错,所以先用 is_variable_set 判断。check_variable_arithmetic 可以先做加减乘除再比较,不会改动变量本身。

在哪里能用变量

原版说明列出的用法:

  • 任何比较单个数字的触发器:pop_amount > mymod_threshold;
  • 任何接受单个数字的效果:add_experience = mymod_xp;
  • while 循环的 count;
  • add_modifier 的 multiplier、add_resource 的 mult;
  • 资源表里带条件的 multiplier;
  • 权重块里 modifier = { add = mymod_var … };
  • 本地化:[This.mymod_signals] 显示变量的值(变量必须已设置)。

读值时可以用点号跨作用域:owner.capital_scope.mymod_var;也可以直接读触发器和修正:trigger:pop_amount、modifier:pop_citizen_happiness、owner.trigger:pop_amount。

变量名请加模组前缀:两个模组在同一个国家上各自 set_variable = { which = counter … },就会互相覆盖。

脚本值

脚本值是一个命名公式,用 value:<名字> 引用,每次引用时重新计算。原版 common/script_values/00_script_values.txt:

Clausewitz 脚本
edict_size_effect = {
	base = 0.01
	mult = trigger:empire_sprawl_over_cap
	add = 1
}

法令费用里的 multiplier = value:edict_size_effect 就是用它让费用随帝国规模增长(见政策与法令)。

运算

从 base(默认 0)开始,按书写顺序依次运算:

写法作用
add / subtract加减
mult / multiply / factor乘
divide / modulo除、取余
set / weight把当前结果替换成这个值
max / min上限 / 下限(文件注释:max 在当前值高于它时设为它,min 相反)
round_to舍入到某个数的倍数
pow乘方,注意溢出
round / ceiling / floor / abs / square / square_root = yes一元运算

注意 原版注释说明 weight 和 factor 写在行内时会覆盖 base 的值,需要相乘请用 mult 或 multiply。

条件运算放进 modifier 块,只有触发器成立时才执行:

Clausewitz 脚本
gaiaseeder_cost_mult = {
	base = 1

	modifier = {
		add = value:gaiaseeder_councilor_mult
		owner = {
			has_councilor = { COUNCILOR = "councilor_idyllic_bloom" }
		}
	}
}

需要带 { } 的触发器的值时,用 complex_trigger_modifier:

Clausewitz 脚本
complex_trigger_modifier = {
	trigger = count_owned_planet
	trigger_scope = owner
	parameters = {
		limit = { pop_amount > 1000 }
	}
	mode = add
	mult = 5
}

参数

脚本值和脚本化触发器/效果一样支持 $参数$。引用时写成 value:名字|参数|值|:

Clausewitz 脚本
gaiaseeder_councilor_mult = {
	base = -0.05
	mult = value:councilor_level|TYPE|councilor_idyllic_bloom|
}

多个参数依次排列:value:my_value|PARAM1|value1|PARAM2|value2|。

提示 文件开头提醒:脚本值在频繁检查的触发器里使用时要注意性能,因为它每次都会重算。

脚本化本地化

common/scripted_loc/ 里定义 defined_text,在本地化文本中按名字调用。原版 00_scripted_loc.txt 的第一个(节选):

Clausewitz 脚本
defined_text = { # Country/leader/pop/species scope
	name = GetEdibleName
	text = {
		trigger = {
			is_species_class = AVI
		}
		localization_key = edible_avi
	}
	text = {
		trigger = {
			is_species_class = MAM
		}
		localization_key = edible_mam
	}
	# ……
}

本地化里这样调用:[Root.GetEdibleName]。游戏在调用处的作用域上依次检查各个 text 的 trigger,把选中的 localization_key 对应的文本放进来。

字段(据 000_example.txt):

字段说明
name在本地化里使用的名字
text = { localization_key trigger weight }候选文本,可以写任意多个
random默认 yes:在可选项中按 weight 随机;no:取权重最高的,同权重取第一个
default所有触发器都不成立时使用的键

还可以把脚本值直接暴露给本地化:

Clausewitz 脚本
defined_text = {
	name = mymod_signal_strength
	value = value:mymod_signal_strength_value
}

注意 name 是全局的,请加模组前缀,例如 GetMymodTitle。原版的 Get 前缀只是习惯。

本地化文件本身的格式见本地化。