当前位置 : 145z游戏站 | 热血传奇 | 技术教程 | 

传奇版本脚本频繁死循环排查:GOTO递归与QFunction触发闭环修复实操

热度:
M2控制台弹“脚本死循环”“GOTO超过上限”“ScriptDeadLoop”,伴随CPU占用飙高、点NPC卡住、角色掉线、Mir200\Log\ScriptLog.txt不停追加同一文件名和行号,本质只有一类问题:某段脚本在无终止条件下反复GOTO、#CALL或触发自身,引擎跳出不了执行栈。下面按定位→成因→修法→参数兜底的顺序拆。

一、先锁文件与行号(别瞎翻全部脚本)
1.看M2Server控制台报错原文,格式通常是:
脚本执行超时:D:\MirServer\Mir200\Envir\QuestDiary\元宝捐献\捐献.txt第38行GOTO@Loop
直接按路径用Notepad++打开对应文件,跳到行号。
2.控制台只写NPC名没写路径:去Envir\Market_Def找同名NPC脚本,看里面#CALL或GOTO引向哪个QuestDiary文件,那就是真凶。
3.连NPC名都没有:死循环九成在你最近新增/改过的文件里,优先翻这四个目录:
•Envir\QuestDiary\(任务、活动、回收、捐献、转盘)

•Envir\Market_Def\(NPC对话体)

-Envir\MapQuest_def\与QManage.txt(进图/离线触发)
•Envir\QFunction-0.txt(攻击、获经验、登录、死亡等全局触发)

二、四类高频死循环写法(对照你脚本改)
1.无条件GOTO跳回自身或互跳
错误示范:
[@Main]
#ACT
SENDMSG5欢迎
GOTO@Main
或[@A]跳[@B]、[@B]又跳[@A],中间没有任何#IF阻断。
修法:主菜单别写GOTO,让引擎等玩家点选项;非要循环就加计数器:
#IFLARGEHUMANLoopCnt3
#ACTBREAK
#ELSEACT
INCHUMANLoopCnt1
GOTO@Main

2.循环回收/检测不判断退出条件
装备回收脚本常见:
#ACT
TAKE装备1
GOTO@Recycle
没先CHECKITEM装备1,背包空了还跳,直接死循环。
修法:循环入口先判定,不满足就BREAK:
#IFCHECKITEM装备1
#ACTTAKE装备1
GOTO@Recycle
#ELSEACTBREAK

3.QFunction/触发事件互锁递归(最隐蔽)
典型:[@GetExp]里GOTO@宗派经验,@宗派经验里AddTextList写文件被引擎算成“又获得经验”,再触发[@GetExp],形成“获经验→写文件→获经验”无限递归;或者[@PlayLevelUp]CALL回等级事件本身。
修法:
•严禁在[@GetExp]、[@PlayLevelUp]、[@OnLogin]里直接GOTO会反触发的段;

•经验结算改到RobotManage.txt定时轮询([@OnTimer30]每分钟跑一次);

-或挪到[@KillMon]、[@OnKillMob]杀怪触发,避开底层事件;
•临时止血:在[@GetExp]段首加//注释或删掉那行GOTO,重启M2看报错是否消失。

4.一个#ACT下挂多个GOTO/#CALL嵌套
GOTO是绝对跳转,执行第一个后后面全忽略,但若多个GOTO分散在不同判定段互相CALL,容易超引擎默认堆栈(GOM默认30层)。
修法:单段只留一个GOTO;多段并行用#IF分支或#CALL独立文件,别链式互CALL;嵌套循环超3层拆文件。

5.变量不重置导致判定恒真
如CheckVarHumanFlag0但后面没SETHumanFlag1,玩家每次点都进同一段;或GetRandomText取值前没mov清空,继承上次的空值反复跑。
修法:循环前movVar0/movS$Temp,处理完立刻SET标记,下次进来走#ELSEACTBREAK。

三、具体修正片段对照
错误回收段:
[@Recycle]
ACT

TAKE沃玛装备1
GIVE元宝5
GOTO@Recycle

修正后:
[@Recycle]
IFCHECKITEM沃玛装备1

ACT

TAKE沃玛装备1
GIVE元宝5
INCHUMANRecCnt1
GOTO@Recycle
ELSEACT

SENDMSG6回收完成,共回收<$HUMAN(RecCnt)>件
SETHUMANRecCnt0
BREAK

QFunction经验互锁修正:
;原写法(删掉)
;[@GetExp]
;#ACT
;GOTO@宗派经验
;新写法:RobotManage.txt
[@OnTimer30]
IFCHECKNAMELIST..\QuestDiary\宗师系统\宗主名单.txt

ACT

CALCVARHUMANZongMenExp+<$EXP>
BREAK

四、引擎层兜底参数(治标不治本,但先保端不崩)
1.打开Mir200\!Setup.txt或Setup.txt,找:
ScriptGotoCountLimit=20(或10/300)
改成5000~50000之间,保存重启M2,临时抬高跳转阈值不再秒报死循环。
2.M2→选项→功能设置→其它控制→脚本循环次数,默认20改50~100测试。
3.递归深度超限的端(GOM等):M2→选项→参数设置→递归深度默认50改200。
注意:改参数只是延后爆炸,逻辑闭环不拆照样循环,只是不弹窗而已。

五、标准排查顺序(照做十分钟定位)
1.备份报错脚本文件到桌面,防止改崩;
2.看M2/Log\ScriptLog.txt拿路径行号;
3.用//逐段注释近期改动,重启M2,注释到不报错那段就是源头;
4.按上面四类成因改:去无条件GOTO、加CHECKITEM/CHECKVAR退出、拆QFunction递归、单#ACT单GOTO;
5.保存→完全重启M2(别只重启登录器)→进游戏点对应NPC/触发任务验证;
6.仍报再抬ScriptGotoCountLimit,但根因必须修脚本。

常见踩坑提醒:Delay设为0塞进循环、坐标节点误差过大导致来回跑脚本卡死、GlobalVar.ini损坏让检测命令空等、插件(绿盟/945类)与DelayGoto冲突,这些表现像死循环,实际是数据或外部依赖异常,查的时候一并看下文件完整性和插件命令兼容。
[顶部]