M2窗口弹“脚本死循环”或“GOTO超过上限”,本质是某段脚本在某个标签里跳不出去,引擎反复执行同一段指令直到触发跳转次数保护。先改参数只能压住报错,真要不再弹必须把跳转逻辑改对。
一、先定位是哪段脚本在作妖
• 看M2Server报错行:会直接写“NPC:XXX 脚本:QuestDiary\活动系统\转盘.txt 行号:XX”,照着路径进 Envirl\QuestDiary\ 对应子目录开那个 txt。
- M2没写细就进 Mir200\Log\ 看 ScriptLog.txt,死循环的特征是同一个文件名+同一行号每秒刷几十条。
• 九成死循环出在你最近动过的文件:新加的NPC、转盘、回收、泡点、登录奖励、QFunction-0.txt 触发段。
二、四种最常见的死循环写法(对照改)
1. 无条件跳自己
[@Main]
#ACT
SENDMSG 5 欢迎
GOTO @Main
改法:去掉 GOTO @Main,或者加条件+计数器,到次数 BREAK。
2. A跳B、B跳A互锁
[@A] 里 GOTO @B,[@B] 里又 GOTO @A,中间没 #IF 阻断。改法:互跳必须靠 Human 变量做一次性开关,进过一次就置1,下次不跳。
3. 循环检测不判退出
装备回收脚本常见:
[@Recycle]
#ACT
TAKE 装备 1
GIVE 元宝 5
GOTO @Recycle
背包空了还在 TAKE,永远跳不出去。改法:循环入口先 #IF CHECKITEM 装备 1 才继续,否则 BREAK。
4. 触发事件递归自己
在 QManage.txt 的 [@@Login] 或 QFunction 的 [@GetExp] 里 GOTO/CALL 到另一个标签,那个标签又触发原事件。改法:登录奖励类必须用 IF EQUAL HUMAN GetGift 0 置1后只发一次,别在触发段里再触发同类事件。
三、标签名和变量也是隐形坑
• GOTO @GetRewrd 但定义是 [@GetReward],引擎找不到标签默认回当前块开头,形成隐式死循环,逐字母核对大小写。
• 用 INC D0 计数但 D0 没初始化,或者字符串 S$ 和数值 P0/D0 比较类型写反,引擎算到异常也报 FQ/死循环。
• 变量用完不清零,下次进脚本判定还为真,又进循环。循环尾加 SET HUMAN XX 0 或 MOVS$XX ""。
四、紧急压报错(治标)
开 Mir200\!Setup.txt,找:
ScriptGotoCountLimit=10
改成 10000~50000,存盘重启 M2。GOM/GEE 也可以在 M2→选项→功能设置→其它控制里把“脚本循环次数”从默认20调到50。
注意:这只能让脚本多跳几万次才崩,真有无条件 GOTO @自己,改再大也迟早卡服,必须回去改逻辑。
五、规范写法替换
• 把 GOTO @X 换成 DELAYGOTO 1000 @X,强制间隔1秒跳,配合计数器 BREAK,泡点/刷怪脚本都用这个。
• 复杂逻辑用 #CALL [路径\文件.txt]@段名 替代连续 GOTO,比裸跳安全。
- 一个 #ACT 段只留一个 GOTO,别写两三个 GOTO 排排站。
• 所有循环首行先写退出条件:检物品数、检变量、检次数,三者至少占一个。
六、改完收尾
• 删掉 QuestDiary 下同名 .bak 备份,避免引擎读到旧版。
- !Setup.txt 里设 ScriptDebug=1 重启,进 Log\ScriptLog.txt 看还有没有同标签狂刷,没有就干净了。
• 玩家身上残留的旧 Human 变量会让修好的脚本再触发一次,用 GM 命令清一下相关变量再测。
按“定位文件→看 GOTO 是否无条件→补 #IF 退出或计数器→改 DELAYGOTO→重启看日志”这个顺序走,老版本里那种天天弹死循环的转盘、回收、泡点 NPC 基本一轮就能清完。

