local Base = require "Battle/Logic/Buff/BuffManager/BuffOperator_Sustained" local BuffOperator_Halo = {} for k,func in pairs(Base) do BuffOperator_Halo[k] = func end local private = { haloBuffInfoList = {}, -- 存储信息:{ buffID = 光环buffid,buffData = 光环buffData entityList = {光环携带者} } -- 记录buffData是为了不要每次遍历都通过buffID从表中查 -内存换cpu buff2EntityExcuteTimeDic = {} -- 记录对于以entity为时间的间隔触发 [buffUpdate][entity] = excuteTime } local ipairs=ipairs local EnumHaloTarget = { None = 0, Enemy = 1, --光环携带者的敌方 Friend = 2, --友方 Self = 3 , -- 自己 FriendAndSelf = 4, -- 友 + 自己 Master = 5, -- 原始主人(不是直系主人) } local tempTable = {} function BuffOperator_Halo.Add(buffData,targetEntity,sourceEntity,missile,ctrlParam,index) local updateData = Base.Add(buffData,targetEntity,sourceEntity,missile,ctrlParam,index) private.AddHaloBuffDir(buffData, targetEntity) return updateData end ---- 执行部分----- function BuffOperator_Halo.Execute(buffData, targetEntity, sourceEntity, updateData) -- 自身加光环时不产生公式效果 end function BuffOperator_Halo.OnUpdate( buffData, updateData, entity, deltaTime, addList) local newupdate = Base.OnUpdate(buffData, updateData, entity, deltaTime, addList) if buffData.CallUseSelfTime then -- 只有频率大于0 ,才认为光环会生效 ;如果频率为0 ,则光环只是对进入的时候才生效一次 if buffData.CallFrequency > FP.Const.Zero then if updateData.BuffCallTimer < (buffData.CallFrequency/1000) then updateData.BuffCallTimer = updateData.BuffCallTimer + deltaTime else updateData.BuffCallTimer:Reset() for i,targetEntity in ipairs(LogicUpdateManager.EntityList_Sync) do private.OnceExcute(entity , targetEntity , buffData ,updateData ) end for i,targetEntity in ipairs(LogicUpdateManager.EntityList_Normal) do private.OnceExcute(entity , targetEntity , buffData ,updateData ) end end end end return newupdate end function BuffOperator_Halo.Delete( buffData, entity, updateData, addList, forceLayerZero) private.RemoveHaloBuffDir(buffData, entity, updateData) Base.Delete(buffData, entity, updateData, addList, forceLayerZero) private.buff2EntityExcuteTimeDic[updateData] = nil end function BuffOperator_Halo.ExclusiveDelete( buffData, entity, addBuffIdExclus, addBuffGroupExclus, updateData) private.RemoveHaloBuffDir(buffData, entity, updateData) Base.ExclusiveDelete(buffData, entity, addBuffIdExclus, addBuffGroupExclus, updateData) private.buff2EntityExcuteTimeDic[updateData] = nil end -- 寻找哪些光环对entity产生效果(每帧执行检测) function BuffOperator_Halo.UpdateHaloBuffEffect( entity) --entity 被各个光环作用 if not private.NeedHandle(entity) then --未激活不处理 return end for _,haloInfo in ipairs(private.haloBuffInfoList) do local buffId = haloInfo.buffID local entityList = haloInfo.entityList local buffData = haloInfo.buffData -- 有entity进入光圈就加buff for i,sourceEntity in ipairs(entityList) do if private.CheckCanEffectCamp(sourceEntity, entity, buffData) then sourceEntity.components.buff:GetAllBuffUpdateData(buffId ,tempTable) -- 这么写的目的是为了新增的buffUpdate也生效(例子:g带有abcd给光圈buff ,都给圈内的f加攻击力,e又给g加了新光圈,f要继续加攻击力) --- 圈内 -- sourceEntity参与战斗时才能对其他entity产生光环效果 if sourceEntity:IsRealActive() and not private.CheckOutRangeRoughly(sourceEntity, entity, buffData) and private.CheckInRangePrecisely(sourceEntity, entity, buffData) then -- 只在进圈时添加buff ,但如果进入圈时没有加上,则要不断的尝试加 if buffData.CallFrequency <= FP.Const.Zero then for _,updateData in ipairs(tempTable) do if private.buff2EntityExcuteTimeDic[updateData] and private.buff2EntityExcuteTimeDic[updateData][entity] then -- 之前已经进入圈内,不处理 else if not private.buff2EntityExcuteTimeDic[updateData] then private.buff2EntityExcuteTimeDic[updateData] = {} end --print("添加buff :" , buffData.CallBuffID) local ctrlParam = RuntimeDataManager.New_BuffCtrl() if updateData then ctrlParam.MissileHurtID = updateData.MissileHurtID ctrlParam.IsTracker = updateData.IsTracker ctrlParam.BuffOverRideFomula = string.isNilOrEmpty(updateData.BuffOverRideFomula) and buffData.BuffFormula or updateData.BuffOverRideFomula end local addSuccess = SystemManager.AddBuff(entity, buffData.CallBuffID, sourceEntity, nil, ctrlParam) if addSuccess then if private.buff2EntityExcuteTimeDic[updateData] then -- 有可能在添加CallBuffID的时候,用免疫互斥把本光环删除了 private.buff2EntityExcuteTimeDic[updateData][entity] = LogicUpdateManager._clientHandleFrame -- 标记已经入圈,且加上了buff end end end end else -- 频率性触发 for _,updateData in ipairs(tempTable) do local lastAddTimer = private.buff2EntityExcuteTimeDic[updateData] and private.buff2EntityExcuteTimeDic[updateData][entity] or -9999 if (LogicUpdateManager._clientHandleFrame - lastAddTimer) * LuaConst.TimeSpanMs >= FP.tonumberV1(buffData.CallFrequency) then local ctrlParam = RuntimeDataManager.New_BuffCtrl() if updateData then ctrlParam.MissileHurtID = updateData.MissileHurtID ctrlParam.IsTracker = updateData.IsTracker ctrlParam.BuffOverRideFomula = string.isNilOrEmpty(updateData.BuffOverRideFomula) and buffData.BuffFormula or updateData.BuffOverRideFomula end if not private.buff2EntityExcuteTimeDic[updateData] then private.buff2EntityExcuteTimeDic[updateData] = {} end --print("添加buff :" , buffData.CallBuffID) local addSuccess = SystemManager.AddBuff(entity, buffData.CallBuffID, sourceEntity, nil, ctrlParam) if addSuccess then private.buff2EntityExcuteTimeDic[updateData][entity] = LogicUpdateManager._clientHandleFrame -- 标记已经入圈,且加上了buff end end end end else --- 圈外 local needDeleteBuff = false for _,updateData in ipairs(tempTable) do local recordInfo = private.buff2EntityExcuteTimeDic[updateData] if recordInfo and recordInfo[entity] then private.buff2EntityExcuteTimeDic[updateData][entity] = nil needDeleteBuff = true end end if needDeleteBuff then --print("删除buff :" , buffData.CallBuffID) SystemManager.DeleteBuff(entity, buffData.CallBuffID, sourceEntity) end end table.clear(tempTable) end end end end -- 间隔性产生的效果 function private.OnceExcute(haloOwnerEntity , targetEntity , buffData ,updateData ) if not private.NeedHandle(targetEntity) then return end if not private.CheckCanEffectCamp(haloOwnerEntity, targetEntity, buffData) then return end if private.CheckOutRangeRoughly(haloOwnerEntity, targetEntity, buffData) then return end if not private.CheckInRangePrecisely(haloOwnerEntity, targetEntity, buffData) then return end local ctrlParam = RuntimeDataManager.New_BuffCtrl() ---- 这个一定要做对象池,用的太多 if updateData then ctrlParam.MissileHurtID = updateData.MissileHurtID ctrlParam.IsTracker = updateData.IsTracker ctrlParam.BuffOverRideFomula = string.isNilOrEmpty(updateData.BuffOverRideFomula) and buffData.BuffFormula or updateData.BuffOverRideFomula end --print("添加buff :" , buffData.CallBuffID) SystemManager.AddBuff(targetEntity, buffData.CallBuffID, haloOwnerEntity, nil, ctrlParam) end function private.AddHaloBuffDir(buffData, entity) if not buffData.CallUseSelfTime then --记录buff对哪些人生效 放入到敌、我光环列表中 local findInfo = nil local buffID = buffData.BuffID for _,info in ipairs(private.haloBuffInfoList) do if info.buffID == buffID then findInfo = info break end end if findInfo then table.insert(findInfo.entityList, entity) -- 不做排重判断 。一个entity可携带多个同样的光环 else local haloInfo = {buffID = buffID ,buffData = buffData, entityList = { entity} } table.insert(private.haloBuffInfoList, haloInfo) end end end -- 删除光环时 ,要删除受光环影响到的实体的buff function private.RemoveHaloBuffDir(buffData, entity, updateData) if not buffData.CallUseSelfTime then local findInfo = nil for _,haloInfo in ipairs(private.haloBuffInfoList) do if buffData.BuffID == haloInfo.buffID then findInfo = haloInfo break end end if findInfo then local entityList = findInfo.entityList table.removebyvalue(entityList,entity) if #entityList == 0 then table.removebyvalue(private.haloBuffInfoList,findInfo) end end end for i,targetEntity in ipairs(LogicUpdateManager.EntityList_Sync) do private.WhenHaloRemoveTryDeleteBuff(targetEntity, entity, buffData, updateData) end for i,targetEntity in ipairs(LogicUpdateManager.EntityList_Normal) do private.WhenHaloRemoveTryDeleteBuff(targetEntity, entity, buffData, updateData) end end function private.WhenHaloRemoveTryDeleteBuff(targetEntity, entity, buffData, updateData) -- 只要在圈内,就删除buff if private.buff2EntityExcuteTimeDic[updateData] and private.buff2EntityExcuteTimeDic[updateData][targetEntity] then SystemManager.DeleteBuff(targetEntity, buffData.CallBuffID, entity) return end if not private.NeedHandle(targetEntity) then return end if not private.CheckCanEffectCamp(entity, targetEntity, buffData) then return end if private.CheckOutRangeRoughly(entity, targetEntity, buffData) then return end if not private.CheckInRangePrecisely(entity, targetEntity, buffData) then return end local updateData = targetEntity.components.buff:GetBuffUpdateDataSourced(buffData.CallBuffID,entity._logicInitData.EntityID) if updateData then --print("删除buff—|— :" , buffData.CallBuffID) SystemManager.DeleteBuff(targetEntity, buffData.CallBuffID, entity) end end --方法CheckOutRangeRoughly存储的变量 防止每次生成 local _tempRadiusV1 = FP.newV1(0) function private.CheckOutRangeRoughly(source,target,buffData) local isOut = false if buffData.HaloRadius < FP.Const.Zero then --HaloRadius小于0代表无限距离 isOut = false elseif buffData.HaloRadius > FP.Const.Zero then local aboutRadius = buffData.HaloRadius local sourceLogicPos = source.components.move.LogicPos local targetLogicPos = target.components.move.LogicPos if _tempRadiusV1:Reset(sourceLogicPos.x):Sub(targetLogicPos.x):Abs() >= aboutRadius then isOut = true end if not isOut and _tempRadiusV1:Reset(sourceLogicPos.z):Sub(targetLogicPos.z):Abs() >= aboutRadius then isOut = true end else local maxDistance = buffData.HaloWidth + buffData.HaloHeight local sourceLogicPos = source.components.move.LogicPos local targetLogicPos = target.components.move.LogicPos if FP.tonumberV1(_tempRadiusV1:Reset(sourceLogicPos.x):Sub(targetLogicPos.x):Abs()) >= maxDistance then isOut = true elseif FP.tonumberV1(_tempRadiusV1:Reset(sourceLogicPos.z):Sub(targetLogicPos.z):Abs()) >= maxDistance then isOut = true end end return isOut end --source:光环的宿主 function private.CheckInRangePrecisely(source,target,buffData) local targetPos = target:GetLogicPos() if buffData.HaloRadius < FP.Const.Zero then --HaloRadius小于0代表无限距离 return true elseif buffData.HaloRadius > FP.Const.Zero then return not FP.V2.IsDistanceGreater(source:GetLogicPos() ,targetPos, buffData.HaloRadius) else return FP.V2.IsPointInRect(targetPos,source:GetLogicPos(),source:GetLogicRotateDir(),buffData.HaloWidth,buffData.HaloHeight,buffData.HaloOffsetX,buffData.HaloOffsetZ) end end function private.CheckCanEffectCamp(source, target, buffData) local isEnemy = CampManager.IsEnemyEntity(source,target) if buffData.HaloTarget == EnumHaloTarget.Enemy then return isEnemy elseif buffData.HaloTarget == EnumHaloTarget.FriendAndSelf then return not isEnemy elseif buffData.HaloTarget == EnumHaloTarget.Friend then return (not isEnemy) and (source ~= target) elseif buffData.HaloTarget == EnumHaloTarget.Self then -- 一般也不会配置,光环怎么能只给自己加呢,还不如加一般buff呢 return source == target elseif buffData.HaloTarget == EnumHaloTarget.Master then return source:GetMasterEntity() == target end return false end function BuffOperator_Halo.Dispose() private.buff2EntityExcuteTimeDic = {} end --需要处理(载具上的司机为false) function private.NeedHandle(entity) if entity.components.base.IsActive -- 为了优化没用 :IsActive() and entity.components.attr:IsAlive() and (not entity.components.buff:GetBuffUpdateData(LuaConst.SpecialBuffs.CantBeTrigger) ) -- 不能被子弹打中的怪,也不能被光环影响 then --未激活不处理 return true end return false end -- 当entity的状态变为不能被光圈生效时 ,则需要移除已生效的buff function BuffOperator_Halo.OnEntityEnterCantBeTriggerState(entity) for _,haloInfo in ipairs(private.haloBuffInfoList) do local buffId = haloInfo.buffID local entityList = haloInfo.entityList local buffData = haloInfo.buffData -- 有entity进入光圈就加buff for i,sourceEntity in ipairs(entityList) do sourceEntity.components.buff:GetAllBuffUpdateData(buffId ,tempTable) -- 这么写的目的是为了新增的buffUpdate也生效(例子:g带有abcd给光圈buff ,都给圈内的f加攻击力,e又给g加了新光圈,f要继续加攻击力) if buffData.CallFrequency <= FP.Const.Zero then for _,updateData in ipairs(tempTable) do if private.buff2EntityExcuteTimeDic[updateData] and private.buff2EntityExcuteTimeDic[updateData][entity] then -- 之前已经进入圈内,不处理 -- 执行出圈 private.buff2EntityExcuteTimeDic[updateData][entity] = nil SystemManager.DeleteBuff(entity, buffData.CallBuffID, sourceEntity) end end end table.clear(tempTable) end end end -- 对外接口:或者某个entity得光环内的人数 -- checkEntity 光环携带者 ; buffCaster:光环的来源者 function BuffOperator_Halo.GetInHaloBuffNum(checkEntity, haloBuffId, buffCaster) local number = 0 for _,haloInfo in ipairs(private.haloBuffInfoList) do local buffId = haloInfo.buffID local entityList = haloInfo.entityList local buffData = haloInfo.buffData if haloBuffId == haloInfo.buffID then for i,sourceEntity in ipairs(entityList) do if checkEntity == sourceEntity then local updateData = sourceEntity.components.buff:GetBuffUpdateData(buffId, buffCaster) local inRangeDic = private.buff2EntityExcuteTimeDic[updateData] if inRangeDic then -- 之前已经进入圈内,不处理 -- 执行出圈 for e, t in pairs(inRangeDic) do number = number + 1 end end break end end break end end return number end -- 对外接口:或者某个entity得光环内的人数 -- checkEntity 光环携带者 ; buffCaster:光环的来源者 function BuffOperator_Halo.GetInHaloBuffGroupNum(checkEntity, haloBuffGroupId, buffCaster) local number = 0 for _,haloInfo in ipairs(private.haloBuffInfoList) do local buffId = haloInfo.buffID local entityList = haloInfo.entityList local buffData = haloInfo.buffData if haloBuffGroupId == buffData.BuffGroup then for i,sourceEntity in ipairs(entityList) do if checkEntity == sourceEntity then local updateData = sourceEntity.components.buff:GetBuffUpdateData(buffId, buffCaster) local inRangeDic = private.buff2EntityExcuteTimeDic[updateData] if inRangeDic then -- 之前已经进入圈内,不处理 -- 执行出圈 for e, t in pairs(inRangeDic) do number = number + 1 end end break end end end end return number end return BuffOperator_Halo