帮我写一个7日签到系统
🤖 回答引擎: 后端Lua |
🕒 时间: 2026-03-25 20:12:33 |
👁️ 阅读: 9
我是lua后端老师!
小仙,想要一个7日签到系统是吧?没问题,这个在996引擎里很常见,我们可以用全局变量和玩家变量配合来实现,确保每天只能签到一次,并且连续签到7天后重置。
核心思路是:
1. 用全局变量记录当前服务器的日期(比如 `GLOBAL(今日日期)`),用于判断是否是新的一天。
2. 用玩家变量记录玩家最后一次签到的日期(比如 `S签到日期`)和已连续签到的天数(比如 `N签到天数`)。
3. 每次登录或点击签到按钮时,进行判断:如果服务器日期和玩家上次签到日期不同,则允许签到,并更新天数;如果相同,则提示今日已签到。
下面是完整的脚本示例,包括登录触发、签到NPC脚本和必要的函数封装:
**第一步:在 `QFunction-0.txt` 中添加登录触发,用于每日重置判断**
```lua
-- 登录触发 @login
function login(actor)
-- 获取当前服务器日期,格式为YYYYMMDD
local currentDate = tonumber(os.date("%Y%m%d"))
local lastGlobalDate = tonumber(getglobalvar("今日日期") or 0)
-- 如果全局记录的日期不是今天,则更新为今天,并清空所有玩家的“今日已签到”标记(如果需要的话)
if currentDate ~= lastGlobalDate then
setglobalvar("今日日期", tostring(currentDate))
-- 这里可以加一些跨天重置的逻辑,比如清空某个全局标记
release_print("新的一天,全局日期已更新为:" .. currentDate)
end
-- 检查玩家上次签到日期
local playerLastDate = tonumber(getplayvar(actor, "S签到日期") or 0)
local signDays = tonumber(getplayvar(actor, "N签到天数") or 0)
-- 如果玩家上次签到日期不是今天,且也不是昨天(说明连续签到断了),则重置签到天数为0
-- 注意:这是一个简单的连续签到判断,更严格的可以检查是否是昨天
if playerLastDate ~= currentDate then
-- 这里简化处理:如果不是今天,就检查是否断签。实际项目中可能需要更精确的日期差值计算
-- 例如:if currentDate - playerLastDate > 1 then
if playerLastDate > 0 and (currentDate - playerLastDate) > 1 then
setplayvar(actor, "N签到天数", "0")
release_print(getbaseinfo(actor, 1) .. " 连续签到已中断,天数重置为0")
end
end
-- 可以在这里发送签到状态给客户端,比如通过 sendmsg
-- sendmsg(actor, "欢迎回来!您的当前连续签到天数为:" .. (tonumber(getplayvar(actor, "N签到天数") or 0)), 1)
end
```
**第二步:创建签到NPC脚本(比如在 `Envir\Market_Def\` 目录下创建 `签到使者-3.txt`)**
```lua
[@main]
您好,我是签到使者!\
每天都可以在我这里领取丰厚的签到奖励。\
您当前的连续签到天数为:<$STR(N签到天数)>天\
<签到/@签到> \
<离开/@exit>
[@签到]
#IF
#ACT
-- 调用签到函数
local result = PlayerSignIn(actor)
if result == 1 then
goto @签到成功
elseif result == 0 then
goto @今日已签到
else
goto @签到失败
end
[@签到成功]
#ACT
-- 根据连续天数发放奖励
GiveSignReward(actor)
sendmsg(actor, "恭喜你签到成功!连续签到天数+1", 1)
goto @main
[@今日已签到]
#ACT
sendmsg(actor, "你今天已经签到过了,请明天再来吧!", 1)
goto @main
[@签到失败]
#ACT
sendmsg(actor, "签到失败,请联系管理员。", 1)
goto @main
```
**第三步:在 `QFunction-0.txt` 或单独的可被引用的Lua文件中封装核心函数**
```lua
-- 玩家签到核心逻辑函数
-- 参数:actor (玩家对象)
-- 返回值:1=签到成功,0=今日已签到,-1=系统错误
function PlayerSignIn(actor)
local currentDate = tonumber(os.date("%Y%m%d"))
local lastGlobalDate = tonumber(getglobalvar("今日日期") or 0)
-- 安全校验:确保全局日期是最新的(理论上登录触发已更新)
if currentDate ~= lastGlobalDate then
setglobalvar("今日日期", tostring(currentDate))
end
local playerLastDate = tonumber(getplayvar(actor, "S签到日期") or 0)
local signDays = tonumber(getplayvar(actor, "N签到天数") or 0)
-- 判断今日是否已签到
if playerLastDate == currentDate then
return 0 -- 今日已签到
end
-- 判断是否连续签到(昨天签到了)
local isContinuous = false
if playerLastDate > 0 and (currentDate - playerLastDate) == 1 then
isContinuous = true
else
-- 如果不是昨天,可能断签了,天数从1开始(或者按业务逻辑重置)
-- 这里我们选择:如果不是连续,则从1开始(或者根据需求,可能重置为0,但登录触发已处理过)
-- 为了逻辑清晰,我们直接使用登录触发处理后的天数。这里只处理连续的情况。
end
-- 更新签到天数和日期
if isContinuous then
signDays = signDays + 1
else
-- 如果上次签到不是昨天,但今天之前签过(即登录触发没重置的情况),天数从1开始
-- 更常见的做法是:只要不是昨天,就重置为1(代表今天第一次签)
if playerLastDate > 0 and (currentDate - playerLastDate) > 1 then
signDays = 1
elseif signDays == 0 then
signDays = 1 -- 从未签到过
-- 如果 signDays 已经因为断签被登录触发重置为0,这里也会变成1
else
signDays = 1 -- 兜底
end
end
-- 限制最大为7天
if signDays > 7 then
signDays = 7
end
setplayvar(actor, "S签到日期", tostring(currentDate))
setplayvar(actor, "N签到天数", tostring(signDays))
release_print(string.format("玩家[%s]签到成功,日期:%s,连续天数:%d", getbaseinfo(actor, 1), currentDate, signDays))
return 1
end
-- 发放签到奖励函数
-- 参数:actor (玩家对象)
function GiveSignReward(actor)
local signDays = tonumber(getplayvar(actor, "N签到天数") or 1)
release_print(string.format("准备为玩家[%s]发放第%d天签到奖励", getbaseinfo(actor, 1), signDays))
-- 根据连续天数发放不同奖励
if signDays == 1 then
giveitem(actor, "金币", 10000) -- 奖励道具名和数量请根据你的物品库修改
sendmsg(actor, "获得第1天签到奖励:金币10000", 1)
elseif signDays == 2 then
giveitem(actor, "强效金创药", 10)
sendmsg(actor, "获得第2天签到奖励:强效金创药x10", 1)
elseif signDays == 3 then
giveitem(actor, "强效魔法药", 10)
sendmsg(actor, "获得第3天签到奖励:强效魔法药x10", 1)
elseif signDays == 4 then
giveitem(actor, "回城卷", 10)
sendmsg(actor, "获得第4天签到奖励:回城卷x10", 1)
elseif signDays == 5 then
giveitem(actor, "祝福油", 1)
sendmsg(actor, "获得第5天签到奖励:祝福油x1", 1)
elseif signDays == 6 then
giveitem(actor, "金币", 50000)
sendmsg(actor, "获得第6天签到奖励:金币50000", 1)
elseif signDays == 7 then
giveitem(actor, "沃玛号角", 1) -- 举例
giveitem(actor, "金币", 100000)
sendmsg(actor, "恭喜完成7日连续签到!获得终极奖励:沃玛号角x1、金币100000", 1)
-- 7天后,可以选择重置天数,或者保持不变。这里我们选择重置,重新开始循环。
setplayvar(actor, "N签到天数", "0")
sendmsg(actor, "七日签到已完成,天数已重置,新的循环开始!", 1)
else
sendmsg(actor, "签到奖励配置异常,请联系管理员。", 1)
end
end
```
**使用说明:**
1. **全局变量**:`GLOBAL(今日日期)` 由系统自动维护。
2. **玩家变量**:
* `S签到日期`:记录玩家上次签到的日期(YYYYMMDD格式)。
* `N签到天数`:记录玩家当前连续签到的天数(1-7)。
3. **流程**:
* 玩家登录时,触发 `@login`,检查日期并处理可能的断签重置。
* 玩家点击NPC签到,调用 `PlayerSignIn` 函数。
* 函数检查 `S签到日期` 是否为今天,如果是则返回“已签到”。
* 如果不是今天,则检查是否与上次签到连续(相差1天),并更新 `N签到天数` 和 `S签到日期`。
* 签到成功后,调用 `GiveSignReward` 根据天数发放奖励。
* 当签到满7天时,发放最终奖励并将 `N签到天数` 重置为0,开始新一轮签到。
**注意事项:**
* 请根据你的实际物品库,修改 `GiveSignReward` 函数中的奖励物品名称和数量。
* 日期判断基于服务器时间 (`os.date`),请确保服务器时间准确。
* 连续签到的判断逻辑(“相差1天”)是核心,这里用的是简化版。如果你的服务器有跨天活动(比如0点刷新),这个逻辑是合适的。如果需要更精确(比如考虑凌晨4点刷新),需要调整日期计算逻辑。
* 记得在 `MapQuest_Def\QManage.txt` 中加载或引用包含这些函数的Lua文件(如果单独存放)。
* 所有 `release_print` 用于后台调试,上线后可考虑移除或改为日志文件输出。
这个系统就够用了,小仙你先部署测试一下,有问题随时问我!如果奖励想做成配置表,或者加上补签功能,我们可以再继续扩展。
← 返回问答库