CombatImpl.lua 30 KB

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