BattleLogic.lua 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. BattleLogic = {}
  2. local floor = math.floor
  3. local min = math.min
  4. -- local objList = BattleDictionary.New()
  5. local removeObjList = BattleList.New()
  6. local MaxRound = 20
  7. local CurRound = 0
  8. local CurCamp = 0
  9. -- local CurSkillPos = {}
  10. local PosList = {}
  11. local PosIsAttackRecord = {} --< 记录当前回合是否attack过
  12. local CurPosition = -1 --< 当前位置
  13. local MoveTimes = 0 --< 行动次数
  14. local curFrame
  15. BattleLogic.Type = 0 --1 故事副本 2 地图探索 3 竞技场 4 秘境boss 5 解锁秘境 6 公会战 7 血战 8 兽潮 9巅峰战
  16. BattleLogic.IsEnd = false
  17. BattleLogic.Result = -1
  18. BattleLogic.Event = BattleEvent.New()
  19. BattleLogic.BuffMgr = BuffManager.New()
  20. local _IsDebug
  21. local fightData
  22. local record
  23. local optionRecord
  24. --是否开启战斗日志
  25. BattleLogic.IsOpenBattleRecord = false
  26. --逻辑帧频
  27. BattleLogic.GameFrameRate = 30
  28. BattleLogic.GameDeltaTime = 1 / BattleLogic.GameFrameRate
  29. --总波次
  30. BattleLogic.TotalOrder = 0
  31. --当前波次
  32. BattleLogic.CurOrder = 0
  33. BattleLogic.SingleRoundStatus = {
  34. RoundBegin = 1,
  35. RoundEnd = 2,
  36. Rounding = 3
  37. }
  38. local actionPool = BattleObjectPool.New(function ()
  39. return { 0, 0 }
  40. end)
  41. local skillPool = BattleObjectPool.New(function ()
  42. return Skill:New()
  43. end)
  44. local tbActionList = BattleList.New()
  45. local rolePool = BattleObjectPool.New(function ()
  46. return RoleLogic.New()
  47. end)
  48. function BattleLogic.Init(data, optionData, maxRound)
  49. if BattleLogic.IsOpenBattleRecord then
  50. record = {}
  51. end
  52. fightData = data
  53. if optionData then
  54. optionRecord = optionData
  55. else
  56. optionRecord = {}
  57. end
  58. BattleLogic.CurOrder = 0
  59. BattleLogic.TotalOrder = #data.enemyData
  60. BattleLogic.Clear()
  61. curFrame = 0
  62. CurRound = 0
  63. MaxRound = maxRound or 20
  64. _IsDebug = false
  65. BattleLogic.Event:ClearEvent()
  66. BattleLogic.BuffMgr:Init()
  67. BattleLogic.IsEnd = false
  68. BattleLogic.Result = -1
  69. RoleManager.Init()
  70. SkillManager.Init()
  71. OutDataManager.Init(fightData)
  72. PassiveManager.Init()
  73. BattleLogManager.Init(fightData)
  74. PosIsAttackRecord = {}
  75. end
  76. -- 检测先手阵营
  77. function BattleLogic.CheckFirstCamp()
  78. -- 默认我方先手
  79. BattleLogic.FirstCamp = 0
  80. -- 数据不存在时,兼容老战斗数据
  81. if not fightData.playerData.firstCamp and not fightData.enemyData[BattleLogic.CurOrder].firstCamp then
  82. return
  83. end
  84. -- 敌方先手
  85. if fightData.playerData.firstCamp == 0 and fightData.enemyData[BattleLogic.CurOrder].firstCamp == 1 then
  86. BattleLogic.FirstCamp = 1
  87. end
  88. end
  89. function BattleLogic.StartOrder()
  90. --
  91. BattleLogic.CurOrder = BattleLogic.CurOrder + 1
  92. if BattleLogic.CurOrder == 1 then
  93. local playerData = fightData.playerData
  94. local enemyData = fightData.enemyData[BattleLogic.CurOrder]
  95. LogYellow("### 数量")
  96. -- WYLog(#playerData)
  97. -- WYLog(#enemyData)
  98. WYLog(#playerData)
  99. for i=1, #playerData do
  100. -- WYLog("player" .. tostring(i))
  101. RoleManager.AddRole(playerData[i], playerData[i].position)
  102. end
  103. for i=1, #enemyData do
  104. RoleManager.AddRole(enemyData[i], enemyData[i].position)
  105. end
  106. --> unit
  107. for _, unitData in pairs(fightData.fightUnitData) do
  108. FightUnitManager.AddUnit(unitData)
  109. end
  110. else
  111. LogYellow("### StartOrder")
  112. RoleManager.ClearEnemy()
  113. local orderList = fightData.enemyData[BattleLogic.CurOrder]
  114. for i=1, #orderList do
  115. RoleManager.AddRole(orderList[i], orderList[i].position)
  116. end
  117. LogYellow("### StartOrder")
  118. LogYellow(#orderList)
  119. end
  120. -- 检测先后手
  121. BattleLogic.CheckFirstCamp()
  122. -- 开始战斗,延时一帧执行,避免战斗还没开始就释放了技能
  123. BattleLogic.TurnRoundNextFrame()
  124. MoveTimes = 0
  125. end
  126. -- 获取当前轮数
  127. function BattleLogic.GetCurRound()
  128. -- body
  129. return CurRound, MaxRound
  130. end
  131. -- 获取当前轮次信息
  132. function BattleLogic.GetCurTurn()
  133. -- body
  134. return CurCamp, CurPosition
  135. end
  136. -- 设置是否是debug
  137. function BattleLogic.SetIsDebug(isDebug)
  138. _IsDebug = isDebug
  139. end
  140. function BattleLogic.GetIsDebug()
  141. return _IsDebug
  142. end
  143. -- 下一帧开始下一轮
  144. local _TurnRoundFlag = 0
  145. function BattleLogic.TurnRoundNextFrame()
  146. _TurnRoundFlag = 0
  147. end
  148. -- 检测是否要轮转
  149. function BattleLogic.CheckTurnRound()
  150. if _TurnRoundFlag == 2 then
  151. return
  152. end
  153. _TurnRoundFlag = _TurnRoundFlag + 1
  154. if _TurnRoundFlag == 2 then
  155. if BattleLogic.CheckSingleRoundStatus() == BattleLogic.SingleRoundStatus.RoundBegin then
  156. CurRound = CurRound + 1
  157. BattleLogic.RoundBegin(function()
  158. BattleLogic.TurnRound()
  159. end)
  160. elseif BattleLogic.CheckSingleRoundStatus() == BattleLogic.SingleRoundStatus.RoundEnd then
  161. BattleLogic.RoundEnd(function()
  162. BattleLogic.TurnRoundNextFrame()
  163. end)
  164. else
  165. BattleLogic.TurnRound()
  166. end
  167. end
  168. end
  169. --> 检测单回合首末 返回两种状态
  170. function BattleLogic.CheckSingleRoundStatus()
  171. local isHave = false
  172. local nullNum = 0
  173. for pos = 1, 18 do
  174. while true
  175. do
  176. if PosIsAttackRecord[pos] then
  177. break
  178. else
  179. nullNum = nullNum + 1
  180. end
  181. local role = RoleManager.GetRoleByPos(pos)
  182. if role and not role:IsRealDead() then
  183. isHave = true
  184. end
  185. break
  186. end
  187. end
  188. if nullNum == 18 then
  189. return BattleLogic.SingleRoundStatus.RoundBegin
  190. else
  191. if isHave then
  192. else
  193. return BattleLogic.SingleRoundStatus.RoundEnd
  194. end
  195. end
  196. return BattleLogic.SingleRoundStatus.Rounding
  197. end
  198. --> 单回合开始
  199. function BattleLogic.RoundBegin(func)
  200. LogGreen(Language[10228]..CurRound)
  201. WYLog("### RoundBegin")
  202. BattleLogManager.Log(
  203. "Round Change",
  204. "round", CurRound
  205. )
  206. -- 轮数变化
  207. BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoundChange, CurRound)
  208. BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
  209. BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
  210. BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
  211. BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
  212. BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
  213. local processQueue = {{FightUnitType.UnitSupport, 0}, {FightUnitType.UnitSupport, 1}}
  214. local index = 1
  215. local next = nil
  216. local processFunc = nil
  217. next = function()
  218. if index == #processQueue then
  219. func()
  220. else
  221. index = index + 1
  222. processFunc()
  223. end
  224. end
  225. processFunc = function()
  226. local unit = FightUnitManager.GetUnit(processQueue[index][1], processQueue[index][2])
  227. if unit then
  228. local haveSkill = unit:CastSkill(function()
  229. next()
  230. end)
  231. if not haveSkill then
  232. next()
  233. end
  234. else
  235. next()
  236. end
  237. end
  238. processFunc()
  239. -- local unit = FightUnitManager.GetUnit(FightUnitType.UnitSupport, 0)
  240. -- if unit then
  241. -- local haveSkill = unit:CastSkill(function()
  242. -- func()
  243. -- end)
  244. -- if not haveSkill then
  245. -- func()
  246. -- end
  247. -- else
  248. -- func()
  249. -- end
  250. -- func()
  251. -- WYLog("RoundBegin延时触发继续")
  252. -- BattleLogic.WaitForTrigger(5, function()
  253. -- func()
  254. -- end)
  255. end
  256. --> 单回合结束
  257. function BattleLogic.RoundEnd(func)
  258. WYLog("### RoundEnd")
  259. PosIsAttackRecord = {}
  260. WYLog("RoundEnd延时触发继续")
  261. BattleLogic.WaitForTrigger(2, function()
  262. func()
  263. end)
  264. end
  265. -- 开始轮转
  266. -- debugTurn 用于判断是否是debug轮转的参数
  267. function BattleLogic.TurnRound(debugTurn)
  268. if BattleLogic.GetIsDebug() and not debugTurn then
  269. LogGreen(Language[10227])
  270. LogBlue("-------------")
  271. BattleLogic.Event:DispatchEvent(BattleEventName.DebugStop)
  272. return
  273. end
  274. LogYellow("BattleLogic.TurnRound")
  275. --> 计算速度最大的执行技能
  276. local maxSpeed = -1
  277. local maxSpeedPos = -1
  278. local SkillRole = nil
  279. for pos = 1, 18 do
  280. while true
  281. do
  282. if PosIsAttackRecord[pos] then
  283. break
  284. end
  285. local role = RoleManager.GetRoleByPos(pos)
  286. if role and not role:IsRealDead() then
  287. local speed = role:GetRoleData(RoleDataName.Speed)
  288. if speed > maxSpeed then
  289. maxSpeed = speed
  290. maxSpeedPos = pos
  291. SkillRole = role
  292. end
  293. end
  294. break
  295. end
  296. end
  297. local isFindRole = false
  298. if maxSpeedPos ~= -1 then
  299. PosIsAttackRecord[maxSpeedPos] = true
  300. isFindRole = true
  301. end
  302. if not isFindRole then
  303. LogYellow("Not Find Role")
  304. BattleLogic.TurnRoundNextFrame()
  305. end
  306. --> 首回合 or 回合更新
  307. -- if CurRound == 0 or not isFindRole then
  308. -- CurRound = CurRound + 1
  309. -- LogGreen(Language[10228]..CurRound)
  310. -- BattleLogManager.Log(
  311. -- "Round Change",
  312. -- "round", CurRound
  313. -- )
  314. -- -- 轮数变化
  315. -- BattleLogic.Event:DispatchEvent(BattleEventName.BattleRoundChange, CurRound)
  316. -- BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
  317. -- BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
  318. -- BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
  319. -- BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
  320. -- BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
  321. -- if not isFindRole then
  322. -- PosIsAttackRecord = {}
  323. -- BattleLogic.TurnRoundNextFrame()
  324. -- return
  325. -- end
  326. -- else
  327. -- -- 切换阵营
  328. -- --CurCamp = (CurCamp + 1) % 2
  329. -- end
  330. CurCamp = SkillRole.camp
  331. CurPosition = SkillRole.position
  332. BattleLogManager.Log(
  333. "Position Change",
  334. "camp", CurCamp,
  335. "position", CurPosition
  336. )
  337. -- LogGreen(Language[10229]..CurCamp)
  338. -- --
  339. -- BattleLogManager.Log(
  340. -- "Camp Change",
  341. -- "camp", CurCamp
  342. -- )
  343. -- -- 当前阵营下一释放技能的位置
  344. -- local cpos = CurSkillPos[CurCamp] + 1
  345. -- -- 找到下一个释放技能的人
  346. -- local SkillRole
  347. -- for p = cpos, 9 do
  348. -- -- 保存当前位置
  349. -- CurSkillPos[CurCamp] = p
  350. -- -- 自己阵营中的位置 + 自己阵营的ID * 9 = 自己在PosList中的位置
  351. -- local role = RoleManager.GetRole(CurCamp, p) --PosList[p + (CurCamp * 9)]
  352. -- if role and not role:IsRealDead() then
  353. -- SkillRole = role
  354. -- break
  355. -- end
  356. -- -- 如果当前位置不能释放技能也需要走buff轮转
  357. -- BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
  358. -- BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
  359. -- BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
  360. -- BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
  361. -- BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
  362. -- end
  363. -- 如果找不到下一个人,直接交换阵营
  364. -- if not SkillRole then
  365. -- LogGreen(Language[10230])
  366. -- BattleLogManager.Log( "No Skill Position" )
  367. -- BattleLogic.TurnRoundNextFrame()
  368. -- return
  369. -- end
  370. -- LogGreen(Language[10231]..CurSkillPos[CurCamp])
  371. -- --
  372. -- BattleLogManager.Log(
  373. -- "Position Change",
  374. -- "position", CurSkillPos[CurCamp]
  375. -- )
  376. -- buff计算
  377. -- BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
  378. -- BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
  379. -- 如果角色无法释放技能
  380. if not SkillRole:IsAvailable() -- 角色不能释放技能
  381. or (SkillRole:IsDead() and not BattleLogic.BuffMgr:HasBuff(SkillRole,BuffName.NoDead)) --将死但没有不死buff
  382. then
  383. -- BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
  384. -- BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
  385. -- BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
  386. BattleLogic.TurnRoundNextFrame() -- 下一个
  387. return
  388. end
  389. -- 行动
  390. SkillRole.Event:DispatchEvent(BattleEventName.RoleTurnStart, SkillRole) -- 开始行动
  391. BattleLogic.Event:DispatchEvent(BattleEventName.RoleTurnStart, SkillRole) -- 开始行动
  392. -- BattleLogic.BuffMgr:TurnUpdate(1) -- 计算恢复血量
  393. -- BattleLogic.BuffMgr:TurnUpdate(2) -- 计算持续伤害(除去流血)
  394. -- 释放技能后,递归交换阵营
  395. MoveTimes = MoveTimes + 1
  396. local haveSkill = SkillRole:CastSkill(function()
  397. -- BattleLogic.BuffMgr:TurnUpdate(3) -- 计算持续伤害(流血)
  398. -- BattleLogic.BuffMgr:TurnUpdate(4) -- 计算其他buff
  399. -- BattleLogic.BuffMgr:PassUpdate() -- 计算buff轮数
  400. SkillRole.Event:DispatchEvent(BattleEventName.RoleTurnEnd, SkillRole) -- 行动结束
  401. BattleLogic.Event:DispatchEvent(BattleEventName.RoleTurnEnd, SkillRole) -- 开始行动
  402. BattleLogic.TurnRoundNextFrame()
  403. end)
  404. --> 无技能时 跳过死循环问题
  405. if not haveSkill then
  406. BattleLogic.TurnRoundNextFrame()
  407. end
  408. end
  409. function BattleLogic.WaitForTrigger(delayTime, action)
  410. delayTime = BattleUtil.ErrorCorrection(delayTime)
  411. local delayFrame = floor(delayTime * BattleLogic.GameFrameRate + 0.5)
  412. if delayFrame == 0 then --0延迟的回调直接调用
  413. action()
  414. return
  415. end
  416. local item = actionPool:Get()
  417. item[1] = curFrame + delayFrame
  418. item[2] = action
  419. tbActionList:Add(item)
  420. end
  421. function BattleLogic.CurFrame()
  422. return curFrame
  423. end
  424. function BattleLogic.Update()
  425. curFrame = curFrame + 1
  426. -- WYLog(curFrame)
  427. local roleResult = RoleManager.GetResult()
  428. if roleResult == 0 then
  429. BattleLogic.BattleEnd(0)
  430. return
  431. end
  432. if CurRound > MaxRound then
  433. BattleLogic.BattleEnd(0)
  434. return
  435. end
  436. if roleResult == 1 then
  437. if BattleLogic.CurOrder == BattleLogic.TotalOrder then
  438. BattleLogic.BattleEnd(1)
  439. else
  440. BattleLogic.Event:DispatchEvent(BattleEventName.BattleOrderChange, BattleLogic.CurOrder + 1)
  441. LogYellow("Update StartOrder")
  442. BattleLogic.StartOrder()
  443. end
  444. end
  445. -- 检测帧事件(技能命中,伤害计算,buff生成)
  446. local index = 1
  447. while index <= tbActionList.size do
  448. local action = tbActionList.buffer[index]
  449. if action[1] <= curFrame then
  450. action[2]()
  451. actionPool:Put(action)
  452. tbActionList:Remove(index)
  453. else
  454. index = index + 1
  455. end
  456. end
  457. -- 检测buff
  458. BattleLogic.BuffMgr:Update()
  459. ---
  460. -- 检测角色状态
  461. RoleManager.Update()
  462. -- 检测死亡
  463. if RoleManager.CheckDead() then -- 单独用一帧执行死亡
  464. return
  465. end
  466. -- 检测复活
  467. if RoleManager.CheckRelive() then -- 单独用一帧执行复活
  468. return
  469. end
  470. -- 检测技能释放
  471. -- 检测轮转
  472. BattleLogic.CheckTurnRound()
  473. -- 技能
  474. SkillManager.Update()
  475. end
  476. function BattleLogic.GetMoveTimes()
  477. return MoveTimes
  478. end
  479. -- 战斗结束
  480. function BattleLogic.BattleEnd(result)
  481. --
  482. LogYellow("### 战斗 逻辑结束")
  483. WYLog(result)
  484. BattleLogic.Event:DispatchEvent(BattleEventName.BeforeBattleEnd, result)
  485. --
  486. BattleLogic.IsEnd = true
  487. BattleLogic.Result = result
  488. BattleLogic.Event:DispatchEvent(BattleEventName.BattleEnd, result)
  489. -- 战斗日志写入
  490. if not BattleLogic.GetIsDebug() then
  491. BattleLogManager.WriteFile()
  492. end
  493. end
  494. --
  495. function BattleLogic.Clear()
  496. -- 清空角色
  497. RoleManager.Clear()
  498. -- 清空事件
  499. while tbActionList.size > 0 do
  500. actionPool:Put(tbActionList.buffer[tbActionList.size])
  501. tbActionList:Remove(tbActionList.size)
  502. end
  503. end