Featured image of post 蛋卷的高级任务编辑器脚本 (OMS)

蛋卷的高级任务编辑器脚本 (OMS)

扩展触发器:判定速度/高度/航向、玩家人数(动态难度)、报名系统等

总体介绍

此脚本可以实现很多DCS编辑器中原本没有或要设置一大串触发器才能实现的功能。它的原理是将其判定的内容写入用户指定的旗标中,以完成相应触发。

比如,我们想根据战区内的玩家数量动态调整游戏难度,只有在玩家数大于某个值时才会出生额外的敌机。
使用OMS可以将该区域内的玩家数写入一个旗标值中,之后可以通过游戏自带的触发器判断,如果旗标值大于XX,则激活额外敌机群组。

此脚本已在狐狸大导演(PP-FOX)精心制作的 马夫湖暴风雪 多人战役中成功应用

点击下载
注意:使用此脚本前,你需要已经对DCS任务编辑器,尤其是如何使用触发器和旗标有一个完整的认识,如果还不能做到这一点,推荐先观看:蛋卷的DCS任务编辑器综合教学

蛋卷的OMS脚本是在MIST脚本基础上编写,更多信息可以看 这里

使用准备

载入脚本

触发器 当任务开始 - 条件 - 动作 执行脚本文件
载入 mist_x_x_xxx.luaOMS_xxx.lua ,注意mist需要在OMS之上

定义参与判定的玩家列表

如果跳过下列操作,则玩家列表定义为所有 客户端 可选单位

自定义设置可用于排除某些单位(如想让制空组玩家不参与触发器判定)或额外添加某些单位(如把某些AI飞机同样当作玩家参与判定),设置方法为:
触发器 当任务开始 - 条件 - 动作 执行脚本,然后写所需的代码(看下面)
玩家单位列表储存在变量 oms.players 中,有几种不同的定义方式,详细解释可以看 这里

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
--定义地图上的所有中国单位为参与判定的玩家:(慎用,这样也包括AI飞机和地面单位)
oms.players = {'[c]China'}

--定义所有美国固定翼单位为参与判定的玩家:
oms.players = {'[c][plane]USA'}

--定义群组uzi-1、uzi-2为参与判定的玩家
oms.players = {'[g]uzi-1','[g]uzi-1'}

--定义单位'colt-1-1'、'colt-1-2'为参与判定的玩家
oms.players = {'colt-1-1''colt-1-2'}
		
--可混用,比如:
--定义所有中国单位、美国直升机和单位'sabre'为参与判定的玩家
oms.players = {'[c]China','[c][helicopter]USA','sabre'}

这种使用 {'[x]xxx','xxx'} 的定义方式被成为 Unit Name Table (UNT),在之后使用具体函数时会用到

使用方法

输出值

OMS的函数可以用触发器动作中的 执行脚本 运行,并把结果写入你指定的旗标中
如需要持续运行,可以用
触发器 持续 - 条件 - 动作 执行脚本
也可以根据任务情况,自定义开始运行的条件和是否需要多次运行

大部分的OMS函数都同时具有把结果输出到旗标或变量名的功能,如检测触发区内有多少玩家的函数 oms.inZone

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
--可以把玩家数量写入一个旗标(如写入10号旗标),此时不用在前面写输出的变量名
oms.inZone({'Combat Zone'},10)

--虽然旗标值必须是非负整数,但旗标名不一定需要是数字
--可以设置成具体的名字,如给旗标起名'playerCount'
oms.inZone({'Combat Zone'},'playerCount')

--也可以把玩家数量输出到一个变量中(如写入playerCount变量)
playerNumber = oms.inZone({'Combat Zone'})
--如果你之后还写了自己的代码,即可调用playerNumber变量

这样你可以使用编辑器自带的旗标判定系统,也可以用后续自己写的代码对输出值进行判断。

所有输出高度、速度、航向和航向差的函数,正常运行时最小输出值均为 1。只有未判定成功时才会输出 0(通常由于需要被判定的单位不存在、已被摧毁或还未出生)。
在编辑器中,旗标值为 0 等同于旗标为假。在使用这些函数时,最好同时判定其输出值大于 0 或旗标为真。

指定单位列表

同时判定多个单位的函数,如上面提到的检测触发区内有多少玩家的函数 oms.inZone,默认会使用一开始定义的所有玩家列表 oms.players
如果需要对其他的单位列表进行判定,可以在使用时输入其UNT,区别如下:

1
2
3
4
5
--判定所有玩家中,有几人在触发区内,并写入旗标inZoneCount
oms.inZone({'Combat Zone'},'inZoneCount')	

--只判定uzi-1和uzi-2小队有几人在触发区内,并写入旗标inZoneCount
oms.inZone({'Combat Zone'},'inZoneCount',{'[g]uzi-1','[g]uzi-2'})

具体功能

判定触发区内单位数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
number = oms.inZone(zoneNames, flag, UNT)

输入值
	zoneNames --触发区列表,如{'zone1','zone2'},
	--可以是多个触发区的组合,且这些触发区不一定要相连
	--即使只有一个触发区,也要写大括号
	flag --输出的旗标名,如输出到变量则可不填
	UNT --判定的单位列表,如使用全体玩家则可不填
输出值
	number --在触发区内的单位数量

判定移动触发区内单位数

触发区跟随某单位移动,但不需要在编辑器实际画出触发区,只需要放置其中心的单位即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
number = oms.inMvZone(zoneUnitNames, zoneRadius, zoneType, flag, UNT)

输入值
	zoneUnitNames --触发区中心单位列表,如{'arco','shell'},即使只有一个单位,也要写大括号
	zoneRadius --触发区半径,已上述各单位为中心,单位米
	zoneType --触发区形状,'c'为圆柱体,无限高度,判定2D距离,'s'为球形,即判定3D距离
	flag --输出的旗标名,如输出到变量则可不填
	UNT --判定的单位列表,如使用全体玩家则可不填
输出值
	number --在触发区内的单位数量
	
--举例 --判断在加油机arco附近1000米内有多少玩家,并写入旗标nearTanker
oms.inMvZone({'arco'}, 1000, 's', 'nearTanker')

多个单位中最高高度

高度单位:英尺 输出为实际海拔高度,非离地高度或气压高度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
altitude = oms.maxASL(flag, zoneNames, UNT)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	zoneNames --触发区列表,用于只在某区域内进行判定,如判定全图可不填
	UNT --判定的单位列表,如使用全体玩家则可不填
输出值
	altitude --最高单位的高度	
--注意 --正常运行时最小输出值为1,如未进行判定(单位不存在)则输出0
	
举例 --找到在触发区CombatZone内飞得最高的玩家,将其高度写入旗标'altitude'
oms.maxASL('altitude', {'CombatZone'})

多个单位中最低高度

高度单位:英尺 输出为实际海拔高度,非离地高度或气压高度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
altitude = oms.mimASL(flag, zoneNames, UNT)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	zoneNames --触发区列表,用于只在某区域内进行判定,如判定全图可不填
	UNT --判定的单位列表,如使用全体玩家则可不填
输出值
	altitude --最低单位的高度	
	
注意 --正常运行时最小输出值为1,如未进行判定(单位不存在)则输出0	

在空中的单位数量

只包括已出生且在天上的单位,不包括未出生或已坠毁单位

1
2
3
4
5
6
7
8
number = oms.inAir(flag, zoneNames, UNT)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	zoneNames --触发区列表,用于只在某区域内进行判定,如判定全图可不填
	UNT --判定的单位列表,如使用全体玩家则可不填
输出值
	number --在空中的单位数量

在地面的单位数量

只包括已出生且在地面的单位,不包括未出生或已坠毁单位

1
2
3
4
5
6
7
8
number = oms.onGnd(flag, zoneNames, UNT)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	zoneNames --触发区列表,用于只在某区域内进行判定,如判定全图可不填
	UNT --判定的单位列表,如使用全体玩家则可不填
输出值
	number --在地面的单位数量

报名系统:固定触发区

当有且只有一个单位进入某区域时,输出其单位名
比如可用于确定所有玩家的长机(如将跑道设置为触发区,第一个上跑道的玩家被定义为长机)
或用于选定某玩家去达成某项挑战等

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
name = oms.signUp(zoneNames, flag, UNT)

输入值
	zoneNames --触发区列表
	flag --输出的旗标名
	--旗标值为0 --区域内无单位
	--旗标值为1 --单个单位进入区域报名成功
	--旗标值为2 --报名失败,区域内单位太多
	UNT --判定的单位列表,如使用全体玩家则可不填
输出值
	name --成功报名的单位名,注意时编辑器里写的名字,不是玩家名
			如超过一个单位会输出'Too Many'
			如无单位会输出'No Unit'
	--这个名字还会写入全局变量oms.challenger中

注意:如果这条代码放在持续运行的触发区中,只有单个单位保持在区域内才会输出其名字,如果之后这个单位离开或过多单位进入,都会导致其名字被替换。如果希望持续记住这个单位的名字,可以使用一个额外的触发器:
触发器 只运行一次 - 条件 旗标值为1 - 动作 执行脚本

1
2
permName = oms.challenger
--这样即使后来条件变化,该单位的名字也会一直存在permName变量中

报名系统:移动触发区

1
2
name = oms.signUpMv(zoneUnitNames, zoneRadius, zoneType, flag, UNT)
--

详见 报名系统:固定触发区

单个单位的海拔高度

高度单位:英尺 输出为实际海拔高度,非离地高度或气压高度

1
2
3
4
5
6
7
8
9
altitude = oms.unitASL(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	altitude --当前海拔高度	
	
注意 --正常运行时最小输出值为1,如未进行判定(单位不存在)则输出0	

单个单位的速度

速度单位:节 输出为3D空间内的绝对速度,非空速

1
2
3
4
5
6
7
8
9
speed = oms.unitSpeed(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	speed --当前速度,相对固定地面的3D速度		
	
注意 --正常运行时最小输出值为1,如未进行判定(单位不存在)则输出0

单个单位的地速

速度单位:节 输出为相对地面的2D水平速度,非空速

1
2
3
4
5
6
7
8
9
speed = oms.unitGndSpeed(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	speed --当前低速,相对固定地面的水平2D速度		
	
注意 --正常运行时最小输出值为1,如未进行判定(单位不存在)则输出0

单个单位的爬升率

单位:英尺/分钟 计算所使用的速度和高度均为绝对速度和海拔高度

1
2
3
4
5
6
7
8
9
rate = oms.unitClimbRate(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	rate --爬升率		
	
注意 --正常运行时最小输出值为1(即单位在平飞或下降),如未进行判定(单位不存在)则输出0

单个单位的下降率

单位:英尺/分钟 计算所使用的速度和高度均为绝对速度和海拔高度

1
2
3
4
5
6
7
8
9
rate = oms.unitDiveRate(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	rate --下降率		
	
注意 --正常运行时最小输出值为1(即单位在平飞或爬升),如未进行判定(单位不存在)则输出0

单个单位的爬升角度

单位:度 为速度矢量所指向的角度,非机头指向角度

1
2
3
4
5
6
7
8
9
angle = oms.unitClimbAngle(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	angle --爬升角度		
	
注意 --正常运行时最小输出值为1(即单位在平飞或俯冲),如未进行判定(单位不存在)则输出0

单个单位的俯冲角度

单位:度 为速度矢量所指向的角度,非机头指向角度

1
2
3
4
5
6
7
8
9
angle = oms.unitDiveAngle(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	angle --俯冲角度		
	
注意 --正常运行时最小输出值为1(即单位在平飞或爬升),如未进行判定(单位不存在)则输出0

单个单位的航向

1
2
3
4
5
6
7
8
9
heading = oms.unitHeading(flag, name)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	name --单位名(不是玩家名),如不填则为默认报名者oms.challenger
输出值
	heading --当前航向,单位度,可能会与机舱内看到的磁航向有偏差		
	
注意 	--正常运行时最小输出值为1,航向正北输出360,如未进行判定(单位不存在)则输出0

两个单位的航向差

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
diff = oms.headingDiff(name1, name2, flag)

输入值
	flag --输出的旗标名,如输出到变量则可不填,为实际偏差的绝对值
	name1 --1号单位名(不是玩家名)
	name2 --2号单位名(不是玩家名)
输出值
	diff --航向差,单位度。单位2比单位1航向偏右输出正值,偏左输出负值
	
注意 	--正常运行时最小输出值为1,即使航向完全相同,如未进行判定(单位不存在)则输出0
	--使用变量输出可看到正负和0,但旗标则只能输出绝对值

随机旗标值

限定一个最小值和最大值,在两者之间随机选中一个整数写入旗标值中
如果不写最大最小值,则默认为 1 ~ 100

1
2
3
4
5
6
7
8
num = oms.randFlag(flag, lowerBound, upperBound)

输入值
	flag --输出的旗标名,如输出到变量则可不填
	lowerBound --随机数最小值
	upperBound --随机数最大值
输出值
	num --生成的随机数

随机时间间隔

时间单位:秒 限定一个最小值和最大值,在两者之间随机选中一个整数作为时间间隔
在此秒数后,将选定的旗标设定为 1

1
2
3
4
5
6
7
8
dt = oms.randTimer(flag, lowerBound, upperBound)

输入值
	flag --在时间间隔达成后,要设定为1的旗标名
	lowerBound --随机时间最小值
	upperBound --随机时间最大值
输出值
	dt --生成的随机时间间隔