传统zmud时间控制使用ts wa,ts用于手动的一些简单环境,用于自动环境不够灵活,也容易被不小心修改。
#wa有等待时间叠加的问题,一旦网络延迟、并发,机器人容易发狂,一般只用于简单控制。
用#alarm比较好,这是一个专门的时间tr,常用的一般有3种:
#alarm -0.5 {#say ok} 表示每隔0.5秒执行一次
#alarm +1 {#say ok} 表示1秒后执行1次,然后这个tr自动删除
#alarm 1:00:00 {#say ok} 只在每天1点整执行
mud机器人的核心就是触发,诚三习惯上把机器人称为tr,所以在可能的情况下,尽可能的根据mud返回的字符串触发命令,每隔1秒执行的话,会给服务器造成无谓的负担。
为了机器人的稳定,我们可以做一个公共状态检测class,这个class最基本的功能就是防止断线,
比如#ALARM {-180} {#case (%random( )) {idle} {#cr} {hoho} {#cr}}
每180秒随机执行一个简单命令,甚至是#cr简单给mud发送一个空行。
基于这个思路,你可以同时执行一个{#add @id.idle 3;#if (@id.idle>10) {#say 你已经发呆了10分钟};#exe @id.run},用于某些机器人停止后的重新恢复。
假如你的机器人正在执行某项任务,可以定义如果机器人停止后的reboot命令:#var @id.run {#say tx;admire}
每个指令执行完毕,#var @id.idle 0,重置发呆检测时间。
总之,通过这个思路你可以给自己的机器人增加一个保险,也可以在不忙的时候自动重新连接,清理一些变量让zmud更稳定高效。
在某些情况下,mud返回的字符串不足以作为触发条件,或者网络不稳定,乃至需要几个id相互配合才能完成任务,那么我们可以用tell id配合定时器来完成。
找一个现成的例子,诚三玩过很多年的天龙八部mud,如果自己的内力有提升上限的空间,可以自己打坐缓慢提升,也可以接受另外几个id传送过来不超过自己上限内力,然后自己dazuo 20以最小的busy时间提升一点上限。
实现思路运行hp,把打坐id的内力状态tell传功id,传功id计算后消耗掉多余当前内力,执行传功指令,向打坐id传送合适的内力。
打坐id的tr很好做,无非就是通过按钮设置有哪几个id给自己传功,然后在收到指令后轮流把状态tell给几个传功id,适当的情况下dazuo 20而已。诚三介绍一下传功的做法,借以说明#alarm的用法:
#CLASS {transid} {disable}
#TRIGGER {~((%w)~)告诉你:(%d) (%d)$} {
#if (%1=@trans.dazuoid) {
判断tell来的消息是否是指定的打坐id,防止错误触发浪费busy时间。
#math trans.need (%3*2-%2)*2
#var trans.nowneed "yes"
hp
计算需要传送的内力值,设定传送状态许可变量@trans.nowneed,执行hp查看自己的状态。
}
}
#TRIGGER {^?? 气血:%s%d/%s%d%*内力:%s(%d)%s/%s(%d)} {
#if (@trans.nowneed="yes" and @trans.nowbusy<>@trans.busy) {
#t- transid
符合给定条件,但是当前busy时间不符合设定busy时间,就关闭tr,执行本次的延时tr,手动输入额外的hp不受影响。
#var trans.nowbusy @trans.busy
#var trans.nowneed "no"
@trans.busy是预先通过按钮提示,手动设定的一个打坐id的busy时间。
#untrigger {<+@trans.busy>}
#alarm {<+@trans.busy>} {
#var trans.nowbusy 0
hp
}
#alarm +x 表示在x时间后执行一次{}中的指令,尽管这个时间tr会自动删除,为了避免异常情况下删除不及时,#untr是一个防范措施。每次传功id执行传送指令,必须间隔事先指定的时间。
由于指定busy时间后,诚三并不能确定busy是否真的结束了,所以说稍显粗糙,偶尔运行会浪费一次busy时间,但不影响总体运行。如果做得再精致一些,可以增加一条判断busy的mud指令,增加一个状态变量控制。
剩下的指令,无非就是计算需要传送的内力值,消耗掉多余的内力,执行传送指令,让打坐id重新检测,然后传功id自己开始恢复内力,重新打开本class等待新的tell指令。
在高级传功id超过2个的时候,打坐id增加内力上限的速度就是 最小busy时间+网络延迟。
tell指令的好处是可以消除网络延时的影响,也最大程度实现tr的通用化,可以多人、多机器配合运行。在某些追求高效的场合,所有id如果全在本地,可以用 :窗口名称:#say hi 直接运行。
#math trans.over (%1-%2-@trans.need-1)
#if (20>@trans.over and @trans.over>0) {#var trans.over 20}
yunqi @trans.over
#2 exert transfer @trans.dazuoid
tell @trans.dazuoid 检测
#if (@trans.over>=@trans.yunqi) {} {yunqi @trans.yunqi}
dazuo @trans.dazuo
#t+ transid
}
}
#CLASS 0
诚三作的tr大多是给别人用的,所以一个好的按钮式弹出菜单,更能直观设定各种初始变量。无非就是把#prompt和一些开关指令做到一个组合按钮上而已。这一个按钮上集合“客户和服务”的开关指令,稍显复杂。
在这里,再次大力推荐rec纪录型变量。本例子用到了几十个变量,如果单独起名字就容易重复,后期维护修改更麻烦,自己都记不住。但是用rec变量就好多了,看起来只是一个@trans变量。
#BUTTON 3 {传功打坐} {} {设置传功id 参数|设置打坐id 参数|——|开始传功|开始打坐|——-|关闭传功打坐系统|———–} {#prompt trans.dazuoid {被传功的id };#prompt trans.yunqi {传功的id需要yunqi 多少 };#prompt trans.dazuo {传功的id需要dazuo 多少 };#prompt trans.busy {传功的id需要busy 多少秒 };#show 设置给 @trans.dazuoid 传功,运行一次 yunqi @trans.yunqi dazuo @trans.dazuo 需要busy @trans.busy 秒|#prompt trans.transida {第一个给你传功的id };#prompt trans.transidb {第二个给你传功的id };#prompt trans.transidc {第三个给你传功的id };#var trans.idnum 1;#show @trans.transida @trans.transidb @trans.transidc 将给你传功||#say 你将要给 @trans.dazuoid 传功,运行一次 yunqi @trans.yunqi dazuo @trans.dazuo 需要busy @trans.busy 秒;#say 开始传功;#t+ transid;#t- dazuoid|#say 开始打坐;#t- transid;#t+ dazuoid;hp||#untrigger {+4};#t- transid;#t- dazuoid;#say 关闭传功打坐系统} {} {} {} {Size} {70} {23} {} {} {} {} {0|0|0|0|0|0|0} {} {} “” {} {一个id传功 另一个id打坐提升内力} {btntrans}