BattleMain.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. -- linux
  2. package.path = package.path ..';../luafight/?.lua';
  3. require("Modules.Battle.Logic.Misc.BattleDefine")
  4. require("Modules.Battle.Logic.Misc.BattleUtil")
  5. require("Modules.Battle.Logic.Misc.BattleQueue")
  6. require("Modules.Battle.Logic.Misc.BattleDictionary")
  7. require("Modules.Battle.Logic.Misc.BattleList")
  8. require("Modules.Battle.Logic.Misc.BattleObjectPool")
  9. require("Modules.Battle.Logic.Base.BattleEvent")
  10. require("Modules.Battle.Logic.Base.Random")
  11. require("Modules.Battle.Logic.Base.RoleData")
  12. require("Modules.Battle.Logic.Base.Buff")
  13. require("Modules.Battle.Logic.Base.Skill")
  14. require("Modules.Battle.Logic.Base.Passivity")
  15. require("Modules.Battle.Logic.BattleLogic")
  16. require("Modules.Battle.Logic.RoleLogic")
  17. local BattleMain = {}
  18. local BattleLogic = BattleLogic
  19. local Random = Random
  20. local BattleRecord
  21. local _BattleErrorCache = {}
  22. local _BattleErrorIndex = 0
  23. local _seed
  24. local _type
  25. local _maxRound
  26. local _fightData
  27. local _optionData
  28. local function pairsByKeys(t)
  29. local a = {}
  30. for n in pairs(t) do
  31. if n then
  32. a[#a+1] = n
  33. end
  34. end
  35. table.sort(a, function( op1, op2 )
  36. local type1, type2 = type(op1), type(op2)
  37. local num1, num2 = tonumber(op1), tonumber(op2)
  38. if ( num1 ~= nil) and (num2 ~= nil) then
  39. return num1 < num2
  40. elseif type1 ~= type2 then
  41. return type1 < type2
  42. elseif type1 == "string" then
  43. return op1 < op2
  44. elseif type1 == "boolean" then
  45. return op1
  46. -- 以上处理: number, string, boolean
  47. else -- 处理剩下的: function, table, thread, userdata
  48. return tostring(op1) < tostring(op2) -- tostring后比较字符串
  49. end
  50. end)
  51. local i = 0
  52. return function()
  53. i = i + 1
  54. return a[i], t[a[i]]
  55. end
  56. end
  57. local function PrintTable(tb)
  58. local indent_str = "{"
  59. local count = 0
  60. for k,v in pairs(tb) do
  61. count = count + 1
  62. end
  63. for k=1, #tb do
  64. local v = tb[k]
  65. if type(v) == "table" then
  66. indent_str = indent_str .. PrintTable(v)
  67. else
  68. indent_str = indent_str .. tostring(v)
  69. end
  70. if k < count then
  71. indent_str = indent_str..","
  72. end
  73. end
  74. local index = 0
  75. for k,v in pairsByKeys(tb) do
  76. index = index + 1
  77. if type(k) ~= "number" then
  78. if type(v) == "table" then
  79. indent_str = string.format("%s%s=%s", indent_str, tostring(k), PrintTable(v))
  80. else
  81. indent_str = string.format("%s%s=%s", indent_str, tostring(k), tostring(v))
  82. end
  83. if index < count then
  84. indent_str = indent_str .. ","
  85. end
  86. end
  87. end
  88. indent_str = indent_str .. "}"
  89. return indent_str
  90. end
  91. local function generateRecordFile()
  92. local time = string.format("%d-%d-%d-%d-%d-%d",
  93. os.date("%Y"),
  94. os.date("%m"),
  95. os.date("%d"),
  96. os.date("%H"),
  97. os.date("%M"),
  98. os.date("%S"))
  99. local file = io.open("luafight/BattleRecord/"..time..".txt", "a")
  100. local record = BattleLogic.GetRecord()
  101. for i=1, #record do
  102. file:write(record[i].."\n")
  103. end
  104. io.close(file)
  105. end
  106. local function addBattleData()
  107. local str = ""
  108. str = str.."seed:\n"..tostring(_seed).."\n"
  109. str = str.."type:\n"..tostring(_type).."\n"
  110. str = str.."fightData:\n"..PrintTable(_fightData).."\n"
  111. str = str.."optionData:\n"..PrintTable(_optionData).."\n"
  112. _BattleErrorIndex = _BattleErrorIndex + 1
  113. if _BattleErrorIndex > 5 then
  114. _BattleErrorIndex = 1
  115. end
  116. _BattleErrorCache[_BattleErrorIndex] = str
  117. end
  118. local function AddRecord(fightData)
  119. BattleRecord = {}
  120. BattleLogic.Event:AddEvent(BattleEventName.AddRole, function (role)
  121. local record = {}
  122. record.uid = role.uid
  123. record.camp = role.camp
  124. record.damage = 0
  125. role.Event:AddEvent(BattleEventName.RoleDamage, function (defRole, damage, bCrit, finalDmg)
  126. record.damage = record.damage + finalDmg
  127. end)
  128. BattleRecord[role.uid] = record
  129. end)
  130. for i=1, #fightData.playerData.teamSkill do
  131. local teamCaster = BattleLogic.GetTeamSkillCaster(0)
  132. local teamSkill = fightData.playerData.teamSkill[i]
  133. local teamType = math.floor(teamSkill[1] / 100)
  134. local str = "order:1".."camp:"..teamCaster.camp.." team"..teamSkill[1]
  135. local record = {}
  136. record.uid = str
  137. record.camp = teamCaster.camp
  138. record.damage = 0
  139. record.order = 1
  140. local curSkill
  141. teamCaster.Event:AddEvent(BattleEventName.SkillCast, function (skill)
  142. if skill.owner.camp == record.camp then
  143. curSkill = skill
  144. end
  145. end)
  146. teamCaster.Event:AddEvent(BattleEventName.RoleDamage, function (defRole, damage, bCrit, finalDmg)
  147. if curSkill and curSkill.teamSkillType == teamType then
  148. record.damage = record.damage + finalDmg
  149. end
  150. end)
  151. BattleRecord[str] = record
  152. end
  153. for i=1, #fightData.enemyData do
  154. for j=1, #fightData.enemyData[i].teamSkill do
  155. local teamCaster = BattleLogic.GetTeamSkillCaster(1)
  156. local teamSkill = fightData.enemyData[i].teamSkill[j]
  157. local teamType = math.floor(teamSkill[1] / 100)
  158. local str = "order:"..i.."camp:"..teamCaster.camp.." team"..teamSkill[1]
  159. local record = {}
  160. record.uid = str
  161. record.camp = teamCaster.camp
  162. record.damage = 0
  163. record.order = i
  164. local curSkill
  165. teamCaster.Event:AddEvent(BattleEventName.SkillCast, function (skill)
  166. if skill.owner.camp == record.camp then
  167. curSkill = skill
  168. end
  169. end)
  170. teamCaster.Event:AddEvent(BattleEventName.RoleDamage, function (defRole, damage, bCrit, finalDmg)
  171. if curSkill and curSkill.teamSkillType == teamType and record.order == BattleLogic.CurOrder then
  172. record.damage = record.damage + finalDmg
  173. end
  174. end)
  175. BattleRecord[str] = record
  176. end
  177. end
  178. end
  179. function BattleMain.Execute(args, fightData, optionData)
  180. _seed = args.seed
  181. _type = args.type
  182. _maxRound = args.maxRound
  183. _fightData = fightData
  184. _optionData = optionData or {}
  185. --该开关用于输出战斗过程中的日志,用于验证前后端是否出现战斗不同步
  186. BattleLogic.IsOpenBattleRecord = false
  187. local isError = false
  188. local errorCache
  189. if xpcall(function ()
  190. Random.SetSeed(args.seed)
  191. BattleLogic.Init(fightData, optionData, _maxRound)
  192. BattleLogic.Type = _type
  193. if _type == 9 or _type == 10 or _type == 11 then
  194. AddRecord(fightData)
  195. end
  196. BattleLogic.StartOrder()
  197. while not BattleLogic.IsEnd do
  198. BattleLogic.Update()
  199. end
  200. end, function (err)
  201. isError = true
  202. errorCache = "error:\n"..debug.traceback(err).."\n"
  203. end) then
  204. local resultList = {}
  205. if BattleLogic.Result == 1 then --胜利记录我方剩余血量
  206. local arr = RoleManager.Query(function (r) return r.camp == 0 end, true)
  207. for i=1, #arr do
  208. resultList[i] = arr[i]:GetRoleData(RoleDataName.Hp)
  209. end
  210. elseif BattleLogic.Result == 0 then --失败记录敌方剩余血量
  211. local arr = RoleManager.Query(function (r) return r.camp == 1 end, true)
  212. for i=1, #arr do
  213. resultList[i] = arr[i]:GetRoleData(RoleDataName.Hp)
  214. end
  215. end
  216. if BattleLogic.IsOpenBattleRecord then
  217. generateRecordFile()
  218. end
  219. -- print -----------------------------------------
  220. --for i=1, #resultList do
  221. -- print("hp:"..resultList[i])
  222. --end
  223. --print("最终运行帧数:"..BattleLogic.CurFrame())
  224. local curRound, maxRound = BattleLogic.GetCurRound()
  225. if curRound > maxRound and _type == 9 then
  226. local playerDamage=0
  227. local enemyDamage=0
  228. for k,v in pairs(BattleRecord)do
  229. if v.camp == 0 then
  230. playerDamage = playerDamage + v.damage
  231. else
  232. enemyDamage = enemyDamage + v.damage
  233. end
  234. end
  235. resultList.result = playerDamage > enemyDamage and 1 or 0
  236. else
  237. resultList.result = BattleLogic.Result
  238. end
  239. if _type == 10 or _type == 11 then -- 公会boss和车迟斗法boss返回伤害值
  240. local playerDamage=0
  241. for k,v in pairs(BattleRecord)do
  242. if v.camp == 0 then
  243. playerDamage = playerDamage + v.damage
  244. end
  245. end
  246. resultList.duration = playerDamage --TODO:公会boss的持续时间传递的是我方总伤害值
  247. else
  248. resultList.duration = BattleLogic.CurFrame() / BattleLogic.GameFrameRate
  249. end
  250. addBattleData()
  251. return resultList
  252. end
  253. if isError then --捕获异常,并输出错误日志
  254. local time = string.format("%d-%d-%d-%d-%d-%d",
  255. os.date("%Y"),
  256. os.date("%m"),
  257. os.date("%d"),
  258. os.date("%H"),
  259. os.date("%M"),
  260. os.date("%S"))
  261. local file = io.open("luafight/LogError/"..time..".txt", "a")
  262. file:write(errorCache)
  263. file:write("seed:\n"..tostring(args.seed).."\n")
  264. file:write("type:\n"..tostring(args.type).."\n")
  265. file:write("fightData:\n"..PrintTable(_fightData).."\n")
  266. file:write("optionData:\n"..PrintTable(_optionData).."\n")
  267. file:write("\n\nlast com.ljsd.battle data:\n")
  268. for i=1, #_BattleErrorCache do
  269. file:write(string.format("\nindex:%d\n", i))
  270. file:write(_BattleErrorCache[i])
  271. end
  272. io.close(file)
  273. end
  274. return { result = -1 }
  275. end
  276. return BattleMain