CombatImpl.lua 32 KB

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