CombatImpl.lua 33 KB

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