功能-自定义指令
1.基础讲解
自定义指令,本质上就是一个识别画面
的线程和一个操作
的线程在同时运行。
识别画面
的线程,对游戏画面进行识别后,通过触发和设置各种状态
,来指导操作
的线程做具体的操作。
操作
的线程,会区分常规循环操作和特殊事件触发操作。没有特殊事件时,以常规循环操作;发生特殊事件时,打断当前操作,进行特殊事件对应的操作。
换成游戏过程来解释就是,假设我当前配队是 安比 + 妮可 + 朱鸢,一个完整的战斗流程大概是以下这样的:
- 正常情况,我需要安比站场打失衡。这是
常规循环操作
。 - 如果怪物攻击,画面出现黄光或者红光,那需要进行闪避,或者格挡。闪光的出现,是
特殊事件触发操作
。 - 当我把怪物打入失衡,触发了
连携技
,需要选择换人。连携技按钮
的出现,是特殊事件触发操作
。 - 连携技换人后,我需要先切换妮可,触发
快速支援
。快速支援按钮
的出现,是特殊事件触发操作
。 - 最后,朱鸢登场后,不断长按普攻清空弹匣。这是
常规循环操作
。
下述就以这个 例子 让你初步了解自定义指令以及如何编写。
注意:本例子仅为讲解而拼凑内容写出,无法用于实战。
1.1.配置文件
目前没有编辑器页面,需自行编辑。 配置文件为 yaml
格式,(不懂的自行找通义千问)
希望有人在理解整套运行框架后可以提供一个可视化布局的设计
配置文件按使用场景存放在不同目录下
- 闪避助手 - config/dodge/
- 自动战斗 - config/auto_battle/
脚本中已经自带了部分配置文件,你可以直接使用,也可以在理解完本页内容后自行修改编写。
编辑时,请复制 *.sample.yml
文件,更改为自己的名称。否则 .sample.yml
的修改会在代码同步时被覆盖。后续所有配置文件同理。
1.2.场景与触发器
我们先来看 scenes
(场景)部分的配置。
scenes:
- triggers: ["闪避识别-黄光", "闪避识别-红光"]
interval: 1
handlers: ...
- triggers: ["按键可用-快速支援"]
interval: 1
handlers: ...
- triggers: ["按键可用-连携技"]
interval: 1
handlers: ...
- triggers: []
interval: 0.5
handlers:
一个自定义指令中,会存在多个场景
(scenes
是一个列表)。
- 会有若干场景需要触发器(triggers),即运行过程中,脚本识别游戏过程发生了某个特殊事件,就会触发这个场景下的处理器(handlers)。如上所示:
- 出现
闪避识别-黄光
或者闪避识别-红光
的时候会触发第1个场景里的处理器 (handlers) - 出现
按键可用-快速支援
的时候会触发第2个场景里的处理器 (handlers) - 出现
按键可用-连携技
的时候会触发第3个场景里的处理器 (handlers)
- 出现
- 由于画面识别是持续不断的,机器性能越好,识别触发事件的频率就越高。因此触发器设置有触发间隔(interval),如上所示:
- 出现
闪避识别-黄光
或者闪避识别-红光
的之后,1秒
内再次出现的闪避识别-黄光
或者闪避识别-红光
,将不会再触发这个场景的处理器 (handlers) - 下面2个场景同理
- 出现
- 只会有最多一个不需要触发器的场景,代表没有特殊事件时,就按这个场景去循环触发动作。例如安比不断地3A重击。
- 有触发器的场景,被触发时,会打断当前正在执行的场景指令,去执行被触发场景的指令。例如
- 安比在打3A重的时候,出现
闪避识别-红光
,就会打断原来的后续攻击,执行闪避。 - 安比在打3A重的时候,将怪物打失衡了,出现
按键可用-连携技
,就会打断后续攻击,执行连携技换人。
- 安比在打3A重的时候,出现
1.3.触发器优先级
还是按上面的配置,我们考虑以下情况
- 场上有多个怪,其中一个出现黄光,我们切出了安比格挡,准备接下一个攻击的动作打失衡(挡刀后那一下重击)
- 这时候另一个怪闪了红光,我们就会打断当前动作去闪避。
- 可实际上这一步是可以不闪的,因为格挡后有一段无敌的时间。
针对这个情况,我们引入优先级的概率,每个场景(触发器),只会被更高优先级的打断。没有设置优先级的视为可以随便打断。
scenes:
- triggers: ["闪避识别-黄光"]
interval: 1
priority: 99
handlers: ...
- triggers: ["闪避识别-红光"]
interval: 1
priority: 99
handlers: ...
- triggers: ["按键可用-快速支援"]
interval: 1
handlers: ...
- triggers: ["按键可用-连携技"]
interval: 1
handlers: ...
- triggers: []
interval: 0.5
handlers:
以上为改造后的例子
- 使用
priority
声明场景的优先级 - 黄光、红光为最高优先级,可以打断其他场景
- 黄光、红光同等优先级,互相之间不可打断
- 其他场景没有优先级,可以随意打断
1.4.状态判断及动作
区分场景后,每个场景中,需要做什么,就是上述的处理器 handlers
部分负责的内容。
每个处理器包含 多组的状态判断(states)
和 执行动作(operations)
states
部分为状态判断
的表达式,满足表达式的情况下,就会执行动作 operations
;不满足的话,就会继续判断下一个states
- triggers: ["闪避识别-黄光", "闪避识别-红光"]
interval: 1
handlers:
- states: "[闪避识别-黄光, 0, 1] & [后台-2-强攻]"
operations:
- op_name: "按键-切换角色-上一个"
post_delay: 0.2
- op_name: "按键-普通攻击"
- states: "[闪避识别-黄光, 0, 1]"
operations:
- op_name: "按键-切换角色-下一个"
post_delay: 0.2
- op_name: "按键-普通攻击"
data: []
- states: "[闪避识别-红光, 0, 1]"
operations:
- op_name: "按键-闪避"
post_delay: 0.2
- op_name: "按键-普通攻击"
data: []
- states: "[自定义-朱鸢-子弹]{6, 9}"
operations:
- op_name: "按键-普通攻击"
way: "按下"
press: 3
上述例子的解释如下
- 如果
闪避识别-黄光
的时间是发生在0~1
秒内,且后台第二个角色是强攻,那么就执行下面的 切上一个 + 平A - 如果1不满足,就继续判断,如果
闪避识别-黄光
的时间是发生在0~1
秒内,就执行下面的 切下一个 + 平A - 如果2不满足,就继续判断,
闪避识别-红光
的时间是发生在0~1
秒内,则执行下面的 闪避 + 平A - 如果3不满足,就继续判断,
自定义-朱鸢-子弹
的时间是发生在0~1
秒内,且子弹数是6~9
之间,那就长按普通。 - 当然4这一行是不可能触发的,因为1~3行的场景已经把这个触发器下的场景都覆盖了;另外脚本目前也没有识别子单数的能力;写这里只是为了文档展示。
1.4.1.状态说明
脚本运行时,会对游戏状态进行识别,我们将状态定义为以下3部分:
- 状态的名称 - 即上述例子中
[]
(中括号)里的内容。脚本支持的状态名称在下述章节再列举。 - 状态的识别时间 - 即什么时候出现(识别到)的这个状态。通常有两种时间,对于画面识别的,为截图时间;对于按键的,为按键时间。
- 状态的值 - 只有部分状态会有值的概念,例如能量条之类的。目前脚本支持的状态都还没有值,但可以在自定义状态中灵活使用。
1.4.2.状态表达式
states
部分是状态表达式,用于判断是否满足条件:
- 表达式中的空格,会被忽略。
- 表达式中,
[]
(中括号),包含的内容为具体的状态判断,会包含2部分:- 状态名称 : 上述例子的
闪避识别-黄光
- 上一次出现(识别到)这个状态,距离现在过去的时间(秒数),是否在后续2个数字(包含)的范围内。上述例子的
0, 1
。如果没有填入数字,则默认为0~1
秒内。 - 状态表达式为空时,代表一种最终兜底的状态,即恒定判断为真。
- 状态名称 : 上述例子的
- 表达式中,
[]
(中括号)后面,可以跟随{}
(大括号),表示判断这个状态下的值,是在后续2个数字(包含)的范围内。数字只能是整数。无大括号时,表示无需考虑状态值。 - 表达式支持运算符
&
(且),|
(或),!
(否),()
(括号),&
和|
没有运算优先级,运算先后顺序建议使用()
保证。
状态表达式例子1
闪避识别-黄光
的时间是发生在 0~1
秒内,且识别到后台第二个角色是强攻是在 0~1
秒内。
- states: "[闪避识别-黄光, 0, 1] & [后台-2-强攻]"
状态表达式例子2
连携技左 或者 连携键右 的按键的时间是发生在 0~12
秒内,即粗略表达怪物的失衡时间。
- states: "[按键-连携技-左, 0, 12] | [按键-连携技-右, 0, 12]"
状态表达式例子3
画面出现黄光、或者红光的时候,且前台不是强攻。这时候可以考虑用强攻角色格挡。
- states: "([闪避识别-黄光] | [闪避识别-红光]) & ![前台-强攻]"
状态表达式例子4
前台角色为朱鸢,且子弹数是6~9颗。
- states: "([前台-朱鸢] & [自定义-朱鸢-子弹]{6, 9}"
1.4.3.指令
operations:
- op_name: "按键-切换角色-上一个"
post_delay: 0.2
满足状态 states
后,可以触发一系列的指令 operations
。
即 operations 是一个列表,每一个的指令包含两部分:
- op_name: 指令名称。
- post_delay: 除了指令名称外,不同的指令下会有不同的可用参数,这里的
post_delay
就是其中一个,表示按键后等待秒数。 - 脚本支持的指令名称和对应的详细参数在下述章节再列举。
1.5.子状态
状态的判断,是可以层层递进的。在满足某个状态下,再进行子状态(sub_states)的判断,可以让你的状态判断减少重复,便于维护。
- states: "[按键-连携技-左, 0, 12] | [按键-连携技-右, 0, 12]"
sub_states:
- states: "[前台-朱鸢]"
sub_states:
- states: "[按键可用-终结技]"
operations:
- op_name: "按键-终结技"
- states: "[按键可用-特殊攻击]"
operations:
- op_name: "按键-特殊攻击"
- states: ""
operations:
- op_name: "按键-普通攻击"
way: "按下"
press: 1
- states: ""
operations:
- op_name: "按键-切换角色-下一个"
上述例子:
- 最外层状态为
[按键-连携技-左, 0, 12] | [按键-连携技-右, 0, 12]
。代表我们粗略认为的怪物失衡时间内,再做后续判断 - 子状态1
[前台-朱鸢]
,不满足的时候看子状态2(空)。代表怪物失衡时,我们应该先看前台是不是朱鸢,如果不是,就走子状态2,切换角色。
- 子状态1
[前台-朱鸢]
满足时,再看里面的子状态[按键可用-终结技]
,[按键可用-特殊攻击]
。代表有大用大,有特殊技用特殊技,什么都没有的时候就长按普通攻击清空弹匣。
这里对子状态做一个总结说明:
- 使用
sub_states
声明这个状态下有子状态,需要继续往下判断。 - 子状态
sub_states
也是一个列表,与处理器 (handlers) 一样,里面包含若干个元素,每个元素的包含- states: 状态判断。
- operations: 指令。
- sub_states: 子状态判断。存在时,
operations
不生效。
- 子状态可以多层嵌套,只要你不晕就行。
1.6.状态处理模板
在你编写多个自定义指令的文件后,你会发现有些逻辑是可以共用的,这部分复制粘贴就浪费时间了。场景模板就是承载公共逻辑的地方,让不同的配置文件可以复用。
引用场景模板的方式如下
handlers:
- states: "[按键-连携技-左, 0, 12] | [按键-连携技-右, 0, 12]"
sub_states: ...
operations: ...
- state_template: "站场模板-击破站场"
这里表示,在不满足第一个状态判断 (粗略判断怪物失衡) 的情况下,接下来的状态判断引用模板 站场模板-击破站场
场景模板的存放位置为 config/auto_battle_state_handler
。
同样,脚本自带部分模板,为 .sample.yml
结尾,你可引用,或复制修复。
场景模板中的内容格式如下
handlers:
- states: "[前台-击破]"
sub_states:
- state_template: "站场模板-全角色"
- states: "[后台-2-击破]"
operations:
- op_name: "按键-切换角色-上一个"
post_delay: 0.1
- states: "[后台-1-击破]"
operations:
- op_name: "按键-切换角色-下一个"
post_delay: 0.1
- states: ""
sub_states:
- state_template: "站场模板-全角色"
这个模板的意思是
- 如果前台角色是击破,那继续引用
站场模板-全角色
,这里会有各个角色的站场的处理逻辑。 - 如果1不满足,就看后台2是不是击破,如果是,就切换角色-上一个
- 如果2不满足,就默认使用切换角色-下一个。
场景模板的整体结构跟上述讲解的场景处理器部分是一致的,它应该包含以下内容:
template_name
: 模板名称,用于界面显示、其它文件中引用。多个同名时,会优先取不是.sample.yml
的。如果用户自定义的模板名字重复,则会随机取一个。handlers
: 处理器部分,同之前描述。
在加入场景模板后,场景处理器(handlers中的元素)中的完整可用的结构如下:
- states: 状态判断表达式
- operations: 满足states时,需要执行的指令列表
- sub_states: 满足states时,需要进行下一层判断。
- sub_states是一个列表,里面元素的结构同handlers中的元素结构。
- 出现 sub_states 时,operations无效。
- state_template: 引用模板
- 模板中的handlers结构,同这里的描述。
- 出现 state_template 时,states, operations, sub_states无效。
- sub_states 和 state_template 可以不断嵌套。
引用模板后,状态的判断顺序依然从上往下。例如:
- states: ...
operations: ...
- state_template: ...
- states: ...
operations: ..
这个代表判断状态1,不满足就使用模板逻辑进行判断,还不满足就使用状态3判断。
1.7.指令模板
同理,指令也可以抽出来做模板复用,后续指令模板还可以当输入宏使用,结合闪避助手变成战斗助手。
引用指令模板的方式,参考站场模板-安比
在 operations
中,填入 operation_template
。同样,引入模板后指令依然按顺序执行。
handlers:
- states: ...
operations:
- op_name: ...
data: ...
- operation_template: "安比-3A特殊攻击"
- op_name: ...
data: ...
而一个指令模板的内容结构,参考安比-3A特殊攻击
模板中仅需包含 指令 operations
,结构与上述的指令结构一致。
operations:
- op_name: ...
data: ...
- op_name: ...
data: ...
在加入指令模板后,operations
中的元素的完整可用的结构如下:
- op_name: 指令名称。
- data: 用于执行指令的参数列表,每个参数均为字符串 需要
"
(双引号)包围。 - operation_template: 指令模板名称。operation_template存在时,前2个参数无效。模板中可继续嵌套模板。
- 脚本支持的指令名称和对应参数在下述章节再列举。
1.8.自定义状态
为了大家可以更加灵活控制自己的逻辑,脚本提供自定义状态的能力。参考以下例子:
- triggers: ["按键可用-连携技"]
interval: 1
handlers:
- states: "![自定义-连携次数, 0, 3]"
sub_states:
- states: "[后台-2-强攻]"
operations:
- op_name: "按键-切换角色-上一个"
post_delay: 0.5
- op_name: "设置状态"
data: ["自定义-连携次数", "0", "1"]
- states: ""
operations:
- op_name: "按键-切换角色-下一个"
post_delay: 0.5
- op_name: "设置状态"
data: ["自定义-连携次数", "0", "1"]
- states: "[自定义-连携次数, 0, 3]{1, 2}"
sub_states:
- states: "[后台-2-支援]"
operations:
- op_name: "按键-切换角色-上一个"
post_delay: 0.5
- op_name: "设置状态"
data: ["自定义-连携次数", "0", "2"]
- states: "[后台-2-强攻]"
operations:
- op_name: "按键-切换角色-上一个"
post_delay: 0.5
- op_name: "设置状态"
data: ["自定义-连携次数", "0", "2"]
- states: ""
operations:
- op_name: "按键-切换角色-下一个"
post_delay: 0.5
- op_name: "设置状态"
data: ["自定义-连携次数", "0", "2"]
这一段大概的意思如下:
- 在连携技触发的时候,我会通过
自定义-连携次数
来判断已经按了多少次连携了,从而决定我切什么角色。 ![自定义-连携次数, 0, 3]
这代表还没有出现这个状态,代表没有按过连携,这时候我们先切强攻角色。- 切换后,我们通过指令
设置状态
来设置自定义-连携次数
这个状态的出现,第一个数值0代表当前时间作为状态的出现时间,第二个数值1代表这个状态的值(连携了1次)。 [自定义-连携次数, 0, 3]{1, 2}
,这代表出现这个状态了,而且值在1~2
之间,也就是已经按了1~2次连携了,这时候我们优先切支援,其次切强攻。因为我们不知道后续还能有几次连携,尽量让支援最后一个触发快速支援。- 切换后,我们通过指令
设置状态
来设置自定义-连携次数
这个状态的值为2。
自定义状态的使用非常灵活,大家可以自由发挥脑洞。
设置状态
指令说明见后续 2.2.可用指令
部分。
注意:自定义状态的名称,必须以 自定义-
作为前缀。
2.基础能力说明
通过上述示例,你已经能理解自定义指令大概的工作方式了。
接下来,你就可以挑选合适的状态
和指令
来构建你的自定义指令。
2.1.可用状态
状态名称 | 判断条件 | 记录时间 | 互斥状态 |
---|---|---|---|
闪避识别-黄光 | 游戏画面出现闪避黄光 | 截图时间 | |
闪避识别-红光 | 游戏画面出现闪避红光 | 截图时间 | |
闪避识别-声音 | 游戏画面没有闪光,且出现需要闪避的音频 | 截图时间 | |
按键-闪避 | 脚本执行按键 | 按键结束时间 | |
按键-切换角色-下一个 | 脚本执行按键 | 按键结束时间 | |
按键-切换角色-上一个 | 脚本执行按键 | 按键结束时间 | |
按键-普通攻击 | 脚本执行按键 | 按键结束时间 | |
按键-特殊攻击 | 脚本执行按键 | 按键结束时间 | |
按键-终结技 | 脚本执行按键 | 按键结束时间 | |
按键-连携技-左 | 脚本执行按键 | 按键结束时间 | |
按键-连携技-右 | 脚本执行按键 | 按键结束时间 | |
按键-连携技-取消 | 脚本执行按键 | 按键结束时间 | |
按键-移动-前 | 脚本执行按键 | 按键结束时间 | |
按键-移动-后 | 脚本执行按键 | 按键结束时间 | |
按键-移动-左 | 脚本执行按键 | 按键结束时间 | |
按键-移动-右 | 脚本执行按键 | 按键结束时间 | |
按键-锁定敌人 | 脚本执行按键 | 按键结束时间 | |
前台-**(角色类型) | 前台角色类型=强攻 (举例) | 截图时间 | 其它前台-**(角色类型) |
后台-1-**(角色类型) | 后台第一个角色类型=强攻 (举例) | 截图时间 | 其它 后台-1-**(角色类型) |
后台-2-**(角色类型) | 后台第二个角色类型=强攻 (举例) | 截图时间 | 其它 后台-2-**(角色类型) |
连携技-1-**(角色类型) | 连携技左边角色类型=强攻 (举例) | 截图时间 | 其它 连携技-1-**(角色类型) |
连携技-2-**(角色类型) | 连携技右边角色类型=强攻 (举例) | 截图时间 | 其它 连携技-2-**(角色类型) |
快速支援-**(角色类型) | 快速支援角色类型=强攻 (举例) | 截图时间 | 其它 快速支援-**(角色类型) |
前台-**(角色名称) | 前台角色=安比 (举例) | 截图时间 | 其它 前台-**(角色名称) |
后台-1-**(角色名称) | 后台第一个角色=安比 (举例) | 截图时间 | 其它 后台-1-**(角色名称) |
后台-2-**(角色名称) | 后台第二个角色=安比 (举例) | 截图时间 | 其它 后台-2-**(角色名称) |
连携技-1-**(角色名称) | 连携技左边角色=安比 (举例) | 截图时间 | 其它 连携技-1-**(角色名称) |
连携技-2-**(角色名称) | 连携技右边角色=安比 (举例) | 截图时间 | 其它 连携技-2-**(角色名称) |
快速支援-**(角色名称) | 快速支援角色=安比 (举例) | 截图时间 | 其它 快速支援-**(角色名称) |
按键可用-特殊攻击 | 特殊攻击键不是灰色的 | 截图时间 | |
按键可用-终结技 | 特殊攻击键不是灰色的 | 截图时间 | |
按键可用-连携技 | 出现连携技头像 | 截图时间 | |
按键可用-快速支援 | 出现快速支援头像 | 截图时间 | |
前台-能量 | 左上角能量条 注意能量最大值为120 | 截图时间 | |
后台-1-能量 | 同上 | 截图时间 | |
后台-2-能量 | 同上 | 截图时间 | |
前台-血量扣减 | 左上角血条出现扣减 | 截图时间 | |
自定义-* | 自定义的状态 | 指令设置状态 的参数时间 |
说明:
2.1.1.角色状态
除了基础状态外,部分角色在前台时会额外触发角色特有的状态。
所有角色状态,在切换角色后,都需要下一次识别才能触发。
状态名称 | 记录时间 | 互斥状态 | 使用示例 |
---|---|---|---|
艾莲-急冻充能 | 截图时间 | [艾莲-急冻充能]{3, 6} | |
苍角-涡流 | 截图时间 | [苍角-涡流]{3, 3} | |
朱鸢-子弹数 | 截图时间 | ![朱鸢-子弹数]{7, 10} 当前子弹数小于7 可以用特殊攻击不溢出 | |
青衣-电压 | 截图时间 | [青衣-电压]{75, 100} 当前可以打重击 | |
赛斯-意气 | 截图时间 | [赛斯-意气]{75, 100} 当前可以打重击 | |
简-萨霍夫跳 | 截图时间 | [简-萨霍夫跳] 当前可以用萨霍夫跳 目前只有检测是否有红点,并没有判断红点数量,因此不需要大括号判断数值 | |
简-狂热心流 | 截图时间 | [简-狂热心流]{1, 50} 当前可以用萨霍夫跳补充狂热心流了 |
2.1.2.默认模版使用的自定义状态
默认模版中,使用了一些自定义状态,用于优化战斗流程。 这些是模版里进行设置,且需要在状态判断中配合使用的,不是脚本运行时自动附带的。
如果你想用,可以引用模版,或者参考模版和下述例子自己设置对应的状态。
2.1.2.1.自定义-黄光切人
黄光切人时设置;不同角色格挡攻击后摇时间不同,由角色模版控制等待多长时间进行后续指令
设置例子
handlers:
- states: "[后台-2-击破]"
operations:
- operation_template: "双反-上一个"
- op_name: "设置状态"
data: [ "自定义-黄光切人" ]
- states: "[后台-1-击破]"
operations:
- operation_template: "双反-下一个"
- op_name: "设置状态"
data: [ "自定义-黄光切人" ]
使用例子
handlers:
- states: "[前台-朱鸢]"
sub_states:
# 格挡出场后
- states: "[自定义-黄光切人]"
operations:
- op_name: "按键-普通攻击"
pre_delay: 0.2
post_delay: 1.5
- op_name: "清除状态"
state: "自定义-黄光切人"
- op_name: "设置状态"
state: "自定义-临时站场"
2.1.2.2.自定义-红光闪避
红光时设置;不同角色闪避攻击后摇时间不同,由角色模版控制等待多长时间进行后续指令
设置例子
handlers:
- states: ""
operations:
- op_name: "按键-闪避"
post_delay: 0.2
- op_name: "按键-普通攻击"
- op_name: "设置状态"
state: "自定义-红光闪避"
使用例子
handlers:
- states: "[前台-朱鸢]"
sub_states:
# 闪避后
- states: "[自定义-红光闪避]"
operations:
- op_name: "按键-普通攻击"
pre_delay: 0.8
post_delay: 1
- op_name: "按键-普通攻击"
post_delay: 1
repeat: 2
- op_name: "清除状态"
state: "自定义-红光闪避"
2.1.2.3.自定义-快速支援换人
快速支援换人时设置;不同角色快速支援攻击后摇时间不同,由角色模版控制等待多长时间进行后续指令
设置例子
scenes:
- triggers: [ "按键可用-快速支援" ]
interval: 1
handlers:
- states: "[按键可用-快速支援]"
operations:
- op_name: "按键-切换角色-下一个"
- op_name: "设置状态"
state: "自定义-快速支援换人"
使用例子
handlers:
- states: "[前台-朱鸢]"
sub_states:
- states: "[自定义-快速支援换人]"
operations:
- op_name: "等待秒数"
data: [ "0.5" ]
- op_name: "清除状态"
data: [ "自定义-快速支援换人" ]
- op_name: "设置状态"
state: "自定义-临时站场"
2.1.2.4.自定义-连携换人
连携换人时设置;不同角色快速支援攻击后摇时间不同,由角色模版控制等待多长时间进行后续指令;同时可用于失衡判断
设置例子
handlers:
- states: "[连携技-1-击破]"
operations:
- op_name: "按键-连携技-左"
- op_name: "设置状态"
state: "自定义-连携换人"
- states: "[连携技-2-击破]"
operations:
- op_name: "按键-连携技-右"
- op_name: "设置状态"
state: "自定义-连携换人"
使用例子
handlers:
- states: "[前台-朱鸢]"
sub_states:
- states: "[自定义-连携换人]"
operations:
- op_name: "等待秒数"
data: [ "1.5" ]
2.1.2.5.自定义-临时站场
想插队站场的时候设置;例如朱鸢黄光出来的时候打几发子弹再切回击破,避免溢出
设置例子
handlers:
- states: "[前台-朱鸢]"
sub_states:
# 格挡出场后
- states: "[自定义-黄光切人]"
operations:
- op_name: "按键-普通攻击"
pre_delay: 0.2
post_delay: 1.5
- op_name: "清除状态"
state: "自定义-黄光切人"
- op_name: "设置状态"
state: "自定义-临时站场"
使用例子
scenes:
- triggers: [ ]
interval: 0.02
handlers:
# 刚开始未识别到角色时候不要乱切
- state_template: "通用模板-锁定敌人"
- state_template: "站场模板-未识别角色"
- states: "[自定义-黄光切人, 0, 2] | [自定义-红光闪避, 0, 2] | [自定义-临时站场]"
sub_states:
- state_template: "站场模板-全角色"
2.1.2.6.自定义-动作不打断
想指令不被触发器打断时设置,例如青衣在打重击的时候不因为闪光打断
设置例子
handlers:
- states: "[前台-青衣]"
sub_states:
- states: "[青衣-电压, 0, 999]{75, 101}"
operations:
- op_name: "设置状态"
state: "自定义-动作不打断"
value: 1
- op_name: "按键-普通攻击"
way: "按下"
press: 3.5
- op_name: "清除状态"
state: "自定义-动作不打断"
- op_name: "清除状态"
state: "自定义-青衣-普攻次数"
使用例子
scenes:
- triggers: [ "闪避识别-黄光", "闪避识别-红光", "闪避识别-声音" ]
interval: 1
handlers:
- states: "![自定义-动作不打断, 0, 999]{1, 1} & [闪避识别-黄光]"
sub_states:
- state_template: "双反模板-强攻"
- state_template: "双反模板-击破"
- state_template: "双反模板-下一个"
- states: "![自定义-动作不打断, 0, 999]{1, 1} & ([闪避识别-红光] | [闪避识别-声音])"
sub_states:
- state_template: "闪A模板-全角色"
2.2.可用指令
指令名称 (op_name) | 参数 |
---|---|
按键-闪避 | pre_delay - 按键前等待秒数(数字) 默认0 post_delay - 按键前等待秒数(数字) 默认0 way - 按键方式(点按、按下、松开) 默认点按 press - 按下秒数(数字) 不填代表不自动松开 repeat - 重复次数(数字) 默认1 |
按键-切换角色-下一个 | 同上 |
按键-切换角色-上一个 | 同上 |
按键-普通攻击 | 同上 |
按键-特殊攻击 | 同上 |
按键-终结技 | 同上 |
按键-连携技-左 | 同上 |
按键-连携技-右 | 同上 |
按键-连携技-取消 | 同上。这个按键比较怪,需要按下一段时间才有效 |
按键-快速支援 | 同上 |
按键-移动-前 | 同上 |
按键-移动-后 | 同上 |
按键-移动-左 | 同上 |
按键-移动-右 | 同上 |
按键-锁定敌人 | 同上 |
等待秒数 | seconds - 秒数(数字) 默认0 |
设置状态 | state - 需要设置的状态名称 seconds - 状态触发距离当前时间的偏移秒数,默认0(当前) value - 需要设置的状态值(整数),默认无 add - 对当前状态值进行增加(整数),value存在时不生效,默认无 |
清除状态 | state - 需要设置的状态名称 |
说明:
设置状态
和清除状态
可以作用于任意状态,只要状态名称填对了。- 触发快速支援时,请使用
按键-快速支援
,这样脚本可以正确计算切换的角色。
2.3.终结技
游戏中,终结技是共用的,如果你希望只能由特定角色使用终结技,可以在文件中加入 allow_ultimate
allow_ultimate:
- agent_type: "强攻"
- agent_name: "安比"
allow_ultimate
是一个列表,里面的元素可以包含 角色类型 agent_type
或者 角色名称 agent_name
配置文件中存在 allow_ultimate
时,只有这里定义的角色在前台,按键可用-终结技
才会被触发。
2.4.识别间隔
识别过程是持续不断的,过于频繁的识别可能带来性能问题,过少的识别可能会反应不及时,因此脚本提供了 识别间隔
的配置。
check_dodge_interval: 0.02
check_agent_interval: [0.4, 0.6]
check_special_attack_interval: [0.4, 0.6]
check_ultimate_interval: [0.4, 0.6]
check_chain_interval: [0.9, 1.1]
check_quick_interval: [0.9, 1.1]
识别间隔可以是一个数字,也可以是两个数字代表一个随机区间。不填入时脚本有默认的间隔。
目前支持以下识别间隔
- check_dodge_interval - 闪避黄光/红光的识别间隔。默认0.02秒。
- check_agent_interval - 识别角色的间隔,理论上只要正确识别5次就足够了,后续脚本会根据按键计算,因此间隔可以大一点。默认0.5秒。
- check_special_attack_interval - 识别特殊攻击按键是否可用的间隔。默认0.5秒。
- check_ultimate_interval - 识别终结技按键是否可用的间隔。默认0.5秒。
- check_chain_interval - 识别连携技按键是否可用的间隔。默认1秒。
- check_quick_interval - 识别快速支援按键是否可用的间隔。默认0.5秒。
3.编写建议
3.1.文件存储
脚本提供的默认配置文件都是以 .sample.yml
结尾的,不要修改这部分文件,也不要新建这种后缀名的文件。否则代码同步时会被作者内容覆盖。
你可以复制改名后再修改使用,各种文件的存放路径统一如下
- 自动战斗 : config/auto_battle
- 闪避助手 : config/dodge
- 场景处理器模板 : config/auto_battle_state_handler
- 指令模板 : config/auto_battle_operation
3.2.触发器
- 偶尔突发的事件,可以用作触发器,例如 闪避识别、连携技、快速支援、爆发技 等,这可以让你的指令在特殊情况下立刻响应。
- 而高频出现的事件,例如 识别到前台角色是安比,这种就不建议在触发器中使用。因为高频的触发判断,可以引起性能问题,后续不方便维护。
- 不需要事件触发的场景,代表平时没有怪物或者其它事件来打断你的操作的场景,用来做角色的连招。
后续脚本框架的发展优化也会以这个为基础思想。
3.3.嵌套触发
试想这么一种场景,你在 触发器1 闪避识别-黄光
里做了一个切人+平A,假如切出的是安比,那会触发一个 前台-安比
的事件。此时,如果你的指令中,有使用 前台-安比
作为触发器2的话,那么触发器2的动作将会执行,触发器1的平A可能会被打断。
因此,需要小心自己指令中是否存在嵌套触发的情况,避免指令丢失。
3.4.攻击按键
游戏中的默认按键,攻击是鼠标的左击,连携技也有鼠标的点击。建议单独给脚本分配一个普通攻击的按键,避免脚本使用鼠标左击进行普通攻击时把连携按掉了。
3.5.失衡判断
目前不支持怪物的失衡识别,但可以通过 按键-连携键-左
和 按键-连携技-右
进行取巧的判断。
即触发连携后,就认为怪物进入失衡了,这时候大概有10+秒的输出空间。
- states: "[按键-连携键-左, 0, 12] | [按键-连携键-右, 0, 12]"
3.6.长按按键
部分角色可能可以通过一直长按攻击键能打出连招,但不推荐使用过长(2s以上)的按键时间。
因为这种操作会一直占据某个按键,甚至一直占据着运行资源,容易在事件触发时造成按键冲突,或无法立刻对事件做出响应。例如闪光时按的闪避无效。
你可以拆分成多个 按下
指令,每个指令是较短的时间,这样脚本能更好打断当前运行。
参考 朱鸢-蓄力3A
3.7.指令长度
由于是采取模拟按键的方式去执行指令,执行过程稍有偏差就会导致角色"呆呆"的,因此不建议一个状态判断里执行过多的指令。
3.8.切换角色后的状态判断
连携、快速支援、格挡、手动换人等切换角色后,建议加入对应状态判断用于过度
例子
handlers:
- states: "[前台-朱鸢]"
sub_states:
# 格挡出场后
- states: "[自定义-黄光切人]"
operations:
- op_name: "按键-普通攻击"
pre_delay: 0.2
post_delay: 1.5
- op_name: "清除状态"
state: "自定义-黄光切人"
- op_name: "设置状态"
state: "自定义-临时站场"
- states: "[自定义-快速支援换人]"
operations:
- op_name: "等待秒数"
data: [ "0.5" ]
- op_name: "清除状态"
data: [ "自定义-快速支援换人" ]
- op_name: "设置状态"
state: "自定义-临时站场"
这么写的作用有
- 可以控制换人后摇动作的时间,在后摇结束后才开始正常连招,防止占用了正常连招的时间导致正常连招卡顿。
- 可以给脚本时间识别切换角色后的状态,例如终结技是否可用、朱鸢子弹数是多少等。因为切换角色的瞬间是没有下一个角色的这些状态的,切换角色后立刻开始正常的状态判断的话,就会出现类似有终结技但不使用,连招一轮后再使用的情况
3.9.状态的时间判断
大部分状态判断都使用了默认值,例如 [青衣-电压]{75, 100}
就是 1秒内
识别到青衣的电压为75以上。
默认值的优势是保证了状态的及时性。
而自定义时间范围可以有以下作用:
- 控制作用时间。例如
[按键-连携技-左, 0, 12] | [按键-连携技-右, 0, 12]
粗略代表了失衡时间。 - 可以沿用旧的识别结果。例如
[青衣-电压, 0, 999]{75, 100}
,代表999秒内识别到这个电压的状态都能使用,这可以让切人瞬间就知道能打重击。但需注意,这种写法需要自行保证 无法识别的过程中,状态不会改变。本例子就是青衣在后台时电压不会改变。
4.编写调试
4.1.指令模板调试
要让你的配置能流畅在自动战斗中使用,建议先对角色的连招进行调试,即先保证你的每一套连招,都能流畅运行。
你可以将你的连招指令,写成一个指令模板,保存在 config/auto_battle_operation
文件夹中,不要使用 .sample.yml
后缀。
项目中已经包含部分角色的指令模板可以使用,你也可以使用。
同时希望大家在完成自己的连招模板后共享出来。
弄了指令模板后,进入【战斗助手】-【指令调试】,然后进入游戏训练场,按F9开始调试。
一个好的指令模板,应该能自己流畅循环,所以建议在训练场中,开启敌人无敌,关闭失衡,单纯循环指令不卡顿即可。
比较容易的调试方式是,最开始只在模板填写2个指令+1个等待时间,调节等待时间让角色能做出第2个动作后,再增加下一个等待时间和指令。直到一套连招都填入后,追加一个最后的等待时间处理角色僵直。最后就可以让这套连招顺畅循环。
4.2.场景调试
在你的每一套角色连招都能流畅循环后,就可以进入场景调试了。入口在【战斗助手】-【自动战斗】上方的调试按钮。
原理是,对游戏画面进行一次截图和识别,然后再运行状态判断和执行指令。
如果调试时候脚本没有按预期做出动作,那你可以只保留部分 states
进行调试
在所有场景都调试通过后,你的配置文件基本就能顺畅运行了。
部分场景有前置依赖,可以通过新建另一个测试配置文件,只写入需要测试的场景进行测试。
5.部分原理说明
下述会列举一些大家在编写自定义指令时,大家可能想了解的脚本运行机制。
5.1.角色识别
在战斗画面对头像进行识别,开始时,以全角色进行匹配识别,效率较低。在连续5次识别成功且角色一致后,就会记录下来这批角色,后续只用这部分角色来识别。
脚本中,触发会换人的按键时,会自动计算并更新角色列表,避免在换人途中短时间内的白色头像无法识别。相关指令如下
- 按键-切换角色-下一个
- 按键-切换角色-上一个
- 按键-连携技-左
- 按键-连携技-右
- 按键-快速支援
在更新角色同时,会对同时更新以下状态
- **-能量 - 跟随角色变化
- 按键可用-终结技 - 会重新判断
- 按键可用-特殊攻击 - 会置为不可用,等待下一次识别