CombatImpl.lua 31 KB

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