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

传奇HERO引擎限时会员脚本:按天计费与到期自动清理

热度:
HERO引擎的会员系统本质就是“一个到期时间戳变量+登录时比对时间”。不限时会员给永久标记,限时会员给一个具体到期时间,登录时拿当前时间和到期时间比,过了就清标记。多个一月会员能累计,就是“延期=取最大值(旧到期时间,当前时间)+天数”,而不是直接覆盖。

先确定变量分工
HERO引擎脚本里:
•U系列变量:玩家私有,可按账号/角色保存,适合存到期时间

•N系列变量:数字型,配合SaveVarHUMAN存盘

•S系列变量:字符型

会员等级用一个变量,比如N会员等级:0=普通、1=一天体验、2=一周、3=一月。会员到期时间用另一个变量存时间戳,比如U会员到期时间(单位秒,或按HERO的日期格式)。HERO里取当前时间常用<DATE>、<TIME>,或者用脚本命令GetTime、GetDateTime,具体看你的HERO版本命令手册。

核心逻辑:购买即延期
不是“设置会员”,是“计算新的到期时间”:
1.取当前时间戳Now
2.取旧的到期时间OldExpire(如果已过期就用Now)
3.NewExpire=Max(OldExpireNow)+天数×86400
4.存NewExpire,设会员等级

这样买一个月时,不管之前剩多少天,都在“到期时间”上往后加30天,自然就累计了。直接MOVU$会员到期时间Now+30天是错的,会覆盖掉剩余时间。

购买脚本写法(NPC)
Market_Def\会员服务.txt:

(@BuyVip)
[@main]
<会员服务中心>\
一天体验会员:<STR(N体验价格)>元宝\
一周会员:<STR(N周价格)>元宝\
一月会员:<STR(N月价格)>元宝\
你的会员等级:<STR(N会员等级)>\
到期时间:<STR(S到期显示)>\
<购买一天体验/@buy_1>\
<购买一周/@buy_7>\
<购买一月/@buy_30>\
<查询/@check>\
<离开/@exit>\

[@buy_1]
IF

CHECKGAMEGOLD<STR(N体验价格)>
ACT

TAKE元宝<STR(N体验价格)>
CALL@AddVip1
SENDMSG6成功开通1天体验会员
GOTO@main
ELSEACT

SENDMSG6元宝不足
GOTO@main

[@buy_7]
IF

CHECKGAMEGOLD<STR(N周价格)>
ACT

TAKE元宝<STR(N周价格)>
CALL@AddVip7
SENDMSG6成功开通7天会员
GOTO@main
ELSEACT

SENDMSG6元宝不足
GOTO@main

[@buy_30]
IF

CHECKGAMEGOLD<STR(N月价格)>
ACT

TAKE元宝<STR(N月价格)>
CALL@AddVip30
SENDMSG6成功开通30天会员
GOTO@main
ELSEACT

SENDMSG6元宝不足
GOTO@main

[@check]
IF

LARGEN$会员等级0
ACT

SENDMSG6当前会员等级:<STR(N会员等级)>,到期:<STR(S到期显示)>
ELSEACT

SENDMSG6你不是会员
GOTO@main

延期子过程(关键)
用CALL传参,HERO里CALL可以带参数写在后面,用$PARAM(0)接:

[@AddVip]
IF

ACT

MOVD0$PARAM(0)
CALCU会员到期时间=U会员到期时间
IF

LARGEU会员到期时间<NOW>
ACT

MOVU会员到期时间<NOW>
BREAK
IF

ACT

CalcVarU$会员到期时间+D0*86400
IF

EQUALD01
ACT

MOVN$会员等级1
IF

EQUALD07
ACT

MOVN$会员等级2
IF

EQUALD030
ACT

MOVN$会员等级3
IF

ACT

SaveVarHUMANU$会员到期时间..\QuestDiary\会员\会员数据.txt
SaveVarHUMANN$会员等级..\QuestDiary\会员\会员数据.txt
BREAK

这里的<NOW>要换成你HERO引擎取当前秒数的实际命令,有的版本是<TIME>,有的是GetTime存入变量。如果HERO不支持CALC直接算时间,就用日期拆分算:把当前日期和到期日期都转成“从某天起的天数”,延期就是天数加N。

到期自动清理:登录时检查
QFunction-0.txt或QuestDiary的[@Login]:

[@Login]
IF

LARGEN$会员等级0
ACT

IF

LARGE<NOW>U会员到期时间
ACT

MOVN$会员等级0
MOVS$到期显示已过期
SaveVarHUMANN$会员等级..\QuestDiary\会员\会员数据.txt
SENDMSG6你的会员已到期,特权已取消
ELSEACT

SENDMSG6欢迎回来,会员剩余时间:<STR(S到期显示)>
BREAK

“在线期间到期”也要处理,不能只靠登录。用定时器,HERO的RunTick或QuestDiary定时器:

[@RunTick]
IF

LARGEN$会员等级0
ACT

IF

LARGE<NOW>U会员到期时间
ACT

MOVN$会员等级0
SaveVarHUMANN$会员等级..\QuestDiary\会员\会员数据.txt
SENDMSG6会员到期,特权已取消
BREAK

会员特权判定统一用一个检查
别到处写LARGEN$会员等级0,容易漏。写成公共检查:

[@CheckVip]
IF

LARGEN$会员等级0
ACT

IF

LARGE<NOW>U会员到期时间
ACT

MOVN$会员等级0
SENDMSG6会员已过期
BREAK
ELSEACT

SENDMSG6会员有效
BREAK

传送员、泡点、打宝加成这些地方都先CALL@CheckVip,过了才给特权。这样到期清理一处改,全服生效。

时间显示问题
U会员到期时间存的是秒数,直接<STR>显示成一串数字很难看。显示前转成日期:HERO有FormatTime或把秒数拆成年月日的命令,没有就存两个变量——到期秒数(用于比对)+到期日期字符串(用于显示)。每次延期时同时写:
MOVS$到期显示某年某月某日
具体格式用HERO的日期格式化命令,查你版本的AddDate/FormatDateTime。

按天累计的坑
“一个月”到底是30天还是自然月?按天算就一律30×86400秒,简单稳定。按自然月(比如1月15到2月15)要用AddMonths类命令,HERO不一定有,没有就老实用30天。

体验会员一天=86400秒;一周=7×86400;一月=30×86400。闰年、跨夏令时不用管,传奇服务端一般用UTC+8固定时区。

防止覆盖剩余时间的完整写法
假设玩家还有10天会员,再买一个月,应该是40天,不是30天。核心就这句:
CalcVarU$会员到期时间+天数×86400
前提是“旧到期时间已经大于当前时间”才直接加,否则要从当前时间开始加。所以前面那段:
IF

LARGEU会员到期时间<NOW>
ACT

MOVU会员到期时间<NOW>
BREAK
就是把“已过期”的情况修正为从现在算起,没过期就保持原值,然后统一加天数。这个分支不能省。

会员名单自动清理
“清理会员名单”有两层:
1.玩家自己的会员标记:登录时LARGE<NOW>U会员到期时间就清N$会员等级,上面已经做了。
2.全服会员列表/排行榜:如果有个全局记录(比如G$变量或文本文件存的会员名单),需要定期扫描。HERO不好直接遍历所有玩家变量,最稳的做法是:
•每个会员登录时走[@CheckVip],过期就清自己的标记

•定时器每小时跑一次全服检查(RunTick配合ForPlay或M2的“遍历在线玩家”命令)

•或者干脆不维护名单,需要时实时查N$会员等级>0的在线玩家

如果你确实要“名单文件自动删行”,用HERO的文件操作命令(LineCount、DeleteLine、LoadVarList),在定时器里读名单文件,逐行仍应玩家的到期变量,过期就删该行。但更简单是名单文件只存“在线且是会员”的人,每次登录重新登记,过期当场注销。

测试步骤
1.建变量:N会员等级、U会员到期时间、S$到期显示
2.写购买NPC,先只测“买一月”
3.买完后查变量值是否=Now+2592000
4.再买一次,看是否变成Now+5184000(累计,不是覆盖)
5.手动把U$会员到期时间改成0或一个过去时间,重新登录看是否清成普通玩家
6.在线挂机,把时间改到到期之后,看RunTick是否自动取消特权
7.查显示:<STR(S到期显示)>是否正常日期

HERO命令差异提醒
HERO不同版本对CalcVar、CALC、SaveVarHUMAN、<$NOW>、AddDate的支持不一样。如果你的版本没有CALC,就用最原始的三段式:
•取当前天数的变量DayNow

•取旧到期天数的变量DayExpire

•新到期天数=Max(DayExpireDayNow)+天数

•存回去

取天数用命令把日期拆成天数,比如从开服基准日算偏移;存盘用SaveVarHUMAN。逻辑一样,只是时间单位从“秒”换成“天”,对一天/一周/一月这种精度完全够用,还避开了秒级时间戳的命令兼容问题。

一个完整的延期片段(按天,兼容性最好)
[@AddVipDay]
ACT

MOVD0$PARAM(0)
IF

LARGEU$到期天0
ACT

IF

LARGEU到期天<今天天数>
ACT

MOVU到期天<今天天数>
BREAK
IF

ACT

CalcVarU$到期天+D0
IF

EQUALD01
ACT

MOVN$会员等级1
IF

EQUALD07
ACT

MOVN$会员等级2
IF

EQUALD030
ACT

MOVN$会员等级3
IF

ACT

SaveVarHUMANU$到期天..\QuestDiary\会员\会员数据.txt
SaveVarHUMANN$会员等级..\QuestDiary\会员\会员数据.txt
BREAK

<$今天天数>用一个启动脚本或每日定时脚本算好存进全局变量,全服复用。这样完全不依赖秒级时间戳命令,HERO老版本也能跑。

到期清理用天数版
[@Login]
IF

LARGEN$会员等级0
ACT

IF

LARGE<今天天数>U到期天
ACT

MOVN$会员等级0
SaveVarHUMANN$会员等级..\QuestDiary\会员\会员数据.txt
SENDMSG6会员已到期
ELSEACT

SENDMSG6会员剩余天数:<STR(U到期天-<$今天天数>)>
BREAK

把“剩余天数”显示出来,玩家体验好很多,也方便你排查累计是否正确。

会员特权示例(传送员判断)
[@go_zuma]
IF

LARGEN$会员等级0
ACT

MAPMOVE0155050
SENDMSG6会员免费传送
BREAK
ELSEACT

IF

CHECKGOLD1000
ACT

TAKE金币1000
MAPMOVE0155050
ELSEACT

SENDMSG6非会员需1000金币
BREAK

所有会员特权点都先走LARGEN$会员等级0,再CALL@CheckVip防过期,结构清晰,后面加特权只改一处。

变量存盘位置
SaveVarHUMAN的路径要写对,HERO里一般是相对于Mir200目录,比如:
SaveVarHUMANN$会员等级..\QuestDiary\会员数据\会员等级.txt
文件名最好按玩家区分,HERO会自动加玩家标识。如果存盘失败,重启后会员全丢,测试时第一件事就是改完买会员,重启M2,看等级还在不在。

一句话结构
购买→AddVip(天数)→到期时间=Max(旧到期现在)+天数→存盘
登录→CheckVip→现在>到期时间→清等级、清名单、存盘
在线→RunTick定时CheckVip→到期当场清理
特权→所有入口先判N$会员等级>0且未过期

这套写法下,买一个月再买一个月就是两个月,到期自动变回普通人,名单靠登录检查+定时扫描自动瘦身,不需要手动维护。
[顶部]