local leishen = {}
-- 主处理函数
function leishen.link(actor, msgid, arg1, arg2, arg3, sMsg)
-- 检查配置
if not cfg_leishen or not next(cfg_leishen) then
lib:msg(actor, "配置错误", 1)
return
end
local rlv_str = getplaydef(ac
🤖 回答引擎: 后端Lua |
🕒 时间: 2026-03-24 17:01:58 |
👁️ 阅读: 5
小仙,你好!我是lua后端老师!
看了你的代码,我发现问题出在定时器的设置上。在**后端脚本**中,你使用了 `setontimer` 来启动一个每秒执行一次的定时器,这个定时器会向客户端发送倒计时数据。但问题在于,你**每次触发特效**时都会创建一个**同名**的定时器,并且没有清理之前的定时器,导致多个定时器同时运行,时间显示就混乱了。
关键点在于 **`setontimer`** 的用法。根据资料,它的第一个参数是触发器ID。你使用 `"leishen_timer_" .. playerId` 作为ID,如果同一个玩家多次点击按钮,就会创建多个ID相同的定时器,它们会相互干扰。
**修复方法:** 在创建新的定时器前,先停止旧的同名定时器。
以下是修改后的**后端**部分代码:
```lua
-- ... (前面的代码省略) ...
elseif arg2 == 4 then
-- Button_5: 触发特效
local config = {
preEff = 83433, -- 预警特效ID
startEff = 83383, -- 技能特效ID
cd = 40, -- 特效cd时间
num = math.random(3, 5) -- 3-5个特效
}
local now = os.time()
local time = getobjintvar(actor, 40) or 0
if now - time > config.cd then
lib:msg(actor, "触发华丽特效!", 1)
local data = {}
data.num = config.num
data.preEff = config.preEff
data.startEff = config.startEff
-- 获取玩家位置
local mapid = getbaseinfo(actor, 3)
local x, y = getbaseinfo(actor, 4), getbaseinfo(actor, 5)
data.mapdata = {}
for i = 1, data.num do
data.mapdata[i] = {
x = x + math.random(-6, 6),
y = y + math.random(-6, 6)
}
end
-- 设置冷却时间
setobjintvar(actor, 40, now)
-- 使用正确的定时器函数
local playerId = getbaseinfo(actor, 0) -- 获取玩家唯一ID
local timerID = "leishen_timer_" .. playerId
local count = 40 -- 总倒计时秒数
-- !!!修复关键:先停止可能存在的旧定时器 !!!
setofftimer(actor, timerID)
-- 设置个人定时器
setontimer(actor, timerID, 1, function()
count = count - 1
if count >= 0 then
-- 发送当前剩余时间给前端
local timeData = {
totalCount = count,
percent = (count / 40) * 100
}
sendluamsg(actor, 2028, tbl2json(timeData))
return true -- 继续定时器
else
-- 定时器结束,关闭定时器
setofftimer(actor, timerID)
return false
end
end)
-- 发送初始特效数据给前端
sendluamsg(actor, 2027, tbl2json(data))
else
local remaining = config.cd - (now - time)
lib:msg(actor, "特效还在冷却中,请等待" .. remaining .. "秒!", 1)
end
end
```
**修改说明:**
1. 在 `setontimer` 之前,增加了 `setofftimer(actor, timerID)`。这确保了每次点击按钮时,旧的同名定时器会被清除,然后启动一个新的、干净的定时器。
2. 这样,倒计时就会从40秒开始,每秒减少1秒,前端接收到的数据才会正常更新。
另外,你的**前端代码**中,`showEffect`函数里注册了 `2028` 消息的回调。每次触发特效都会注册一次,也可能导致多个回调函数同时执行。虽然你最后在倒计时为0时取消了注册,但在倒计时过程中,如果多次触发,还是会有问题。不过,后端定时器修复后,前端问题应该也会随之解决。
记住,在使用 `setontimer` 这类定时器时,管理好它们的生命周期(开启和关闭)非常重要,不然很容易出现这种“定时器叠加”的bug。如果还有不明白的,随时可以问我,或者请教浮生梦尊师!
小仙,你好!我是lua后端老师!
看了你的代码,我发现问题出在定时器的设置上。在**后端脚本**中,你使用了 `setontimer` 来启动一个每秒执行一次的定时器,这个定时器会向客户端发送倒计时数据。但问题在于,你**每次触发特效**时都会创建一个**同名**的定时器,并且没有清理之前的定时器,导致多个定时器同时运行,时间显示就混乱了。
关键点在于 **`setontimer`** 的用法。根据资料,它的第一个参数是触发器ID。你使用 `"leishen_timer_" .. playerId` 作为ID,如果同一个玩家多次点击按钮,就会创建多个ID相同的定时器,它们会相互干扰。
**修复方法:** 在创建新的定时器前,先停止旧的同名定时器。
以下是修改后的**后端**部分代码:
```lua
-- ... (前面的代码省略) ...
elseif arg2 == 4 then
-- Button_5: 触发特效
local config = {
preEff = 83433, -- 预警特效ID
startEff = 83383, -- 技能特效ID
cd = 40, -- 特效cd时间
num = math.random(3, 5) -- 3-5个特效
}
local now = os.time()
local time = getobjintvar(actor, 40) or 0
if now - time > config.cd then
lib:msg(actor, "触发华丽特效!", 1)
local data = {}
data.num = config.num
data.preEff = config.preEff
data.startEff = config.startEff
-- 获取玩家位置
local mapid = getbaseinfo(actor, 3)
local x, y = getbaseinfo(actor, 4), getbaseinfo(actor, 5)
data.mapdata = {}
for i = 1, data.num do
data.mapdata[i] = {
x = x + math.random(-6, 6),
y = y + math.random(-6, 6)
}
end
-- 设置冷却时间
setobjintvar(actor, 40, now)
-- 使用正确的定时器函数
local playerId = getbaseinfo(actor, 0) -- 获取玩家唯一ID
local timerID = "leishen_timer_" .. playerId
local count = 40 -- 总倒计时秒数
-- !!!修复关键:先停止可能存在的旧定时器 !!!
setofftimer(actor, timerID)
-- 设置个人定时器
setontimer(actor, timerID, 1, function()
count = count - 1
if count >= 0 then
-- 发送当前剩余时间给前端
local timeData = {
totalCount = count,
percent = (count / 40) * 100
}
sendluamsg(actor, 2028, tbl2json(timeData))
return true -- 继续定时器
else
-- 定时器结束,关闭定时器
setofftimer(actor, timerID)
return false
end
end)
-- 发送初始特效数据给前端
sendluamsg(actor, 2027, tbl2json(data))
else
local remaining = config.cd - (now - time)
lib:msg(actor, "特效还在冷却中,请等待" .. remaining .. "秒!", 1)
end
end
```
**修改说明:**
1. 在 `setontimer` 之前,增加了 `setofftimer(actor, timerID)`。这确保了每次点击按钮时,旧的同名定时器会被清除,然后启动一个新的、干净的定时器。
2. 这样,倒计时就会从40秒开始,每秒减少1秒,前端接收到的数据才会正常更新。
另外,你的**前端代码**中,`showEffect`函数里注册了 `2028` 消息的回调。每次触发特效都会注册一次,也可能导致多个回调函数同时执行。虽然你最后在倒计时为0时取消了注册,但在倒计时过程中,如果多次触发,还是会有问题。不过,后端定时器修复后,前端问题应该也会随之解决。
记住,在使用 `setontimer` 这类定时器时,管理好它们的生命周期(开启和关闭)非常重要,不然很容易出现这种“定时器叠加”的bug。如果还有不明白的,随时可以问我,或者请教浮生梦尊师!
← 返回问答库