-- 采集前触发
function collectmonex(actor, mon_idx, mon_name, mon_uid)
func_collectmonex(actor, mon_idx, mon_name, mon_uid)
end
-- 采集跳转
function func_collectmonex(actor, mon_idx, mon_name, mon_uid)
-- 锁键
local lockKey = actor .. "_" .. mon_ui
🤖 回答引擎: 后端Lua |
🕒 时间: 2026-06-17 20:50:22 |
👁️ 阅读: 8
我是lua后端老师!
小仙你好,看了你的代码,问题主要出在获取怪物对象这一步。在996引擎中,`getmonbyuserid` 函数的第一个参数是**玩家对象的ID**,而不是玩家对象本身。你代码里用 `actor` 作为参数,这通常是一个字符串类型的玩家ID,这是正确的。但问题可能在于,你传入的 `mon_uid` 参数可能不是正确的怪物唯一ID。
让我帮你分析并修正一下:
1. **检查 `mon_uid` 参数来源**:`collectmonex` 函数是由 `@collectmonex` 触发的,这个触发会传递 `mon_uid`。你需要确保这个 `mon_uid` 确实是当前怪物的唯一标识。一个常见的验证方法是,在触发里直接打印一下看看。
2. **修正 `getmonbyuserid` 的调用**:你代码中的调用 `getmonbyuserid(actor, mon_uid)` 语法本身没问题,但为了清晰和避免混淆,我们可以更明确地写出。同时,我们需要在关键步骤添加调试信息来定位问题。
这是修改后的 `func_collectmonex` 函数中关于灵兽蛋采集的部分,我们加入调试打印:
```lua
-- 采集跳转
function func_collectmonex(actor, mon_idx, mon_name, mon_uid)
-- 锁键
local lockKey = actor .. "_" .. mon_uid
release_print(string.format("[DEBUG] 玩家 %s 开始采集,怪物名:%s, 怪物UID:%s", actor, mon_name, mon_uid)) -- 调试行
-- 灵兽蛋采集逻辑
if mon_name == "灵兽蛋[初级]" or mon_name == "灵兽蛋[中级]" or mon_name == "灵兽蛋[高级]" then
-- 1. 检查每日次数
if getplaydef(actor, "J14") >= 5 then
sendmsg(actor, 1, '{"Msg":"<font color=\'#ff0000\'>今日抓捕次数已达上限!!</font>","Type":9}')
return
end
-- 2. 原子化读取与检查A15表
local t = getsysvar("A15")
if t == "" then
t = "{}"
end
local tbl = json2tbl(t)
-- 3. 检查这个怪物是否已被其他玩家(任何角色)锁定
for key, timestamp in pairs(tbl) do
if string.find(key, "_" .. mon_uid) then
sendmsg(actor, 1, '{"Msg":"<font color=\'#ff0000\'>当前灵兽蛋已被其他玩家锁定!!</font>","Type":9}')
return
end
end
-- 4. 检查这个【角色】是否已经锁定了一个怪物
for key, timestamp in pairs(tbl) do
if string.find(key, actor .. "_") then
sendmsg(actor, 1, '{"Msg":"<font color=\'#ff0000\'>你已经在采集一个灵兽蛋了!!</font>","Type":9}')
return
end
end
-- 5. 获取怪物对象并检查是否存在
-- 使用玩家ID (actor) 和 怪物UID (mon_uid) 获取怪物对象
local mon_obj = getmonbyuserid(actor, mon_uid) -- 获取怪物对象
release_print(string.format("[DEBUG] 获取到的怪物对象 mon_obj: %s", tostring(mon_obj))) -- 调试行
if not mon_obj or mon_obj == "" then
sendmsg(actor, 1, '{"Msg":"<font color=\'#ff0000\'>灵兽蛋已消失!!</font>","Type":9}')
release_print(string.format("[DEBUG] 怪物对象无效,可能UID错误或怪物已死。UID: %s", mon_uid)) -- 调试行
return
end
-- 可以进一步获取怪物信息确认
local mon_name_check = getbaseinfo(mon_obj, 1)
local mon_map = getbaseinfo(mon_obj, 3)
release_print(string.format("[DEBUG] 确认怪物信息,名称:%s, 地图:%s", mon_name_check, mon_map)) -- 调试行
-- 6. 一切就绪,写入锁定记录
tbl[lockKey] = os.time()
setsysvar("A15", tbl2json(tbl))
-- 7. 存储采集信息到玩家变量
setplaydef(actor, "S$采集地图id", getbaseinfo(mon_obj, 3))
setplaydef(actor, "S$采集地图x", getbaseinfo(mon_obj, 4))
setplaydef(actor, "S$采集地图y", getbaseinfo(mon_obj, 5))
setplaydef(actor, "S$采集怪物UID", mon_uid)
-- 8. 开始采集进度条
local tiem = DATA.hd_info["抓捕灵兽"].tiem_num[mon_name]
showprogressbardlg(actor, tiem, "@caiji_true", "灵兽蛋采集中...%s%%", 1, "@caiji_false")
end
-- ... 其余酒神材料逻辑 ...
end
```
**修改要点和排查思路:**
1. **添加调试信息**:我在关键位置加了 `release_print`。重启服务器后,触发一次采集,然后在 `M2Server->查看->日志信息` 里过滤 `[DEBUG]`,就能看到打印的信息。这会告诉你 `mon_uid` 是什么,以及 `getmonbyuserid` 是否真的返回了空值。
2. **确认触发参数**:确保 `@collectmonex` 这个触发传递的 `mon_uid` 是正确的、唯一的怪物标识。有时候不同的触发或引擎版本,参数顺序或含义可能有细微差别,需要查证官方文档或示例。
3. **检查怪物状态**:`getmonbyuserid` 只能获取**当前地图**上**存活**的怪物。如果怪物在触发采集前因为任何原因(比如被其他玩家打死、刷新消失)已经不存在了,那么也会返回空。你的锁逻辑就是为了防止这个,但锁是在获取怪物对象*之后*才加的,所以这里仍有时间窗口。你可以考虑调整逻辑顺序,或者检查是否是网络延迟、玩家操作过快导致。
4. **函数参数确认**:你代码中 `getmonbyuserid(actor, mon_uid)` 的调用是正确的。`actor` 是玩家ID(字符串),`mon_uid` 是怪物唯一ID(数字或字符串),这个用法符合引擎规范。
**总结一下排查步骤:**
1. 加上面的调试代码。
2. 重启服务器,让一个玩家去采集灵兽蛋。
3. 在M2日志里查看 `[DEBUG]` 开头的打印信息。
4. 重点关注 `mon_uid` 的值,以及 `mon_obj` 是否为 `nil` 或空字符串。
如果发现 `mon_uid` 不对或者为空,那就要去检查触发设置。如果 `mon_uid` 正确但 `mon_obj` 还是为空,那很可能就是怪物在采集触发的那一刻已经不存在于地图上了。
你先按这个思路排查一下,看看调试信息输出了什么。如果还有问题,把调试日志贴出来,我们再继续分析!
← 返回问答库