Hero引擎传奇必学:一招搞定!让指定玩家只能领1次元宝 + 限制同IP多号刷元宝

来源: 作者: 点击:
玩家A 点NPC只能领取一次元宝(比如8888元宝)。

限制同一个IP地址下,只能有 1个或N个 角色领取这个元宝(防止开小号无限刷)。

使用工具: Hero引擎 (M2) + NPC脚本 (QFunction-0.txt 或其他脚本文件)

核心原理:
个人标识记录: 给每个成功领取元宝的 玩家角色 打上一个永久的标记(用变量)。

IP记录与计数: 获取玩家IP地址,把它记录到一个公共列表(可以是文本文件或变量)里,并对这个IP下的领取次数进行计数。

双重检测: NPC脚本在给元宝前,先检查:

玩家A 自己有没有领过(查个人标识)。

玩家A 当前的IP地址有没有达到领取次数上限(查IP计数)。

详细步骤和脚本:

第一步:编写NPC对话脚本(基础框架)

假设你的NPC名字叫 奖励大使,脚本通常放在 Merchant.txt 或 Market_Def 目录下的 .txt 文件中(具体位置看你的版本目录结构)。这里以 NPC对话 为例。

;-------------------------------------------------------
奖励大使 - 唯一元宝领取处

;-------------------------------------------------------
[@main]
欢迎来到【8888元宝福利】领取点!\ \
满足以下条件即可领取:\ \
<我符合条件,领取8888元宝/@领取元宝>\ \
<了解详情/@详情>\ \
<离开/@exit>

[@详情]
这里是8888元宝福利的说明:\ \
每个角色仅可领取一次!\ \

每个IP地址限制领取3次!\ \ ; 这里假设你设定一个IP最多领3个号

<返回/@main>

[@领取元宝]
IF
这里等下要添加检查条件!!!先留空

ACT

GIVE 元宝 8888
SENDMSG 0 【%s】在奖励大使处领取了8888元宝奖励,真是好运!
SENDMSG 6 恭喜你成功领取了8888元宝!
这里等下要添加标记记录!!!先留空

goto @main
ELSESAY

很抱歉,领取条件不满足!请联系管理员咨询详细规则。\
<返回/@main>
ELSEACT

goto @main

第二步:实现「指定人物只能领取一次」(个人标识法)

使用 永久个人变量 (VAR) 来标记玩家。
在 @领取元宝 的 #IF 段添加领取条件: 检查一个变量(如 领取8888)是否为0(没领过)。

在 @领取元宝 的 #ACT 段给玩家加标记: 成功领取后,将该变量设置为1(已领取)。

修改后的 @领取元宝 脚本:

[@领取元宝]
IF

CHECKVAR HUMAN 领取8888 = 0 ; 检查玩家这个变量是否等于0 (没领过)
注意:等下还要加IP检查,先放这里只检查个人是否领过

ACT

SET [888] 1 ; 设置一个临时的条件标志[888]=1,代表个人条件通过,等待后续IP检查(这步不是必须,是为了脚本结构清晰)
GOTO @检查IP ; 跳到专门检查IP的地方
ELSESAY

提示:你已经领取过8888元宝奖励了,每人只能领取一次哦!\
<返回/@main>

第三步:实现「限制IP领取次数」(文本文件记录法)

Hero引擎本身获取IP地址不太方便,但可以通过读取玩家登录日志(!RunLog目录)的方式获取。
重要提示:
这个方法 不是实时 的!因为玩家登录信息会记录到日志文件,M2引擎会定期(通常是10秒-1分钟)写入一次日志文件。所以玩家刚上线时可能IP还没记录,或者领取时IP可能还没更新到日志。

这个方法 需要服务器时间与日志文件格式稳定。默认的日志格式包含IP地址。

这是一个 折中方案。追求实时精准IP限制,需要在网关上下功夫,这对脚本来说比较困难。

脚本思路:

使用 GetRandomText .\Log\连接成功.txt .\IP地址.txt 来解析最新的玩家IP信息。

使用一个文本文件(如 IP领取次数.txt)记录每个IP的领取次数。

解析当前玩家的名字在连接日志中对应的行,提取出IP地址。

在 IP领取次数.txt 文件中查找这个IP,如果找到就检查次数;没找到就算新IP,次数=0。

判断次数是否超过你设定的上限(比如3次)。

如果没超过,则给元宝、增加这个IP的领取次数(并记录玩家名字)、同时标记玩家自己已领取。

如果超过,则提示失败。
完整的 @检查IP 脚本:

[@检查IP]
IF

CHECK [888] 1 ; 确保上一步的个人检查通过了
ACT
--- Step 1: 获取当前玩家名字 ---

MOV S1 <$USERNAME>
--- Step 2: 解析最新日志文件,找该玩家的IP ---

2.1 复制连接成功日志到临时文件 (确保路径正确!)

GetRandomText .\Log\连接成功.txt .\TempLog.txt
2.2 在临时文件中搜索玩家名字出现的最后一行 (最可能包含当前IP)

MOV S0 0 ; 初始化计数
MOV P1 0 ; 初始化找到标志
WHILE S0 <= 20000 ; 循环次数上限防止死循环
GetString .\TempLog.txt S0 <$STR(S1)> S10 ; 在文件中从第S0行开始找包含S1字符的行
BREAK (<$STR(S10)> = "") ; 没找到就跳出
MOV P0 <$STR(S10)> ; 将找到的行存到P0
INC S0 1 ; 行号+1继续找下一条
MOV P1 1 ; 标记找到了至少一行
ENDWHILE
2.3 如果没有找到该玩家的记录,则认为他没有成功登录(很可能是刚上线没写日志),不允许领取

IF

EQUAL P1 0
ACT

MOV S2 0 ; 默认IP为0(找不到)
MOV S3 0 ; 默认次数0
GOTO @检查IP次数结束
ELSEACT
--- Step 3: 从找到的那行日志(P0)里提取IP ---

MOVR S11 P0 ; 取整行的长度
MOV S2 "" ; 清空S2准备放IP
MOV S4 "" ; 临时字符
MOV D7 0 ; 计数
WHILE D7 < <$STR(S11)>
GetString <$STR(P0)> D7 1 S4 ; 取第D7个字符
日志中IP格式通常类似 [2024-05-26 14:15:12] (127.0.0.1:1234) 登录成功:玩家名(角色名)

思路:找第一个 '(' 后到第一个 ':' 前的部分,就是IP

IF

EQUAL <$STR(S4)> "("
ACT

MOV D6 D7
INC D6 1 ; D6指向IP第一个字符的位置
WHILE D7 < <$STR(S11)>
GetString <$STR(P0)> D7 1 S4
IF

EQUAL <$STR(S4)> ":"
ACT

GetText <STR(P0)> D6 <STR(D7)> S2 ; 从(D6)截取到(D7-1)位置的内容到S2 (就是IP)
BREAK
ELSEACT

INC D7 1
ENDWHILE
BREAK
ELSEACT

INC D7 1
ENDWHILE
--- Step 4: 读取 IP领取次数.txt 文件,获取该IP(S2)的当前领取次数 ---

LOADVAR GLOBAL .\QuestDiary\IP领取次数.txt ... ; Hero读取文本文件变量并不方便,这里省略复杂的LOADVAR处理流程
实际操作建议简化:用一个全局变量管理很难。下面采用一种简化的循环检查文件内容的方法(效率稍低)

MOV S5 "" ; 存放要检查的IP地址行
MOV S3 0 ; 默认该IP领取次数=0
OpenFile .\QuestDiary\IP领取次数.txt
While
GetText S5 ; 读文件一行到S5
IF

CHECKTEXTLIST ..\..\QuestDiary\IP领取次数.txt <$STR(S2)> ; 检查这一行是否包含IP(S2)
或者更准确:用空格或制表符分割行,判断第一列是IP,第二列是次数

Hero处理字符串分割比较弱,这里假设文件格式为: IP地址 领取次数 玩家名1 玩家名2 ... (换行)

提取第一列字符串为当前行记录的IP,比较是否等于S2

(此处代码复杂,省略具体分割代码,假设找到一行以S2开头)

ACT

GetListString <$STR(S5)> 1 S3 ; 假设空格分割,第二列是次数 (具体列数按你文件格式)
BREAK
ELSEACT

ENDWHILE
CloseFile
--- Step 5: 检查次数(S3)是否小于上限(假设3次) ---

[@检查IP次数结束]
IF

LARGE <$STR(S3)> 2 ; 假设限制每个IP只能有3个角色领取 (0,1,2 都小于3)
或者用 CHECKVAR GLOBAL IP_<$STR(S2)> > 2 (如果用全局变量管理IP计数,变量名规则)

ACT

SENDMSG 6 提示:同一个IP地址最多允许领取3次元宝(您的IP:<STR(S2)> 已用次数:<STR(S3)>)。领取失败!
CLEAR [888]
DELETELINE .\TempLog.txt ; 清理临时文件
goto @main
IF

SMALL <$STR(S3)> 3 ; 小于3,即0,1,2次
ACT
--- Step 6: 允许领取! ---

GIVE 元宝 8888
SENDMSG 0 【%s】在奖励大使处领取了8888元宝奖励,真是好运!(IP:<STR(S2)>, 同IP已领次数:<STR(S3)>)
SENDMSG 6 恭喜你成功领取了8888元宝!(你的IP:<STR(S2)>,同IP已领次数:<STR(S3)+1>)
--- Step 7: 更新玩家领取标记 ---

CALCVAR HUMAN 领取8888 = 1 ; 或者 SETVAR HUMAN 领取8888 = 1
SAVEVAR HUMAN 领取8888 ..\QuestDiary\人物变量.txt ; 保存变量
--- Step 8: 更新IP领取次数 ---

方法1 (简单追加):在 IP领取次数.txt 文件中追加一行: IP地址 次数 玩家名列表

先找有没有这个IP的记录

IF
(再次尝试查找,如果能找到,就更新次数和玩家列表)

... 脚本省略,比较复杂 ...

方法2 (简化): 直接追加一行,格式: <STR(S2)> <STR(S3)+1> <$STR(S1)>

AddTextListEx .\QuestDiary\IP领取次数.txt <STR(S2)>\t<CALC(<STR(S3)>+1)>\t<STR(S1)>\
DELETELINE .\TempLog.txt ; 清理临时文件
goto @main
ELSEACT
理论上不会走到这里

DELETELINE .\TempLog.txt
goto @main

关键点说明和注意事项:
个人标识 (VAR):

VAR 是 Hero 引擎的永久个人数值变量。范围通常是 (0-99)。

使用 SETVAR HUMAN 领取8888 = 1 设置变量值,CALCVAR HUMAN 领取8888 = 1 效果一样。

使用 CHECKVAR HUMAN 领取8888 = 0 检查是否未领取。

务必保存变量: SAVEVAR HUMAN 领取8888 ..\QuestDiary\人物变量.txt 将该变量永久存储到文件。否则重启服务器就丢失了!

变量名 领取8888 自己定义,确保唯一。
IP获取 (通过日志 连接成功.txt):

这是一种折中、非实时的方法。

路径 .\Log\连接成功.txt 通常是相对于 MirServer\Mir200 目录的。务必要根据你服务器的实际路径修改!

脚本中解析IP的逻辑比较复杂且脆弱,依赖于日志的固定格式。如果你的 MirServer 设置修改过日志格式,这个脚本很可能失效。

使用临时文件 .\TempLog.txt 是为了避免直接操作原始日志文件。
IP次数记录 (IP领取次数.txt):

这是一个你自己维护的文本文件,格式建议为:IP地址(Tab)领取次数(Tab)玩家名1,玩家名2,玩家名3 (换行)。使用制表符(\t)分割。

使用 AddTextListEx 命令追加新记录。这个命令可以自动添加换行符。AddTextList 只是添加文本。

脚本中没有做“更新已有IP记录”的操作(即找到该IP行,修改次数和玩家列表)。为了简单,采用的是“每次都追加新记录”的方式。这会导致文件里有很多重复的IP记录(同一IP不同玩家领取)。你可以根据需要修改脚本,实现找到旧记录更新次数+名字列表,找不到才追加新记录(需要更复杂的文件读写和字符串操作)。
变量命名和保存:

个人变量文件名 (如 ..\QuestDiary\人物变量.txt) 和 IP记录文件名 (如 ..\QuestDiary\IP领取次数.txt) 可以自己定义,放到 QuestDiary 目录便于管理。

确保存放这些文件的路径 MirServer\Mir200\Envir\QuestDiary\ 存在或有写权限。
效率和稳定性:

频繁读写文件(日志解析、IP记录读写)在高并发(很多人同时点)时会对服务器性能有影响。

日志解析逻辑较复杂,容易出现异常(比如找不到IP)。要做好错误处理(上面脚本省略了很多错误处理)。

更优方案建议 (如果觉得脚本太复杂):
放弃脚本IP限制,专注角色唯一领取: 如果你的服主要是防止单人双开/三开小号,只做角色唯一限制已经能阻止绝大多数滥用。放弃IP限制可以大大简化脚本。

使用其他标识代替IP: 比如限制同一天或同段时间内领取的总人数(用全局计数器GLOBAL),或者使用更复杂的账号系统标识(如果你的登录器支持)。

使用专业反外挂网关 (推荐): 像侠客、绿盟等网关通常内置强大的IP限制功能,可以在网关层面直接限制一个IP登录账号数、连接数、或者对特定命令(如访问某个NPC)的频率限制。这是最专业、实时、高效的解决方案。

找技术员定制: 如果想在脚本层面实现更稳定高效的IP限制,可能需要修改插件或使用更高级的脚本函数。

总结:

本文提供了一个在 Hero 引擎下实现 “指定人物只领一次元宝”+“限制同IP多号刷” 的详细脚本方案。核心是利用:
VAR (个人变量) 标记玩家角色。

解析登录日志 获取玩家大致IP。

自定义文本文件 记录IP领取次数。

特别注意其非实时性和复杂性。根据你的服的具体情况和抗风险需求,可以考虑简化方案(只做角色唯一限制)或采用网关级别的解决方案。务必在测试服充分测试后再上线正式服!