local Effect = require("Modules/Battle/Logic/Base/Effect") EffectCaster = {} local effectPool = BattleObjectPool.New(function () return { type = 0, args = {}} -- type, {args, ...} end) local effectGroupPool = BattleObjectPool.New(function () return { chooseId = 0, effects = {}} -- chooseId, {effect1, effect2, ...} end) function EffectCaster:New() local o = {} setmetatable(o, {__index = self}) return o end function EffectCaster:Init(skill, effects, targets) self.skill = skill self.targets = targets or {} self.effectList = {} for i=1, #effects do local v = effects[i] local effectGroup = effectGroupPool:Get() -- chooseId, {effect1, effect2, ...} effectGroup.chooseId = v[1] -- chooseId for j=2, #v do -- effectList local effect = effectPool:Get() -- type, {args, ...} effect.type = v[j][1] for k=2, #v[j] do effect.args[k-1] = v[j][k] end effectGroup.effects[j-1] = effect end table.insert(self.effectList, effectGroup) end end function EffectCaster:DoEffect(caster, target, eff, duration, skill) local e = {type = 0, args = {}} e.type = eff.type for i=1, #eff.args do e.args[i] = eff.args[i] end -- 检测被动技能对技能参数的影响 local function _PassiveCheck(pe) if pe then e = pe end end caster.Event:DispatchEvent(BattleEventName.SkillEffectBefore, skill, e, _PassiveCheck,target,eff) target.Event:DispatchEvent(BattleEventName.BeSkillEffectBefore, skill, e, _PassiveCheck) -- if Effect[e.type] then Effect[e.type](caster, target, e.args, duration, skill) end end function EffectCaster:takeEffect(caster, target, effects, effectIndex, duration, skill) for k=1, #effects do -- 如果不是第一个效果对列的第一个效果则判断是否命中 if k ~= 1 and effectIndex == 1 then if self:CheckTargetIsHit(target) then self:DoEffect(caster, target, effects[k], duration, skill) end else self:DoEffect(caster, target, effects[k], duration, skill) end end end function EffectCaster:ChooseTarget() -- self.effectTargets = {} self.targetIsHit = {} -- 先计算出技能的目标 for i=1, #self.effectList do -- 是否重新选择目标 local isReTarget = true if self.targets and self.targets[i] then self.effectTargets[i] = self.targets[i] -- 判断是否有有效目标 for _, role in ipairs(self.effectTargets[i]) do if not role:IsRealDead() then isReTarget = false end end end -- 重新选择目标 if isReTarget then local effectGroup = self.effectList[i] local chooseId = effectGroup.chooseId self.effectTargets[i] = BattleUtil.ChooseTarget(self.skill.owner, chooseId) -- 检测被动对攻击目标的影响 if i == 1 then local function _PassiveTarget(targets) self.effectTargets[i] = targets end self.skill.owner.Event:DispatchEvent(BattleEventName.SkillTargetCheck, _PassiveTarget,self.skill) end end end end -- 释放技能 -- func 技能释放完成回调 function EffectCaster:Cast() -- 选择目标 self:ChooseTarget() -- 对目标造成相应的效果 for i=1, #self.effectList do local effectGroup = self.effectList[i] local chooseId = effectGroup.chooseId local arr = self.effectTargets[i] if arr and #arr > 0 then -- 效果延迟1帧生效 BattleLogic.WaitForTrigger(BattleLogic.GameDeltaTime, function() local effects = effectGroup.effects local weight = math.floor(chooseId % 10000 / 100) local count = math.min(chooseId % 10, #arr) if count == 0 then count = #arr end -- 全部同时生效 for j=1, count do if arr[j] and not arr[j]:IsRealDead() then -- 检测是否命中 if i == 1 then self.targetIsHit[arr[j]] = BattleUtil.CheckIsHit(self.skill.owner, arr[j],self.skill) end self:takeEffect(self.skill.owner, arr[j], effects, i, self.skill.hitTime, self.skill) end end end) end end end -- 遍历技能命中目标 function EffectCaster:ForeachTargets(func) local targets = self:GetDirectTargets() for _, role in ipairs(targets) do if func then func(role) end end end -- 获取直接选择目标Id function EffectCaster:GetDirectChooseId() local effectGroup = self.effectList[1] local chooseId = effectGroup.chooseId return chooseId end -- 获取技能的直接目标,和策划规定第一个效果的目标为直接效果目标,(包含miss的目标) function EffectCaster:GetDirectTargets() return self.effectTargets[1] end -- 获取直接目标,不包含miss的目标,可能为空 function EffectCaster:GetDirectTargetsNoMiss() local list = {} for _, role in ipairs(self.effectTargets[1]) do if self:CheckTargetIsHit(role) then table.insert(list, role) end end return list end -- 获取直接目标和没有被放逐的目标,不包含miss的目标,可能为空 function EffectCaster:GetDirectTargetsNoExile() local list = {} for _, role in ipairs(self.effectTargets[1]) do if not role.isExile then table.insert(list, role) end end return list end -- 获取技能目标最大人数 function EffectCaster:GetMaxTargetNum() local mainEffect = self.effectList[1] if not mainEffect then return 0 end return BattleUtil.GetMaxTargetNum(mainEffect.chooseId) end -- 判断是否命中 function EffectCaster:CheckTargetIsHit(role) return self.targetIsHit[role] end function EffectCaster:Dispose() for _, effectGroup in ipairs(self.effectList) do for k=1, #effectGroup.effects do local effect = effectGroup.effects[k] for j=1, #effect.args do effect.args[j] = nil end effectPool:Put(effect) effectGroup.effects[k] = nil end effectGroupPool:Put(effectGroup) end self.effectList = {} end return EffectCaster