CombatImpl.lua 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. local Msg = require("core.Msg")
  2. local Util = require("common.Util")
  3. local CombatObj = require("combat.CombatObj")
  4. local CombatDefine = require("combat.CombatDefine")
  5. local TargetMode = require("combat.TargetMode")
  6. local Skill = require("combat.Skill")
  7. local CombatBuff = require("combat.CombatBuff")
  8. local RoleAttr = require("role.RoleAttr")
  9. local RoleDefine = require("role.RoleDefine")
  10. local BeSkill = require("combat.BeSkill")
  11. local HeroExcel = require("excel.hero").hero
  12. local MonsterExcel = require("excel.monster").monster
  13. local BattleMonsterExcel = require("excel.battlemonster").monster
  14. local CombatExcel = require("excel.combat").combat
  15. local SkillExcel = require("excel.skill").skill
  16. -- local BufferExcel = require("excel.buffer").buffer
  17. -- local ProjectLogic = require("platform.ProjectLogic")
  18. objList = objList or {}
  19. helpList = helpList or {}
  20. elfList = elfList or {}
  21. attackOrder = attackOrder or {} -- 出手次序 [index]->pos
  22. round = round or 1 -- 当前回合
  23. attackIndex = attackIndex or 1 -- 当前进攻对象的index
  24. result = result or {} -- 计算结果
  25. sideAttrList = sideAttrList or {} -- 攻守双方人物属性
  26. skillUseList = skillUseList or {} -- 使用过的技能
  27. cmdUseList = cmdUseList or {} -- 使用过的额外作用setFightMode
  28. bufferUseList = bufferUseList or {} -- 使用过的buffer
  29. frameSkillList = frameSkillList or {} -- 当前小回合触发的被动技能
  30. frameBufferList = frameBufferList or {} -- 当前小回合触发的buffer
  31. mergeFrameBufferList = mergeFrameBufferList or {} --合并后的buffer
  32. frameSayList = frameSayList or {} -- 触发buffer的被动技能(需要喊话
  33. frameReviceList = frameReviceList or {} -- 复活列表
  34. fanjiList = fanjiList or {}
  35. beSkillUseList = beSkillUseList or {} -- 需要判断使用情况的技能
  36. isFanji = false
  37. comboType = 0
  38. isPVP = 0
  39. comboHurtRate = 0
  40. --[[
  41. commonArgs = {
  42. type -- 战斗类型
  43. hpLimit -- 血量上限,默认为角色HP,对应特定关卡
  44. }
  45. ]]
  46. commonArgs = commonArgs or {}
  47. comboList = comboList or {}
  48. beSkillPosUseList = beSkillPosUseList or {} --友军技能使用列表
  49. totalAtkCnt = 0 -- 总共攻击次数 reyes test
  50. maxRound = CombatDefine.COMBAT_ROUND_MAX
  51. petCD = CombatDefine.PET_CD
  52. nowAttacker = nowAttacker or nil
  53. firstAttack = {}
  54. fightMode = {0,0,0,0}
  55. initBackup = {0,0}
  56. comboPosList = {}
  57. totalHurt = 0
  58. useZhuijiObjList = {} --本场战斗使用过追击的英雄列表
  59. function init(type)
  60. Util.initTable(objList)
  61. Util.initTable(helpList)
  62. Util.initTable(elfList)
  63. Util.initTable(attackOrder)
  64. Util.initTable(result)
  65. Util.initTable(skillUseList)
  66. Util.initTable(cmdUseList)
  67. Util.initTable(bufferUseList)
  68. Util.initTable(frameSkillList)
  69. Util.initTable(frameBufferList)
  70. Util.initTable(frameSayList)
  71. Util.initTable(fanjiList)
  72. Util.initTable(beSkillUseList)
  73. Util.initTable(beSkillPosUseList)
  74. Util.initTable(commonArgs)
  75. Util.initTable(comboList)
  76. Util.initTable(initBackup)
  77. Util.initTable(frameReviceList)
  78. Util.initTable(useZhuijiObjList)
  79. round = 0
  80. attackIndex = nil
  81. isFanji = false
  82. comboType = 0
  83. totalAtkCnt = 0
  84. totalHurt = 0
  85. commonArgs.type = type
  86. maxRound = CombatDefine.COMBAT_ROUND_MAX
  87. petCD = CombatDefine.PET_CD
  88. nowAttacker = nil
  89. local combatConfig = CombatExcel[type]
  90. if combatConfig and combatConfig.hpLimit == 1 then
  91. commonArgs.hpLimit = 1
  92. end
  93. isPVP = combatConfig.PVP
  94. end
  95. local function mergeFrameBuffer()
  96. Util.initTable(mergeFrameBufferList)
  97. mergeFrameBufferList = {[1] = {},[2] = {},[3] = {}}
  98. for k,v in ipairs(frameBufferList) do
  99. mergeFrameBufferList[v.op][v.id] = mergeFrameBufferList[v.op][v.id] or {}
  100. local obj = objList[v.pos]
  101. mergeFrameBufferList[v.op][v.id][v.pos] = mergeFrameBufferList[v.op][v.id][v.pos] or {id = v.id,cnt = 0,op = v.op,attrs = {},pos = v.pos,hpNow = obj.hp}
  102. local data = mergeFrameBufferList[v.op][v.id][v.pos]
  103. data.cnt = data.cnt + v.cnt
  104. if v.attrs then
  105. for k,v in pairs(v.attrs) do
  106. data.attrs[k] = data.attrs[k] or 0
  107. data.attrs[k] = data.attrs[k] + v
  108. end
  109. end
  110. end
  111. Util.initTable(frameBufferList)
  112. local len = 0
  113. for _,v in ipairs(mergeFrameBufferList) do
  114. for _,v1 in pairs(v) do
  115. for _,v2 in pairs(v1) do
  116. frameBufferList[#frameBufferList+1] = v2
  117. end
  118. end
  119. end
  120. end
  121. function setRoleAttr(side, attr)
  122. sideAttrList[side] = sideAttrList[side] or {}
  123. local sideAttr = sideAttrList[side]
  124. RoleAttr.initCombatAttr(sideAttr)
  125. if attr then
  126. for key, value in pairs(attr) do
  127. sideAttr[key] = value
  128. end
  129. end
  130. end
  131. function getValue(obj, key)
  132. if not obj then return 0 end
  133. if not obj.attr then return obj.pos end
  134. return obj.attr[key] or obj.pos
  135. end
  136. function setData(pos, hero)
  137. local obj = CombatObj.objs[pos]
  138. CombatObj.init(obj)
  139. --加入背包索引
  140. obj.bagIndex = hero.bagIndex or 0
  141. obj.uuid = hero.uuid
  142. obj.id = hero.id
  143. obj.job = hero.job
  144. obj.body = hero.body
  145. obj.head = hero.head
  146. obj.quality = hero.quality
  147. obj.star = hero.star
  148. obj.type = hero.type
  149. obj.lv = hero.lv
  150. obj.isGedangCnt = 0
  151. obj.camp = hero.camp
  152. obj.sex = hero.sex or 0
  153. obj.relic = hero.relic or {}
  154. obj.relic.relicID = hero.relic and hero.relic.relicID or 0
  155. obj.relic.star = hero.relic and hero.relic.star or 0
  156. obj.skillList = hero.skillList or {}
  157. obj.formationPos = hero.formationPos
  158. if CombatDefine.isBackup(obj) == CombatDefine.BACKUP_TYPE0 then
  159. obj.beSkillList = hero.beSkillList or {}
  160. else
  161. obj.beSkillList = {}
  162. obj.backUpSkillList = hero.beSkillList or {}
  163. end
  164. obj.normalTarget = nil
  165. obj.isBoss = hero.isBoss -- 仅显示用
  166. obj.isGongMing = hero.isGongMing or 0
  167. CombatObj.setInitAttr(obj, hero.attrs)
  168. obj.isSysAttrChange = nil
  169. obj.weaponEffectIdList = hero.weaponEffectIdList
  170. if hero.type == CombatDefine.COMBAT_OBJ_TYPE1 then
  171. obj.hurtType = HeroExcel[obj.id].hurtType
  172. else
  173. obj.hurtType = MonsterExcel[obj.id].hurtType
  174. if not obj.hurtType then
  175. if BattleMonsterExcel[obj.id] then
  176. obj.hurtType = BattleMonsterExcel[obj.id].hurtType or 0
  177. else
  178. obj.hurtType = 0
  179. end
  180. end
  181. end
  182. if pos == CombatDefine.BACKUP_POS[1] then
  183. initBackup[1] = obj.backupPos
  184. elseif pos == CombatDefine.BACKUP_POS[2] then
  185. initBackup[2] = obj.backupPos
  186. end
  187. objList[obj.pos] = obj
  188. end
  189. function setHelp(side,helpType,help)
  190. local pos = CombatDefine.getHelpPos(side,helpType)
  191. local obj = CombatObj.helps[pos]
  192. CombatObj.initHelp(obj)
  193. obj.id = help.id
  194. obj.lv = help.lv or 0
  195. obj.quality = help.quality or 0
  196. obj.head = help.head or 0
  197. obj.body = help.body or 0
  198. obj.icon = help.icon or 0
  199. obj.weight = help.weight or 0
  200. obj.height = help.height or 0
  201. obj.skillList = help.skillList or {}
  202. obj.beSkillList = help.beSkillList or {}
  203. obj.lvAttrsAdd = help.lvAttrsAdd or {}
  204. obj.zhuHun = help.zhuHun
  205. obj.jinglianLV = help.jinglianLV
  206. obj.skillLV = help.skillLV
  207. obj.hurt = help.hurt
  208. obj.args = help.args
  209. obj.buffers = help.buffers
  210. helpList[pos] = obj
  211. end
  212. function setElf(pos, elf)
  213. local elfObj = CombatObj.elfs[pos]
  214. CombatObj.initElf(elfObj)
  215. elfObj.id = elf.id
  216. elfObj.body = elf.body or 0
  217. elfObj.head = elf.head or 0
  218. elfObj.quality = elf.quality or 1
  219. elfObj.skillList = elf.skillList or {}
  220. elfObj.beSkillList = elf.beSkillList or {}
  221. elfList[pos] = elfObj
  222. end
  223. function setMaxRound(value)
  224. maxRound = value
  225. end
  226. function setFightMode(data)
  227. for k in pairs(fightMode) do
  228. fightMode[k] = 0
  229. end
  230. if data then
  231. if data[1] == CombatDefine.FIGHT_MODE1 then
  232. fightMode = {data[1], data[2], data[3], 0}
  233. elseif data[1] == CombatDefine.FIGHT_MODE2 then
  234. fightMode = {data[1], data[2], data[3], data[4]}
  235. else
  236. fightMode = {data[1], data[2], data[3], 0}
  237. end
  238. end
  239. end
  240. local function cmp(a,b)
  241. if a.helpType ~= CombatDefine.HELP_TYPE0 or b.helpType ~= CombatDefine.HELP_TYPE0 then
  242. -- if a.helpType == CombatDefine.HELP_TYPE0 then
  243. -- return false
  244. -- elseif b.helpType == CombatDefine.HELP_TYPE0 then
  245. -- return true
  246. -- else
  247. -- local aSpeed = a.speed or 0
  248. -- local bSpeed = b.speed or 0
  249. -- if aSpeed > bSpeed then
  250. -- return true
  251. -- elseif aSpeed == bSpeed then
  252. -- return a.pos < b.pos
  253. -- else
  254. -- return false
  255. -- end
  256. -- end
  257. if a.helpType == CombatDefine.HELP_TYPE0 then
  258. return false
  259. elseif b.helpType == CombatDefine.HELP_TYPE0 then
  260. return true
  261. elseif a.helpType == CombatDefine.HELP_TYPE1 and b.helpType == CombatDefine.HELP_TYPE2 then
  262. return true
  263. elseif a.helpType == CombatDefine.HELP_TYPE2 and b.helpType == CombatDefine.HELP_TYPE1 then
  264. return false
  265. else
  266. local aSpeed = a.speed or 0
  267. local bSpeed = b.speed or 0
  268. if aSpeed > bSpeed then
  269. return true
  270. elseif aSpeed == bSpeed then
  271. return a.pos < b.pos
  272. else
  273. return false
  274. end
  275. end
  276. end
  277. local aSpeed = getValue(a, RoleDefine.SPEED)
  278. local bSpeed = getValue(b, RoleDefine.SPEED)
  279. if aSpeed > bSpeed then
  280. return true
  281. elseif aSpeed == bSpeed then
  282. return a.pos < b.pos
  283. else
  284. return false
  285. end
  286. end
  287. local function canAttack(obj)
  288. if not obj then
  289. return
  290. end
  291. if obj.helpType == CombatDefine.HELP_TYPE0 then
  292. local pos = obj.pos%CombatDefine.COMBAT_HERO_CNT
  293. if obj.hp > 0 and (pos > 0 or obj.backupPos) then
  294. -- 确定释放的技能是否带霸体
  295. local atkSkillID = getSkillID(obj)
  296. --local skillConfig = SkillExcel[atkSkillID]
  297. local skillConfig = Skill.GetSkillConfig(atkSkillID)
  298. if skillConfig and skillConfig.isBati == 1 then
  299. return true
  300. end
  301. if not CombatBuff.isStop(obj) then
  302. return true
  303. elseif CombatBuff.isStop(obj) then
  304. return false, "isStop"
  305. end
  306. end
  307. elseif obj.helpType == CombatDefine.HELP_TYPE1 then
  308. return petCD == 0
  309. elseif obj.helpType == CombatDefine.HELP_TYPE2 then
  310. for i = 1,#obj.skillList do
  311. local skill = obj.skillList[i]
  312. if (skill[3] == 0 or (skill[2] - round) % skill[3] == 0) and Skill.SkillCondCheck(obj, skill[1]) then
  313. return true
  314. end
  315. end
  316. return false
  317. elseif obj.helpType == CombatDefine.HELP_TYPE3 then
  318. elseif obj.helpType == CombatDefine.HELP_TYPE4 then
  319. end
  320. end
  321. function initAttackOrder()
  322. Util.initTable(attackOrder)
  323. -- 确定最高速度
  324. local atkSpeed = 0
  325. local atkSide = 0
  326. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  327. local obj = objList[i]
  328. if canAttack(obj) then
  329. attackOrder[#attackOrder + 1] = obj
  330. local speed = getValue(obj, RoleDefine.SPEED)
  331. if speed > atkSpeed then
  332. atkSpeed = speed
  333. atkSide = obj.side
  334. end
  335. end
  336. end
  337. for _,pos in ipairs(CombatDefine.SIDE2HELPPOS[0]) do
  338. local obj = helpList[pos]
  339. if obj and canAttack(obj) then
  340. attackOrder[#attackOrder + 1] = obj
  341. obj.speed = nil
  342. if obj.side == atkSide then
  343. obj.speed = atkSpeed
  344. end
  345. end
  346. end
  347. -- 精灵
  348. for _,pos in ipairs(CombatDefine.SIDE2ELFPOS[0]) do
  349. local elfObj = elfList[pos]
  350. if elfObj and canAttack(elfObj) then
  351. attackOrder[#attackOrder + 1] = elfObj
  352. if elfObj.side == atkSide then
  353. elfObj.speed = atkSpeed
  354. end
  355. end
  356. end
  357. table.sort(attackOrder,cmp)
  358. firstAttack = {true,true}
  359. end
  360. --用于战斗对象复活后插入出手列表的函数
  361. function InsertAttackOrder(pos)
  362. local targetObj = objList[pos]
  363. if not canAttack(targetObj) then
  364. return
  365. end
  366. local sameSideObjs = {}
  367. for i=1,#attackOrder do
  368. local obj = attackOrder[i]
  369. if obj.pos == pos then
  370. return
  371. end
  372. local res = canAttack(obj)
  373. if res and obj.side == targetObj.side then
  374. sameSideObjs[#sameSideObjs + 1] = obj
  375. end
  376. end
  377. sameSideObjs[#sameSideObjs + 1] = targetObj
  378. if #sameSideObjs > 1 then
  379. table.sort(sameSideObjs, cmp)
  380. --没过出手回合才加入
  381. if sameSideObjs[1].pos ~= pos then
  382. attackOrder[#attackOrder + 1] = targetObj
  383. end
  384. end
  385. end
  386. local tempList = {}
  387. function updateAttackOrder()
  388. for i = 1,#tempList do
  389. tempList[i] = nil
  390. end
  391. --当前不能出手, 但是下一轮可能可以出手的对象列表
  392. local maybeObjList = {}
  393. for i = 2,#attackOrder do
  394. local obj = attackOrder[i]
  395. -- if canAttack(obj) then
  396. -- tempList[#tempList + 1] = obj
  397. -- end
  398. local res1, tag = canAttack(obj)
  399. if res1 then
  400. tempList[#tempList + 1] = obj
  401. elseif tag == "isStop" then
  402. --那些被控制的英雄只有没过他的出手时机才加入列表中。可能会有给敌方驱散负面buff的技能, 所以不需要判断 tempList 里面是否有我方可出手英雄
  403. if #tempList > 0 then
  404. maybeObjList[#maybeObjList + 1] = obj
  405. end
  406. end
  407. end
  408. if #tempList > 1 then
  409. table.sort(tempList,cmp)
  410. end
  411. --只有当前轮有能出手的英雄, 才把 maybeObjList 中的对象加入到 tempList 中
  412. if #tempList >= 1 then
  413. for _, v in ipairs(maybeObjList) do
  414. tempList[#tempList + 1] = v
  415. end
  416. end
  417. for i = 1,#attackOrder do
  418. attackOrder[i] = tempList[i]
  419. end
  420. end
  421. local function clCombatResult()
  422. for i= 1,CombatDefine.COMBAT_HERO_ALL_CNT do
  423. local obj = objList[i]
  424. if obj then
  425. obj.combatResult[1] = 0
  426. obj.combatResult[2] = 0
  427. for k in pairs(obj.combatResult[3]) do
  428. obj.combatResult[3][k] = nil
  429. end
  430. obj.combatResult[4] = 0
  431. for k in pairs(obj.combatResult[5]) do
  432. obj.combatResult[5][k] = nil
  433. end
  434. end
  435. end
  436. end
  437. local function beforeCombat()
  438. Util.initTable(frameSkillList)
  439. Util.initTable(frameBufferList)
  440. Util.initTable(frameSayList)
  441. Util.initTable(fanjiList)
  442. Util.initTable(beSkillUseList)
  443. Util.initTable(beSkillPosUseList)
  444. Util.initTable(comboList)
  445. clCombatResult()
  446. isFanji = false
  447. comboType = 0
  448. end
  449. -- 战斗回合开始前操作
  450. function onRoundBegin()
  451. round = round + 1
  452. -- 超出15回合
  453. if round > maxRound then
  454. return
  455. end
  456. petCD = petCD - 1
  457. if round == 1 or petCD < 0 then
  458. petCD = CombatDefine.PET_CD - 1
  459. end
  460. attackIndex = 1
  461. --正常buffer添加只会在小回合结束后添加。此处大回合开始时触发被动技能添加buffer需要特殊处理添加战斗帧操作
  462. beforeCombat()
  463. BeSkill.onRoundBegin(round)
  464. initAttackOrder()
  465. --每回合开始处理buff
  466. if #frameBufferList > 0 or #frameSayList > 0 then
  467. addFrame()
  468. mergeFrameBuffer()
  469. for k,v in ipairs(frameBufferList) do
  470. setBufferList(v)
  471. end
  472. for _,v in ipairs(frameSayList) do
  473. setSaySkill(v[1],v[2],v[3])
  474. end
  475. end
  476. if fightMode[1] == CombatDefine.FIGHT_MODE1 then
  477. if round > fightMode[2] then
  478. fightMode[4] = fightMode[4] + fightMode[3]
  479. end
  480. end
  481. end
  482. function getNormalSkill(obj)
  483. return obj.skillList[#obj.skillList][1]
  484. end
  485. function getSkillID(obj)
  486. local skillID
  487. if obj.helpType == CombatDefine.HELP_TYPE0 then
  488. for i = 1,#obj.skillList do
  489. local skill = obj.skillList[i]
  490. if (skill[3] == 0 or (skill[2] - round) % skill[3] == 0) and Skill.SkillCondCheck(obj, skill[1]) then
  491. skillID = skill[1]
  492. skill[2] = round + skill[3]
  493. break
  494. end
  495. if skill[3] > 0 and skill[2] < round then
  496. skill[2] = skill[2] + skill[3]
  497. end
  498. end
  499. if CombatBuff.isStatus(obj,{"hunluan"}) or CombatBuff.isChaofen(obj) or CombatBuff.IsCanNoUseSkill(obj) then
  500. skillID = obj.skillList[#obj.skillList][1]
  501. end
  502. if fightMode[1] == CombatDefine.FIGHT_MODE2 then
  503. -- 如果是援军 必定选择大招
  504. if obj.backupPos ~= nil then
  505. for i = 1,#obj.skillList do
  506. local skill = obj.skillList[i]
  507. local skillList = fightMode[2]
  508. for k, v in pairs(skillList) do
  509. if v == skill[1] then
  510. skillID = skill[1]
  511. break
  512. end
  513. end
  514. end
  515. else
  516. -- 如果是第一回合 且不是防守方 使用大招
  517. if round == 1 then
  518. if obj.side == CombatDefine.ATTACK_SIDE then
  519. for i = 1,#obj.skillList do
  520. local skill = obj.skillList[i]
  521. --local skillConfig = SkillExcel[skill[1]]
  522. local skillConfig = Skill.GetSkillConfig(skill[1])
  523. if skillConfig.cvSound == 8 then
  524. skillID = skill[1]
  525. break
  526. end
  527. end
  528. end
  529. end
  530. end
  531. end
  532. elseif obj.helpType == CombatDefine.HELP_TYPE1 then
  533. for i = 1,#obj.skillList do
  534. local skill = obj.skillList[i]
  535. if (skill[3] == 0 or (skill[2] - round) % skill[3] == 0) and Skill.SkillCondCheck(obj, skill[1]) then
  536. skillID = skill[1]
  537. skill[2] = round + skill[3]
  538. break
  539. end
  540. end
  541. elseif obj.helpType == CombatDefine.HELP_TYPE2 then -- 精灵
  542. for i = 1,#obj.skillList do
  543. local skill = obj.skillList[i]
  544. if (skill[3] == 0 or (skill[2] - round) % skill[3] == 0) and Skill.SkillCondCheck(obj, skill[1]) then
  545. skillID = skill[1]
  546. skill[2] = round + skill[3]
  547. break
  548. end
  549. end
  550. elseif obj.helpType == CombatDefine.HELP_TYPE3 then
  551. elseif obj.helpType == CombatDefine.HELP_TYPE4 then
  552. end
  553. skillID = BeSkill.onSkillID(obj,skillID)
  554. return skillID
  555. end
  556. function checkSideResult(pos)
  557. local cnt = 0
  558. local obj
  559. for i= 1,CombatDefine.COMBAT_HERO_CNT do
  560. if pos > CombatDefine.COMBAT_HERO_CNT then
  561. obj = objList[i]
  562. else
  563. obj = objList[i + CombatDefine.COMBAT_HERO_CNT]
  564. end
  565. if obj and obj.hp > 0 then
  566. cnt = cnt + 1
  567. end
  568. end
  569. if cnt == 0 then
  570. return true
  571. end
  572. end
  573. local function checkResult()
  574. local attackCnt = 0
  575. local defendCnt = 0
  576. local obj
  577. for i= 1,CombatDefine.COMBAT_HERO_CNT do
  578. obj = objList[i]
  579. if obj and obj.hp > 0 then
  580. attackCnt = attackCnt + 1
  581. end
  582. obj = objList[i + CombatDefine.COMBAT_HERO_CNT]
  583. if obj and obj.hp > 0 then
  584. defendCnt = defendCnt + 1
  585. end
  586. end
  587. result.attackCnt = attackCnt
  588. result.defendCnt = defendCnt
  589. if attackCnt > 0 and defendCnt == 0 then
  590. result.isWin = true
  591. end
  592. if attackCnt == 0 or defendCnt == 0 then
  593. return true
  594. end
  595. end
  596. -- 计算援军上阵附带属性比例
  597. local function calcBackUpSkill(obj, star)
  598. --local skillConfig = SkillExcel[CombatDefine.BACKUP_BUFF_SKILL[1]]
  599. local skillConfig = Skill.GetSkillConfig(CombatDefine.BACKUP_BUFF_SKILL[1])
  600. if not skillConfig then return end
  601. local buffers = CombatBuff.getSkillBuffers(skillConfig)
  602. if not buffers then return end
  603. for i = 1, #buffers do
  604. local bufferID = buffers[i][1]
  605. --local conf = BufferExcel[bufferID]
  606. local conf = CombatBuff.GetBuffConfig(bufferID)
  607. if conf then
  608. conf.attrRate = CombatDefine.BACKUP_BUFF_REATE[star]
  609. end
  610. end
  611. end
  612. local function checkBackup()
  613. for side = 1, 2 do
  614. local backupObj = objList[CombatDefine.BACKUP_POS[side]]
  615. if backupObj and not backupObj.backupPos then
  616. for index, pos in ipairs(CombatDefine.SIDE2POS[side]) do
  617. local obj = objList[pos]
  618. -- 剧情模式 强行把援军上阵到指定位置
  619. if fightMode[1] == CombatDefine.FIGHT_MODE2 then
  620. if not obj and round == fightMode[3] and index == fightMode[4] then
  621. backupObj.backupPos = pos
  622. local attrs = {}
  623. attrs[RoleDefine.BACKUP_COMBAT] = pos
  624. addFrame()
  625. setSkillID(backupObj,99999)
  626. setExtraHit(backupObj,nil,Skill.getCMD2ID("backup"),attrs)
  627. -- 使用上场技能 设定buffer的cmd 确定附加属性星级
  628. calcBackUpSkill(backupObj, backupObj.star)
  629. BeSkill.onBackupBegin(backupObj)
  630. -- 强制速度
  631. backupObj.attr[RoleDefine.SPEED] = 9999
  632. break
  633. end
  634. else
  635. if obj and obj.hp <= 0 and pos ~= CombatDefine.BACKUP_POS[side] then
  636. obj.beBackup = 1
  637. backupObj.backupPos = pos
  638. local attrs = {}
  639. attrs[RoleDefine.BACKUP_COMBAT] = pos
  640. addFrame()
  641. setSkillID(backupObj,99999)
  642. setExtraHit(backupObj,nil,Skill.getCMD2ID("backup"),attrs)
  643. -- 使用上场技能
  644. calcBackUpSkill(backupObj, backupObj.star)
  645. BeSkill.onBackupBegin(backupObj)
  646. break
  647. end
  648. end
  649. end
  650. end
  651. end
  652. end
  653. local function afterCombat(attacker,isRoundEnd)
  654. --回合结束处理被动技能时如果是最后一次攻击是反击,不会触发。
  655. if isRoundEnd then
  656. isFanji = false
  657. comboType = 0
  658. checkBackup()
  659. end
  660. --处理回合尾加只生效一轮的buffer,在大回合结束单独加一帧,大回合结束要删buffer。避免客户端出现先删后加的要求导致没有buffer可删。同时显示已经删掉的buffer
  661. if isRoundEnd and #frameBufferList > 0 then
  662. addFrame()
  663. mergeFrameBuffer()
  664. for k,v in ipairs(frameBufferList) do
  665. setBufferList(v)
  666. end
  667. for _,v in ipairs(frameSayList) do
  668. setSaySkill(v[1],v[2],v[3])
  669. end
  670. Util.initTable(frameBufferList)
  671. Util.initTable(frameSayList)
  672. end
  673. BeSkill.onRoundEnd(isRoundEnd, attacker)
  674. CombatBuff.onRoundEnd(attacker,isRoundEnd)
  675. if #frameBufferList > 0 or #frameSayList > 0 then
  676. addFrame()
  677. mergeFrameBuffer()
  678. for k,v in ipairs(frameBufferList) do
  679. setBufferList(v)
  680. end
  681. for _,v in ipairs(frameSayList) do
  682. setSaySkill(v[1],v[2],v[3])
  683. end
  684. Util.initTable(frameBufferList)
  685. Util.initTable(frameSayList)
  686. end
  687. afterRevice()
  688. if attacker and attacker.pos <= CombatDefine.COMBAT_HERO_ALL_CNT and firstAttack[attacker.side] then
  689. firstAttack[attacker.side] = false
  690. end
  691. end
  692. local function afterFanji()
  693. if #frameBufferList > 0 or #frameSayList > 0 then
  694. addFrame()
  695. mergeFrameBuffer()
  696. for k,v in ipairs(frameBufferList) do
  697. setBufferList(v)
  698. end
  699. for pos,v in ipairs(frameSayList) do
  700. setSaySkill(v[1],v[2],v[3])
  701. end
  702. Util.initTable(frameBufferList)
  703. Util.initTable(frameSayList)
  704. end
  705. isFanji = false
  706. end
  707. function afterBuff()
  708. if #frameBufferList > 0 or #frameSayList > 0 then
  709. mergeFrameBuffer()
  710. for k,v in ipairs(frameBufferList) do
  711. setBufferList(v)
  712. end
  713. for _,v in ipairs(frameSayList) do
  714. setSaySkill(v[1],v[2],v[3])
  715. end
  716. Util.initTable(frameBufferList)
  717. Util.initTable(frameSayList)
  718. end
  719. end
  720. local function afterCombo()
  721. if #frameBufferList > 0 or #frameSayList > 0 then
  722. addFrame()
  723. mergeFrameBuffer()
  724. for k,v in ipairs(frameBufferList) do
  725. setBufferList(v)
  726. end
  727. for _,v in ipairs(frameSayList) do
  728. setSaySkill(v[1],v[2],v[3])
  729. end
  730. Util.initTable(frameBufferList)
  731. Util.initTable(frameSayList)
  732. end
  733. comboType = 0
  734. end
  735. function calcFrame()
  736. -- 没有能出手的人,开始下一个回合
  737. if not attackOrder[1] then
  738. onRoundBegin()
  739. end
  740. -- 超出15回合
  741. if round > maxRound then
  742. return
  743. end
  744. if not attackOrder[1] then
  745. -- 此回合 双方都没有能出手的英雄
  746. -- 回合 Buff结算
  747. afterCombat(nil ,not attackOrder[1])
  748. if checkResult() then return end
  749. return true
  750. end
  751. beforeCombat()
  752. local attacker = attackOrder[1]
  753. if attacker then
  754. -- 目前mpAtkRate 永远为nil
  755. local skillID,mpAtkRate = getSkillID(attacker)
  756. -- buff作用效果
  757. --skillID = 10131
  758. if skillID then
  759. Skill.use(attacker,skillID,mpAtkRate)
  760. CombatBuff.BuffHandleAfterSkill(attacker)
  761. addObjResultOut(attacker,round)
  762. end
  763. end
  764. --技能buff
  765. afterBuff()
  766. CombatBuff.beforeFanji()
  767. --BeSkill.beforeFanji(attacker)
  768. fanji()
  769. afterFanji()
  770. combo()
  771. afterCombo()
  772. afterRevice()
  773. updateAttackOrder()
  774. afterCombat(attacker,not attackOrder[1])
  775. if checkResult() then return end
  776. return true
  777. end
  778. function addFrame()
  779. if not result.frames then
  780. result.frames = {}
  781. end
  782. local frame = {}
  783. frame.round = round
  784. frame.petCD = petCD
  785. frame.skillList = {}
  786. frame.bufferList = {}
  787. frame.sayList = {}
  788. result.frames[#result.frames + 1] = frame
  789. return frame
  790. end
  791. function setSkillID(obj,skillID)
  792. onUseSkill(skillID)
  793. local pos = obj.pos
  794. local frame = result.frames[#result.frames]
  795. local skillData = {}
  796. skillData.attackPos = pos
  797. skillData.skillID = skillID
  798. skillData.hitList = {}
  799. skillData.extraList = {}
  800. skillData.petList = {}
  801. frame.skillList[#frame.skillList+1] = skillData
  802. end
  803. function setSaySkill(pos,skillID,contentType)
  804. if contentType == 0 then
  805. return
  806. end
  807. --if pos > CombatDefine.COMBAT_HERO_ALL_CNT then
  808. -- return
  809. --end
  810. onUseSkill(skillID)
  811. local frame = result.frames[#result.frames]
  812. frame.sayList[pos] = frame.sayList[pos] or {}
  813. frame.sayList[pos][#frame.sayList[pos]+ 1] = skillID
  814. end
  815. function setSkillHit(target,hpValue,mpValue,flag,attacker,skillID)
  816. local frame = result.frames[#result.frames]
  817. local skillFrame = frame.skillList[#frame.skillList]
  818. if not (not target.isPet and skillFrame.skillID == skillID and skillFrame.attackPos and skillFrame.attackPos == attacker.pos) then
  819. addFrame()
  820. setSkillID(attacker,skillID)
  821. frame = result.frames[#result.frames]
  822. skillFrame = frame.skillList[#frame.skillList]
  823. end
  824. local pos = target.pos
  825. if not skillFrame.hitList[pos] then
  826. skillFrame.hitList[pos] = {}
  827. end
  828. if not skillFrame.hitList[pos].attrs then
  829. skillFrame.hitList[pos].attrs = {}
  830. end
  831. skillFrame.hitList[pos].flag = flag or 0
  832. skillFrame.hitList[pos].hpNow = target.hp
  833. local frameAttrs = skillFrame.hitList[pos].attrs
  834. if hpValue and hpValue ~= 0 then
  835. frameAttrs[#frameAttrs + 1] = {RoleDefine.HP_COMBAT,hpValue}
  836. if target.side == CombatDefine.DEFEND_SIDE and hpValue < 0 then
  837. frameAttrs[#frameAttrs + 1] = {RoleDefine.HURT_COMBAT_TOTAL,math.floor(totalHurt)}
  838. end
  839. end
  840. end
  841. function isSkillFrameEmpty()
  842. local frame = result.frames and result.frames[#result.frames]
  843. if not frame then
  844. return true
  845. end
  846. local skillFrame = frame.skillList[#frame.skillList]
  847. if not skillFrame then
  848. return true
  849. end
  850. end
  851. function setExtraHit(target,hpValue,cmd,attrs)
  852. local frame = result.frames[#result.frames]
  853. local skillFrame = frame.skillList[#frame.skillList]
  854. --处理下没有使用技能的情况
  855. if not skillFrame then
  856. print("======================没有使用技能====================")
  857. setSkillID({pos = 99}, 66666)
  858. skillFrame = frame.skillList[#frame.skillList]
  859. end
  860. local pos = target.pos
  861. if not skillFrame.extraList[pos] then
  862. skillFrame.extraList[pos] = {}
  863. end
  864. if not skillFrame.extraList[pos].attrs then
  865. skillFrame.extraList[pos].attrs = {}
  866. end
  867. skillFrame.extraList[pos].flag = 0
  868. if not skillFrame.extraList[pos].cmd then
  869. skillFrame.extraList[pos].cmd = cmd or 0
  870. end
  871. skillFrame.extraList[pos].hpNow = target.hp
  872. local frameAttrs = skillFrame.extraList[pos].attrs
  873. if hpValue and hpValue ~= 0 then
  874. frameAttrs[#frameAttrs + 1] = {RoleDefine.HP_COMBAT,hpValue}
  875. if target.side == CombatDefine.DEFEND_SIDE and hpValue < 0 then
  876. frameAttrs[#frameAttrs + 1] = {RoleDefine.HURT_COMBAT_TOTAL,math.floor(totalHurt)}
  877. end
  878. end
  879. if attrs then
  880. for k,v in pairs(attrs) do
  881. frameAttrs[#frameAttrs + 1] = {k,v}
  882. end
  883. end
  884. onUseCmd(cmd)
  885. end
  886. function setBufferList(data)
  887. if not data then
  888. return
  889. end
  890. local frame = result.frames[#result.frames]
  891. if not frame.bufferList[data.pos] then
  892. frame.bufferList[data.pos] = {}
  893. end
  894. local bufferList = frame.bufferList[data.pos]
  895. local frameBuffer = {}
  896. frameBuffer.id = data.id
  897. frameBuffer.cnt = data.cnt
  898. frameBuffer.round = data.round
  899. frameBuffer.op = data.op
  900. frameBuffer.hpNow = data.hpNow
  901. frameBuffer.attrs = {}
  902. if data.attrs then
  903. local hpValue = 0
  904. for k,v in pairs(data.attrs) do
  905. frameBuffer.attrs[#frameBuffer.attrs + 1] = {k,v}
  906. if data.pos > CombatDefine.COMBAT_HERO_CNT and k == RoleDefine.HP_COMBAT and v < 0 then
  907. hpValue = hpValue + v
  908. end
  909. end
  910. if hpValue < 0 then
  911. frameBuffer.attrs[#frameBuffer.attrs + 1] = {RoleDefine.HURT_COMBAT_TOTAL,math.floor(totalHurt)}
  912. end
  913. end
  914. bufferList[#bufferList + 1] = frameBuffer
  915. end
  916. function onUseSkill(skillID)
  917. skillUseList[skillID] = 1
  918. end
  919. function onUseCmd(cmd)
  920. if not cmd or cmd == 0 then return end
  921. cmdUseList[cmd] = 1
  922. end
  923. function onAddBuffer(bufferID)
  924. bufferUseList[bufferID] = 1
  925. end
  926. function addFrameSkill(pos,skillID)
  927. frameSkillList[#frameSkillList + 1] = {pos,skillID}
  928. end
  929. function addFrameBuffer(obj,buffer,op,bufferCnt)
  930. local data = {}
  931. data.id = buffer.id
  932. data.cnt = bufferCnt or 1
  933. data.round = buffer.round
  934. data.op = op
  935. data.attrs = {}
  936. if buffer.attrs then
  937. for k,v in pairs(buffer.attrs) do
  938. if v ~= 0 then
  939. data.attrs[k] = data.attrs[k] or 0
  940. data.attrs[k] = data.attrs[k] + v
  941. end
  942. end
  943. end
  944. data.pos = obj.pos
  945. data.hpNow = obj.hp
  946. frameBufferList[#frameBufferList + 1] = data
  947. end
  948. function addSaySkill(obj,skillConfig)
  949. if skillConfig.contentType == 0 then
  950. return
  951. end
  952. if obj.pos > CombatDefine.COMBAT_HERO_ALL_CNT then
  953. return
  954. end
  955. frameSayList[#frameSayList + 1] = {obj.pos,skillConfig.id,skillConfig.contentType}
  956. end
  957. function addRevice(attackPos, obj, bufferID, skillID)
  958. frameReviceList[#frameReviceList + 1] = {obj.pos, attackPos, bufferID, skillID}
  959. end
  960. function afterRevice()
  961. if #frameReviceList > 0 then
  962. for k, v in ipairs(frameReviceList) do
  963. local obj = objList[v[1]]
  964. if obj then
  965. addFrame()
  966. CombatBuff.reviceObj(v[2], obj, v[3], v[4])
  967. end
  968. end
  969. Util.initTable(frameReviceList)
  970. if #frameBufferList > 0 or #frameSayList > 0 then
  971. mergeFrameBuffer()
  972. for k,v in ipairs(frameBufferList) do
  973. setBufferList(v)
  974. end
  975. for _,v in ipairs(frameSayList) do
  976. setSaySkill(v[1],v[2],v[3])
  977. end
  978. Util.initTable(frameBufferList)
  979. Util.initTable(frameSayList)
  980. end
  981. end
  982. end
  983. function addBeSkillUse(obj,attackerPos,skillID)
  984. beSkillUseList[obj.pos] = beSkillUseList[obj.pos] or {}
  985. beSkillUseList[obj.pos][attackerPos] = beSkillUseList[obj.pos][attackerPos] or {}
  986. beSkillUseList[obj.pos][attackerPos][skillID] = beSkillUseList[obj.pos][attackerPos][skillID] or 0
  987. beSkillUseList[obj.pos][attackerPos][skillID] = beSkillUseList[obj.pos][attackerPos][skillID] + 1
  988. end
  989. function getBeSkillUse(obj,attackerPos,skillID)
  990. return beSkillUseList[obj.pos] and beSkillUseList[obj.pos][attackerPos] and beSkillUseList[obj.pos][attackerPos][skillID] or 0
  991. end
  992. function addBeSkillPosUse(pos,skillID)
  993. beSkillPosUseList[pos] = beSkillPosUseList[pos] or {}
  994. beSkillPosUseList[pos][skillID] = beSkillPosUseList[pos][skillID] or 0
  995. beSkillPosUseList[pos][skillID] = beSkillPosUseList[pos][skillID] + 1
  996. end
  997. function getBeSkillPosUse(pos,skillID)
  998. return beSkillPosUseList[pos] and beSkillPosUseList[pos][skillID]
  999. end
  1000. function getBeSkillSideUse(pos,skillID)
  1001. local side
  1002. if pos <= CombatDefine.COMBAT_HERO_CNT then
  1003. side = CombatDefine.ATTACK_SIDE
  1004. elseif pos <= CombatDefine.COMBAT_HERO_ALL_CNT then
  1005. side = CombatDefine.DEFEND_SIDE
  1006. else
  1007. return
  1008. end
  1009. local skillCnt = 0
  1010. for _,v in ipairs(CombatDefine.SIDE2POS[side]) do
  1011. if v ~= pos and beSkillPosUseList[v] and beSkillPosUseList[v][skillID] then
  1012. skillCnt = skillCnt + beSkillPosUseList[v][skillID]
  1013. end
  1014. end
  1015. return skillCnt
  1016. end
  1017. function setObjResult(pos,value)
  1018. local obj
  1019. if pos <= CombatDefine.COMBAT_HERO_ALL_CNT then
  1020. obj = objList[pos]
  1021. elseif pos == CombatDefine.PET_ATKPOS then
  1022. obj = helpList[pos]
  1023. elseif pos == CombatDefine.PET_DEFPOS then
  1024. obj = helpList[pos]
  1025. elseif CombatDefine.ELF_MIN_POS <= pos and CombatDefine.ELF_MAX_POS >= pos then
  1026. obj = elfList[pos]
  1027. end
  1028. if not obj then
  1029. return
  1030. end
  1031. if value > 0 then
  1032. obj.result[2] = obj.result[2] + value
  1033. elseif value < 0 then
  1034. obj.result[1] = obj.result[1] - value
  1035. if obj.side == CombatDefine.ATTACK_SIDE then
  1036. totalHurt = totalHurt - value
  1037. end
  1038. end
  1039. end
  1040. function fanji()
  1041. isFanji = true
  1042. for i = 1,#fanjiList do
  1043. local fanjiData = fanjiList[i]
  1044. if fanjiData[1].hp > 0 then
  1045. Skill.use(fanjiData[1],fanjiData[2],fanjiData[3])
  1046. end
  1047. end
  1048. end
  1049. function comboAgain(obj, type, hurtRate, comboSkillID, skip)
  1050. if not obj or obj.hp <=0 then return end
  1051. local stop = CombatBuff.isStop(obj)
  1052. --新增条件,如果控制buff只有chanrao也能继续执行
  1053. if stop and skip == nil and not CombatBuff.IsJustHaveChanraoBuff(obj) then return end
  1054. local skillID = comboSkillID or getSkillID(obj)
  1055. if skillID then
  1056. comboType = type
  1057. comboHurtRate = hurtRate
  1058. if type == 999 then --追击
  1059. local objPos = obj.pos
  1060. local objTag = obj.uuid or obj.id
  1061. useZhuijiObjList[objPos] = {}
  1062. useZhuijiObjList[objPos][objTag] = (useZhuijiObjList[objPos][objTag] or 0) + 1
  1063. end
  1064. Skill.use(obj, skillID)
  1065. comboType = 0
  1066. end
  1067. end
  1068. function combo()
  1069. local comboSkillID
  1070. for k,v in pairs(comboPosList) do
  1071. comboPosList[k] = nil
  1072. end
  1073. for k, v in ipairs(comboList) do
  1074. --for i = 1,#comboList do
  1075. local obj = v[1]
  1076. if obj.hp > 0 then
  1077. local type = v[2] or 0
  1078. local hurtRate = v[3] or 10000
  1079. comboSkillID = nil
  1080. local argSkill = v[4] or 0
  1081. if argSkill ~= 0 then
  1082. comboSkillID = argSkill
  1083. else
  1084. if type == 2 then
  1085. comboSkillID = getNormalSkill(obj)
  1086. end
  1087. end
  1088. local t = v[5] or 1
  1089. local skip = v[6]
  1090. if not (comboPosList[obj.pos] and comboPosList[obj.pos][t] and comboPosList[obj.pos][0] >= 3) then --避免组合技能触发多次连击,比如10813
  1091. comboAgain(obj, type, hurtRate, comboSkillID, skip)
  1092. comboPosList[obj.pos] = comboPosList[obj.pos] or {}
  1093. comboPosList[obj.pos][0] = comboPosList[obj.pos][0] or 0
  1094. comboPosList[obj.pos][0] = comboPosList[obj.pos][0] + 1
  1095. comboPosList[obj.pos][t] = 1
  1096. end
  1097. end
  1098. end
  1099. end
  1100. function setObjBearResult(obj, value)
  1101. if not obj then
  1102. return
  1103. end
  1104. if value < 0 then
  1105. obj.result[3] = obj.result[3] - value
  1106. end
  1107. end
  1108. function addObjResultOut(obj, round)
  1109. if not obj then
  1110. return
  1111. end
  1112. if obj.pos > CombatDefine.COMBAT_HERO_ALL_CNT then
  1113. obj.result[4] = obj.result[4] + 1
  1114. else
  1115. obj.result[4] = round
  1116. end
  1117. end
  1118. --即时添加buffer帧
  1119. function instantFrameBuffer(obj,skillID)
  1120. if #frameBufferList > 0 or #frameSayList > 0 then
  1121. addFrame()
  1122. if obj and skillID then
  1123. setSkillID(obj, skillID)
  1124. end
  1125. mergeFrameBuffer()
  1126. for k,v in ipairs(frameBufferList) do
  1127. setBufferList(v)
  1128. end
  1129. for _,v in ipairs(frameSayList) do
  1130. setSaySkill(v[1],v[2],v[3])
  1131. end
  1132. Util.initTable(frameBufferList)
  1133. Util.initTable(frameSayList)
  1134. end
  1135. end