CombatImpl.lua 32 KB

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