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
SENDMSG0【%s】在奖励大使处领取了8888元宝奖励,真是好运!
SENDMSG6恭喜你成功领取了8888元宝!
这里等下要添加标记记录!!!先留空

goto@main
ELSESAY

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

goto@main

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

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

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

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

[@领取元宝]
IF

CHECKVARHUMAN领取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
---Step1:获取当前玩家名字---

MOVS1<$USERNAME>
---Step2:解析最新日志文件,找该玩家的IP---

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

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

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

IF

EQUALP10
ACT

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

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

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

IF

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

MOVD6D7
INCD61;D6指向IP第一个字符的位置
WHILED7<<$STR(S11)>
GetString<$STR(P0)>D71S4
IF

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

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

INCD71
ENDWHILE
BREAK
ELSEACT

INCD71
ENDWHILE
---Step4:读取IP领取次数.txt文件,获取该IP(S2)的当前领取次数---

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

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

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

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

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

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

ACT

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

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

[@检查IP次数结束]
IF

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

ACT

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

SMALL<$STR(S3)>3;小于3,即012次
ACT
---Step6:允许领取!---

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

CALCVARHUMAN领取8888=1;或者SETVARHUMAN领取8888=1
SAVEVARHUMAN领取8888..\QuestDiary\人物变量.txt;保存变量
---Step8:更新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)。

使用SETVARHUMAN领取8888=1设置变量值,CALCVARHUMAN领取8888=1效果一样。

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

务必保存变量:SAVEVARHUMAN领取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领取次数。

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