Rank.lua 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. RankScript = {}
  2. local rankScriptConst = {
  3. -- 排行榜刷新时间id
  4. RANK_REFRESH_TIME = 16,
  5. -- 排行榜上限人数id
  6. RANK_LIMIT_MEMBERS = 17,
  7. -- 排行榜奖励时间id
  8. RANK_REWARD_TIME = 10002,
  9. -- 排行榜类型
  10. RANK_TYPES = {
  11. levelType = 1,
  12. BraveTestType = 2,
  13. FightValueType = 3,
  14. },
  15. -- 职业类型
  16. CAREERS = {
  17. 0, 1, 2, 3, 4, 5, 6
  18. },
  19. -- 发奖励周期时间
  20. REWARD_PERIOD = 7 * 24 * 60 * 60,
  21. -- REWARD_PERIOD = 10,
  22. -- 奖励邮件
  23. REWARD_MAIL = 110001,
  24. REWARD_TITLE = "排行榜",
  25. -- 本地或跨服排行榜
  26. LOCAL_RANK = 1,
  27. CROSS_RANK = 2,
  28. }
  29. function RankScript.stopRefreshData(actor)
  30. -- 暂时不做
  31. end
  32. -- 请求排行榜数据
  33. function RankScript.loadRankData(actor, msgData)
  34. local career = tonumber(msgData["career"])
  35. local type = tonumber(msgData["type"])
  36. local rootType = tonumber(msgData["roottype"]) or 1
  37. if career == nil or type == nil then
  38. return
  39. end
  40. -- 请求数据
  41. local id = ConfigDataManager.getTableValue("cfg_rank", "id", "roottype", rootType, "career", career, "type", type)
  42. if id == "" or id == nil then
  43. return
  44. end
  45. local rankRoles = RankScript.getRankDataByPrimaryKey(actor, tonumber(id), rootType)
  46. -- if rankRoles ~= nil and next(rankRoles) ~= nil then
  47. -- local sendMsg = RankScript.buidClientNeedRankData(actor, id, rankRoles)
  48. -- sendluamsg(actor, LuaMessageIdToClient.SEND_RANK_DATA_TO_CLIENT, sendMsg)
  49. -- else
  50. -- sendluamsg(actor, LuaMessageIdToClient.SEND_RANK_DATA_TO_CLIENT, {})
  51. -- end
  52. local sendMsg = RankScript.buidClientNeedRankData(actor, id, rankRoles)
  53. sendluamsg(actor, LuaMessageIdToClient.SEND_RANK_DATA_TO_CLIENT, sendMsg)
  54. end
  55. -- 构建客户端需要排行榜数据,上榜的和个人的
  56. function RankScript.buidClientNeedRankData(actor, id, rankDatas)
  57. local myRankData = RankScript.getMyRankDataByPrimaryKey(actor, id) or {}
  58. local sendMsg = {
  59. id = id,
  60. rankDatas = rankDatas,
  61. myRankData = myRankData
  62. }
  63. return sendMsg
  64. end
  65. function RankScript.initAndSendReward()
  66. local rankRewardTime = ConfigDataManager.getTableValue("cfg_global", "value", "id", rankScriptConst.RANK_REWARD_TIME)
  67. if rankRewardTime == "" or rankRewardTime == nil then
  68. return
  69. end
  70. -- gameDebug.print("rankRewardTime:", rankRewardTime)
  71. local weekAndHour = string.splitByAll(rankRewardTime, "#")
  72. local forWeek = tonumber(weekAndHour[1]) + 1
  73. local forHour = tonumber(weekAndHour[2])
  74. local nowTime = getbaseinfo("now")
  75. local nowYear = year(nowTime)
  76. local nowMonth = month(nowTime)
  77. local nowDay = day(nowTime)
  78. local nowHour = hour(nowTime)
  79. local nowMinute = minute(nowTime)
  80. local nowSecond = second(nowTime)
  81. -- 计算目标星期和时间
  82. local targetDayOfWeek = forWeek
  83. local targetTime = { hour = forHour, min = 0, sec = 0 }
  84. -- 查找目标日期
  85. local targetDate = { year = nowYear, month = nowMonth, day = nowDay }
  86. while os.date("*t", os.time(targetDate))["wday"] ~= targetDayOfWeek do
  87. targetDate.day = targetDate.day + 1
  88. end
  89. -- 检查目标时间是否已经过去
  90. local nowDateTime = {
  91. year = nowYear,
  92. month = nowMonth,
  93. day = nowDay,
  94. hour = nowHour,
  95. min = nowMinute,
  96. sec = nowSecond
  97. }
  98. local targetDateTime = {
  99. year = targetDate.year,
  100. month = targetDate.month,
  101. day = targetDate.day,
  102. hour = targetTime.hour,
  103. min = targetTime.min,
  104. sec = targetTime.sec
  105. }
  106. if os.time(targetDateTime) < os.time(nowDateTime) then
  107. targetDate.day = targetDate.day + 7
  108. end
  109. -- 计算目标日期和时间
  110. targetDateTime = {
  111. year = targetDate.year,
  112. month = targetDate.month,
  113. day = targetDate.day,
  114. hour = targetTime.hour,
  115. min = targetTime.min,
  116. sec = targetTime.sec
  117. }
  118. local targetDateTimeTime = os.time(targetDateTime)
  119. -- 计算延迟
  120. local delay = targetDateTimeTime - os.time(nowDateTime)
  121. setontimerex(102, rankScriptConst.REWARD_PERIOD, delay)
  122. end
  123. function ontimerex102()
  124. -- 定时发奖励
  125. local serverType = getbaseinfo("servertype")
  126. local rankDatas = {}
  127. if serverType == 2 then
  128. RankScript.crossUpdate()
  129. rankDatas = getsysvar("Q$rankCrossData", 1) or {}
  130. else
  131. RankScript.updateRankOnTimeOrNight(false)
  132. rankDatas = getsysvar("Q$rankData") or {}
  133. end
  134. if next(rankDatas) ~= nil then
  135. RankScript.sendReward(rankDatas)
  136. end
  137. end
  138. -- 发奖励
  139. function RankScript.sendReward(rankDatas)
  140. for oneId, rankDataList in pairs(rankDatas) do
  141. local currLine = ConfigDataManager.getTable("cfg_rank", "id", oneId)[1]
  142. local rewardRule = currLine["rewardrule"]
  143. local rewardThing = currLine["reward"]
  144. -- lg('rewardRule', rewardRule)
  145. -- lg('rewardThing', rewardThing)
  146. if rewardRule == "" or rewardThing == "" then
  147. goto nextReward
  148. end
  149. local rewardRuleList = string.splitByAll(rewardRule, "#")
  150. -- lg('rewardRuleList:', rewardRuleList)
  151. local rewardThingByRankno = string.splitByAll(rewardThing, "|")
  152. -- lg('rewardThingByRankno:', rewardThingByRankno)
  153. local rewardThingMap = {}
  154. for rankno, itemAndCount in ipairs(rewardThingByRankno) do
  155. if itemAndCount ~= "" and itemAndCount ~= nil then
  156. local item = string.splitByAll(itemAndCount, "#")[1]
  157. local count = string.splitByAll(itemAndCount, "#")[2]
  158. if item and count then
  159. rewardThingMap[rankno] = { item, count }
  160. end
  161. end
  162. end
  163. -- lg('rewardThingMap:', rewardThingMap)
  164. if #rewardRuleList > 0 and #rewardThingMap > 0 then
  165. -- lg('有奖励可以发放')
  166. for _, currRole in ipairs(rankDataList) do
  167. local rankNo = currRole["rankno"]
  168. if array.contains(rewardRuleList, tostring(rankNo)) then
  169. -- lg('该角色发放奖励')
  170. local actor = currRole["actor"]
  171. local item = rewardThingMap[rankNo][1]
  172. local count = rewardThingMap[rankNo][2]
  173. local itemBing = ConfigDataManager.getTableValue("cfg_bind", "bind", "id", 14)
  174. if item and count then
  175. sendconfigmailbyrid(actor, actor:toString(),
  176. rankScriptConst.REWARD_MAIL, { [tonumber(item)] = tonumber(count) },
  177. rankScriptConst.REWARD_TITLE, itemBing)
  178. end
  179. end
  180. end
  181. end
  182. :: nextReward ::
  183. end
  184. end
  185. function RankScript.isNight()
  186. local nowTime = getbaseinfo("now")
  187. local nowHour = hour(nowTime)
  188. local nowMinute = minute(nowTime)
  189. if nowHour == 0 and nowMinute <= 10 and nowMinute >= 3 then
  190. return true
  191. end
  192. return false
  193. end
  194. -- 变量改为Q类型,凌晨清除数据后要将所有数据重刷一遍
  195. function RankScript.updateAll()
  196. if RankScript.isNight() then
  197. local nowTime = getbaseinfo("now")
  198. local nowHour = hour(nowTime)
  199. local nowMinute = minute(nowTime)
  200. info("凌晨刷新排行榜全部数据,当前时间:", "hour:", nowHour, "min:", nowMinute)
  201. -- 角色信息刷新
  202. RankScript.updateRoles()
  203. -- 排行榜数据全刷新
  204. RankScript.updateRankOnTimeOrNight(false)
  205. end
  206. end
  207. -- 获取所有本地角色数据
  208. function RankScript.updateRoles()
  209. local serverType = getbaseinfo("servertype")
  210. if serverType == 1 then
  211. local roles = getallrolesummaryinfos()
  212. local allRoles = {}
  213. if roles then
  214. for _, role in ipairs(roles) do
  215. local actor = role["actor"]
  216. local buidRole = RankScript.buildOneRole(actor)
  217. table.insert(allRoles, buidRole)
  218. end
  219. info("排行榜刷新全部角色信息成功")
  220. setsysvar("Q$allRankRoles", allRoles)
  221. end
  222. -- 重启立即全部更新
  223. RankScript.updateRankOnTimeOrNight(false)
  224. end
  225. end
  226. function RankScript.addNewRole(actor)
  227. local role = RankScript.buildOneRole(actor)
  228. local allRole = getsysvar(actor, "Q$allRankRoles") or {}
  229. for i = #allRole, 1, -1 do
  230. local storeRole = allRole[i]
  231. local actorInRole = storeRole["actor"]
  232. if actorInRole:toString() == actor:toString() then
  233. return
  234. end
  235. end
  236. table.insert(allRole, role)
  237. setsysvar(actor, "Q$allRankRoles", allRole)
  238. end
  239. function RankScript.removeRole(actor)
  240. local allRole = getsysvar(actor, "Q$allRankRoles") or {}
  241. for i = #allRole, 1, -1 do
  242. local role = allRole[i]
  243. local actorInRole = role["actor"]
  244. if actorInRole:toString() == actor:toString() then
  245. table.remove(allRole, i)
  246. break
  247. end
  248. end
  249. setsysvar(actor, "Q$allRankRoles", allRole)
  250. end
  251. -- 更新在线状态
  252. function RankScript.updateOnline(actor, state)
  253. local allRole = getsysvar(actor, "Q$allRankRoles") or {}
  254. for i = #allRole, 1, -1 do
  255. local role = allRole[i]
  256. local actorInRole = role["actor"]
  257. if actorInRole:toString() == actor:toString() then
  258. role["online"] = state
  259. role["actor"] = actor
  260. break
  261. end
  262. end
  263. setsysvar(actor, "Q$allRankRoles", allRole)
  264. end
  265. -- 开启更新定时器
  266. function RankScript.openRankTimer()
  267. local refreshTime = ConfigDataManager.getTableValue("cfg_global", "value", "id", rankScriptConst.RANK_REFRESH_TIME)
  268. if refreshTime == "" or refreshTime == nil then
  269. return
  270. end
  271. refreshTime = tonumber(refreshTime)
  272. if refreshTime <= 0 then
  273. return
  274. end
  275. refreshTime = refreshTime * 60
  276. setontimerex(101, refreshTime)
  277. end
  278. -- 定时刷新排行榜数据
  279. function ontimerex101()
  280. if RankScript.isNight() then
  281. return
  282. end
  283. local serverType = getbaseinfo("servertype")
  284. if serverType == 1 then
  285. -- 本地
  286. RankScript.updateRankOnTimeOrNight(true)
  287. AngelMajorGrail.initGrailRanking()
  288. end
  289. if serverType == 2 then
  290. -- 跨服
  291. RankScript.crossUpdate()
  292. -- AngelMajorGrail.initGrailRanking()
  293. end
  294. end
  295. -- 更新排行榜数据,true本地定时刷新,false本地凌晨刷新
  296. function RankScript.updateRankOnTimeOrNight(isOnTimer)
  297. local serverType = getbaseinfo("servertype")
  298. if serverType == 1 then
  299. -- 本地
  300. local allRoleInfos = getsysvar("Q$allRankRoles")
  301. if allRoleInfos ~= nil and next(allRoleInfos) ~= nil then
  302. RankScript.updateLocalRankData(allRoleInfos, isOnTimer)
  303. else
  304. info("刷新排行榜时角色信息为空")
  305. end
  306. end
  307. end
  308. -- 更新本地排行榜数据
  309. function RankScript.updateLocalRankData(allRoleInfos, isOnTime)
  310. local flag = isOnTime and "定时" or "凌晨"
  311. info("定时或凌晨更新排行榜数据--" .. "角色数量信息:" .. #allRoleInfos .. " 是否定时:" .. flag)
  312. local rankTables = ConfigDataManager.getList("cfg_rank")
  313. if rankTables == nil or next(rankTables) == nil then
  314. return
  315. end
  316. local limitCount = ConfigDataManager.getTableValue("cfg_global", "value", "id",
  317. rankScriptConst.RANK_LIMIT_MEMBERS)
  318. if tonumber(limitCount) <= 0 or limitCount == "" or limitCount == nil then
  319. return
  320. end
  321. RankScript.giveAllData(allRoleInfos, isOnTime)
  322. local rolesByCareerCategory = {}
  323. for _, career in ipairs(rankScriptConst.CAREERS) do
  324. local currRoles = RankScript.filterRolesByCareer(allRoleInfos, career)
  325. if currRoles ~= nil and next(currRoles) ~= nil then
  326. rolesByCareerCategory[career] = currRoles
  327. end
  328. end
  329. local rankDatas = getsysvar("Q$rankData") or {}
  330. local tempRankData = {}
  331. if isOnTime then
  332. -- 定时刷新
  333. for _, type in pairs(rankScriptConst.RANK_TYPES) do
  334. RankScript.updateDataOnTimer(rolesByCareerCategory, type, rankDatas,
  335. limitCount, tempRankData)
  336. end
  337. else
  338. -- 凌晨刷新
  339. for _, type in pairs(rankScriptConst.RANK_TYPES) do
  340. RankScript.updateDataOnNight(rolesByCareerCategory, type,
  341. limitCount, tempRankData)
  342. end
  343. end
  344. -- lg("刷新后排行榜数据", tempRankData)
  345. setsysvar("Q$rankData", tempRankData)
  346. end
  347. function RankScript.giveAllData(allRoleInfos, isOnTime)
  348. for _, role in ipairs(allRoleInfos) do
  349. local actor = role["actor"]
  350. local isOnline = role["online"]
  351. if (isOnTime and isOnline) or (not isOnTime) then
  352. -- 等级赋值
  353. role["level"] = getbaseinfo(actor, "level")
  354. role["unionname"] = getbaseinfo(actor, "guildname")
  355. role["rankTime"] = getplaydef(actor, "T$levelRankTime") or getbaseinfo("nowsec")
  356. -- 试炼赋值
  357. local braveTestInfo = getplaydef(actor, "T$braveTestInfos") or {}
  358. role["braveLevel"] = braveTestInfo["currLevel"] or 0
  359. role["braveTime"] = braveTestInfo["braveTime"] or 0
  360. -- 战斗赋值
  361. local myCareer = role["career"]
  362. local attrValue
  363. if tonumber(myCareer) == 2 then
  364. attrValue = getattrinfo(actor, "maxmc")
  365. else
  366. attrValue = getattrinfo(actor, "maxdc")
  367. end
  368. local armor = getattrinfo(actor, "armor") or 0
  369. local fightValue = tonumber(attrValue or 0) + tonumber(armor)
  370. if fightValue == 0 then
  371. local mapId = getbaseinfo(actor, "unimapid")
  372. local currActor = getactor(actor, actor:toString(), mapId)
  373. if tonumber(myCareer) == 2 then
  374. attrValue = getattrinfo(currActor, "maxmc")
  375. else
  376. attrValue = getattrinfo(currActor, "maxdc")
  377. end
  378. armor = getattrinfo(currActor, "armor") or 0
  379. fightValue = tonumber(attrValue or 0) + tonumber(armor)
  380. end
  381. role["fightValue"] = fightValue
  382. end
  383. end
  384. end
  385. -- 根据职业筛选角色
  386. function RankScript.filterRolesByCareer(allRoleInfos, career)
  387. local currRoles = {}
  388. -- 综合榜不做职业筛选
  389. if tonumber(career) == rankScriptConst.CAREERS[1] then
  390. -- 综合榜会覆盖其他榜的排名,复制一份新的
  391. return array.deepCopy(allRoleInfos)
  392. end
  393. for _, roleInfo in ipairs(allRoleInfos) do
  394. if tonumber(roleInfo["career"]) == tonumber(career) then
  395. table.insert(currRoles, roleInfo)
  396. end
  397. end
  398. return currRoles
  399. end
  400. -- 根据类型定时更新排行榜数据
  401. function RankScript.updateDataOnTimer(rolesByCareerCategory, type, rankDatas,
  402. limitCount, tempRankData)
  403. if rolesByCareerCategory == nil or type == nil or type <= 0 then
  404. return
  405. end
  406. for career, rolesInCareerCategory in pairs(rolesByCareerCategory) do
  407. -- 如果是多个类型,因为是同一份roles引用,后面的type设置value会覆盖前面的,应该重新复制一份
  408. local roles = array.deepCopy(rolesInCareerCategory)
  409. local currLineId = ConfigDataManager.getTableValue("cfg_rank", "id", "roottype", rankScriptConst.LOCAL_RANK,
  410. "career", career, "type", type)
  411. if currLineId == "" or currLineId == nil then
  412. return
  413. end
  414. local lastHadStoreRoles = rankDatas[currLineId] or {}
  415. -- 创建一个哈希表来存储上次排名中的角色信息
  416. local lastRoleMap = {}
  417. if next(lastHadStoreRoles) ~= nil then
  418. for _, lastRole in ipairs(lastHadStoreRoles) do
  419. lastRoleMap[lastRole["actor"]:toString()] = lastRole
  420. end
  421. end
  422. if tonumber(type) == rankScriptConst.RANK_TYPES.levelType then
  423. for _, role in ipairs(roles) do
  424. local actor = role["actor"]
  425. local actorStr = actor:toString()
  426. local isOnline = role["online"]
  427. local lastRole = lastRoleMap[actorStr]
  428. if isOnline then
  429. if lastRole then
  430. -- 存在上次排名记录
  431. local newLevel = role["level"]
  432. role["value"] = newLevel
  433. local preLevel = lastRole["value"]
  434. if preLevel ~= newLevel then
  435. local now = getbaseinfo("nowsec")
  436. role["rankTime"] = now
  437. setplaydef(actor, "T$levelRankTime", now)
  438. end
  439. else
  440. -- 不存在上次排名记录
  441. local newLevel = role["level"]
  442. role["value"] = newLevel
  443. local ranKTime = role["rankTime"]
  444. setplaydef(actor, "T$levelRankTime", ranKTime)
  445. end
  446. else
  447. -- 离线角色处理
  448. if lastRole then
  449. -- lg("不在线存在上次排名记录")
  450. role["unionname"] = lastRole["unionname"]
  451. role["value"] = lastRole["value"]
  452. role["rankTime"] = lastRole["rankTime"]
  453. else
  454. -- lg("不在线不存在上次排名记录")
  455. role["value"] = 0
  456. end
  457. end
  458. end
  459. RankScript.sortRolesByValueAndOnRankTime(roles)
  460. elseif tonumber(type) == rankScriptConst.RANK_TYPES.BraveTestType then
  461. -- 勇气试炼榜
  462. for _, role in ipairs(roles) do
  463. local actor = role["actor"]
  464. local actorStr = actor:toString()
  465. local isOnline = role["online"]
  466. local lastRole = lastRoleMap[actorStr]
  467. if isOnline then
  468. role["value"] = role["braveLevel"] or 0
  469. else
  470. -- 离线角色处理
  471. if lastRole then
  472. -- 存在上次排名记录
  473. role["value"] = lastRole["value"]
  474. role["braveTime"] = lastRole["braveTime"]
  475. else
  476. -- 不存在上次排名记录
  477. role["value"] = 0
  478. role["braveTime"] = 0
  479. end
  480. end
  481. end
  482. -- 试炼榜排序
  483. RankScript.sortRolesByValueAndBraveTime(roles)
  484. elseif tonumber(type) == rankScriptConst.RANK_TYPES.FightValueType then
  485. -- 战斗力榜
  486. for _, role in ipairs(roles) do
  487. local actor = role["actor"]
  488. local actorStr = actor:toString()
  489. local isOnline = role["online"]
  490. local lastRole = lastRoleMap[actorStr]
  491. if isOnline then
  492. role["value"] = role["fightValue"]
  493. else
  494. -- 离线角色处理
  495. if lastRole then
  496. -- 存在上次排名记录
  497. role["unionname"] = lastRole["unionname"]
  498. role["value"] = lastRole["value"]
  499. else
  500. -- 不存在上次排名记录
  501. role["value"] = 0
  502. end
  503. end
  504. end
  505. -- 战斗力榜排序
  506. RankScript.sortRolesByFightValue(roles)
  507. end
  508. -- 限制上榜人数
  509. RankScript.limitAndSetNo(roles, type, limitCount, currLineId, tempRankData)
  510. end
  511. end
  512. -- 凌晨清除数据后要将所有数据重刷一遍
  513. function RankScript.updateDataOnNight(rolesByCareerCategory, type, limitCount, tempRankData)
  514. if rolesByCareerCategory == nil or type == nil or type <= 0 then
  515. return
  516. end
  517. for career, rolesInCareerCategory in pairs(rolesByCareerCategory) do
  518. local roles = array.deepCopy(rolesInCareerCategory)
  519. local currLineId = ConfigDataManager.getTableValue("cfg_rank", "id", "roottype", rankScriptConst.LOCAL_RANK,
  520. "career", career,
  521. "type", type)
  522. if currLineId == "" or currLineId == nil then
  523. return
  524. end
  525. if tonumber(type) == rankScriptConst.RANK_TYPES.levelType then
  526. for _, role in pairs(roles) do
  527. role["value"] = role["level"]
  528. end
  529. RankScript.sortRolesByValueAndOnRankTime(roles)
  530. elseif tonumber(type) == rankScriptConst.RANK_TYPES.BraveTestType then
  531. for _, role in pairs(roles) do
  532. role["value"] = role["braveLevel"]
  533. end
  534. RankScript.sortRolesByValueAndBraveTime(roles)
  535. elseif tonumber(type) == rankScriptConst.RANK_TYPES.FightValueType then
  536. for _, role in pairs(roles) do
  537. role["value"] = role["fightValue"]
  538. end
  539. RankScript.sortRolesByFightValue(roles)
  540. end
  541. RankScript.limitAndSetNo(roles, type, limitCount, currLineId, tempRankData)
  542. end
  543. end
  544. -- 跨服刷新
  545. function RankScript.crossUpdate()
  546. local serverType = getbaseinfo("servertype")
  547. if serverType == 2 then
  548. local result = {}
  549. local hosts = gethosts()
  550. local limitCount = ConfigDataManager.getTableValue("cfg_global", "value", "id",
  551. rankScriptConst.RANK_LIMIT_MEMBERS)
  552. for _, type in pairs(rankScriptConst.RANK_TYPES) do
  553. for _, career in pairs(rankScriptConst.CAREERS) do
  554. local id = ConfigDataManager.getTableValue("cfg_rank", "id", "roottype", rankScriptConst.LOCAL_RANK,
  555. "type", type, "career", career)
  556. local crossId = ConfigDataManager.getTableValue("cfg_rank", "id", "roottype", rankScriptConst.CROSS_RANK,
  557. "type", type, "career", career)
  558. if not string.isNullOrEmpty(crossId) then
  559. local mergeRoleData = {}
  560. for _, host in ipairs(hosts) do
  561. local rankDatas = getsysvar(host, "Q$rankData") or {}
  562. local rankData = rankDatas[id] or {}
  563. RankScript.arrayMerge(mergeRoleData, rankData)
  564. end
  565. if tonumber(type) == rankScriptConst.RANK_TYPES.levelType then
  566. RankScript.sortRolesByValueAndOnRankTime(mergeRoleData)
  567. elseif tonumber(type) == rankScriptConst.RANK_TYPES.BraveTestType then
  568. RankScript.sortRolesByValueAndBraveTime(mergeRoleData)
  569. elseif tonumber(type) == rankScriptConst.RANK_TYPES.FightValueType then
  570. RankScript.sortRolesByFightValue(mergeRoleData)
  571. end
  572. RankScript.limitAndSetNo(mergeRoleData, type, tonumber(limitCount), crossId, result)
  573. end
  574. end
  575. end
  576. -- lg(result)
  577. setsysvar("Q$rankCrossData", result, 1)
  578. for _, host in ipairs(hosts) do
  579. setsysvar(host, "Q$rankCrossData", result)
  580. end
  581. end
  582. end
  583. function RankScript.arrayMerge(arr1, arr2)
  584. for i, v in ipairs(arr2) do
  585. table.insert(arr1, v)
  586. end
  587. end
  588. -- 限制上榜人数,并设置排名
  589. function RankScript.limitAndSetNo(roles, type, limitCount, currLineId, tempRankData)
  590. local tobeStoreRoles = {}
  591. for i = 1, math.min(#roles, tonumber(limitCount)) do
  592. local role = roles[i]
  593. local actor = role["actor"]
  594. local condition = ConfigDataManager.getTableValue("cfg_rank", "rankcondition", "id", currLineId)
  595. if tonumber(type) == rankScriptConst.RANK_TYPES.levelType then
  596. local result = RankScript.checkCondition(actor, condition, type, { level = role["value"] })
  597. if result then
  598. table.insert(tobeStoreRoles, roles[i])
  599. end
  600. elseif tonumber(type) == rankScriptConst.RANK_TYPES.BraveTestType then
  601. local result = RankScript.checkCondition(actor, condition, type, { braveLevel = role["value"] })
  602. if result then
  603. table.insert(tobeStoreRoles, roles[i])
  604. end
  605. elseif tonumber(type) == rankScriptConst.RANK_TYPES.FightValueType then
  606. local result = RankScript.checkCondition(actor, condition, type, { fightValue = role["value"] })
  607. if result then
  608. table.insert(tobeStoreRoles, roles[i])
  609. end
  610. end
  611. end
  612. RankScript.setRankno(tobeStoreRoles, limitCount)
  613. tempRankData[currLineId] = tobeStoreRoles
  614. end
  615. -- ======================================等级榜排序============================================
  616. function RankScript.sortRolesByValueAndOnRankTime(roles)
  617. -- 这里上个排名只有五十个名额,可能发生之前上过榜,但上次没上榜,这里从上次排行榜中找不到自己
  618. -- 找不到自己,那同样的数值肯定别人比自己先上榜,这里也不影响排序
  619. table.sort(roles, function(a, b)
  620. if a["value"] == nil and b["value"] == nil then
  621. return false
  622. elseif a["value"] == nil then
  623. return false
  624. elseif b["value"] == nil then
  625. return true
  626. end
  627. -- 首先按照value降序排列
  628. if a["value"] > b["value"] then
  629. return true
  630. elseif a["value"] < b["value"] then
  631. return false
  632. else
  633. return RankScript.onRankTimeComparator(a, b)
  634. end
  635. end)
  636. end
  637. function RankScript.onRankTimeComparator(a, b)
  638. -- 两个人都上过榜,但两个人上次上榜数值可能不一样,不过走到这里表示现在两个人数值一样,按照上次上榜时间比较
  639. -- 如果a和b都有rankTime,应该都有上榜时间,则比较rankTime
  640. if a["rankTime"] and b["rankTime"] then
  641. if tonumber(a["rankTime"]) == tonumber(b["rankTime"]) then
  642. -- 比较id
  643. local reslut = RankScript.sortOnId(a, b)
  644. return reslut
  645. else
  646. return tonumber(a["rankTime"]) < tonumber(b["rankTime"])
  647. end
  648. end
  649. -- 如果只有一个有rankTime,那么有rankTime的排前面
  650. return a["rankTime"] ~= nil
  651. end
  652. function RankScript.sortOnId(a, b)
  653. local aId = a["actor"]:toString()
  654. local bId = b["actor"]:toString()
  655. return aId < bId
  656. end
  657. -- ========================================试炼榜排序==========================================
  658. function RankScript.sortRolesByValueAndBraveTime(roles)
  659. table.sort(roles, function(a, b)
  660. if a["value"] > b["value"] then
  661. return true
  662. elseif a["value"] < b["value"] then
  663. return false
  664. else
  665. return RankScript.onBraveTimeComparator(a, b)
  666. end
  667. end)
  668. end
  669. function RankScript.onBraveTimeComparator(a, b)
  670. if tonumber(a["braveTime"]) == tonumber(b["braveTime"]) then
  671. local reslut = RankScript.sortOnId(a, b)
  672. return reslut
  673. end
  674. return tonumber(a["braveTime"]) < tonumber(b["braveTime"])
  675. end
  676. -- =================战斗力榜排序=================
  677. function RankScript.sortRolesByFightValue(roles)
  678. table.sort(roles, function(a, b)
  679. if a["value"] > b["value"] then
  680. return true
  681. elseif a["value"] < b["value"] then
  682. return false
  683. else
  684. return a["actor"]:toString() < b["actor"]:toString()
  685. end
  686. end)
  687. end
  688. -- =========================给本次排行榜数据设置排名======================================
  689. function RankScript.setRankno(tobeStoreRoles, limitCount)
  690. -- 排行榜榜单容量
  691. local capacity = tonumber(limitCount)
  692. if capacity == nil then
  693. capacity = #tobeStoreRoles
  694. else
  695. capacity = math.min(capacity, #tobeStoreRoles)
  696. end
  697. -- 允许并列排名
  698. for i, roleInfo in ipairs(tobeStoreRoles) do
  699. if i == 1 then
  700. roleInfo["rankno"] = 1
  701. else
  702. -- 判断和前一个名次是否并列
  703. local equal = RankScript.rankNoIsEquals(tobeStoreRoles, i)
  704. if equal then
  705. roleInfo["rankno"] = tobeStoreRoles[i - 1]["rankno"]
  706. else
  707. roleInfo["rankno"] = i
  708. end
  709. end
  710. end
  711. end
  712. function RankScript.rankNoIsEquals(tobeStoreRoles, nowIndex)
  713. local preRole = tobeStoreRoles[nowIndex - 1]
  714. local currRole = tobeStoreRoles[nowIndex]
  715. return tonumber(currRole["value"]) == tonumber(preRole["value"])
  716. end
  717. function RankScript.getRankDataByPrimaryKey(actor, id, localOrCross)
  718. if localOrCross == rankScriptConst.LOCAL_RANK then
  719. local rankDatas = getsysvar(actor, "Q$rankData") or {}
  720. -- lg("排行榜数据", rankDatas)
  721. if next(rankDatas) == nil then
  722. return {}
  723. end
  724. return rankDatas[tostring(id)] or {}
  725. elseif localOrCross == rankScriptConst.CROSS_RANK then
  726. local serverType = getbaseinfo("servertype")
  727. local rankDatas = {}
  728. if serverType == 1 then
  729. rankDatas = getsysvar(actor, "Q$rankCrossData") or {}
  730. -- lg("跨服排行榜数据类型",serverType, rankDatas)
  731. elseif serverType == 2 then
  732. rankDatas = getsysvar("Q$rankCrossData", 1) or {}
  733. -- lg("跨服排行榜数据类型",serverType, rankDatas)
  734. end
  735. if next(rankDatas) == nil then
  736. return {}
  737. end
  738. return rankDatas[tostring(id)] or {}
  739. end
  740. end
  741. function RankScript.getMyRankDataByPrimaryKey(actor, id)
  742. -- 找到自己,但自己的职业可能不符合当前查询条件的职业
  743. local currTable = ConfigDataManager.getTable("cfg_rank", "id", id)
  744. if currTable == nil or next(currTable) == nil then
  745. return nil
  746. end
  747. local currCareer = currTable[1]["career"]
  748. local currType = currTable[1]["type"]
  749. local roleInfo = RankScript.buildOneRole(actor)
  750. if tonumber(currType) == rankScriptConst.RANK_TYPES.levelType then
  751. local level = getbaseinfo(actor, "level") or 1
  752. roleInfo["actor"] = actor:toString()
  753. roleInfo["value"] = level
  754. return roleInfo
  755. elseif tonumber(currType) == rankScriptConst.RANK_TYPES.BraveTestType then
  756. local braveTestInfo = getplaydef(actor, "T$braveTestInfos") or {}
  757. local braveLevel = braveTestInfo["currLevel"] or 0
  758. roleInfo["actor"] = actor:toString()
  759. roleInfo["value"] = braveLevel
  760. roleInfo["braveTime"] = braveTestInfo["braveTime"] or 0
  761. return roleInfo
  762. elseif tonumber(currType) == rankScriptConst.RANK_TYPES.FightValueType then
  763. local myCareer = roleInfo["career"]
  764. local attrValue
  765. if tonumber(myCareer) == 2 then
  766. attrValue = getattrinfo(actor, "maxmc")
  767. else
  768. attrValue = getattrinfo(actor, "maxdc")
  769. end
  770. local armor = getattrinfo(actor, "armor") or 0
  771. local fightValue = tonumber(attrValue or 0) + tonumber(armor)
  772. roleInfo["actor"] = actor:toString()
  773. roleInfo["value"] = fightValue
  774. return roleInfo
  775. end
  776. -- end
  777. end
  778. -- 更新勇者试炼关卡信息
  779. function RankScript.updateBraveTestInfos(actor, currLevel, braveTimeMillis)
  780. local braveTestInfo = getplaydef(actor, "T$braveTestInfos")
  781. if braveTestInfo == nil then
  782. braveTestInfo = {
  783. currLevel = tonumber(currLevel),
  784. braveTime = tonumber(braveTimeMillis)
  785. }
  786. else
  787. braveTestInfo.currLevel = tonumber(currLevel)
  788. braveTestInfo.braveTime = tonumber(braveTimeMillis)
  789. end
  790. setplaydef(actor, "T$braveTestInfos", braveTestInfo)
  791. end
  792. -- 根据类型检查条件
  793. function RankScript.checkCondition(actor, condition, type, param)
  794. if tonumber(type) == rankScriptConst.RANK_TYPES.levelType then
  795. local currLevel = param["level"]
  796. return currLevel >= tonumber(condition)
  797. elseif tonumber(type) == rankScriptConst.RANK_TYPES.BraveTestType then
  798. local braveLevel = param["braveLevel"]
  799. return braveLevel >= tonumber(condition)
  800. elseif tonumber(type) == rankScriptConst.RANK_TYPES.FightValueType then
  801. local fightVlue = param["fightValue"]
  802. return fightVlue >= tonumber(condition)
  803. end
  804. return true
  805. end
  806. function RankScript.buildOneRole(actor)
  807. local role = {}
  808. role["actor"] = actor
  809. role["career"] = getbaseinfo(actor, "getbasecareer")
  810. role["name"] = getbaseinfo(actor, "rolename")
  811. role["value"] = 0
  812. local serverId = getbaseinfo(actor, "originalserverid")
  813. role["serverid"] = serverId
  814. role["online"] = false
  815. return role
  816. end
  817. function RankScript.mergeAndUpdate()
  818. local roles = getallrolesummaryinfos()
  819. local allRoles = {}
  820. if roles then
  821. for _, role in ipairs(roles) do
  822. local actor = role["actor"]
  823. local buidRole = RankScript.buildOneRole(actor)
  824. table.insert(allRoles, buidRole)
  825. end
  826. info("合服后排行榜刷新全部角色信息成功, 角色数量:", #allRoles)
  827. setsysvar("Q$allRankRoles", allRoles)
  828. end
  829. RankScript.updateRankOnTimeOrNight(false)
  830. end
  831. -- ====================测试========================
  832. function updaterank(actor)
  833. -- lg("定时刷新排行榜数据")
  834. local curr1 = getbaseinfo("now")
  835. RankScript.updateRankOnTimeOrNight(true)
  836. local curr2 = getbaseinfo("now")
  837. local time = curr2 - curr1
  838. lg("耗时:", time)
  839. end
  840. function testnight()
  841. local curr1 = getbaseinfo("now")
  842. RankScript.updateRankOnTimeOrNight(false)
  843. local curr2 = getbaseinfo("now")
  844. local time = curr2 - curr1
  845. lg("耗时:", time)
  846. end
  847. function updaterole()
  848. RankScript.updateRoles()
  849. end
  850. function updaterole_data()
  851. local curr1 = getbaseinfo("now")
  852. gameDebug.debug(RankScript.updateAll)
  853. local curr2 = getbaseinfo("now")
  854. local time = curr2 - curr1
  855. lg("耗时:", time)
  856. end
  857. function crossupdate()
  858. local t1 = getbaseinfo("now")
  859. RankScript.crossUpdate()
  860. local t2 = getbaseinfo("now")
  861. local time = t2 - t1
  862. lg("耗时:", time)
  863. end
  864. function rankreward(actor)
  865. local serverType = getbaseinfo("servertype")
  866. local rankDatas = {}
  867. if serverType == 2 then
  868. RankScript.crossUpdate()
  869. rankDatas = getsysvar("Q$rankCrossData", 1) or {}
  870. else
  871. RankScript.updateRankOnTimeOrNight(false)
  872. rankDatas = getsysvar("Q$rankData") or {}
  873. end
  874. if next(rankDatas) ~= nil then
  875. RankScript.sendReward(rankDatas)
  876. end
  877. end
  878. function clearrank(actor)
  879. local serverType = getbaseinfo("servertype")
  880. if serverType == rankScriptConst.LOCAL_RANK then
  881. setsysvar(actor, "Q$rankData", {})
  882. elseif serverType == rankScriptConst.CROSS_RANK then
  883. setsysvar("Q$rankCrossData", {}, 1)
  884. end
  885. end