传奇防刷屏验证码脚本完整实例 上线强制验证与机器人定时验证多引擎写法详解

来源: 作者: 点击:
防刷屏验证码的核心逻辑就一条:脚本生成一个随机数,要求玩家在限定时间内通过对话框输入相同的数字,输入正确解除禁言或放行,输入错误或超时未输入则踢下线。下面按引擎类型拆解几种可直接使用的脚本写法。

## 上线强制验证码脚本

这是最基础的防刷屏方案。玩家上线瞬间自动禁言,弹出验证码输入框,30秒内未输入正确则强制踢下线。以3K引擎为例,脚本写入QManage.txt的[@Login]触发段中:

```
[@Login]
#IF
CHECKLEVEL > 0
#ACT
MOVR N2 10000000
Gmexecute Shutup Self 99999
DELAYGOTO 30 @Delayk
#SAY
为了防止恶意刷屏和挂僵尸攻击,不便之处请原谅。\
请输入验证码进行ID激活,否则30秒后自动掉线。\
<点这里输入以下验证码/@@InPutInteger1>\
验证码:<$STR(N2)>

[@InPutInteger1]
#IF
EQUAL N2 N1
#ACT
Gmexecute ReleaseShutup Self
SENDMSG 6 验证码核验通过,你可以正常游戏了。
BREAK
CLOSE
#ELSEACT
SENDMSG 6 验证码输入不正确。
```

MOVR N2 10000000 生成一个随机数存入N2变量,范围0到10000000。@@InPutInteger1 是对话框输入接口,玩家输入的数字会自动存入N1变量。EQUAL N2 N1 比对两个变量是否相等,相等则解除禁言,不相等则提示错误。

这里的关键是Gmexecute Shutup Self 99999,它在上线瞬间给玩家施加一个持续时间极长的禁言状态,玩家无法发送任何聊天消息,直到验证通过后由Gmexecute ReleaseShutup Self解除。DELAYGOTO 30 @Delayk 设置30秒延时跳转,超时后进入[@Delayk]段落执行踢人逻辑。

[@Delayk]段落写法:

```
[@Delayk]
#IF
CHECKNAMELIST ..\QuestDiary\数据文件\验证通过.txt
#ACT
SENDMSG 6 30秒时间到,你是已验证账户不受影响。
#ELSEACT
SENDMSG 6 30秒时间到,你还没有通过验证,系统决定踢你下线。
KICK
```

已验证的玩家会被写入白名单文件,30秒延时到达后检查白名单,在白名单中则不受影响,不在则执行KICK命令踢下线。

## 机器人定时验证码脚本

上线验证只能拦住挂僵尸攻击,对已经在线挂机的玩家没有约束。需要配合机器人脚本实现定时弹出验证码。

机器人脚本文件AutoRunRobot.txt中增加一行:

```
#AutoRun NPC MIN30 @验证码
```

这行配置表示每30分钟自动触发一次[@验证码]段落。然后在RobotManage.txt中编写验证逻辑:

```
[@验证码]
#IF
CHECKLEVEL > 0
#ACT
MOVR N3 10000000
SENDMSG 6 系统防挂机验证:请在60秒内输入验证码<$STR(N3)>,否则将被踢下线。
Gmexecute Shutup Self 99999
DELAYGOTO 60 @验证超时
#SAY
防挂机验证已触发,请及时输入验证码。\
<点击输入验证码/@@InPutInteger2>\
验证码:<$STR(N3)>

[@InPutInteger2]
#IF
EQUAL N3 N4
#ACT
Gmexecute ReleaseShutup Self
SENDMSG 6 验证通过。
BREAK
CLOSE
#ELSEACT
SENDMSG 6 验证码错误,请重新输入。
```

机器人脚本每30分钟给所有在线玩家发一次验证码,60秒内没有正确输入的玩家被踢下线。实际使用中,30分钟的间隔可以根据服务器玩家数量和刷屏严重程度调整,刷屏严重时缩短到15分钟。

## 带错误次数限制的验证脚本

上面的基础版本只记录一次输入结果,玩家有60秒时间反复尝试。更严格的版本需要记录错误次数,超过3次直接踢下线。

变量分配上,N5记录错误次数,N6记录验证是否已通过:

```
[@验证码]
#IF
CHECKLEVEL > 0
#ACT
MOVR N3 10000000
MOV N5 0
MOV N6 0
Gmexecute Shutup Self 99999
DELAYGOTO 60 @验证超时
SENDMSG 6 请在60秒内输入验证码<$STR(N3)>,超过3次错误将被踢下线。
#SAY
防挂机验证触发。\
<输入验证码/@@InPutInteger3>\
验证码:<$STR(N3)>\
剩余尝试次数:<$STR(N5)>/3

[@InPutInteger3]
#IF
EQUAL N6 1
#ACT
SENDMSG 6 你已经通过验证了。
BREAK
CLOSE
#IF
EQUAL N3 N4
#ACT
MOV N6 1
Gmexecute ReleaseShutup Self
SENDMSG 6 验证通过。
BREAK
CLOSE
#ELSEACT
INC N5 1
#IF
CHECK N5 >= 3
#ACT
SENDMSG 6 验证错误次数已达3次,你将被踢下线。
KICK
#ELSEACT
SENDMSG 6 验证码错误,你还有<$STR(N5)>次机会。
GOTO @验证码
```

INC N5 1 每次输入错误时错误计数自增1,CHECK N5 >= 3 判断是否达到3次上限。N6变量的作用是防止玩家在已经通过验证后再次触发输入框导致状态混乱。GOTO @验证码 在错误后重新生成新验证码并重置计时,确保玩家有完整的60秒重新验证。

## LegendM2引擎的SetRandomNo写法

LegendM2引擎提供了内置的随机验证码命令,不需要手动用MOVR生成随机数。脚本更简洁:

```
[@Main]
#IF
CHECKLEVEL > 0
#ACT
SetRandomNo
#SAY
<输入验证码/@@CheckNo>:<$RANDOMNO>

[@@CheckNo]
#IF
CheckRandomNo
#ACT
SENDMSG 6 验证码输入正确。
CLOSE
#ELSEACT
SENDMSG 6 验证码输入错误。
CLOSE
```

SetRandomNo 让系统自动生成一个随机验证码,存储在<$RANDOMNO>常量中。@@CheckNo 是专用的验证码输入接口,玩家输入的内容自动与系统生成的验证码比对。CheckRandomNo 条件判断验证是否通过。

这个写法的优势在于引擎层面处理了随机数的生成和比对,不需要手动管理变量,也不会因为变量编号冲突导致验证失效。

## GOM引擎的弹出验证码窗口触发

GOM引擎在2019年版本中增加了弹出验证码窗口时的触发接口,写法与其他引擎有所不同:

```
[@ShowGameValidateDlg]
#IF
#ACT
SENDMSG 6 开始验证
BREAK
```

这个触发段在验证码窗口弹出时自动执行,可以配合检测命令做更复杂的逻辑。GOM引擎的验证码系统与登录器深度绑定,实际使用时需要在M2的选项菜单中开启验证码功能,并配置验证间隔和超时时间,脚本层主要负责验证通过或失败后的处理逻辑。

## 变量选择与冲突排查

防刷屏脚本使用的变量必须避开服务端已有任务的变量编号。N0到N99区间通常被引擎保留或版本任务占用,建议从N200之后开始分配。查看版本中已有的变量使用情况,可以通过M2Server控制台的变量查看功能,或者搜索QManage.txt、QFunction-0.txt中已有的MOV和MOVR语句。

上线验证和机器人验证使用的是不同的变量组。上线验证用N1和N2,机器人验证用N3、N4、N5,互不干扰。如果多个验证脚本共用同一个变量,会出现玩家在上线验证时输入的验证码被机器人验证的比对逻辑错误匹配的情况。

MOVR命令生成的随机数范围不要太小。MOVR N2 100 只生成0到100之间的随机数,玩家试几次就能猜中。建议范围设置到10000000以上,确保随机性足够。

## 防止脚本被挂机工具绕过

验证码机制本身有被挂机工具OCR识别的风险。提高防绕过能力可以从三个方向入手。

第一,缩短验证时间。60秒对真人玩家来说足够,但对挂机工具的OCR识别流程来说时间很紧张,缩短到30秒可以显著提高绕过难度。

第二,增加输入格式要求。在验证码前拼接固定文字,要求玩家输入“NSH+数字”,挂机工具即使识别出了数字,没有拼接前缀也会验证失败。

第三,将验证码放入动态对话框中。不直接在聊天框显示验证码数字,而是让玩家点击一个NPC或物品后弹出一个包含验证码的对话框,挂机工具需要模拟完整的点击和读取流程才能获取验证码。

## 调试与生效检查

脚本写完后放入QManage.txt或QFunction-0.txt,重启M2Server生效。在M2Server控制台中输入@ReloadManage可以重新加载QManage.txt,不需要重启整个服务端。修改RobotManage.txt后,在控制台输入@ReloadRobot重新加载机器人脚本。

验证脚本不触发,先检查@Login段的触发条件。如果服务端中已经有其他的[@Login]段落,新增的验证脚本必须与已有段落合并或使用条件分支,不能出现两个独立的[@Login]标识。同样的规则适用于[@验证码]标识。

输入框弹出但输入后没有反应,检查@@InPutInteger后面的编号是否与脚本中处理的编号一致。@@InPutInteger1接收的输入存入N1,@@InPutInteger2存入N2,编号必须严格对应。如果用了@@InPutInteger1但脚本中检查的是N2变量,比对会永远失败。

所有脚本文件必须保存为ANSI编码。用记事本另存为时在编码下拉菜单中选ANSI,选UTF-8会导致验证码数字乱码,玩家看到的是问号,无法完成验证。