AreaBattleCS.lua 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  1. -- 战区争霸(跨服)
  2. local InnerMsg = require("core.InnerMsg")
  3. local Log = require("common.Log")
  4. local Timer = require("core.Timer")
  5. local Util = require("common.Util")
  6. local MiddleManager = require("middle.MiddleManager")
  7. local AreaBattleDB = require("areaBattle.AreaBattleDB")
  8. local AreaBattleDefine = require("areaBattle.AreaBattleDefine")
  9. local CombatVideo = require("combat.CombatVideo")
  10. local CombatDefine = require("combat.CombatDefine")
  11. local CombatLogicCS = require("combat.CombatLogicCS")
  12. local BattleDataCS = require("battleDataManager.BattleDataCS")
  13. -- 当天处于星期几(星期六为7, 星期天为1)
  14. local wDay
  15. -- 玩家战斗数据缓存表
  16. local battleDataCache = {}
  17. -- 请求序列表, 用于向普通获取玩家战斗数据
  18. local requestArr = {}
  19. local function updateWDay()
  20. wDay = Util.getWeekDay()
  21. end
  22. local function getTodayStartTime()
  23. local now = os.time()
  24. return Util.getDayStartTime(now)
  25. end
  26. local function isOpen()
  27. if not wDay then
  28. updateWDay()
  29. end
  30. if not table.find(AreaBattleDefine.OPEN_WDAY_AREA, wDay) then
  31. return false
  32. end
  33. local now = os.time()
  34. local toDayStartTime = getTodayStartTime()
  35. if wDay == AreaBattleDefine.OPEN_WDAY_AREA[1] and now < (toDayStartTime + AreaBattleDefine.PREPARE_STATE_START_SEC) then
  36. return false
  37. end
  38. if wDay == AreaBattleDefine.OPEN_WDAY_AREA[2] and now > (toDayStartTime + AreaBattleDefine.END_STATE_START_SEC) then
  39. return false
  40. end
  41. return true
  42. end
  43. -- 参战服务器日志格式: "serverId1, serverId2,serverId3"
  44. -- 服务器匹配列表日志格式: "serverId1-serverId2-serverId3-serverId4", 从一个serverId开始, 按顺序每两个serverId匹配到一起战斗
  45. -- 参战服务器信息日志个数: serverId | 本服战胜次数| 本服战败次数 | 战胜玩家uuid-战胜玩家uui
  46. local function writeLog(logStr)
  47. Log.write(Log.LOGID_OSS_AREABATTLE_BATTLE, logStr)
  48. end
  49. -- 计算一个服的总战力
  50. local function calcSrvPower(playerArray)
  51. local power = 0
  52. for _, v in ipairs(playerArray or {}) do
  53. power = power + (v.power or 0)
  54. end
  55. return power
  56. end
  57. -- 获取战斗对象的区服Id, uuid
  58. local function getBattleObjInfo(matchIdx, battleIdx, objIdentity)
  59. local matchSrvArr = AreaBattleDB.GetMatchSrvArr()
  60. local matchData = matchSrvArr[matchIdx]
  61. if not matchData then
  62. return
  63. end
  64. local targetSrvId = matchData[objIdentity]
  65. if not targetSrvId then
  66. return
  67. end
  68. local serverList = AreaBattleDB.GetServerList()
  69. if not serverList[targetSrvId] then
  70. return
  71. end
  72. local srvPlayerArr = serverList[targetSrvId].playerInfoArr
  73. local playerInfo = srvPlayerArr[battleIdx]
  74. return targetSrvId, playerInfo and playerInfo.uuid
  75. end
  76. -- 进入新一轮的处理
  77. local function newRoundHandle()
  78. local stateDB = AreaBattleDB.GetState()
  79. -- 上一轮奖励没有发放, 在新一轮开始时, 先发奖
  80. if stateDB == AreaBattleDefine.STATE_AWARD then
  81. AwardPrizesHandle()
  82. end
  83. -- 清除录像数据
  84. CombatVideo.ClearOutVideoByCombatType(CombatVideo.VIDEOTYPE_AREABATTLE)
  85. -- 重置录像缓存
  86. AreaBattleDB.ResetVideoShowCache()
  87. -- 重置战区争霸数据
  88. AreaBattleDB.ResetData()
  89. -- 更新状态
  90. AreaBattleDB.UpdateState(AreaBattleDefine.STATE_PREPARE)
  91. -- 通知普通服
  92. NotifySrvJoin()
  93. -- 重置缓存数据
  94. battleDataCache = {}
  95. requestArr = {}
  96. end
  97. -- 服务器分组算法
  98. local function matchAlgorithm(serverArr, len)
  99. local usedTb = {}
  100. local pairTb = {}
  101. local function getNextUnuseIdx(nowIdx)
  102. for i=nowIdx, len do
  103. if not usedTb[i] then
  104. return i
  105. end
  106. end
  107. end
  108. local function checkRandIdx(startIdx, endIdx)
  109. local tbl= {}
  110. for i= startIdx, endIdx do
  111. if i <= len and not usedTb[i] then
  112. table.insert(tbl, i)
  113. end
  114. end
  115. return tbl
  116. end
  117. local currentIdx = 1
  118. while currentIdx <= len do
  119. currentIdx = getNextUnuseIdx(currentIdx)
  120. if not currentIdx then
  121. break
  122. end
  123. local startIdx = currentIdx+1
  124. local endIdx = currentIdx+3
  125. local correctTb = checkRandIdx(startIdx, endIdx)
  126. local matchIdx = correctTb[math.random(1, #correctTb)]
  127. usedTb[currentIdx] = true
  128. usedTb[matchIdx] = true
  129. table.insert(pairTb, {serverArr[currentIdx], serverArr[matchIdx]})
  130. currentIdx = currentIdx + 1
  131. end
  132. return pairTb
  133. end
  134. -- 生成匹配列表
  135. local function genMacthArr()
  136. local joinSrvArr = AreaBattleDB.GetJoinSrvArr()
  137. local joinSrvArr_cp = Util.copyTable(joinSrvArr)
  138. if not joinSrvArr_cp or #joinSrvArr_cp <= 0 then
  139. return
  140. end
  141. local srvCnt = #joinSrvArr_cp
  142. if srvCnt > 1 then
  143. if srvCnt % 2 ~= 0 then
  144. local deleteSrvId = joinSrvArr_cp[srvCnt]
  145. joinSrvArr_cp[srvCnt] = nil
  146. srvCnt = srvCnt - 1
  147. -- 新修改: 被移除的服务器为轮空服, 轮空服改为发战败服奖励, 发奖励时需要用到参战玩家数据, 所以不删除轮空服数据
  148. -- 把被移除的服务器从服务器数据列表中移除
  149. -- local serverList = AreaBattleDB.GetServerList()
  150. -- serverList[deleteSrvId] = nil
  151. -- AreaBattleDB.UpdateServerList(serverList)
  152. -- 记录日志
  153. local logStr = "移除多余的区服, 区服Id: " .. deleteSrvId
  154. writeLog(logStr)
  155. end
  156. table.sort(joinSrvArr_cp)
  157. local matchArr = matchAlgorithm(joinSrvArr_cp, srvCnt)
  158. AreaBattleDB.UpdateMatchSrvArr(matchArr)
  159. end
  160. end
  161. -- 获取玩家的战斗数据
  162. local function getPlayerBattleData(serverId, playerUuid, extraArgs)
  163. extraArgs.serverId = serverId
  164. extraArgs.playerUuid = playerUuid
  165. BattleDataCS.GetPlayerCombatData(serverId, playerUuid, BattleDataCS.AREABTTLE_TAG, CombatDefine.COMBAT_TYPE33, extraArgs)
  166. end
  167. -- 分批请求玩家战斗数据
  168. function Timed_GetPlayerBattleData()
  169. if not requestArr or not next(requestArr) then
  170. return
  171. end
  172. local maxNum = math.min(#requestArr, AreaBattleDefine.GET_BATTLE_MAX_CNT_TIMES)
  173. for i=1, maxNum do
  174. local info = table.remove(requestArr)
  175. getPlayerBattleData(info[1], info[2], info[3])
  176. end
  177. if #requestArr > 0 then
  178. Timer.addLater(2, Timed_GetPlayerBattleData, requestArr)
  179. end
  180. end
  181. -- 向普通服请求战斗数据
  182. local function requestPlayerBattleData()
  183. local matchSrvArr = AreaBattleDB.GetMatchSrvArr()
  184. local serverList = AreaBattleDB.GetServerList()
  185. if not matchSrvArr or #matchSrvArr == 0 or not next(serverList) then
  186. return
  187. end
  188. for idx, matchSrvTb in ipairs(matchSrvArr) do
  189. local serverId1 = matchSrvTb[1]
  190. local serverId2 = matchSrvTb[2]
  191. local playerArr1 = serverList[serverId1] and serverList[serverId1].playerInfoArr or {}
  192. local playerArr2 = serverList[serverId2] and serverList[serverId2].playerInfoArr or {}
  193. local maxPlayerCnt = math.max(#playerArr1, #playerArr2)
  194. for i=1, maxPlayerCnt do
  195. local playerUuid1 = playerArr1[i] and playerArr1[i].uuid
  196. local playerUuid2 = playerArr2[i] and playerArr2[i].uuid
  197. if playerUuid1 then
  198. local args = {
  199. firstIdx = idx,
  200. secondIdx = i,
  201. identity = 1, --身份,1-进攻方, 2-防御方
  202. serverId = 0,
  203. playerUuid = "",
  204. }
  205. -- getPlayerBattleData(serverId1, playerUuid1, args)
  206. requestArr[#requestArr+1] = {serverId1, playerUuid1, args}
  207. end
  208. if playerUuid2 then
  209. local args = {
  210. firstIdx = idx,
  211. secondIdx = i,
  212. identity = 2, --身份,1-进攻方, 2-防御方
  213. serverId = 0,
  214. playerUuid = "",
  215. }
  216. -- getPlayerBattleData(serverId2, playerUuid2, args)
  217. requestArr[#requestArr+1] = {serverId2, playerUuid2, args}
  218. end
  219. end
  220. end
  221. local now = os.time()
  222. AreaBattleDB.UpdateUpLoadStartTi(now)
  223. Timed_GetPlayerBattleData()
  224. end
  225. -- 处于准备阶段处理, 给服务器进行匹配, 并通知普通服上传玩家战斗数据
  226. local function prepareHandle()
  227. local stateDB = AreaBattleDB.GetState()
  228. if stateDB ~= AreaBattleDefine.STATE_PREPARE then
  229. return
  230. end
  231. -- 服务器进行匹配
  232. genMacthArr()
  233. -- 让普通服上传战斗数据
  234. -- requestPlayerBattleData()
  235. end
  236. -- 上一轮 ~ 新一轮准备阶段的处理
  237. local function earlyHanle()
  238. local now = os.time()
  239. local stateDB = AreaBattleDB.GetState()
  240. local nowRoundStartTi = AreaBattleDB.GetNowRoundStartTi()
  241. local diffDays = Util.diffDay(nowRoundStartTi)
  242. -- 开启新一轮活动
  243. if nowRoundStartTi <= 0 or diffDays >= 2 then
  244. return newRoundHandle()
  245. end
  246. -- 处于准备阶段, 普通服上传完本服排名前15的玩家数据后,如果还没有对服务器进行分组, 则生成服务器匹配列表, 并通知这些服务器上传本服玩家战斗数据
  247. if diffDays < 2 and now - nowRoundStartTi >= AreaBattleDefine.SERVER_DATA_TIME and stateDB == AreaBattleDefine.STATE_PREPARE then
  248. local matchSrvArr = AreaBattleDB.GetMatchSrvArr()
  249. if not matchSrvArr or not next(matchSrvArr) then
  250. prepareHandle()
  251. end
  252. end
  253. end
  254. -- 进入战斗阶段的处理
  255. local function BattleStageHandle()
  256. local stateDB = AreaBattleDB.GetState()
  257. if stateDB ~= AreaBattleDefine.STATE_BATTLE then
  258. return
  259. end
  260. StartBattle()
  261. end
  262. -- 战斗结束, 把结果更新到DB
  263. local function updateDBBattleResult(battleInfo)
  264. local attackerServerId = battleInfo.attackerServerId
  265. local attackerUuid = battleInfo.attackerUuid
  266. local defenerServerId = battleInfo.defenerServerId
  267. local defenerUuid = battleInfo.defenerUuid
  268. local isWin = battleInfo.isWin
  269. local serverList = AreaBattleDB.GetServerList()
  270. local attackerSrvData = serverList[attackerServerId]
  271. if attackerSrvData then
  272. if isWin == 1 then
  273. attackerSrvData.winTimes = (attackerSrvData.winTimes or 0) + 1
  274. attackerSrvData.winPlayerArr = attackerSrvData.winPlayerArr or {}
  275. table.insert(attackerSrvData.winPlayerArr, attackerUuid)
  276. else
  277. attackerSrvData.defeatTimes = (attackerSrvData.defeatTimes or 0) + 1
  278. end
  279. end
  280. local defenerSrvData = serverList[defenerServerId]
  281. if defenerSrvData then
  282. if isWin == 0 then
  283. defenerSrvData.winTimes = (defenerSrvData.winTimes or 0) + 1
  284. defenerSrvData.winPlayerArr = defenerSrvData.winPlayerArr or {}
  285. table.insert(defenerSrvData.winPlayerArr, defenerUuid)
  286. else
  287. defenerSrvData.defeatTimes = (defenerSrvData.defeatTimes or 0) + 1
  288. end
  289. end
  290. AreaBattleDB.UpdateServerList(serverList)
  291. end
  292. -- 检查服务器是否是轮空服
  293. local function isByeServer(matchSrvArr, serverId)
  294. local isBye = true
  295. for _, serverTb in ipairs(matchSrvArr or {}) do
  296. if table.find(serverTb, serverId) then
  297. isBye = false
  298. break
  299. end
  300. end
  301. return isBye
  302. end
  303. -- 生成用于通知各个普通服发奖的数据
  304. local function genNotifyInfo(serverInfo, matchSrvArr, serverId)
  305. local info = {
  306. isWin = 0,
  307. winPlayerArr = {},
  308. defeatPlayerArr = {},
  309. isBye = 0, -- 是否轮空
  310. }
  311. local isBye = isByeServer(matchSrvArr, serverId)
  312. if isBye then
  313. info.isBye = 1
  314. else
  315. if (serverInfo.winTimes or 0) > (serverInfo.defeatTimes or 0) then
  316. info.isWin = 1
  317. end
  318. for _, playerInfo in ipairs(serverInfo.playerInfoArr) do
  319. if table.find(serverInfo.winPlayerArr, playerInfo.uuid) then
  320. table.insert(info.winPlayerArr, playerInfo.uuid)
  321. else
  322. table.insert(info.defeatPlayerArr, playerInfo.uuid)
  323. end
  324. end
  325. end
  326. return info
  327. end
  328. -- 生成日志
  329. local function genLog()
  330. local t1, t2 = {}, {}
  331. local joinSrvArr = AreaBattleDB.GetJoinSrvArr()
  332. for idx, srvId in ipairs(joinSrvArr or {}) do
  333. t1[idx] = srvId
  334. end
  335. local str1 = table.concat(t1, ",")
  336. writeLog(str1)
  337. local len = 0
  338. local matchSrvArr = AreaBattleDB.GetMatchSrvArr()
  339. for _, srvTb in ipairs(matchSrvArr or {}) do
  340. for _, servrId in ipairs(srvTb) do
  341. len = len + 1
  342. t2[len] = servrId
  343. end
  344. end
  345. local str2 = table.concat(t2, "-")
  346. writeLog(str2)
  347. local serverList = AreaBattleDB.GetServerList()
  348. for serverId, srvInfo in pairs(serverList or {}) do
  349. local t = {serverId, srvInfo.winTimes or 0, srvInfo.defeatTimes or 0}
  350. if srvInfo.winPlayerArr and #srvInfo.winPlayerArr > 0 then
  351. local s = table.concat(Util.copyTable(srvInfo.winPlayerArr), "-")
  352. table.insert(t, s)
  353. end
  354. local str3 = table.concat(t, "|")
  355. writeLog(str3)
  356. end
  357. end
  358. -------------------------------------------C2N-------------------------------------------
  359. -- 通知普通服,争霸开始
  360. function NotifySrvJoin()
  361. local msgData = InnerMsg.wl.WL_AREABATTLE_OPEN
  362. local fdList = MiddleManager.MiddleManager_GetAllFD()
  363. for _, fd in pairs(fdList) do
  364. InnerMsg.sendMsg(fd, msgData)
  365. end
  366. end
  367. -- 通知普通服发奖
  368. function NotifySrvAwardPrizes(fd, args)
  369. local msgData = InnerMsg.wl.WL_AREABATTLE_SEND_REWARD
  370. msgData.srvBattleRes = args
  371. InnerMsg.sendMsg(fd, msgData)
  372. end
  373. -------------------------------------------N2C-----------------------------------------------
  374. -- 普通服加入战斗
  375. function N2C_JoinBattle(msg)
  376. local sourceServerId = msg.sourceServerId
  377. local joinBattleArray = msg.joinBattleArray
  378. local joinSrvArr = AreaBattleDB.GetJoinSrvArr()
  379. local serverList = AreaBattleDB.GetServerList()
  380. if not table.find(joinSrvArr, sourceServerId) and not serverList[sourceServerId] then
  381. -- 参战列表
  382. table.insert(joinSrvArr, sourceServerId)
  383. AreaBattleDB.UpdateJoinSrvArr(joinSrvArr)
  384. -- 服务器列表
  385. serverList[sourceServerId] = {
  386. winTimes = 0,
  387. defeatTimes = 0,
  388. winPlayerArr = {},
  389. playerInfoArr = joinBattleArray
  390. }
  391. AreaBattleDB.UpdateServerList(serverList)
  392. end
  393. end
  394. -- 普通服请求争霸活动的基本数据
  395. function N2C_GetBaseInfo(msg)
  396. local fd = MiddleManager.getFDBySvrIndex(msg.sourceServerId)
  397. local msgData = InnerMsg.wl.WL_AREABATTLE_BASEINFO_QUERY
  398. msgData.playerUuid = msg.playerUuid
  399. local state = AreaBattleDB.GetState()
  400. msgData.stage = state
  401. msgData.startTime, msgData.endTime = 0, 0
  402. local toDayStartTime = getTodayStartTime()
  403. if not wDay then
  404. updateWDay()
  405. end
  406. if wDay == AreaBattleDefine.OPEN_WDAY_AREA[1] then
  407. msgData.startTime = toDayStartTime + AreaBattleDefine.PREPARE_STATE_START_SEC
  408. msgData.endTime = toDayStartTime + 86400 + AreaBattleDefine.END_STATE_START_SEC
  409. elseif wDay == AreaBattleDefine.OPEN_WDAY_AREA[2] then
  410. msgData.startTime = toDayStartTime - 86400 + AreaBattleDefine.PREPARE_STATE_START_SEC
  411. msgData.endTime = toDayStartTime + AreaBattleDefine.END_STATE_START_SEC
  412. local now = os.time()
  413. if state == AreaBattleDefine.STATE_AWARD and now < toDayStartTime + AreaBattleDefine.END_STATE_START_SEC then
  414. msgData.stage = AreaBattleDefine.STATE_BATTLE
  415. end
  416. else
  417. local subDay = AreaBattleDefine.OPEN_WDAY_AREA[1] - wDay
  418. msgData.startTime = toDayStartTime + subDay * 86400 + AreaBattleDefine.PREPARE_STATE_START_SEC
  419. msgData.endTime = toDayStartTime + (subDay + 1) * 86400 + AreaBattleDefine.END_STATE_START_SEC
  420. end
  421. InnerMsg.sendMsg(fd, msgData)
  422. end
  423. -- 普通服请求本服参战玩家列表
  424. function N2C_GetJoinPlayerArr(msg)
  425. local sourceServerId = msg.sourceServerId
  426. local fd = MiddleManager.getFDBySvrIndex(sourceServerId)
  427. local msgData = InnerMsg.wl.WL_AREABATTLE_JOINPLAYER_QUERY
  428. msgData.errCode = 0
  429. msgData.playerArray = {}
  430. msgData.playerUuid = msg.playerUuid
  431. local joinSrvArr = AreaBattleDB.GetJoinSrvArr()
  432. local mathcList = AreaBattleDB.GetMatchSrvArr()
  433. -- 没有参加
  434. if not joinSrvArr or not table.find(joinSrvArr, sourceServerId) then
  435. msgData.errCode = -1
  436. return InnerMsg.sendMsg(fd, msgData)
  437. end
  438. -- 匹配列表还没生成
  439. if not mathcList or not next(mathcList) then
  440. msgData.errCode = -2
  441. return InnerMsg.sendMsg(fd, msgData)
  442. end
  443. local isInMathcArr = false
  444. for _, matchSrvTb in ipairs(mathcList) do
  445. if table.find(matchSrvTb, sourceServerId) then
  446. isInMathcArr = true
  447. break
  448. end
  449. end
  450. -- 参加了,但是被移除, 没有在本轮匹配列表中
  451. if not isInMathcArr then
  452. msgData.errCode = -3
  453. return InnerMsg.sendMsg(fd, msgData)
  454. end
  455. local serverList = AreaBattleDB.GetServerList()
  456. msgData.playerArray = serverList[sourceServerId] and serverList[sourceServerId].playerInfoArr or {}
  457. InnerMsg.sendMsg(fd, msgData)
  458. end
  459. -- 普通服请求本次参战的区服的匹配列表
  460. -- { { {server1, power1}, {server2, power2} }, }
  461. function N2C_GetMatchList(msg)
  462. local sourceServerId = msg.sourceServerId
  463. local fd = MiddleManager.getFDBySvrIndex(sourceServerId)
  464. local msgData = InnerMsg.wl.WL_AREABATTLE_MATCHLIST_QUERY
  465. msgData.playerUuid = msg.playerUuid
  466. msgData.matchList = {}
  467. local mathcList = AreaBattleDB.GetMatchSrvArr()
  468. local serverList = AreaBattleDB.GetServerList()
  469. for k, matchSrvTb in ipairs(mathcList) do
  470. msgData.matchList[k] = {}
  471. for idx, serverId in ipairs(matchSrvTb) do
  472. if serverList[serverId] then
  473. -- table.insert(msgData.matchList[k], serverId)
  474. local power = calcSrvPower(serverList[serverId].playerInfoArr)
  475. -- table.insert(msgData.matchList[k], power)
  476. msgData.matchList[k][idx] = {serverId, power}
  477. end
  478. end
  479. end
  480. InnerMsg.sendMsg(fd, msgData)
  481. end
  482. -- 普通服请求本服的战斗录像展示数据
  483. function N2C_GetVideoShowData(msg)
  484. local sourceServerId = msg.sourceServerId
  485. local fd = MiddleManager.getFDBySvrIndex(sourceServerId)
  486. local msgData = InnerMsg.wl.WL_AREABATTLE_VIDEOSHOW_QUERY
  487. msgData.errCode = 0
  488. msgData.playerUuid = msg.playerUuid
  489. msgData.videoShowData = {}
  490. msgData.srvInfo = {}
  491. local state = AreaBattleDB.GetState()
  492. if state ~= AreaBattleDefine.STATE_AWARD and state ~= AreaBattleDefine.STATE_END then
  493. msgData.errCode = -1
  494. return InnerMsg.sendMsg(fd, msgData)
  495. end
  496. local videoSecondIdx, leftSrvId, rightSrvId = 0, 0, 0
  497. local matchSrvArr = AreaBattleDB.GetMatchSrvArr()
  498. for k, srvTb in ipairs(matchSrvArr or {}) do
  499. if table.find(srvTb, sourceServerId) then
  500. videoSecondIdx = k
  501. leftSrvId = srvTb[1]
  502. rightSrvId = srvTb[2]
  503. break
  504. end
  505. end
  506. -- 本轮没有参加活动
  507. if videoSecondIdx == 0 then
  508. msgData.errCode = -3
  509. return InnerMsg.sendMsg(fd, msgData)
  510. end
  511. local serverList = AreaBattleDB.GetServerList()
  512. if serverList[leftSrvId] then
  513. msgData.srvInfo.leftSrvId = leftSrvId
  514. msgData.srvInfo.leftWinTimes = serverList[leftSrvId].winTimes or 0
  515. msgData.srvInfo.leftSrvPower = calcSrvPower(serverList[leftSrvId].playerInfoArr)
  516. end
  517. if serverList[rightSrvId] then
  518. msgData.srvInfo.rightSrvId = rightSrvId
  519. msgData.srvInfo.rightWinTimes = serverList[rightSrvId].winTimes or 0
  520. msgData.srvInfo.rightSrvPower = calcSrvPower(serverList[rightSrvId].playerInfoArr)
  521. end
  522. local videoArr = AreaBattleDB.GetSrvVideoShowData(videoSecondIdx)
  523. -- msgData.videoShowData = videoArr
  524. for _, v in ipairs(videoArr) do
  525. if (v.atkData and v.atkData.uuid == msg.playerUuid) or (v.defenerData and v.defenerData.uuid == msg.playerUuid) then
  526. table.insert(msgData.videoShowData, 1, v)
  527. else
  528. msgData.videoShowData[#msgData.videoShowData+1] = v
  529. end
  530. end
  531. InnerMsg.sendMsg(fd, msgData)
  532. end
  533. ---------------------------------------------------------------------------------------------
  534. function oneMin()
  535. if _G.is_middle ~= true then return end
  536. if not isOpen() then
  537. return
  538. end
  539. -- 与 onHour() 处理错开
  540. if Util.getMin() == 0 then
  541. return
  542. end
  543. local now = os.time()
  544. local toDayStartTime = getTodayStartTime()
  545. -- 活动第一天, 当前时间 >= 开启时间
  546. if wDay == AreaBattleDefine.OPEN_WDAY_AREA[1] then
  547. earlyHanle()
  548. end
  549. -- 活动最后一天, 当前时间 < 活动结束时间
  550. if wDay == AreaBattleDefine.OPEN_WDAY_AREA[2] then
  551. earlyHanle()
  552. local stateDB = AreaBattleDB.GetState()
  553. -- local nowRoundStartTi = AreaBattleDB.GetNowRoundStartTi()
  554. -- 当前处于准备阶段, 但是当前时间 >= 对战开始时间, 则进入对战阶段
  555. if now >= (toDayStartTime + AreaBattleDefine.BATTLE_STATE_START_SEC) and stateDB == AreaBattleDefine.STATE_PREPARE then
  556. -- 防止某些情况下,进入准备阶段后普通服数据还没上传完就进入对战阶段
  557. local upLoadStartTi = AreaBattleDB.GetUpLoadStartTi()
  558. if now - upLoadStartTi > AreaBattleDefine.BATTLE_DATA_TIME then
  559. -- 重启跨服后导致战斗数据缓存没了,则重新获取。 -- 新逻辑: 每次进入战斗阶段时才让普通服上传玩家战斗数据
  560. if not next(battleDataCache) then
  561. if #requestArr == 0 then
  562. return requestPlayerBattleData()
  563. end
  564. end
  565. -- 处于请求战斗数据过程中, 等请求完再进入战斗
  566. if #requestArr > 0 then
  567. return
  568. end
  569. AreaBattleDB.UpdateState(AreaBattleDefine.STATE_BATTLE)
  570. BattleStageHandle()
  571. return
  572. end
  573. end
  574. -- 当前时间 >= 发奖时间
  575. if now >= (toDayStartTime + AreaBattleDefine.END_STATE_START_SEC) and stateDB == AreaBattleDefine.STATE_AWARD then
  576. AwardPrizesHandle()
  577. AreaBattleDB.UpdateState(AreaBattleDefine.STATE_END)
  578. end
  579. end
  580. end
  581. function onHour(hour)
  582. if _G.is_middle ~= true then return end
  583. if hour == 0 or not wDay then
  584. updateWDay()
  585. end
  586. if not table.find(AreaBattleDefine.OPEN_WDAY_AREA, wDay) then
  587. return
  588. end
  589. -- 对战阶段
  590. if wDay == AreaBattleDefine.OPEN_WDAY_AREA[2] and hour >= 12 then
  591. local now = os.time()
  592. local stateDB = AreaBattleDB.GetState()
  593. -- local nowRoundStartTi = AreaBattleDB.GetNowRoundStartTi()
  594. local upLoadStartTi = AreaBattleDB.GetUpLoadStartTi()
  595. -- 防止某些情况下,进入准备阶段后,普通服数据还没上传完就进入对战阶段
  596. if stateDB == AreaBattleDefine.STATE_PREPARE and (now - upLoadStartTi > AreaBattleDefine.BATTLE_DATA_TIME) then
  597. -- 重启跨服后导致战斗数据缓存没了,则重新获取。-- 新逻辑: 每次进入战斗阶段时才让普通服上传玩家战斗数据
  598. if not next(battleDataCache) then
  599. -- 可能存在响应比较慢的情况,保证只执行一次 requestPlayerBattleData
  600. if #requestArr == 0 then
  601. return requestPlayerBattleData()
  602. end
  603. end
  604. -- 处于请求战斗数据过程中, 等请求完再进入战斗
  605. if #requestArr > 0 then
  606. return
  607. end
  608. AreaBattleDB.UpdateState(AreaBattleDefine.STATE_BATTLE)
  609. BattleStageHandle()
  610. end
  611. end
  612. -- 发奖阶段
  613. if wDay == AreaBattleDefine.OPEN_WDAY_AREA[2] and hour >= 22 then
  614. local stateDB = AreaBattleDB.GetState()
  615. if stateDB == AreaBattleDefine.STATE_AWARD then
  616. AwardPrizesHandle()
  617. AreaBattleDB.UpdateState(AreaBattleDefine.STATE_END)
  618. end
  619. end
  620. end
  621. -- 通知普通服发奖
  622. function BrocastServer(srvTb)
  623. for fd, notifyInfo in pairs(srvTb) do
  624. NotifySrvAwardPrizes(fd, notifyInfo)
  625. end
  626. end
  627. -- 分批次通知普通服
  628. function BatchServer()
  629. local matchSrvArr = AreaBattleDB.GetMatchSrvArr()
  630. if not matchSrvArr or not next(matchSrvArr) then
  631. return
  632. end
  633. local len, delay_sec = 0, 0
  634. local srvTb = {}
  635. local serverList = AreaBattleDB.GetServerList()
  636. for serverId, serverInfo in pairs(serverList or {}) do
  637. local fd = MiddleManager.getFDBySvrIndex(serverId)
  638. if fd then
  639. len = len + 1
  640. local notifyInfo = genNotifyInfo(serverInfo, matchSrvArr, serverId)
  641. srvTb[fd] = notifyInfo
  642. end
  643. if len >= AreaBattleDefine.BATCH_MAX_SRV_NUM then
  644. delay_sec = delay_sec + 5
  645. Timer.addLater(delay_sec, BrocastServer, srvTb)
  646. srvTb = {}
  647. len = 0
  648. end
  649. end
  650. if len > 0 then
  651. delay_sec = delay_sec + 5
  652. Timer.addLater(delay_sec, BrocastServer, srvTb)
  653. end
  654. end
  655. -- 发奖
  656. function AwardPrizesHandle()
  657. genLog()
  658. BatchServer()
  659. end
  660. -- 开始战斗
  661. function StartBattle()
  662. for firstIdx, battleDList in pairs(battleDataCache) do
  663. for secondIdx, playerBattleData in pairs(battleDList) do
  664. local attackerInfo = playerBattleData.attackerInfo
  665. local defenerInfo = playerBattleData.defenerInfo
  666. local args = {
  667. isWin = 0,
  668. attackerServerId = "",
  669. attackerUuid = "",
  670. defenerServerId = "",
  671. defenerUuid = ""
  672. }
  673. if attackerInfo and defenerInfo then -- 正常情况
  674. args.attackerServerId = attackerInfo.serverId
  675. args.attackerUuid = attackerInfo.playerUuid
  676. args.defenerServerId = defenerInfo.serverId
  677. args.defenerUuid = defenerInfo.playerUuid
  678. args.videoSecondIdx = firstIdx
  679. -- CombatLogicCS.combatBegin(attackerInfo.battleData, defenerInfo.battleData, CombatDefine.COMBAT_TYPE33, FightEnd, args)
  680. local ok, err = pcall(CombatLogicCS.combatBegin, attackerInfo.battleData, defenerInfo.battleData, CombatDefine.COMBAT_TYPE33, FightEnd, args)
  681. if not ok then
  682. local str = string.format("BattleErr, firstIdx: %d, secondIdx: %d, attackerSrvId: %d, defenerSrvId: %d, attackerUuid: %s, defenerUuid: %s, err: %s",
  683. firstIdx, secondIdx, args.attackerServerId, args.defenerServerId, args.attackerUuid, args.defenerUuid, err)
  684. writeLog(str)
  685. end
  686. elseif attackerInfo or defenerInfo then
  687. -- 有一方战斗数据异常, 则跳过战斗,有战斗数据的一方胜利
  688. local errPlayerIdx = 1
  689. if attackerInfo then
  690. args.isWin = 1
  691. args.attackerServerId = attackerInfo.serverId
  692. args.attackerUuid = attackerInfo.playerUuid
  693. local srvId, playerUuid = getBattleObjInfo(firstIdx, secondIdx, 2)
  694. args.defenerServerId = srvId
  695. args.defenerUuid = playerUuid
  696. errPlayerIdx = 2
  697. else
  698. local srvId, playerUuid = getBattleObjInfo(firstIdx, secondIdx, 1)
  699. args.attackerServerId = srvId
  700. args.attackerUuid = playerUuid
  701. args.isWin = 0
  702. args.defenerServerId = defenerInfo.serverId
  703. args.defenerUuid = defenerInfo.playerUuid
  704. end
  705. updateDBBattleResult(args)
  706. local str = string.format("BattleDataERR,Err Identity: %d, firstIdx: %d, secondIdx: %d", errPlayerIdx, firstIdx, secondIdx)
  707. writeLog(str)
  708. end
  709. end
  710. end
  711. AreaBattleDB.UpdateState(AreaBattleDefine.STATE_AWARD)
  712. battleDataCache = {}
  713. end
  714. -- 外部调用
  715. -- 收到玩家的战斗数据后, 进行缓存
  716. function BattleDataHanle(msg)
  717. if msg.errCode == 1 then
  718. local extraArgs = msg.extraArgs
  719. local firstIdx = extraArgs.firstIdx
  720. local secondIdx = extraArgs.secondIdx
  721. local identity = extraArgs.identity
  722. battleDataCache[firstIdx] = battleDataCache[firstIdx] or {}
  723. battleDataCache[firstIdx][secondIdx] = battleDataCache[firstIdx][secondIdx] or {}
  724. local targetTb = battleDataCache[firstIdx][secondIdx]
  725. local playerBattleData = nil
  726. if identity == 1 then
  727. if not targetTb.attackerInfo then
  728. targetTb.attackerInfo = {}
  729. playerBattleData = targetTb.attackerInfo
  730. end
  731. end
  732. if identity == 2 then
  733. if not targetTb.defenerInfo then
  734. targetTb.defenerInfo = {}
  735. playerBattleData = targetTb.defenerInfo
  736. end
  737. end
  738. if playerBattleData then
  739. -- playerBattleData.errCode = errCode
  740. playerBattleData.serverId = extraArgs.serverId
  741. playerBattleData.playerUuid = extraArgs.playerUuid
  742. playerBattleData.battleData = {
  743. objList = msg.objList,
  744. helpList = msg.helpList,
  745. roleBase = msg.roleBase,
  746. formation = msg.formation,
  747. jiBan = msg.jiBan,
  748. elfList = msg.elfList,
  749. }
  750. end
  751. end
  752. -- 开始进入战斗
  753. -- StartBattle()
  754. end
  755. -- 外部调用, 来自本模块的战斗结束后的回调函数
  756. function FightEnd(result, combatType, combatInfo, extraArgs)
  757. if result == CombatDefine.RESULT_WIN then
  758. extraArgs.isWin = 1
  759. end
  760. updateDBBattleResult(extraArgs)
  761. combatInfo.time = os.time()
  762. CombatVideo.SaveCombatVideo(CombatVideo.VIDEOTYPE_AREABATTLE, combatInfo, extraArgs.videoSecondIdx)
  763. end