利用传奇脚本处理HERO引擎出现角色同名的问题 从登录检测到强制改名的完整实操方法

来源: 作者: 点击:
一、HERO引擎里角色同名的几种来源

在HERO引擎架设的传奇版本中,角色名并不只是一个显示用的称呼,它是行会、师徒、结婚、好友、屏蔽名单、排行榜、邮件、限时称号、无限仓库等系统相互关联的主键。名字一旦出现重复,这些系统就会指向错误的对象,轻则显示错乱,重则丢数据。

常见的同名来源主要有这么几类。

第一类是合区合并。多个区服各自运行了一段时间,玩家注册时彼此并不知道对方存在,合区把数据并到一起,重名就暴露出来了。这是最普遍的一类,也是很多版本忽然出现大量同名报错的直接原因。

第二类是跨区共用同一套账号库或者数据库。同一账号体系下的不同区服,本来就容易出现一样的名字,尤其是玩家用同一个习惯名字反复建号的情况。

第三类是直接复制模板版本。把别人的服务端整体拷贝过来,名单文件、存档、脚本里带进来的角色数据本身就带着同名。

第四类是看似不同、其实同名的假象。名字里夹了全角空格、半角空格、特殊符号,或者大小写混用,肉眼看不出差别,脚本按字符串比对时却可能被判定为同一个名字或者判定成两个名字,两种结果都会出问题。

还有一类是人工操作造成的,手动改名、手动复制角色数据,把名字改成了已经存在的名字。

二、同名会带来哪些具体后果

搞清楚后果,才知道为什么要用脚本去堵。HERO引擎下的同名,主要会引发下面这些现象。

一是仓库和装备错位。无限仓库、公共仓库这类按名字读写的数据,遇到重名时很容易只认一个角色的存档,另一个角色的仓库内容丢失或者被覆盖。这是合区之后最常见的投诉。

二是关系数据错乱。行会成员、师徒、结婚对象、屏蔽列表按名字匹配,同名会让 A 的关系挂到 B 的身上。

三是排行榜、称号、充值归属出错。按名字统计的榜单会把两个人算成一个人,充值和点券的归属也可能张冠李戴。

四是登录与脚本判断失效。很多登录脚本会拿角色名去做条件判断,名字重复会让判断逻辑整体失灵,出现该给的不给、该拦的不拦。

正因如此,处理同名的思路并不是等出了问题再补,而是在玩家进入游戏的那一刻就做检测,把重名挡在门外或者就地改名。

三、处理同名的整体思路

HERO引擎处理同名,主流做法是利用登录触发脚本,把"检测"和"处置"两步串起来。

检测这一步,靠的是一个名单文件。引擎提供了一系列针对名单文件的读写命令,脚本在玩家登录时读名单、比名字,就能知道这个名字是不是已经被占用。

处置这一步,通常有三种策略,可以按需选择。

第一种是直接拦截。检测到重名,弹出提示框告知玩家换名,然后用踢人命令把玩家踢下线,玩家改好名字再进。

第二种是强制改名。检测到重名后,直接调用改名命令把角色名换成一个新的、不冲突的名字,或者拉起一个改名界面让玩家实时输入。

第三种是只记录不处理。先把这个名字登记进名单文件,等后续统一处理,适合测试阶段或者数据量还不大的时候。

三种策略里,拦截加提示是最稳妥的,改动小、风险低;强制改名体验更顺,但对命令的支持要求更高。

四、要用到的核心命令逐个说明

下面这些是处理同名时最常用的脚本命令,不同引擎与版本在命名和参数上可能略有差异,以你手上引擎自带的脚本说明为准。

CHECKNAMELIST 路径 用来判断当前玩家的角色名,是否已经存在于指定的名单文件里。名单文件一般一行一个名字。

ADDNAMELIST 路径 把当前玩家的角色名写入名单文件。

DELNAMELIST 路径 名字 把指定名字从名单文件里移除,改名成功之后要用到。

CheckTextList 路径 文本 判断指定文本是否作为一行存在于文件里,比名字比对更灵活,可以拿来存"名字加账号加区服"的组合键。

AddTextListEx 路径 文本 往文件里追加一行文本,配合上面那条命令做组合键登记。

ISNEWHUMAN 判断当前登录的是不是一个新角色,用来区分"第一次进游戏"和"老角色回访",是很关键的一个条件。

CHECKLEVELEX 等级 做等级判断,常见用法是给老号加一道等级门槛,避免误伤正常玩家。

MESSAGEBOX 内容 弹出提示框,把换名原因讲清楚。

KICK 把玩家踢下线,配合提示框使用。

CHANGEHUMNAME 原名字 新名字 直接修改角色名,强制改名路线上会用到。

$USERNAME、$USERID、$SERVERNAME 分别代表角色名、账号、区服名。这三个变量在脚本里必须全部大写,写成小写引擎读不到,这一点在HERO引擎上尤其容易踩。

五、一份能直接用的登录检测脚本

把下面这段放在登录触发的位置,路径按自己的目录结构替换。这段脚本的逻辑是:已经登记过的老号,如果名字在名单里,直接提示并踢下线;第一次登录的新角色,如果名字已经被别人用了,同样提示并踢下线;如果是全新且不冲突的名字,就登记进名单。

text
;登录时触发
#IF
CHECKNAMELIST ..\QuestDiary\ANGEL\新人名单.txt
CHECKLEVELEX 40
#ACT
MESSAGEBOX 你现在的名字已被封,请换名后重新登陆
KICK

#IF
ISNEWHUMAN
CHECKNAMELIST ..\QuestDiary\ANGEL\新人名单.txt
#ACT
MESSAGEBOX 游戏中已经有当前名字,请换名后重新登陆
KICK

#IF
ISNEWHUMAN
NOT CHECKNAMELIST ..\QuestDiary\ANGEL\新人名单.txt
#ACT
ADDNAMELIST ..\QuestDiary\ANGEL\新人名单.txt


第一段的用途是兜底,针对那些名字已经进了名单、后面又要重新登录的老号,用等级条件把正常的老玩家和需要拦下的号区分开。

第二段是核心,只对 ISNEWHUMAN 成立的新角色做检查,名字在名单里就提示换名并踢下线。

第三段是登记,新角色名字不冲突,就写进名单,供后续登录比对。

六、这份脚本的短板在哪里

直接拿上面这段去用,有几个坑必须提前知道,否则上线之后会挨骂。

最大的问题是新角色占了名字。玩家新建一个号,登录一次脚本就把名字记进名单了,如果这个玩家当场下线,名字就永久占住,之后再想用这个名字登录,就会一直被当成重名拦截。名字越常见的号,越容易撞上这个坑。

第二个问题是只比名字不比区服。合区之后,同一个名字出现在两个不同的区服,很可能两个都是合法玩家,脚本却会把其中一个当成非法重名踢掉。

第三个问题是路径和大小写。名单文件的路径写错、目录不存在、文件编码不是引擎认的编码,脚本都会静默失效。名字里带空格和符号时,全角半角不统一也会让比对结果和预期不一样。

第四个问题是变量大小写。前面提到过,HERO引擎对变量大小写敏感,$USERNAME 写成 $username 可能就读不到值,脚本看着正常,实际一直不生效。

七、改进方案:只在真的跨区同名时才要求改名

要绕开上面第二个坑,就得把比对的粒度从"名字"提升到"名字加账号加区服"组合。思路是维护两张表,一张记录所有出现过的名字,一张记录"名字:账号:区服"的组合,只有当名字存在、而对应的组合不存在时,才判定为真正的跨区重名。

text
;登录触发,跨区同名检测
#IF
NOT CHECKNAMELIST ..\..\..\同名检测\角色名单.txt
#ACT
ADDNAMELIST ..\..\..\同名检测\角色名单.txt
AddTextListEx ..\..\..\同名检测\角色ID表.txt <$USERNAME>:<$USERID>:<$SERVERNAME>
BREAK

#IF
CHECKNAMELIST ..\..\..\同名检测\角色名单.txt
NOT CheckTextList ..\..\..\同名检测\角色ID表.txt <$USERNAME>:<$USERID>:<$SERVERNAME>
#ACT
MESSAGEBOX 你的角色名与其他区服玩家重复,请使用改名NPC改名后重新登陆
KICK


这段脚本里,名字第一次出现就直接登记,不再有任何拦截。只有当名字被别人占用、并且这个占用者的账号或区服和当前登录的不是同一个时,才提示改名。这样既能挡住真正的重名,又不会误伤同号的正常玩家。

配套还要准备一个改名NPC,让被拦下的玩家有路可走,把名字改成一个不冲突的新名字。改名成功后,要把旧名字从名单里删掉,把新名字登记进去。

text
[@改名]
#IF
NOT CheckTextList ..\..\..\同名检测\角色ID表.txt <$STR(S6)>:<$USERID>:<$SERVERNAME>
#ACT
CHANGEHUMNAME <$USERNAME> <$STR(S6)>
DELNAMELIST ..\..\..\同名检测\角色名单.txt <$USERNAME>
ADDNAMELIST ..\..\..\同名检测\角色名单.txt <$STR(S6)>
AddTextListEx ..\..\..\同名检测\角色ID表.txt <$STR(S6)>:<$USERID>:<$SERVERNAME>
MESSAGEBOX 改名成功,请重新登陆
KICK

#IF
CheckTextList ..\..\..\同名检测\角色ID表.txt <$STR(S6)>:<$USERID>:<$SERVERNAME>
#ACT
MESSAGEBOX 该名字已被占用,请换一个


玩家输入的新名字如果已经被别人用掉,就提示换一个;不冲突就执行改名,同时把名单和组合表都更新干净,避免留下一堆脏数据。

八、部署与排查清单

脚本写完不代表能用,下面这份清单按顺序过一遍,能省掉大部分折腾。

名单文件要先建好,目录要真实存在,路径用相对路径时注意层级,..\ 表示上一级。文件编码统一成引擎能识别的编码,名字里不要混入不可见字符。

脚本必须放在登录触发的位置。HERO引擎的登录触发一般挂在主功能脚本的登录段,不同引擎的入口文件名不一样,按自己引擎的说明放,放错位置等于没写。

改完脚本要重启引擎或者重新加载脚本,让引擎把新的逻辑读进去,否则跑的还是旧逻辑。

变量一律大写,路径里的反斜杠数量要和实际目录层级对齐。

测试要覆盖三种情况:全新名字、自己同号重复登录、他人跨区同名登录。三种情况分别走一遍,确认拦截和放行的分支都对。

上线前先备份名单文件和相关脚本,出问题时能快速回退。

九、和其他引擎的差异

同样的思路在GOM、GEE这类引擎上也能用,但细节不一样。路径写法上,有的引擎要把单个点改成两个点;输入框标签的写法有的要双@有的要单@;在线检测命令有的写成 CheckOnline 名字,有的写成 名字.CheckOnline;打开大对话框、设置头顶图标这类命令的参数个数和顺序也各不相同。从别的版本移植脚本时,这些差异最容易导致脚本报错或者静默失效,移植后一定要逐条对照引擎说明核对,不要直接照搬。

十、小结

HERO引擎下的角色同名,本质是合区和跨库之后,名字这个主键不再唯一。处理它的核心不是事后修补,而是在登录入口用脚本把检测做在前面。名单文件负责记录,ISNEWHUMAN 负责区分新老角色,CHECKNAMELIST 和 CheckTextList 负责比对,MESSAGEBOX 和 KICK 负责处置,改名NPC负责给玩家留一条修正的路。

比对粒度从单纯的名字升级到"名字加账号加区服",是这套方案能不能真正用在生产环境上的分水岭。粒度停在名字上,就只能接受误伤正常玩家的代价;粒度提到组合键,才能在拦住重名的同时,不打扰那些本本分分的老号。把路径、编码、变量大小写这些细节都照顾到,一套登录同名检测脚本就能稳稳地跑下去。