local effect = require("Modules/Battle/Logic/Base/Effect") local floor = math.floor local max = math.max local min = math.min --local BattleConst = BattleConst --local RoleDataName = RoleDataName --local BattleEventName = BattleEventName 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) Skill = {} function Skill:New() local o = {cd=0,effectList = BattleList.New(),owner=0,sp=0,spPass=0,isTeamSkill=false,teamSkillType=0 } setmetatable(o, self) self.__index = self return o end function Skill:Init(role, effectData, type, targets, isAdd, isRage) --type 0 异妖 1 点技 2 滑技 local isTeamSkill = type == 0 self.type = type --skill = {技能ID, 命中时间, 持续时间, 伤害次数, {目标id1, 效果1, 效果2, ...},{目标id2, 效果3, 效果4, ...}, ...} --效果 = {效果类型id, 效果参数1, 效果参数2, ...} self.effectList:Clear() self.owner = role self.isTeamSkill = isTeamSkill self.teamSkillType = isTeamSkill and floor(effectData[1] / 100) or 0 self.id = effectData[1] -- 技能ID self.hitTime = effectData[2] -- 效果命中需要的时间 self.continueTime = effectData[3] -- 命中后伤害持续时间 self.attackCount = effectData[4] -- 伤害持续时间内伤害次数 self.targets = targets or {} self.isAdd = isAdd self.isRage = isRage for i=5, #effectData do local v = effectData[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 self.effectList:Add(effectGroup) end end function Skill:Dispose() while self.effectList.size > 0 do local effectGroup = self.effectList.buffer[self.effectList.size] 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) self.effectList:Remove(self.effectList.size) end end local function takeEffect(caster, target, effects, duration, skill) for k=1, #effects do local e = {type = 0, args = {}} e.type = effects[k].type for i=1, #effects[k].args do e.args[i] = effects[k].args[i] end -- 检测被动技能对技能参数的影响 local function _PassiveCheck(pe) if pe then e = pe end end caster.Event:DispatchEvent(BattleEventName.SkillEffectBefore, skill, e, _PassiveCheck) target.Event:DispatchEvent(BattleEventName.BeSkillEffectBefore, skill, e, _PassiveCheck) -- if effect[e.type] then effect[e.type](caster, target, e.args, duration, skill) BattleLogManager.Log( "Take Effect", "tcamp", target.camp, "tpos", target.position, "type", e.type ) end end end -- 释放技能 -- func 技能释放完成回调 function Skill:Cast(func) self.castDoneFunc = func self.effectTargets = {} -- 先计算出技能的目标 for i=1, self.effectList.size 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 -- 重新选择目标a if isReTarget then local effectGroup = self.effectList.buffer[i] local chooseId = effectGroup.chooseId self.effectTargets[i] = BattleUtil.ChooseTarget(self.owner, chooseId) -- 检测被动对攻击目标的影响 if i == 1 then local function _PassiveTarget(targets) self.effectTargets[i] = targets end self.owner.Event:DispatchEvent(BattleEventName.SkillTargetCheck, _PassiveTarget) end end end -- BattleLogManager.Log( "Cast Skill", "camp", self.owner.camp, "pos", self.owner.position, "type", self.type, "isRage", tostring(self.isRage), "isAdd", tostring(self.isAdd) ) -- 对目标造成相应的效果 for i=1, self.effectList.size do local effectGroup = self.effectList.buffer[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 = floor(chooseId % 10000 / 100) local count = 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 takeEffect(self.owner, arr[j], effects, self.hitTime, self) end end end) end end if self.isTeamSkill then self.owner.curSkill = self end -- 释放技能开始 self.owner.Event:DispatchEvent(BattleEventName.SkillCast, self) BattleLogic.Event:DispatchEvent(BattleEventName.SkillCast, self) -- 只对效果1的目标发送事件,效果1是技能的直接伤害目标 for _, tr in ipairs(self.effectTargets[1]) do tr.Event:DispatchEvent(BattleEventName.BeSkillCast, self) end --技能的施法时间计算,根据当前目标id关联的持续时间,取其中时间最长的一个 local duration = self.hitTime + self.continueTime -- 结算时间向后延长0.2秒,避免在效果结算完成前就结束了技能释放 BattleLogic.WaitForTrigger(duration + 0.2, function() self.owner.Event:DispatchEvent(BattleEventName.SkillCastEnd, self) BattleLogic.Event:DispatchEvent(BattleEventName.SkillCastEnd, self) -- 只对效果1的目标发送事件,效果1是技能的直接伤害目标 for _, tr in ipairs(self.effectTargets[1]) do tr.Event:DispatchEvent(BattleEventName.BeSkillCastEnd, self) end -- 技能结束 self:EndSkill() end) end -- 获取技能的直接目标,和策划规定第一个效果的目标为直接效果目标 function Skill:GetDirectTargets() return self.effectTargets[1] end -- 获取技能目标最大人数 function Skill:GetMaxTargetNum() local mainEffect = self.effectList.buffer[1] if not mainEffect then return 0 end return BattleUtil.GetMaxTargetNum(mainEffect.chooseId) end -- 结束技能 function Skill:EndSkill() -- 技能后摇 -- 技能结束后摇后结束技能释放 BattleLogic.WaitForTrigger(0.3, function() -- 结束回调 if self.castDoneFunc then self.castDoneFunc() end end) -- self.effectTargets = {} end