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

传奇脚本死循环QFunction位置GOTO命令彻底排查与修复

热度:
你碰到的这个“脚本死循环”报错,根源在`[@GetExp]`这个触发段里。系统每获得一次经验,就触发一次这个段,而段里连着三个`goto`命令,其中`goto@宗派经验`这一跳,跳过去执行完,正常情况下应该用`break`或`return`把流程断掉,但你没有,导致程序逻辑乱套,在特定条件下疯狂循环,M2检测到1秒内执行了多次相同脚本,就直接报错中断。下面把修复步骤拆开,每一步干什么、为什么这么干,全给你讲清楚。

**第一步:先看报错信息,定位问题在哪**

报错原文是:
`[脚本死循环]NPC:QFunction位置:0(0:0)命令:GOTO@宗派经验1秒1次`

翻译成人话:
-**NPC:QFunction**:出问题的脚本在`QFunction-0.txt`文件里。
-**位置:0(0:0)**:脚本坐标显示0,说明不是地图上的NPC,是功能触发段。
-**命令:GOTO@宗派经验**:循环的元凶是`GOTO@宗派经验`这条命令。
-**1秒1次**:系统检测到这段脚本在1秒内反复执行,判定为死循环,强制中断了。

**第二步:分析`[@GetExp]`段的错误写法**

你的原脚本是这样的:

```
[@GetExp]
#act
goto@宗派经验
goto@烽火001
goto@冲级赛
break
```

错误点在于:
1.**`goto`命令的逻辑**:`goto`是跳转命令,跳到指定段执行,执行完会**返回**原跳转点的下一行继续执行。
2.**流程举例**:假设执行到`goto@宗派经验`,程序跳去`[@宗派经验]`段,执行完里面的所有命令,遇到`break`或执行完最后一行,它会**返回到`[@GetExp]`段**,接着执行下一行`goto@烽火001`。
3.**问题在哪**:问题不在返回,而在`[@宗派经验]`段里**可能又触发了`[@GetExp]`**。如果`[@宗派经验]`里的操作(比如加经验、改文件)再次触发了经验获得事件,就会再次进入`[@GetExp]`,形成一个套娃式的循环。

**第三步:分析`[@宗派经验]`段的隐患**

你的`[@宗派经验]`段写了文件读写操作:

```
GetRandomName..\QuestDiary\宗师系统\经验\<$USERNAME>.txtS28
movd21<$STR(S28)>
MOVd22<$GETEXP>
INCd21<$STR(d22)>
MOVS27<$STR(d21)>
DelTextList<$STR(S28)>..\QuestDiary\宗师系统\经验\<$USERNAME>.txt
AddTextList<$STR(S27)>..\QuestDiary\宗师系统\经验\<$USERNAME>.txt
```

这里面藏着两个可能触发死循环的坑:

1.**`<$GETEXP>`这个变量**:`<$GETEXP>`是当前获得的经验值。在`[@GetExp]`触发时,这个值已经产生了。但你在`[@宗派经验]`里又去读取它,本身没问题,问题在于后面你**删文件、加文件**这些操作,会不会间接导致系统重新计算经验或触发其他事件?某些引擎在修改文件时会触发文件监控,如果文件监控关联了经验相关事件,就可能再次进入`[@GetExp]`。

2.**文件操作本身**:`DelTextList`和`AddTextList`是对文本文件进行读写。如果这个文件被其他脚本监控,或者宗师系统本身有定时检测机制,在你修改文件的一瞬间触发了其他事件,那个事件里又有加经验的逻辑,那就会二次触发`[@GetExp]`。

**第四步:给出正确的修改方案**

核心原则:**在`[@GetExp]`里不要用`goto`跳转,改用`call`或者直接写命令**,并且确保每个被调用的段都执行完就彻底退出。

**方案一:最简单粗暴的改法(推荐)**

把`goto`换成`call`。`call`命令执行完子段后会返回,但你可以用`break`控制流程,或者在子段里不加可能触发循环的操作。

修改`[@GetExp]`为:

```
[@GetExp]
#act
call@宗派经验
call@烽火001
call@冲级赛
break
```

并且在`[@宗派经验]`段末尾明确加上`return`或`break`:

```
[@宗派经验]
#if
CHECKNAMELIST..\QuestDiary\宗师系统\宗主名单.txt
#ACT
GetRandomName..\QuestDiary\宗师系统\经验\<$USERNAME>.txtS28
movd21<$STR(S28)>
MOVd22<$GETEXP>
INCd21<$STR(d22)>
MOVS27<$STR(d21)>
DelTextList<$STR(S28)>..\QuestDiary\宗师系统\经验\<$USERNAME>.txt
AddTextList<$STR(S27)>..\QuestDiary\宗师系统\经验\<$USERNAME>.txt
break
```

**方案二:合并命令,减少跳转**

如果`[@宗派经验]`、`[@烽火001]`、`[@冲级赛]`这三个段逻辑简单,可以直接把它们的命令合并到`[@GetExp]`里,用一个段执行完所有操作,彻底消除跳转。

```
[@GetExp]
#if
CHECKNAMELIST..\QuestDiary\宗师系统\宗主名单.txt
#ACT
GetRandomName..\QuestDiary\宗师系统\经验\<$USERNAME>.txtS28
movd21<$STR(S28)>
MOVd22<$GETEXP>
INCd21<$STR(d22)>
MOVS27<$STR(d21)>
DelTextList<$STR(S28)>..\QuestDiary\宗师系统\经验\<$USERNAME>.txt
AddTextList<$STR(S27)>..\QuestDiary\宗师系统\经验\<$USERNAME>.txt

#IF
#ACT
;这里是烽火001的代码

#IF
#ACT
;这里是冲级赛的代码

break
```

**第五步:检查宗师系统其他脚本**

有时候死循环不在明处,在暗处。你需要检查:

1.**宗师系统里有没有其他`[@GetExp]`触发**:在整个`QFunction-0.txt`里搜索`[@GetExp]`,确保只有一个,没有重复定义。
2.**文件操作是否被监控**:看看`.\QuestDiary\宗师系统\`文件夹下有没有其他脚本在监听文件变化,比如有脚本每隔几秒读一次这个经验文件,读到的内容变化时又触发加经验逻辑。
3.**`<$GETEXP>`的用法**:确认这个变量在你引擎里是只读还是可写。如果是可写的,你在`INCd21<$STR(d22)>`这一步修改了数值,会不会导致经验值被重新写入数据库,从而再次触发`[@GetExp]`。

**第六步:终极测试方法**

修改完脚本后,保存文件,在M2上重新加载所有脚本(或者重启M2)。然后找个号进游戏,打一只怪获得经验,观察M2控制台有没有再次报错。如果还报,看报错内容是不是同一个位置。如果是,说明问题没根除,需要把`[@宗派经验]`里的代码逐行注释掉,用排除法找到具体哪一行命令触发了循环。

比如先注释掉文件删除和添加那两行,只保留变量操作,测试还循环不循环。如果不循环了,问题就出在`DelTextList`和`AddTextList`这两行上,需要研究这两个命令在你引擎里的具体机制,或者换一种方式读写文件。
[顶部]