CombatImpl.lua 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  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. -- 战斗回合开始前操作
  340. function onRoundBegin()
  341. round = round + 1
  342. -- 超出15回合
  343. if round > maxRound then
  344. return
  345. end
  346. petCD = petCD - 1
  347. if round == 1 or petCD < 0 then
  348. petCD = CombatDefine.PET_CD - 1
  349. end
  350. attackIndex = 1
  351. --正常buffer添加只会在小回合结束后添加。此处大回合开始时触发被动技能添加buffer需要特殊处理添加战斗帧操作
  352. beforeCombat()
  353. BeSkill.onRoundBegin(round)
  354. initAttackOrder()
  355. --每回合开始处理buff
  356. if #frameBufferList > 0 or #frameSayList > 0 then
  357. addFrame()
  358. mergeFrameBuffer()
  359. for k,v in ipairs(frameBufferList) do
  360. setBufferList(v)
  361. end
  362. for _,v in ipairs(frameSayList) do
  363. setSaySkill(v[1],v[2],v[3])
  364. end
  365. end
  366. if fightMode[1] == CombatDefine.FIGHT_MODE1 then
  367. if round > fightMode[2] then
  368. fightMode[4] = fightMode[4] + fightMode[3]
  369. end
  370. end
  371. end
  372. function getNormalSkill(obj)
  373. return obj.skillList[#obj.skillList][1]
  374. end
  375. function getSkillID(obj)
  376. local skillID
  377. if obj.helpType == CombatDefine.HELP_TYPE0 then
  378. for i = 1,#obj.skillList do
  379. local skill = obj.skillList[i]
  380. if skill[3] == 0 or (skill[2] - round) % skill[3] == 0 then
  381. skillID = skill[1]
  382. skill[2] = round + skill[3]
  383. break
  384. end
  385. if skill[3] > 0 and skill[2] < round then
  386. skill[2] = skill[2] + skill[3]
  387. end
  388. end
  389. if CombatBuff.isStatus(obj,{"hunluan"}) or CombatBuff.isChaofen(obj) or CombatBuff.IsCanNoUseSkill(obj) then
  390. skillID = obj.skillList[#obj.skillList][1]
  391. end
  392. if fightMode[1] == CombatDefine.FIGHT_MODE2 then
  393. -- 如果是援军 必定选择大招
  394. if obj.backupPos ~= nil then
  395. for i = 1,#obj.skillList do
  396. local skill = obj.skillList[i]
  397. local skillList = fightMode[2]
  398. for k, v in pairs(skillList) do
  399. if v == skill[1] then
  400. skillID = skill[1]
  401. break
  402. end
  403. end
  404. end
  405. else
  406. -- 如果是第一回合 且不是防守方 使用大招
  407. if round == 1 then
  408. if obj.side == CombatDefine.ATTACK_SIDE then
  409. for i = 1,#obj.skillList do
  410. local skill = obj.skillList[i]
  411. local skillConfig = SkillExcel[skill[1]]
  412. if skillConfig.cvSound == 8 then
  413. skillID = skill[1]
  414. break
  415. end
  416. end
  417. end
  418. end
  419. end
  420. end
  421. elseif obj.helpType == CombatDefine.HELP_TYPE1 then
  422. for i = 1,#obj.skillList do
  423. local skill = obj.skillList[i]
  424. if skill[3] == 0 or (skill[2] - round) % skill[3] == 0 then
  425. skillID = skill[1]
  426. skill[2] = round + skill[3]
  427. break
  428. end
  429. end
  430. elseif obj.helpType == CombatDefine.HELP_TYPE2 then
  431. elseif obj.helpType == CombatDefine.HELP_TYPE3 then
  432. elseif obj.helpType == CombatDefine.HELP_TYPE4 then
  433. end
  434. skillID = BeSkill.onSkillID(obj,skillID)
  435. return skillID
  436. end
  437. function checkSideResult(pos)
  438. local cnt = 0
  439. local obj
  440. for i= 1,CombatDefine.COMBAT_HERO_CNT do
  441. if pos > CombatDefine.COMBAT_HERO_CNT then
  442. obj = objList[i]
  443. else
  444. obj = objList[i + CombatDefine.COMBAT_HERO_CNT]
  445. end
  446. if obj and obj.hp > 0 then
  447. cnt = cnt + 1
  448. end
  449. end
  450. if cnt == 0 then
  451. return true
  452. end
  453. end
  454. local function checkResult()
  455. local attackCnt = 0
  456. local defendCnt = 0
  457. local obj
  458. for i= 1,CombatDefine.COMBAT_HERO_CNT do
  459. obj = objList[i]
  460. if obj and obj.hp > 0 then
  461. attackCnt = attackCnt + 1
  462. end
  463. obj = objList[i + CombatDefine.COMBAT_HERO_CNT]
  464. if obj and obj.hp > 0 then
  465. defendCnt = defendCnt + 1
  466. end
  467. end
  468. result.attackCnt = attackCnt
  469. result.defendCnt = defendCnt
  470. if attackCnt > 0 and defendCnt == 0 then
  471. result.isWin = true
  472. end
  473. if attackCnt == 0 or defendCnt == 0 then
  474. return true
  475. end
  476. end
  477. -- 计算援军上阵附带属性比例
  478. local function calcBackUpSkill(star)
  479. local skillConfig = SkillExcel[CombatDefine.BACKUP_BUFF_SKILL[1]]
  480. if not skillConfig then return end
  481. local buffers = CombatBuff.getSkillBuffers(skillConfig)
  482. if not buffers then return end
  483. for i = 1, #buffers do
  484. local bufferID = buffers[i][1]
  485. local conf = BufferExcel[bufferID]
  486. if conf then
  487. conf.attrRate = CombatDefine.BACKUP_BUFF_REATE[star]
  488. end
  489. end
  490. end
  491. local function checkBackup()
  492. for side = 1, 2 do
  493. local backupObj = objList[CombatDefine.BACKUP_POS[side]]
  494. if backupObj and not backupObj.backupPos then
  495. for index, pos in ipairs(CombatDefine.SIDE2POS[side]) do
  496. local obj = objList[pos]
  497. -- 剧情模式 强行把援军上阵到指定位置
  498. if fightMode[1] == CombatDefine.FIGHT_MODE2 then
  499. if not obj and round == fightMode[3] and index == fightMode[4] then
  500. backupObj.backupPos = pos
  501. local attrs = {}
  502. attrs[RoleDefine.BACKUP_COMBAT] = pos
  503. addFrame()
  504. setSkillID(backupObj,99999)
  505. setExtraHit(backupObj,nil,Skill.getCMD2ID("backup"),attrs)
  506. -- 使用上场技能 设定buffer的cmd 确定附加属性星级
  507. calcBackUpSkill(backupObj.star)
  508. BeSkill.onBackupBegin(backupObj)
  509. -- 强制速度
  510. backupObj.attr[RoleDefine.SPEED] = 9999
  511. break
  512. end
  513. else
  514. if obj and obj.hp <= 0 and pos ~= CombatDefine.BACKUP_POS[side] then
  515. obj.beBackup = 1
  516. backupObj.backupPos = pos
  517. local attrs = {}
  518. attrs[RoleDefine.BACKUP_COMBAT] = pos
  519. addFrame()
  520. setSkillID(backupObj,99999)
  521. setExtraHit(backupObj,nil,Skill.getCMD2ID("backup"),attrs)
  522. -- 使用上场技能
  523. calcBackUpSkill(backupObj.star)
  524. BeSkill.onBackupBegin(backupObj)
  525. break
  526. end
  527. end
  528. end
  529. end
  530. end
  531. end
  532. local function afterCombat(attacker,isRoundEnd)
  533. --回合结束处理被动技能时如果是最后一次攻击是反击,不会触发。
  534. if isRoundEnd then
  535. isFanji = false
  536. comboType = 0
  537. checkBackup()
  538. end
  539. --处理回合尾加只生效一轮的buffer,在大回合结束单独加一帧,大回合结束要删buffer。避免客户端出现先删后加的要求导致没有buffer可删。同时显示已经删掉的buffer
  540. if isRoundEnd and #frameBufferList > 0 then
  541. addFrame()
  542. mergeFrameBuffer()
  543. for k,v in ipairs(frameBufferList) do
  544. setBufferList(v)
  545. end
  546. for _,v in ipairs(frameSayList) do
  547. setSaySkill(v[1],v[2],v[3])
  548. end
  549. Util.initTable(frameBufferList)
  550. Util.initTable(frameSayList)
  551. end
  552. BeSkill.onRoundEnd(isRoundEnd, attacker)
  553. CombatBuff.onRoundEnd(attacker,isRoundEnd)
  554. if #frameBufferList > 0 or #frameSayList > 0 then
  555. addFrame()
  556. mergeFrameBuffer()
  557. for k,v in ipairs(frameBufferList) do
  558. setBufferList(v)
  559. end
  560. for _,v in ipairs(frameSayList) do
  561. setSaySkill(v[1],v[2],v[3])
  562. end
  563. Util.initTable(frameBufferList)
  564. Util.initTable(frameSayList)
  565. end
  566. afterRevice()
  567. if attacker and attacker.pos <= CombatDefine.COMBAT_HERO_ALL_CNT and firstAttack[attacker.side] then
  568. firstAttack[attacker.side] = false
  569. end
  570. end
  571. local function afterFanji()
  572. if #frameBufferList > 0 or #frameSayList > 0 then
  573. addFrame()
  574. mergeFrameBuffer()
  575. for k,v in ipairs(frameBufferList) do
  576. setBufferList(v)
  577. end
  578. for pos,v in ipairs(frameSayList) do
  579. setSaySkill(v[1],v[2],v[3])
  580. end
  581. Util.initTable(frameBufferList)
  582. Util.initTable(frameSayList)
  583. end
  584. isFanji = false
  585. end
  586. function afterBuff()
  587. if #frameBufferList > 0 or #frameSayList > 0 then
  588. mergeFrameBuffer()
  589. for k,v in ipairs(frameBufferList) do
  590. setBufferList(v)
  591. end
  592. for _,v in ipairs(frameSayList) do
  593. setSaySkill(v[1],v[2],v[3])
  594. end
  595. Util.initTable(frameBufferList)
  596. Util.initTable(frameSayList)
  597. end
  598. end
  599. local function afterCombo()
  600. if #frameBufferList > 0 or #frameSayList > 0 then
  601. addFrame()
  602. mergeFrameBuffer()
  603. for k,v in ipairs(frameBufferList) do
  604. setBufferList(v)
  605. end
  606. for _,v in ipairs(frameSayList) do
  607. setSaySkill(v[1],v[2],v[3])
  608. end
  609. Util.initTable(frameBufferList)
  610. Util.initTable(frameSayList)
  611. end
  612. comboType = 0
  613. end
  614. function calcFrame()
  615. -- 没有能出手的人,开始下一个回合
  616. if not attackOrder[1] then
  617. onRoundBegin()
  618. end
  619. -- 超出15回合
  620. if round > maxRound then
  621. return
  622. end
  623. if not attackOrder[1] then
  624. -- 此回合 双方都没有能出手的英雄
  625. -- 回合 Buff结算
  626. afterCombat(nil ,not attackOrder[1])
  627. if checkResult() then return end
  628. return true
  629. end
  630. beforeCombat()
  631. local attacker = attackOrder[1]
  632. if attacker then
  633. -- 目前mpAtkRate 永远为nil
  634. local skillID,mpAtkRate = getSkillID(attacker)
  635. -- buff作用效果
  636. --skillID = 10131
  637. if skillID then
  638. Skill.use(attacker,skillID,mpAtkRate)
  639. addObjResultOut(attacker,round)
  640. end
  641. end
  642. --技能buff
  643. afterBuff()
  644. CombatBuff.beforeFanji()
  645. --BeSkill.beforeFanji(attacker)
  646. fanji()
  647. afterFanji()
  648. combo()
  649. afterCombo()
  650. afterRevice()
  651. updateAttackOrder()
  652. afterCombat(attacker,not attackOrder[1])
  653. if checkResult() then return end
  654. return true
  655. end
  656. function addFrame()
  657. if not result.frames then
  658. result.frames = {}
  659. end
  660. local frame = {}
  661. frame.round = round
  662. frame.petCD = petCD
  663. frame.skillList = {}
  664. frame.bufferList = {}
  665. frame.sayList = {}
  666. result.frames[#result.frames + 1] = frame
  667. return frame
  668. end
  669. function setSkillID(obj,skillID)
  670. onUseSkill(skillID)
  671. local pos = obj.pos
  672. local frame = result.frames[#result.frames]
  673. local skillData = {}
  674. skillData.attackPos = pos
  675. skillData.skillID = skillID
  676. skillData.hitList = {}
  677. skillData.extraList = {}
  678. skillData.petList = {}
  679. frame.skillList[#frame.skillList+1] = skillData
  680. end
  681. function setSaySkill(pos,skillID,contentType)
  682. if contentType == 0 then
  683. return
  684. end
  685. --if pos > CombatDefine.COMBAT_HERO_ALL_CNT then
  686. -- return
  687. --end
  688. onUseSkill(skillID)
  689. local frame = result.frames[#result.frames]
  690. frame.sayList[pos] = frame.sayList[pos] or {}
  691. frame.sayList[pos][#frame.sayList[pos]+ 1] = skillID
  692. end
  693. function setSkillHit(target,hpValue,mpValue,flag,attacker,skillID)
  694. local frame = result.frames[#result.frames]
  695. local skillFrame = frame.skillList[#frame.skillList]
  696. if not (not target.isPet and skillFrame.skillID == skillID and skillFrame.attackPos and skillFrame.attackPos == attacker.pos) then
  697. addFrame()
  698. setSkillID(attacker,skillID)
  699. frame = result.frames[#result.frames]
  700. skillFrame = frame.skillList[#frame.skillList]
  701. end
  702. local pos = target.pos
  703. if not skillFrame.hitList[pos] then
  704. skillFrame.hitList[pos] = {}
  705. end
  706. if not skillFrame.hitList[pos].attrs then
  707. skillFrame.hitList[pos].attrs = {}
  708. end
  709. skillFrame.hitList[pos].flag = flag or 0
  710. skillFrame.hitList[pos].hpNow = target.hp
  711. local frameAttrs = skillFrame.hitList[pos].attrs
  712. if hpValue and hpValue ~= 0 then
  713. frameAttrs[#frameAttrs + 1] = {RoleDefine.HP_COMBAT,hpValue}
  714. if target.side == CombatDefine.DEFEND_SIDE and hpValue < 0 then
  715. frameAttrs[#frameAttrs + 1] = {RoleDefine.HURT_COMBAT_TOTAL,math.floor(totalHurt)}
  716. end
  717. end
  718. end
  719. function isSkillFrameEmpty()
  720. local frame = result.frames and result.frames[#result.frames]
  721. if not frame then
  722. return true
  723. end
  724. local skillFrame = frame.skillList[#frame.skillList]
  725. if not skillFrame then
  726. return true
  727. end
  728. end
  729. function setExtraHit(target,hpValue,cmd,attrs)
  730. local frame = result.frames[#result.frames]
  731. local skillFrame = frame.skillList[#frame.skillList]
  732. local pos = target.pos
  733. if not skillFrame.extraList[pos] then
  734. skillFrame.extraList[pos] = {}
  735. end
  736. if not skillFrame.extraList[pos].attrs then
  737. skillFrame.extraList[pos].attrs = {}
  738. end
  739. skillFrame.extraList[pos].flag = 0
  740. if not skillFrame.extraList[pos].cmd then
  741. skillFrame.extraList[pos].cmd = cmd or 0
  742. end
  743. skillFrame.extraList[pos].hpNow = target.hp
  744. local frameAttrs = skillFrame.extraList[pos].attrs
  745. if hpValue and hpValue ~= 0 then
  746. frameAttrs[#frameAttrs + 1] = {RoleDefine.HP_COMBAT,hpValue}
  747. if target.side == CombatDefine.DEFEND_SIDE and hpValue < 0 then
  748. frameAttrs[#frameAttrs + 1] = {RoleDefine.HURT_COMBAT_TOTAL,math.floor(totalHurt)}
  749. end
  750. end
  751. if attrs then
  752. for k,v in pairs(attrs) do
  753. frameAttrs[#frameAttrs + 1] = {k,v}
  754. end
  755. end
  756. onUseCmd(cmd)
  757. end
  758. function setBufferList(data)
  759. if not data then
  760. return
  761. end
  762. local frame = result.frames[#result.frames]
  763. if not frame.bufferList[data.pos] then
  764. frame.bufferList[data.pos] = {}
  765. end
  766. local bufferList = frame.bufferList[data.pos]
  767. local frameBuffer = {}
  768. frameBuffer.id = data.id
  769. frameBuffer.cnt = data.cnt
  770. frameBuffer.round = data.round
  771. frameBuffer.op = data.op
  772. frameBuffer.hpNow = data.hpNow
  773. frameBuffer.attrs = {}
  774. if data.attrs then
  775. local hpValue = 0
  776. for k,v in pairs(data.attrs) do
  777. frameBuffer.attrs[#frameBuffer.attrs + 1] = {k,v}
  778. if data.pos > CombatDefine.COMBAT_HERO_CNT and k == RoleDefine.HP_COMBAT and v < 0 then
  779. hpValue = hpValue + v
  780. end
  781. end
  782. if hpValue < 0 then
  783. frameBuffer.attrs[#frameBuffer.attrs + 1] = {RoleDefine.HURT_COMBAT_TOTAL,math.floor(totalHurt)}
  784. end
  785. end
  786. bufferList[#bufferList + 1] = frameBuffer
  787. end
  788. function onUseSkill(skillID)
  789. skillUseList[skillID] = 1
  790. end
  791. function onUseCmd(cmd)
  792. if not cmd or cmd == 0 then return end
  793. cmdUseList[cmd] = 1
  794. end
  795. function onAddBuffer(bufferID)
  796. bufferUseList[bufferID] = 1
  797. end
  798. function addFrameSkill(pos,skillID)
  799. frameSkillList[#frameSkillList + 1] = {pos,skillID}
  800. end
  801. function addFrameBuffer(obj,buffer,op,bufferCnt)
  802. local data = {}
  803. data.id = buffer.id
  804. data.cnt = bufferCnt or 1
  805. data.round = buffer.round
  806. data.op = op
  807. data.attrs = {}
  808. if buffer.attrs then
  809. for k,v in pairs(buffer.attrs) do
  810. if v ~= 0 then
  811. data.attrs[k] = data.attrs[k] or 0
  812. data.attrs[k] = data.attrs[k] + v
  813. end
  814. end
  815. end
  816. data.pos = obj.pos
  817. data.hpNow = obj.hp
  818. frameBufferList[#frameBufferList + 1] = data
  819. end
  820. function addSaySkill(obj,skillConfig)
  821. if skillConfig.contentType == 0 then
  822. return
  823. end
  824. if obj.pos > CombatDefine.COMBAT_HERO_ALL_CNT then
  825. return
  826. end
  827. frameSayList[#frameSayList + 1] = {obj.pos,skillConfig.id,skillConfig.contentType}
  828. end
  829. function addRevice(attackPos, obj, bufferID, skillID)
  830. frameReviceList[#frameReviceList + 1] = {obj.pos, attackPos, bufferID, skillID}
  831. end
  832. function afterRevice()
  833. if #frameReviceList > 0 then
  834. for k, v in ipairs(frameReviceList) do
  835. local obj = objList[v[1]]
  836. if obj then
  837. addFrame()
  838. CombatBuff.reviceObj(v[2], obj, v[3], v[4])
  839. end
  840. end
  841. Util.initTable(frameReviceList)
  842. if #frameBufferList > 0 or #frameSayList > 0 then
  843. mergeFrameBuffer()
  844. for k,v in ipairs(frameBufferList) do
  845. setBufferList(v)
  846. end
  847. for _,v in ipairs(frameSayList) do
  848. setSaySkill(v[1],v[2],v[3])
  849. end
  850. Util.initTable(frameBufferList)
  851. Util.initTable(frameSayList)
  852. end
  853. end
  854. end
  855. function addBeSkillUse(obj,attackerPos,skillID)
  856. beSkillUseList[obj.pos] = beSkillUseList[obj.pos] or {}
  857. beSkillUseList[obj.pos][attackerPos] = beSkillUseList[obj.pos][attackerPos] or {}
  858. beSkillUseList[obj.pos][attackerPos][skillID] = beSkillUseList[obj.pos][attackerPos][skillID] or 0
  859. beSkillUseList[obj.pos][attackerPos][skillID] = beSkillUseList[obj.pos][attackerPos][skillID] + 1
  860. end
  861. function getBeSkillUse(obj,attackerPos,skillID)
  862. return beSkillUseList[obj.pos] and beSkillUseList[obj.pos][attackerPos] and beSkillUseList[obj.pos][attackerPos][skillID] or 0
  863. end
  864. function addBeSkillPosUse(pos,skillID)
  865. beSkillPosUseList[pos] = beSkillPosUseList[pos] or {}
  866. beSkillPosUseList[pos][skillID] = beSkillPosUseList[pos][skillID] or 0
  867. beSkillPosUseList[pos][skillID] = beSkillPosUseList[pos][skillID] + 1
  868. end
  869. function getBeSkillPosUse(pos,skillID)
  870. return beSkillPosUseList[pos] and beSkillPosUseList[pos][skillID]
  871. end
  872. function getBeSkillSideUse(pos,skillID)
  873. local side
  874. if pos <= CombatDefine.COMBAT_HERO_CNT then
  875. side = CombatDefine.ATTACK_SIDE
  876. elseif pos <= CombatDefine.COMBAT_HERO_ALL_CNT then
  877. side = CombatDefine.DEFEND_SIDE
  878. else
  879. return
  880. end
  881. local skillCnt = 0
  882. for _,v in ipairs(CombatDefine.SIDE2POS[side]) do
  883. if v ~= pos and beSkillPosUseList[v] and beSkillPosUseList[v][skillID] then
  884. skillCnt = skillCnt + beSkillPosUseList[v][skillID]
  885. end
  886. end
  887. return skillCnt
  888. end
  889. function setObjResult(pos,value)
  890. local obj
  891. if pos <= CombatDefine.COMBAT_HERO_ALL_CNT then
  892. obj = objList[pos]
  893. elseif pos == CombatDefine.PET_ATKPOS then
  894. obj = helpList[pos]
  895. elseif pos == CombatDefine.PET_DEFPOS then
  896. obj = helpList[pos]
  897. end
  898. if not obj then
  899. return
  900. end
  901. if value > 0 then
  902. obj.result[2] = obj.result[2] + value
  903. elseif value < 0 then
  904. obj.result[1] = obj.result[1] - value
  905. if obj.side == CombatDefine.ATTACK_SIDE then
  906. totalHurt = totalHurt - value
  907. end
  908. end
  909. end
  910. function fanji()
  911. isFanji = true
  912. for i = 1,#fanjiList do
  913. local fanjiData = fanjiList[i]
  914. if fanjiData[1].hp > 0 then
  915. Skill.use(fanjiData[1],fanjiData[2],fanjiData[3])
  916. end
  917. end
  918. end
  919. function comboAgain(obj, type, hurtRate, comboSkillID, skip)
  920. if not obj or obj.hp <=0 then return end
  921. local stop = CombatBuff.isStop(obj)
  922. --新增条件,如果控制buff只有chanrao也能继续执行
  923. if stop and skip == nil and not CombatBuff.IsJustHaveChanraoBuff(obj) then return end
  924. local skillID = comboSkillID or getSkillID(obj)
  925. if skillID then
  926. comboType = type
  927. comboHurtRate = hurtRate
  928. Skill.use(obj, skillID)
  929. comboType = 0
  930. end
  931. end
  932. function combo()
  933. local comboSkillID
  934. for k,v in pairs(comboPosList) do
  935. comboPosList[k] = nil
  936. end
  937. for k, v in ipairs(comboList) do
  938. --for i = 1,#comboList do
  939. local obj = v[1]
  940. if obj.hp > 0 then
  941. local type = v[2] or 0
  942. local hurtRate = v[3] or 10000
  943. comboSkillID = nil
  944. local argSkill = v[4] or 0
  945. if argSkill ~= 0 then
  946. comboSkillID = argSkill
  947. else
  948. if type == 2 then
  949. comboSkillID = getNormalSkill(obj)
  950. end
  951. end
  952. local t = v[5] or 1
  953. local skip = v[6]
  954. if not (comboPosList[obj.pos] and comboPosList[obj.pos][t] and comboPosList[obj.pos][0] >= 3) then --避免组合技能触发多次连击,比如10813
  955. comboAgain(obj, type, hurtRate, comboSkillID, skip)
  956. comboPosList[obj.pos] = comboPosList[obj.pos] or {}
  957. comboPosList[obj.pos][0] = comboPosList[obj.pos][0] or 0
  958. comboPosList[obj.pos][0] = comboPosList[obj.pos][0] + 1
  959. comboPosList[obj.pos][t] = 1
  960. end
  961. end
  962. end
  963. end
  964. function setObjBearResult(obj, value)
  965. if not obj then
  966. return
  967. end
  968. if value < 0 then
  969. obj.result[3] = obj.result[3] - value
  970. end
  971. end
  972. function addObjResultOut(obj, round)
  973. if not obj then
  974. return
  975. end
  976. if obj.pos > CombatDefine.COMBAT_HERO_ALL_CNT then
  977. obj.result[4] = obj.result[4] + 1
  978. else
  979. obj.result[4] = round
  980. end
  981. end
  982. --即时添加buffer帧
  983. function instantFrameBuffer(obj,skillID)
  984. if #frameBufferList > 0 or #frameSayList > 0 then
  985. addFrame()
  986. if obj and skillID then
  987. setSkillID(obj, skillID)
  988. end
  989. mergeFrameBuffer()
  990. for k,v in ipairs(frameBufferList) do
  991. setBufferList(v)
  992. end
  993. for _,v in ipairs(frameSayList) do
  994. setSaySkill(v[1],v[2],v[3])
  995. end
  996. Util.initTable(frameBufferList)
  997. Util.initTable(frameSayList)
  998. end
  999. end