--[[ 道具系统的说明: 1. 数据结构:道具可看成共n(5)个桶,使用时用最上层的道具 ... | ... | ... | ... | ... propInfo | propInfo | propInfo | propInfo | propInfo propInfo | propInfo | propInfo | propInfo | propInfo ----------|-------------|-----------|------------|-------------- BtnIndex1 | BtnIndex2 | BtnIndex3 | BtnIndex4 | BtnIndex5 ————————————————————————————————— 2. 同一个btnIndex 只能同时使用一个道具。如果在using时新增了道具,且新道具需置顶,则再次点击同btn,则禁止使用。 (如果以后策划要此case中能使用btn,可向其推荐方案:新道具置顶时置于次顶。如果策划坚持能同时使用同按钮的多个道具则将 使用时间放入propInfo里) 3. 道具时序相关图 : 获得---->(设置initCD)---->CD结束----->点击Btn--->StartUse--->using(使用中)----->finish(使用完毕)+ 发动效果--->进入CD(CD中) 注:CD同道具ID公用同一个CD ,无btnIndex的限制 。initCD 只当本身无此道具时才设置,若有则不设置。(得新得道具时CD剩余20秒,initCD10秒,则CD是10秒,虽和大部分游戏不太一样但先听策划的吧) --]] local BattlePropComponent = class("BattlePropComponent") local EnumOverlayType = LuaConst.EnumBattlePropOverlayType local private = {} function private.CreatePropInfo(btnIndex, battlePropData, unlimitedUse) local propInfo = { btnIndex = btnIndex, -- 当前处于哪个按钮堆栈里 battlePropID = battlePropData.ID, lifeTime = battlePropData.Lifetime, -- 剩余生命时长(毫秒) count = 1, -- 如果配置了同道具合并(OverlayType=2\3),则count >1 unlimitedUse = unlimitedUse, -- 是否可无限使用 ,无限使用时count在使用后不变 } return propInfo end function BattlePropComponent:initialize(entity) self.propTotalNumDic = {} -- key:战斗道具id ,val:数量(所有按钮的总数量统计,条件判断使用,目的:在获取某个道具总数量时并不用遍历查询) self.propCDDic = {} -- key:道具id ,val: 剩余CD值leftCD 。毫秒,不受缩放影响 【单独记录是为了1.优化cd倒计时不用遍历propDic的stackList,2.道具的CD都共用,不用每个propInfo记录】 self.propTotalCDDic = {} -- key:道具id ,val: CD总值。为了优化所以不放在propCDDic里面 self.propDic = {} -- 所获得的现有道具数据。 key:btnIndex ,val :stackList = { propInfo ,propInfo ,propInfo } ,propInfo = {} -- 暂时不考虑同btnIndex同时使用多个道具 self.curUsingBattlePropDic = {} -- key:btnIndex , val:当前正在使用道具propInfo self.curUsingTimerDic = {} -- key:btnIndex ,val: (单位:毫秒)当前使用道具状态持续时长(暂时不考虑时间缩放) end --region 新增道具 -- 新增一个道具 unlimitedUse: 可无限使用 function BattlePropComponent:AddOneProp(btnIndex, battlePropData, unlimitedUse) local battlePropID = battlePropData.ID local overlayType = battlePropData.OverlayType -- 记录当前数量 local curCount = self.propTotalNumDic[battlePropID] or 0 -- 放入对应位置,并修改信息 local stackList = self.propDic[btnIndex] if stackList == nil then stackList = {} self.propDic[btnIndex] = stackList end if overlayType == EnumOverlayType.Stack then -- 堆叠 local propInfo = private.CreatePropInfo(btnIndex, battlePropData, unlimitedUse) local listPos = battlePropData.IsNewToUp and #stackList+1 or 1 table.insert(stackList, listPos, propInfo) if curCount == 0 then self:EnterCD(battlePropID, battlePropData.InitCD) end self:SetPropTotalNumber(battlePropID, curCount + 1) elseif overlayType == EnumOverlayType.Integrat or overlayType == EnumOverlayType.Refresh then -- 合并 或 刷新 local propInfo = nil local findIndex = -1 for i, info in ipairs(stackList) do if info.battlePropID == battlePropID then propInfo = info findIndex = i break end end if propInfo == nil then -- 此位置之前无本道具 propInfo = private.CreatePropInfo(btnIndex, battlePropData, unlimitedUse) local listPos = battlePropData.IsNewToUp and #stackList+1 or 1 table.insert(stackList, listPos, propInfo) if curCount == 0 then self:EnterCD(battlePropID, battlePropData.InitCD) end self:SetPropTotalNumber(battlePropID, curCount + 1) else propInfo.lifeTime = battlePropData.OverlayLifetimeType == 0 and battlePropData.Lifetime or propInfo.lifeTime if overlayType == EnumOverlayType.Integrat then propInfo.count = propInfo.count + 1 self:SetPropTotalNumber(battlePropID, curCount + 1) end if battlePropData.IsNewToUp then table.remove(stackList,findIndex) table.insert(stackList,propInfo) end propInfo.unlimitedUse = unlimitedUse end end end --endregion --使用一个道具完毕 function BattlePropComponent:UsePropInfoOver(btnIndex, propInfo, battlePropData) if not propInfo.unlimitedUse then -- 如果无限次使用的话,则数量不变 if propInfo.count > 1 then -- 如果次数多于1,减少次数 propInfo.count = propInfo.count - 1 else -- 如果次数等于1,则从stack删除 local stackList = self.propDic[btnIndex] for i, pinfo in ipairs(stackList) do if pinfo == propInfo then table.remove(stackList,i) break end end end -- 更新总统计数量 local number = self.propTotalNumDic[propInfo.battlePropID] or 0 if number > 0 then local count = number - 1 self:SetPropTotalNumber(propInfo.battlePropID,count) else logging.error(LTAG.ERROR, "[gws]: 已经没有道具了,怎么还能使用。需要程序查原因。battlePropID =", propInfo.battlePropID) end end -- 设置当前btnIndex为不使用状态 self:SetCurUsingBattleProp(btnIndex, nil) --设置CD self:EnterCD(propInfo.battlePropID, battlePropData.CD) end --删除某一位置下的所有道具,but BattlePropID function BattlePropComponent:DeleteAllBattlePropsInBtnIndex(btnIndex, butBattlePropID, outFindList) local stackList = self.propDic[btnIndex] if stackList then for i=#stackList,1,-1 do local propInfo = stackList[i] if propInfo.battlePropID ~= butBattlePropID then table.remove(stackList, i) self:SetPropTotalNumber(propInfo.battlePropID, self.propTotalNumDic[propInfo.battlePropID] - propInfo.count) table.insert(outFindList,propInfo.battlePropID) end end end end -- 强制删除道具 count:去掉个个数, nil:此位置全删 (如有调用删除逻辑别直接用此方法,请用BattlePropSystem.DeleteBattleProp) function BattlePropComponent:DeleteBattleProp(btnIndex, index, count) local stackList = self.propDic[btnIndex] if stackList then local propInfo = stackList[index] if propInfo then if count == nil or count >= propInfo.count then table.remove(stackList, index) self:SetPropTotalNumber(propInfo.battlePropID, self.propTotalNumDic[propInfo.battlePropID] - propInfo.count) else propInfo.count = propInfo.count - count self:SetPropTotalNumber(propInfo.battlePropID, self.propTotalNumDic[propInfo.battlePropID] - count) end if self.propTotalNumDic[propInfo.battlePropID] < 0 then logging.error(LTAG.ERROR, "[gws]: 道具删除后数量小于0了 !btnIndex = ",btnIndex, ",index = ", index) self:SetPropTotalNumber(propInfo.battlePropID,0) end end end end -- 统计数量 function BattlePropComponent:SetPropTotalNumber(battlePropID, count) self.propTotalNumDic[battlePropID] = count if count <= 0 or count == nil then -- 这种道具不存在后,CD要清理掉 self.propCDDic[battlePropID] = nil self.propTotalCDDic[battlePropID] = nil end end -- 设置当前正在使用的道具 function BattlePropComponent:SetCurUsingBattleProp(btnIndex, propInfo, battlePropData) if propInfo then self.curUsingBattlePropDic[btnIndex] = propInfo self:SetCurUsingTimer(btnIndex, battlePropData.Duration) else self.curUsingBattlePropDic[btnIndex] = nil self:SetCurUsingTimer(btnIndex,nil) end end -- 设置当前正在使用的道具的使用时间 function BattlePropComponent:SetCurUsingTimer(btnIndex, duration) self.curUsingTimerDic[btnIndex] = duration end -- 进入CD function BattlePropComponent:EnterCD(battlePropID, cd) if cd and cd > 0 then self.propCDDic[battlePropID] = cd self.propTotalCDDic[battlePropID] = cd end end -- CD 好了 function BattlePropComponent:ExitCD(battlePropID) self.propCDDic[battlePropID] = nil self.propTotalCDDic[battlePropID] = nil end -- 拷贝数据 function BattlePropComponent:Copy(battlePropComp) for k,v in pairs(battlePropComp.propTotalNumDic) do-- pairs safe self.propTotalNumDic[k] = v end table.clear(self.propCDDic) for k,v in pairs(battlePropComp.propCDDic) do-- pairs safe self.propCDDic[k] = v end table.clear(self.propTotalCDDic) for k,v in pairs(battlePropComp.propTotalCDDic) do-- pairs safe self.propTotalCDDic[k] = v end for k,stackList in pairs(battlePropComp.propDic) do-- pairs safe self.propDic[k] = {} for i,propInfo in ipairs(stackList) do self.propDic[k][i] = propInfo end end for k,v in pairs(battlePropComp.curUsingBattlePropDic) do-- pairs safe self.curUsingBattlePropDic[k] = v end for k,v in pairs(battlePropComp.curUsingTimerDic) do-- pairs safe self.curUsingTimerDic[k] = v end end --region 查询代码 -- 获取最近得到的道具propInfo function BattlePropComponent:GetTopBattlePropInfo(btnIndex) local stackList = self.propDic[btnIndex] if stackList and #stackList > 0 then return stackList[#stackList] else return nil end end -- 获取一个道具的数量 function BattlePropComponent:GetBattlePropNum(battlePropID) return self.propTotalNumDic[battlePropID] or 0 end -- 获取所有道具的总数量 function BattlePropComponent:GetBattlePropTotalNum() local count = 0 for id,num in pairs(self.propTotalNumDic) do -- pairs safe count = count + num end return count end --endregion 查询代码 return BattlePropComponent