CombatImpl.lua 32 KB

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