CombatImpl.lua 31 KB

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