来回跑和死循环在传奇服务端中是两个不同层面的问题。来回跑是脚本的路径逻辑出了问题,角色在A点和B点之间无意义往返,操作指令本身还能响应,但路线始终无法到达预期目标。死循环则是脚本的执行流程出了故障,系统陷入无限循环调用,M2引擎在1秒内反复执行同一段脚本,CPU占用飙升,最终报错并强制中断。两者经常同时出现,因为路径节点设置错误或条件判断缺失,既可能导致来回跑,也可能进一步触发死循环。
排查的第一步是看引擎日志。打开Mir200目录下的Logs文件夹,搜索“脚本死循环”关键词,日志中会明确标注问题脚本所在的文件、NPC名称、触发的标签和命令。比如“[脚本死循环] NPC:QFunction 位置:0(0:0) 命令:GOTO@宗派经验 1秒1次”,这表示问题出在QFunction-0.txt文件中的@GetExp触发段,循环元凶是GOTO@宗派经验这条命令。如果没有日志,也可以根据游戏内的触发场景反推:和某个NPC对话后卡住,就找对应的NPC脚本文件;进入某张地图后出现异常,就查MapQuestDef目录下对应地图的脚本。
## 一、来回跑与死循环的区分和关联
来回跑的核心表现是角色在固定两点或几个节点之间反复折返,或停在某个坐标附近来回移动无法脱出。主要原因有三个:坐标记录不准确,比如把盟重的坐标写成了比奇的坐标,角色到达后无法触发下一步指令,系统只能重新规划路线;节点距离过近或重叠,比如两个路径点相距不到10格,脚本的移动判定出现冲突;移动速度设置过高,被服务器判定为异常行为后强制拉回原位,形成来回拉扯。
死循环的表现则更为剧烈。服务端方面,M2Server日志持续输出重复报错,CPU占用率飙升,最终提示脚本执行超时或直接崩溃。游戏内方面,对话框反复弹出同一内容无法关闭,提交任务物品后操作无响应,或者活动怪物无限刷新。来回跑如果持续时间过长,也会转化为死循环,因为脚本在不断重试路径的过程中,GOTO跳转次数持续累积,一旦超过引擎设定的阈值就会触发死循环报错。
判断的简单方法是看M2日志有无报错。没有报错但角色在来回走,是路径逻辑问题;有“[脚本死循环]”报错且CPU占用异常,则是执行流程出了问题。两者需要同时排查,因为路径设置错误往往是死循环的间接诱因。
## 二、引擎参数的第一轮调整
在修改任何脚本之前,先检查!setup.txt文件中的ScriptGotoCountLimit参数。这个参数控制脚本GOTO跳转的最大次数,默认值通常为10次或300次。路径来回跑的脚本往往需要较多次跳转来完成检测和移动,如果参数值过低,正常的来回跑流程也会被误判为死循环。
找到D:\mirserver\Mir200\!setup.txt,搜索ScriptGotoCountLimit,将数值改为10000到50000之间。修改后必须重启M2引擎才能生效。但需要注意,这个参数只是防止误判的缓冲机制,不是死循环的根治方案。如果脚本本身存在逻辑闭环,调大参数只会延迟报错时间,不能从根本上解决问题。有技术文档指出,M2引擎对GOTO的承受能力存在上限,参数设置过大会让引擎在临近崩溃值之前没有机会发出预警,导致直接死机。
GEE引擎还需要检查M2Server的选项设置。在M2Server中打开“选项-功能设置-其它控制”,其中有一个脚本循环次数参数,默认值为20,可以调整为30或50。这个参数与!setup.txt中的ScriptGotoCountLimit是互补关系,前者控制单次脚本执行的循环检测频率,后者控制GOTO跳转的总次数上限。
## 三、来回跑脚本的路径修复
参数调整后如果来回跑现象仍然存在,需要修复脚本的路径逻辑。
坐标校验是第一步。打开脚本文件,逐个检查路径节点的坐标是否与实际地图匹配。打开游戏内置的坐标显示功能,手动走到目标位置记录精确坐标,与脚本中填写的数值逐一核对。部分版本的地图更新后坐标会有微调,误差超过5格就需要重新记录。
节点距离和循环间隔需要调整。来回跑脚本中相邻两个路径点的距离不应小于10格,否则移动指令的判定会出现冲突,角色在两个过近的点之间反复横跳。单次循环的总时长建议不少于120秒,过短的循环会导致角色频繁瞬移,被服务器判定为异常行为。
移动速度的设置也需要注意。在脚本工具的参数中将移动速度设为“中等”,不要追求最高速度。高速移动在部分引擎中会触发反外挂机制,角色被强制拉回起点,表现就是来回跑。地图路径上的障碍物同样需要排查,用脚本工具自带的地图标记功能圈出节点,确认两点之间的直线上没有墙壁或NPC阻挡。
对于使用MoveTo或WalkTo移动指令的脚本,需要确认坐标与地图ID的对应关系。一个常见错误是将盟重省的坐标写在了比奇省的地图ID下面,角色到达目标坐标后发现地图不匹配,脚本不断重试移动指令,形成来回跑。修复方法是检查每个移动指令中的地图编号与当前所在地图是否一致。
## 四、GOTO跳转滥用导致死循环的修复
来回跑脚本中大量使用GOTO来实现流程控制,这是死循环最常见的诱因。
一个#ACT块中只能使用一个GOTO命令。如果写成了“goto@标签A”紧接着又写“goto@标签B”,第一个跳转执行完毕后会返回到原位置继续执行第二个跳转,形成交叉循环。正确的做法是将两个跳转拆分成独立的#IF判断段,或者用#CALL替代多个GOTO。
延迟跳转命令是GOTO的替代方案。将“goto@循环检测”改为“delaygoto1000@循环检测”,强制每次跳转间隔至少1秒。DELAYGOTO的时间单位是毫秒,1000代表1秒。这个延迟不仅打破了时间上的指令重合,还给服务器留出了处理前一个操作的时间缓冲。但需要注意,DELAYGOTO的时间设置不要过短,GOM引擎中如果设置成2000毫秒(2秒),脚本执行的节奏会比较合理,设置成2(即2毫秒)几乎等于没有延迟,起不到缓解作用。
QFunction触发脚本的死循环需要特别处理。以@GetExp为例,这个段在每次获得经验时都会触发,如果其中包含了GOTO@宗派经验,而@宗派经验执行完毕后没有明确的终止标记,服务端会再次触发@GetExp,形成“触发→跳转→执行完毕→再次触发”的无限循环。修复方法是在@GetExp中添加防重入判断,同时给@宗派经验脚本添加BREAK或RETURN命令明确终止流程。
## 五、变量未重置导致的判定失效
循环判定脚本中变量未正确清空,是死循环的另一个高发原因。
使用GetRandomText读取文本内容时,如果读取到空值,变量不会赋值为空,而是继承上一次的值。这样上次的值永远是最后一个有效数据,导致循环条件一直成立,脚本永远无法跳出。解决办法是每次使用GetRandomText之前,先用mov命令清空相关变量。例如“mov S$在线玩家”,确保变量从空值状态开始读取。
循环计数变量也需要在每轮循环结束后检查状态。使用LARGE命令判断计数变量是否超过阈值,超过则执行BREAK跳出循环,未超过则INCN$循环次数1递增后继续。这个结构可以防止计数变量未更新导致的无限循环。以一个来回跑脚本的循环检测为例,在[@循环检测]标签中添加“#IF LARGE N$循环次数 100 #ACT BREAK”,可以强制在循环超过100次后退出。
## 六、脚本逻辑重构的规范
修复死循环的根本在于编写脚本时就建立规范。
减少GOTO的使用频率。复杂的流程逻辑尽量拆分成独立的子脚本,减少嵌套层数。跨脚本调用使用#CALL时注意GOM引擎的堆栈限制,默认上限为30次,超过这个次数会引发异常。
每个循环结构必须有明确的终止条件。使用WHILE或FOR循环时,必须设置循环次数上限或动态终止条件。遍历在线玩家列表的脚本必须判断是否已经读取到名单末尾,不能无限读取空值。
来回跑脚本的特殊处理需要在每个节点添加停留时间限制,避免因条件不满足而无限等待。同时设置合理的循环间隔,单次循环建议不少于120秒,配合背包检测和血量检测作为触发条件。如果某个节点的条件在长时间内无法满足,脚本应该跳出当前循环并重新评估路径,而不是在原地无限重试。
## 七、临时应急处理
当服务端已经出现死循环报错且无法立即修复脚本时,首先在M2Server中手动重启引擎或重启整个服务端,让脚本执行队列清空。重启前删除服务端缓存目录下的临时文件,确保修改后的脚本正常加载,避免旧缓存导致修改不生效。
排查过程中建议逐段注释脚本进行测试。将怀疑有问题的脚本段用注释符号临时屏蔽,观察问题是否消失。如果问题消失,说明该段脚本存在逻辑缺陷;如果问题仍然存在,继续排查下一段。这种二分法可以快速缩小问题范围,避免在大量代码中盲目搜索。
传奇来回跑脚本死循环怎么办 从日志定位到修复的完整操作流程
来源:
作者:
点击:

