CombatImpl.lua 30 KB

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