Skill.lua 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. local effect = require("Modules/Battle/Logic/Base/Effect")
  2. local floor = math.floor
  3. local max = math.max
  4. local min = math.min
  5. --local BattleConst = BattleConst
  6. --local RoleDataName = RoleDataName
  7. --local BattleEventName = BattleEventName
  8. -- local CombatControl = ConfigManager.GetConfig(ConfigName.CombatControl)
  9. local effectPool = BattleObjectPool.New(function ()
  10. return { type = 0, args = {}} -- type, {args, ...}
  11. end)
  12. local effectGroupPool = BattleObjectPool.New(function ()
  13. return { chooseId = 0, effects = {}} -- chooseId, {effect1, effect2, ...}
  14. end)
  15. Skill = {}
  16. function Skill:New()
  17. local o = {cd=0,effectList = BattleList.New(),owner=0,sp=0,spPass=0,isTeamSkill=false,teamSkillType=0 }
  18. setmetatable(o, self)
  19. self.__index = self
  20. return o
  21. end
  22. function Skill:Init(role, effectData, type, targets, isAdd) --type 0 异妖 1 点技 2 滑技
  23. local isTeamSkill = type == 0
  24. self.type = type
  25. --skill = {技能ID, 命中时间, 持续时间, 伤害次数, {目标id1, 效果1, 效果2, ...},{目标id2, 效果3, 效果4, ...}, ...}
  26. --效果 = {效果类型id, 效果参数1, 效果参数2, ...}
  27. self.effectList:Clear()
  28. self.owner = role
  29. self.isTeamSkill = isTeamSkill
  30. self.teamSkillType = isTeamSkill and floor(effectData[1] / 100) or 0
  31. self.id = effectData[1] -- 技能ID
  32. self.hitTime = effectData[2] -- 效果命中需要的时间
  33. self.continueTime = effectData[3] -- 命中后伤害持续时间
  34. self.attackCount = effectData[4] -- 伤害持续时间内伤害次数
  35. -- self.ReturnTime = CombatControl[self.id].ReturnTime
  36. self.ReturnTime = effectData[5] --< 技能总时长
  37. self.CastBullet = effectData[6] --< 技能释放时间点 起点为动作开始
  38. self.repeatAttackTimes = effectData[7] --< 技能伤害次数
  39. --> ext参数
  40. self.ext_slot = effectData[8].slot --< 技能槽位
  41. self.targets = targets or {}
  42. self.isAdd = isAdd
  43. -- self.isRage = isRage
  44. self.totalDmg = {}
  45. for i=9, #effectData do
  46. local v = effectData[i]
  47. local effectGroup = effectGroupPool:Get() -- chooseId, {effect1, effect2, ...}
  48. effectGroup.chooseId = v[1] -- chooseId
  49. for j=2, #v do -- effectList
  50. local effect = effectPool:Get() -- type, {args, ...}
  51. effect.type = v[j][1]
  52. for k=2, #v[j] do
  53. effect.args[k-1] = v[j][k]
  54. end
  55. effectGroup.effects[j-1] = effect
  56. end
  57. self.effectList:Add(effectGroup)
  58. end
  59. end
  60. function Skill:Dispose()
  61. while self.effectList.size > 0 do
  62. local effectGroup = self.effectList.buffer[self.effectList.size]
  63. for k=1, #effectGroup.effects do
  64. local effect = effectGroup.effects[k]
  65. for j=1, #effect.args do
  66. effect.args[j] = nil
  67. end
  68. effectPool:Put(effect)
  69. effectGroup.effects[k] = nil
  70. end
  71. effectGroupPool:Put(effectGroup)
  72. self.effectList:Remove(self.effectList.size)
  73. end
  74. end
  75. local function DoEffect(caster, target, eff, duration, skill)
  76. local e = {type = 0, args = {}}
  77. e.type = eff.type
  78. for i=1, #eff.args do
  79. e.args[i] = eff.args[i]
  80. end
  81. -- 检测被动技能对技能参数的影响
  82. local function _PassiveCheck(pe)
  83. if pe then
  84. e = pe
  85. end
  86. end
  87. caster.Event:DispatchEvent(BattleEventName.SkillEffectBefore, skill, e, _PassiveCheck)
  88. target.Event:DispatchEvent(BattleEventName.BeSkillEffectBefore, skill, e, _PassiveCheck)
  89. --
  90. LogGreen("### DoEffect 作用点")
  91. LogGreen(duration)
  92. LogGreen(e.type)
  93. if effect[e.type] then
  94. effect[e.type](caster, target, e.args, duration, skill)
  95. BattleLogManager.Log(
  96. "Take Effect",
  97. "tcamp", target.camp,
  98. "tpos", target.position,
  99. "type", e.type
  100. )
  101. end
  102. end
  103. function Skill:takeEffect(caster, target, effects, effectIndex, duration, skill)
  104. for k=1, #effects do
  105. -- 如果不是第一个效果对列的第一个效果则判断是否命中
  106. if k ~= 1 and effectIndex == 1 then
  107. if self:CheckTargetIsHit(target) then
  108. DoEffect(caster, target, effects[k], duration, skill)
  109. end
  110. else
  111. DoEffect(caster, target, effects[k], duration, skill)
  112. end
  113. end
  114. end
  115. -- 释放技能
  116. -- func 技能释放完成回调
  117. function Skill:Cast(func)
  118. self.castDoneFunc = func
  119. --
  120. BattleLogManager.Log(
  121. "Cast Skill",
  122. "camp", self.owner.camp,
  123. "pos", self.owner.position,
  124. "type", self.type,
  125. -- "isRage", tostring(self.isRage),
  126. "isAdd", tostring(self.isAdd)
  127. )
  128. local repeatTimes = self.repeatAttackTimes or 1 --< 多段
  129. repeatTimes = math.max(1, repeatTimes) --< repeatTimes need > 1
  130. --> 单次攻击 可能多个目标
  131. local function AttackOnce()
  132. self.effectTargets = {}
  133. self.targetIsHit = {}
  134. -- 先计算出技能的目标
  135. for i=1, self.effectList.size do
  136. -- 是否重新选择目标
  137. local isReTarget = true
  138. if self.targets and self.targets[i] then
  139. self.effectTargets[i] = self.targets[i]
  140. -- 判断是否有有效目标
  141. for _, role in ipairs(self.effectTargets[i]) do
  142. if not role:IsRealDead() then
  143. isReTarget = false
  144. end
  145. end
  146. end
  147. -- 重新选择目标a
  148. if isReTarget then
  149. local effectGroup = self.effectList.buffer[i]
  150. local chooseId = effectGroup.chooseId
  151. self.effectTargets[i] = {}
  152. self.effectTargets[i] = BattleUtil.ChooseTarget(self.owner, chooseId)
  153. -- 检测被动对攻击目标的影响
  154. if i == 1 then
  155. local function _PassiveTarget(targets)
  156. self.effectTargets[i] = targets
  157. end
  158. self.owner.Event:DispatchEvent(BattleEventName.SkillTargetCheck, _PassiveTarget, self)
  159. end
  160. end
  161. end
  162. -- 对目标造成相应的效果
  163. for i=1, self.effectList.size do
  164. local effectGroup = self.effectList.buffer[i]
  165. local chooseId = effectGroup.chooseId
  166. local arr = self.effectTargets[i]
  167. if arr and #arr > 0 then
  168. -- 效果延迟1帧生效
  169. BattleLogic.WaitForTrigger(BattleLogic.GameDeltaTime, function()
  170. local effects = effectGroup.effects
  171. -- local weight = floor(chooseId % 10000 / 100)
  172. local count = min(chooseId % 10, #arr)
  173. if count == 0 then
  174. count = #arr
  175. end
  176. -- 全部同时生效
  177. for j=1, count do
  178. BattleLogic.WaitForTrigger(self.ReturnTime / 1000 * (j - 1), function()
  179. if arr[j] and not arr[j]:IsRealDead() then
  180. -- 检测是否命中
  181. if i == 1 then
  182. self.targetIsHit[arr[j]] = BattleUtil.CheckIsHit(self.owner, arr[j])
  183. end
  184. LogGreen("### takeEffect")
  185. self:takeEffect(self.owner, arr[j], effects, i, self.hitTime, self)
  186. end
  187. end)
  188. -- if arr[j] and not arr[j]:IsRealDead() then
  189. -- -- 检测是否命中
  190. -- if i == 1 then
  191. -- self.targetIsHit[arr[j]] = BattleUtil.CheckIsHit(self.owner, arr[j])
  192. -- end
  193. -- self:takeEffect(self.owner, arr[j], effects, i, self.hitTime, self)
  194. -- -- if i == 1 then
  195. -- -- self.targetIsHit[arr[j]] = BattleUtil.CheckIsHit(self.owner, arr[j])
  196. -- -- takeEffect(self.owner, arr[j], effects, self.hitTime, self)
  197. -- -- else
  198. -- -- -- 未命中的目标不会产生后续技能效果
  199. -- -- if self:CheckTargetIsHit(arr[j]) then
  200. -- -- takeEffect(self.owner, arr[j], effects, self.hitTime, self)
  201. -- -- end
  202. -- -- end
  203. -- end
  204. end
  205. self.totalDmg = {}
  206. local function floatTotalDmg(idx)
  207. if not self.totalDmg[idx] then
  208. return
  209. end
  210. local totalnum = 0
  211. for i = 1, #self.totalDmg do
  212. totalnum = totalnum + self.totalDmg[i]
  213. end
  214. BattleLogic.Event:DispatchEvent(BattleEventName.FloatTotal, totalnum)
  215. end
  216. BattleLogic.WaitForTrigger(self.hitTime, function ()
  217. if self.totalDmg then
  218. if self.attackCount ~= 1 then
  219. for i = 1, #self.continueTime do
  220. local time = 0
  221. for j = 1, i do
  222. time = time + self.continueTime[j] / 1000
  223. end
  224. BattleLogic.WaitForTrigger(time, function()
  225. floatTotalDmg(i + 1)
  226. end)
  227. end
  228. floatTotalDmg(1)
  229. else
  230. floatTotalDmg(1)
  231. end
  232. end
  233. end)
  234. end)
  235. end
  236. end
  237. if self.isTeamSkill then
  238. self.owner.curSkill = self
  239. end
  240. -- 释放技能开始
  241. -- self.owner.Event:DispatchEvent(BattleEventName.SkillCast, self)
  242. -- BattleLogic.Event:DispatchEvent(BattleEventName.SkillCast, self)
  243. self.owner.Event:DispatchEvent(BattleEventName.SkillCast, self)
  244. BattleLogic.Event:DispatchEvent(BattleEventName.SkillCast, self)
  245. local targetNum = #self.effectTargets[1]
  246. for i = 1, targetNum do
  247. BattleLogic.WaitForTrigger(self.ReturnTime / 1000 * (i - 1), function()
  248. self.owner.Event:DispatchEvent(BattleEventName.SkillFireOnce, self, i)
  249. end)
  250. end
  251. -- 只对效果1的目标发送事件,效果1是技能的直接伤害目标
  252. -- for _, tr in ipairs(self.effectTargets[1]) do
  253. -- tr.Event:DispatchEvent(BattleEventName.BeSkillCast, self)
  254. -- end
  255. local EndSkillProcess = function()
  256. self.owner.Event:DispatchEvent(BattleEventName.SkillCastEnd, self)
  257. BattleLogic.Event:DispatchEvent(BattleEventName.SkillCastEnd, self)
  258. -- 只对效果1的目标发送事件,效果1是技能的直接伤害目标
  259. for _, tr in ipairs(self.effectTargets[1]) do
  260. tr.Event:DispatchEvent(BattleEventName.BeSkillCastEnd, self)
  261. end
  262. -- 技能结束
  263. self:EndSkill()
  264. end
  265. BattleLogic.WaitForTrigger(self.ReturnTime / 1000 * targetNum, function()
  266. repeatTimes = repeatTimes - 1
  267. if repeatTimes == 0 then
  268. EndSkillProcess()
  269. else
  270. AttackOnce()
  271. end
  272. end)
  273. end
  274. AttackOnce()
  275. end
  276. -- func 技能释放完成回调
  277. function Skill:CastUnit(func)
  278. self.castDoneFunc = func
  279. local function SkillPlay()
  280. self.effectTargets = {}
  281. self.targetIsHit = {}
  282. -- 先计算出技能的目标
  283. for i=1, self.effectList.size do
  284. -- 是否重新选择目标
  285. local isReTarget = true
  286. if self.targets and self.targets[i] then
  287. self.effectTargets[i] = self.targets[i]
  288. -- 判断是否有有效目标
  289. for _, role in ipairs(self.effectTargets[i]) do
  290. if not role:IsRealDead() then
  291. isReTarget = false
  292. end
  293. end
  294. end
  295. -- 重新选择目标a
  296. if isReTarget then
  297. local effectGroup = self.effectList.buffer[i]
  298. local chooseId = effectGroup.chooseId
  299. self.effectTargets[i] = {}
  300. self.effectTargets[i] = BattleUtil.ChooseTarget(self.owner, chooseId)
  301. -- 检测被动对攻击目标的影响
  302. if i == 1 then
  303. local function _PassiveTarget(targets)
  304. self.effectTargets[i] = targets
  305. end
  306. self.owner.Event:DispatchEvent(BattleEventName.SkillTargetCheck, _PassiveTarget, self)
  307. end
  308. end
  309. end
  310. -- 对目标造成相应的效果
  311. for i=1, self.effectList.size do
  312. local effectGroup = self.effectList.buffer[i]
  313. local chooseId = effectGroup.chooseId
  314. local arr = self.effectTargets[i]
  315. if arr and #arr > 0 then
  316. -- 效果延迟1帧生效
  317. BattleLogic.WaitForTrigger(BattleLogic.GameDeltaTime, function()
  318. local effects = effectGroup.effects
  319. -- local weight = floor(chooseId % 10000 / 100)
  320. local count = min(chooseId % 10, #arr)
  321. if count == 0 then
  322. count = #arr
  323. end
  324. -- 全部同时生效
  325. for j=1, count do
  326. if arr[j] and not arr[j]:IsRealDead() then
  327. -- 检测是否命中
  328. if i == 1 then
  329. self.targetIsHit[arr[j]] = BattleUtil.CheckIsHit(self.owner, arr[j])
  330. end
  331. LogGreen("### takeEffect")
  332. self:takeEffect(self.owner, arr[j], effects, i, self.hitTime, self)
  333. end
  334. end
  335. end)
  336. end
  337. end
  338. self.owner.Event:DispatchEvent(BattleEventName.SkillCast, self)
  339. BattleLogic.Event:DispatchEvent(BattleEventName.SkillCast, self)
  340. -- local targetNum = #self.effectTargets[1]
  341. -- for i = 1, targetNum do
  342. -- BattleLogic.WaitForTrigger(self.ReturnTime / 1000 * (i - 1), function()
  343. -- self.owner.Event:DispatchEvent(BattleEventName.SkillFireOnce, self, i)
  344. -- end)
  345. -- end
  346. local EndSkillProcess = function()
  347. self.owner.Event:DispatchEvent(BattleEventName.SkillCastEnd, self)
  348. BattleLogic.Event:DispatchEvent(BattleEventName.SkillCastEnd, self)
  349. -- 只对效果1的目标发送事件,效果1是技能的直接伤害目标
  350. for _, tr in ipairs(self.effectTargets[1]) do
  351. tr.Event:DispatchEvent(BattleEventName.BeSkillCastEnd, self)
  352. end
  353. -- 技能结束
  354. self:EndSkill()
  355. end
  356. BattleLogic.WaitForTrigger(self.ReturnTime / 1000, function()
  357. EndSkillProcess()
  358. end)
  359. end
  360. SkillPlay()
  361. end
  362. -- 获取技能的直接目标,和策划规定第一个效果的目标为直接效果目标,(包含miss的目标)
  363. function Skill:GetDirectTargets()
  364. return self.effectTargets[1]
  365. end
  366. -- 获取直接目标,不包含miss的目标,可能为空
  367. function Skill:GetDirectTargetsNoMiss()
  368. local list = {}
  369. for _, role in ipairs(self.effectTargets[1]) do
  370. if self:CheckTargetIsHit(role) then
  371. table.insert(list, role)
  372. end
  373. end
  374. return list
  375. end
  376. -- 获取技能目标最大人数
  377. function Skill:GetMaxTargetNum()
  378. local mainEffect = self.effectList.buffer[1]
  379. if not mainEffect then
  380. return 0
  381. end
  382. return BattleUtil.GetMaxTargetNum(mainEffect.chooseId)
  383. end
  384. -- 判断是否命中
  385. function Skill:CheckTargetIsHit(role)
  386. return self.targetIsHit[role]
  387. end
  388. -- 结束技能
  389. function Skill:EndSkill()
  390. -- 技能后摇
  391. -- 技能结束后摇后结束技能释放
  392. BattleLogic.WaitForTrigger(0.3, function()
  393. -- 结束回调
  394. if self.castDoneFunc then self.castDoneFunc() end
  395. end)
  396. --
  397. self.effectTargets = {}
  398. end