CombatImpl.lua 30 KB

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