CombatImpl.lua 32 KB

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