设计约定:
追加错误码
ITEM_CANT_USE = -106, — 该物品不可使用
ITEM_USE_CD = -107, — 使用冷却中
ITEM_USE_COND_FAIL = -108, — 使用条件不满足(等级、行会、副本等)
追加到 item_mgr.lua 代码
— 使用物品统一入口
— @param player 玩家对象
— @param item 物品实例
— @param use_cnt 本次使用数量
— @param extra_param 扩展参数 {target_uid, select_idx…礼包多选之类}
— @return ret, msg
function ItemMgr:UseItem(player, item, use_cnt, extra_param)
local role_id = player:GetRoleId()
use_cnt = math.floor(use_cnt or 1)
local cfg = ConfigMgr:GetItemCfg(item.item_id)
— 基础校验
if not cfg or not cfg.can_use then
return ERR.ITEM_CANT_USE, "该物品不能使用"
end
if use_cnt <= 0 or use_cnt > item.count then
return ERR.ITEM_COUNT_INVALID, "使用数量非法"
end
— 唯一物品只能单次使用1个
if cfg.is_unique and use_cnt > 1 then
return ERR.ITEM_UNIQUE_EXIST, "唯一道具只能单次使用1个"
end
— CD校验,CD数据存在player临时data里
if cfg.use_cd > 0 then
local last_use = player:GetTempData("item_cd_"..item.item_id) or 0
local now = os.time()
if now – last_use < cfg.use_cd then
return ERR.ITEM_USE_CD, string.format("冷却中,剩余%d秒", cfg.use_cd – (now – last_use))
end
end
— 策划配置的前置条件(等级、转生、是否在副本内等)
if cfg.use_cond then
local ok, tip = self:CheckUseCond(player, cfg.use_cond)
if not ok then
return ERR.ITEM_USE_COND_FAIL, tip
end
end
— 消耗数量
local remain = item.count – use_cnt
local consume_item = {}
— 复制一份被消耗的物品用于日志
for k, v in pairs(item) do
consume_item[k] = v
end
consume_item.count = use_cnt
— 扣数量逻辑
if remain <= 0 then
— 全部用完,销毁物品
ItemMgr:DestroyItem(item, "item_use")
else
item.count = remain
end
— 更新CD时间
if cfg.use_cd and cfg.use_cd > 0 then
player:SetTempData("item_cd_"..item.item_id, os.time())
end
— 写消耗日志
LogMgr:WriteItemLog(role_id, "item_use", {consume_item})
— 抛出事件,业务逻辑订阅这个事件实现,解耦!
EventMgr:Fire("ITEM_USE", player, consume_item, extra_param or {})
return ERR.SUCCESS, "使用成功"
end
— 使用条件校验函数(配置驱动)
— cond 配置示例:{level=50, no_dungeon=true, no_battle=false}
function ItemMgr:CheckUseCond(player, cond)
local role_attr = AttrMgr:GetPlayerAttr(player)
if cond.level and role_attr.level < cond.level then
return false, string.format("需要等级%d", cond.level)
end
if cond.rein and role_attr.rein < cond.rein then
return false, string.format("需要转生%d重", cond.rein)
end
if cond.no_dungeon and player:IsInInstance() then
return false, "副本内无法使用"
end
if cond.no_battle and player:IsInBattle() then
return false, "战斗状态无法使用"
end
return true, "ok"
end
配套 客户端消息协议 proto
// 请求使用物品
message C2SUseItem {
uint64 item_uid = 1;
uint32 use_cnt = 2;
map<string, string> extra_param = 3;
}
message S2CUseItemRsp {
int32 ret = 1;
string msg = 2;
}
BagMgr 消息处理器(玩家背包点击使用,转发调用ItemMgr)
背包负责:根据uid找到格子物品、锁定保护校验,再调用ItemMgr.UseItem
— bag_mgr.lua 追加
function BagMgr:OnC2SUseItem(player, req)
local uid = req.item_uid
local use_cnt = req.use_cnt
local extra = req.extra_param
local bag_data = player:GetBagData()
local find_pos = nil
local target_item = nil
for pos, item in pairs(bag_data.items) do
if item and item.uid == uid then
find_pos = pos
target_item = item
break
end
end
if not target_item then
player:SendMsg("S2CUseItemRsp", {ret=-1, msg="物品不存在"})
return
end
— 锁定物品禁止使用
if target_item.is_lock then
player:SendMsg("S2CUseItemRsp", {ret=-1, msg="物品已锁定"})
return
end
local ret, msg = ItemMgr:UseItem(player, target_item, use_cnt, extra)
player:SendMsg("S2CUseItemRsp", {ret=ret, msg=msg})
— 使用成功同步背包
if ret == 0 then
self:SyncBagAll(player)
end
end
事件订阅示例(各个业务模块监听 ITEM_USE,示例)
— 礼包奖励 RewardMgr 订阅示例
EventMgr:Subscribe("ITEM_USE", function(player, consume_item, extra)
local cfg = ConfigMgr:GetItemCfg(consume_item.item_id)
if cfg.item_type ~= 10 then return end — 10=礼包类型
— 发放礼包奖励
RewardMgr:GiveReward(player, cfg.reward_list)
end)
— 回城卷轴 传送逻辑 MapMgr订阅
EventMgr:Subscribe("ITEM_USE", function(player, consume_item, extra)
local cfg = ConfigMgr:GetItemCfg(consume_item.item_id)
if cfg.item_type ~= 11 then return end — 11=回城卷
MapMgr:PlayerTeleport(player, cfg.tele_map_id, cfg.tele_x, cfg.tele_y)
end)
— 药品Buff BuffMgr订阅
EventMgr:Subscribe("ITEM_USE", function(player, consume_item, extra)
local cfg = ConfigMgr:GetItemCfg(consume_item.item_id)
if cfg.item_type ~= 12 then return end — 12=药品
BuffMgr:AddBuff(player, cfg.buff_id, cfg.buff_time)
end)
使用流程时序
客户端点击物品 → C2SUseItem
→ BagMgr 根据uid查找物品、锁定校验
→ ItemMgr:UseItem 做通用校验(CD、等级、数量)
→ 扣减/销毁物品,写日志
→ Fire ITEM_USE事件
→ RewardMgr / BuffMgr / MapMgr 各自监听处理对应效果
→ 返回S2CUseItemRsp + 同步背包
网硕互联帮助中心


评论前必须登录!
注册