OpenServerAct = {} local this = {} ---全服首杀数据 local GLOBAL_FIRST_KILL = "R$global_first_kill_info" ---开服活动排行数据(未排序) local OPEN_SERVER_ACT_RANK = "R$open_server_act_rank_info" -----玩家最大装备强化等级 --OpenServerAct.MAX_STRENGTHEN_LV = "T$max_strengthen_level" -----玩家最大装备追加等级 --OpenServerAct.MAX_APPEND_LV = "T$max_append_level" --玩家个人首杀数据 local PERSONAL_FIRST_KILL = "T$personal_first_kill_info" ----开服活动排行数据(已排序) --local OPEN_SERVER_SORT_RANK = "R$open_server_sort_rank" --个人挑战奖励 local NEW_AREA_PERSONAL_REWARD = "T$new_area_personal_reward" ---全服奖励邮件是否发放(0点清空) local GLOBAL_RANK_AWARD_EMAIL = "Q$global_rank_award_email" ---开服活动常量 local Const = { ---奖励状态 AwardStatus = { ---默认(无奖励) DEFAULT = 0, ---未领取 NOT_RECEIVE = 1, ---已领取 RECEIVED = 2, }, AwardType = { ---击杀奖励 KILL = 1, ---伤害第一奖励 HURT = 2, }, RankAward = { ---一键领取 default = 0, ---排行奖励 rank = 1, ---个人奖励 personal = 2, } } ---首杀活动 OpenServerAct.FirstKill = { ---boss首杀 BOSS = 10001, ---黄金怪 GOLD_MONSTER = 10002, } ---阶段排行类型 OpenServerAct.StageRank = { ---装备强化(全身强化到达指定等级或以上) EQUIP_MAX_STRENGTHEN_LV = 20001, ---装备追加(全身追加到达指定等级或以上) EQUIP_MAX_APPEND_LV = 20002, ---装备首爆(从掉落中获得指定道具ITEM) EQUIP_FIRST_DROP = 20003, } ---实时排行类型 OpenServerAct.RealTimeRank = { ---等级竞技(角色等级达到指定等级或以上) ROLE_LEVEL = 20004, ---卓越竞技( 装备卓越词条达到指定数量) SUPERIOR_ENTRY_COUNT = 20005, ---首饰竞技(全身装备首饰等级) JEWELRY_LEVEL = 20006, } ---活动道具绑定配置 local BIND_CFG = 13 ---实时排行榜缓存 local REAL_TIME_RANK = {} ---排行刷新间隔(5分钟的秒时长) local REFRESH_INTERVAL = 60 * 5 ---排行榜上次刷新时间 local LAST_FLUSH_TIME = 0 ---每日结算时间点 local SETTLEMENT_HOUR = 22 function this.GetNewRankValue(rid,roleName,newValue,nowTime) ---排行值 local rankValue = { rid = rid, name = roleName, value = newValue, time = nowTime, } return rankValue end function this.GetNewSortRankData(rankValue) local sortRankData = { rid = rankValue.rid, name = rankValue.name, value = rankValue.value, time = rankValue.time, status = Const.AwardStatus.NOT_RECEIVE, } return sortRankData end function OpenServerAct.IsDataKey(varName) if string.equalsIgnoreCase(varName,GLOBAL_FIRST_KILL) or string.equalsIgnoreCase(varName,OPEN_SERVER_ACT_RANK) then return true else return false end end ---合服事件触发 function OpenServerAct.Combine(varName) --清空全服数据 this.SaveGlobalFirstKill(nil) this.SaveGlobalRankInfo(nil) end --活动是否结束 function this.IsEnd(index) --local condition = ConfigDataManager.getTableValue("cfg_newarea_ranking","condition","id",index) --if not string.isNullOrEmpty(condition) then -- local ret = tonumber(checkcondition(actor, condition)) -- if tonumber(ret) ~= 1 then -- return true; -- end --end local openDay = tonumber(getserveropendays(actor)) local startTime = tonumber(ConfigDataManager.getTableValue("cfg_newarea_ranking","starttime","id",index)) local endTime = tonumber(ConfigDataManager.getTableValue("cfg_newarea_ranking","endtime","id",index)) if endTime == nil then return false end if openDay < endTime then if startTime == nil or openDay >= startTime then return false end end return true; end ---活动页面是否关闭 function this.IsClose(index) local openDay = tonumber(getserveropendays(actor)) local closeTime = tonumber(ConfigDataManager.getTableValue("cfg_newarea_ranking", "uitime", "id", index)) return openDay >= closeTime end ---获取全局排行数量限制 function this.GetGlobalRankLimit() local rankCfg = ConfigDataManager.getTableValue("cfg_global", "value", "id", GlobalConfigId.OPEN_SERVER_ACT_RANK) if string.isNullOrEmpty(rankCfg) then return nil end local rankArray = string.split(rankCfg, "#") return tonumber(rankArray[2]) end ---获取全局排行奖励邮件时间 function this.GetGlobalRankAwardEmailTime() local rankCfg = ConfigDataManager.getTableValue("cfg_global", "value", "id", GlobalConfigId.OPEN_SERVER_ACT_RANK) if string.isNullOrEmpty(rankCfg) then return nil end local rankArray = string.split(rankCfg, "#") return tonumber(rankArray[1]) end ---获取全局首杀数据 function this.GetGlobalFirstKill() local globalFirstInfo = getsysvar(GLOBAL_FIRST_KILL) if globalFirstInfo == nil then globalFirstInfo = {} end return globalFirstInfo end ---保存全局首杀数据 function this.SaveGlobalFirstKill(globalFirstInfo) setsysvar(GLOBAL_FIRST_KILL,globalFirstInfo) end ---获取个人首杀数据 function this.GetPersonalFirstKill(actor) local personalFirstKillInfo = getplaydef(actor, PERSONAL_FIRST_KILL) if personalFirstKillInfo == nil then personalFirstKillInfo = {} end return personalFirstKillInfo end ---保存个人首杀数据 function this.SavePersonalFirstKill(actor,personalFirstKillInfo) setplaydef(actor,PERSONAL_FIRST_KILL,personalFirstKillInfo) end ---获取全局排行榜数据 function this.GetGlobalRankInfo() local globalRankInfo = getsysvar(OPEN_SERVER_ACT_RANK) if globalRankInfo == nil then globalRankInfo = { ---奖励排行数据 award_rank = {}, ---实时排行数据 sort_rank = {}, ---玩家冲榜记录(计算个人奖励名次) personal_rank_record = {}, } end return globalRankInfo end ---保存全局排行榜数据 function this.SaveGlobalRankInfo(globalRankInfo) setsysvar(OPEN_SERVER_ACT_RANK,globalRankInfo) end ---获取个人奖励及排名数据 function this.GetNewAreaPersonalReward(actor) local personalRewardInfo = getplaydef(actor, NEW_AREA_PERSONAL_REWARD) if personalRewardInfo == nil then personalRewardInfo = {} end return personalRewardInfo end ---保存个人奖励数据 function this.SaveNewAreaPersonalReward(actor, personalReward) setplaydef(actor, NEW_AREA_PERSONAL_REWARD, personalReward) end function this.GetRankAwardMailStatus() local status = getsysvar(GLOBAL_RANK_AWARD_EMAIL) if status == nil then return Const.AwardStatus.NOT_RECEIVE end return status end function this.SaveRankAwardMailStatus(status) setsysvar(GLOBAL_RANK_AWARD_EMAIL,status) end ---获取排行榜奖励名次限制 function this.GetRankRewardLimit(group, goalValue) local cfgList = {} if goalValue == nil then cfgList = ConfigDataManager.getTable("cfg_newarea_rankingreward", "group", group) else cfgList = ConfigDataManager.getTable("cfg_newarea_rankingreward", "group", group, "tasktype", goalValue) end if table.isNullOrEmpty(cfgList) then return 0 end return table.count(cfgList) end ---获取玩家各活动数据 function this.GetSubRankValue(actor,rankType) if rankType == OpenServerAct.StageRank.EQUIP_MAX_STRENGTHEN_LV then return EquipAndAppear.GetEquipInfoRecordeValue(actor,EquipAndAppear.RecordeType.MAX_STRENGTH_LEVEL) elseif rankType == OpenServerAct.StageRank.EQUIP_MAX_APPEND_LV then return EquipAndAppear.GetEquipInfoRecordeValue(actor,EquipAndAppear.RecordeType.MAX_APPEND_LEVEL) elseif rankType == OpenServerAct.StageRank.EQUIP_FIRST_DROP then return 0 elseif rankType == OpenServerAct.RealTimeRank.ROLE_LEVEL then local playerLevel = tonumber(getbaseinfo(actor, "level")) return playerLevel elseif rankType == OpenServerAct.RealTimeRank.SUPERIOR_ENTRY_COUNT then return EquipAndAppear.GetEquipInfoRecordeValue(actor,EquipAndAppear.RecordeType.MAX_ENTRY_COUNT) elseif rankType == OpenServerAct.RealTimeRank.JEWELRY_LEVEL then return EquipAndAppear.GetEquipInfoRecordeValue(actor,EquipAndAppear.RecordeType.MAX_JEWELRY_LEVEL) end return 0 end ---全服首杀变化包 function this.GlobalFirstKillChange(actor,group,monsterCfgId,killInfo) local changeInfo = { group = group, monsterCfgId = monsterCfgId, killInfo = killInfo } sendluamsg(actor, LuaMessageIdToClient.RES_GLOBAL_FIRST_KILL_CHANGE, changeInfo) end ---个人首杀变化包 function this.PersonalFirstKillChange(actor,group,monsterCfgId,status) local changeInfo = { group = group, monsterCfgId = monsterCfgId, status = status, } sendluamsg(actor, LuaMessageIdToClient.RES_PERSONAL_FIRST_KILL_CHANGE, changeInfo) end ---排行数据变化包 function this.RankValueChange(actor,rankType,changeGoal) local change = { rankType = rankType, goalChange = changeGoal } sendluamsg(actor, LuaMessageIdToClient.OPEN_SERVER_ACT_RANK_CHANGE, change) end ---玩家排名奖励变化包 function this.RankRewardChange(actor,rankType,goalValue,awardData) local change = { rankType = rankType, goalValue = goalValue, awardData = awardData } sendluamsg(actor, LuaMessageIdToClient.OPEN_SERVER_ACT_REWARD_CHANGE, change) end ---登录触发 function OpenServerAct.Login(actor) --this.CheckPlayerReward(actor) end --function getfirstkillinfotest(actor) -- OpenServerAct.SendFirstKillInfo(actor) --end ---发送首杀数据 function OpenServerAct.SendFirstKillInfo(actor) --全服首杀 local globalFirstKillInfo = this.GetGlobalFirstKill() --个人首杀 local personalFirstKillInfo = this.GetPersonalFirstKill(actor) local firstKillInfo = { global = globalFirstKillInfo, personal = personalFirstKillInfo } --jprint("getfirstkillinfotest:",firstKillInfo) sendluamsg(actor, LuaMessageIdToClient.RES_OPEN_SERVER_FIRST_KILL_INFO, firstKillInfo) end function OpenServerAct.UpdateFirstKill(killerActor, maxHurtRid,maxHate,monsterCfgId) local success, errorInfo = xpcall(this.UpdateFirstKill, debug.traceback, killerActor, maxHurtRid,maxHate,monsterCfgId) gameDebug.assertPrint(success, "怪物死亡开服活动更新异常:", killerActor, maxHurtRid,maxHate,monsterCfgId, errorInfo) end ---更新首杀数据 function this.UpdateFirstKill(killerActor, maxHurtRid,maxHate,monsterCfgId) if killerActor == nil then return end local firstKillGroup = OpenServerAct.FirstKill for _, group in pairs(firstKillGroup) do this.UpdateFirstKillInfo(killerActor, group, monsterCfgId,maxHurtRid,maxHate) end end function this.UpdateFirstKillInfo(actor, group, configId,hurt,hate) local index = ConfigDataManager.getTableValue("cfg_newarea_rankingboss", "index","group",group, "rankingboss", configId) if string.isNullOrEmpty(index) or tonumber(index) <= 0 then return end local actEnd = this.IsEnd(group) if actEnd then return end ---刷新全服数据 this.UpdateGlobalFirstKill(actor, group, configId,hurt,hate) end ---更新首杀数据 function this.UpdateGlobalFirstKill(actor, group, configId,hurt,hate) local globalFirstKill = this.GetGlobalFirstKill() local firstKillGroup = globalFirstKill[group] if table.isNullOrEmpty(firstKillGroup) then firstKillGroup = {} end local firstKillData = firstKillGroup[configId] local globalChange = false if table.isNullOrEmpty(firstKillData) then firstKillData = this.BuildFirstKillInfo(actor, hurt,hate) globalChange = true end --刷新玩家个人数据 local personalLimit = ConfigDataManager.getTableValue("cfg_newarea_rankingboss", "personalcondition","group",group, "rankingboss", configId) local personalCount = firstKillData.personal_count if personalLimit ~= nil and personalCount <= tonumber(personalLimit) then local ok = this.UpdatePersonalFirstKill(actor, group, configId) if ok then firstKillData.personal_count = personalCount + 1 globalChange = true end end if globalChange then firstKillGroup[configId] = firstKillData globalFirstKill[group] = firstKillGroup --jprint("更新全服首杀记录",firstKillData) --保存数据 this.SaveGlobalFirstKill(globalFirstKill) --刷新数据 this.GlobalFirstKillChange(actor,group,configId,firstKillData) end end ---构建首杀数据 function this.BuildFirstKillInfo(killer, hurt,hate) local kill = getbaseinfo(killer, "rid") local killName = getbaseinfo(killer, "rolename") local hurtName = "" local hurtRole = getrolesummaryinfobyrid(hurt) if not table.isNullOrEmpty(hurtRole) then hurtName = hurtRole.name end ---首杀数据 local firstKillData = { ---伤害第一 hurt = { rid = hurt, name = hurtName, status = Const.AwardStatus.NOT_RECEIVE, }, ---击杀者 kill = { rid = kill, name = killName, status = Const.AwardStatus.NOT_RECEIVE, }, ---个人首杀人数 personal_count = 0, -----仇恨第一 --hate = { -- rid = hate, -- status = Const.AwardStatus.NOT_RECEIVE, --}, } jprint("构建首杀数据",firstKillData) return firstKillData end ---领取全服首杀奖励 function OpenServerAct.ReceiveGlobalFirstKill(actor,msgData) jprint("领取全服首杀奖励",msgData) local group = tonumber(msgData["group"]) local configId = tonumber(msgData["configId"]) local awardType = tonumber(msgData["type"]) local globalFirstKill = this.GetGlobalFirstKill() local firstKillGroup = globalFirstKill[group] if table.isNullOrEmpty(firstKillGroup) then noticeTip.noticeinfo(actor, StringIdConst.TEXT362) return end local firstKillData = firstKillGroup[configId] if table.isNullOrEmpty(firstKillData) then noticeTip.noticeinfo(actor, StringIdConst.TEXT362) return end local success = this.CulFirstKillAward(actor, firstKillData, group, configId,awardType) if not success then return end firstKillGroup[configId] = firstKillData globalFirstKill[group] = firstKillGroup this.SaveGlobalFirstKill(globalFirstKill) ---响应 this.GlobalFirstKillChange(actor,group,configId,firstKillData) --jprint("领取全服首杀记录",firstKillData) end ---计算全服首杀奖励 function this.CulFirstKillAward(actor,firstKillData,group,configId,awardType) local rid = tonumber(getbaseinfo(actor, "rid")) local result = {} if awardType == Const.AwardType.KILL then if firstKillData.kill.rid ~= rid then noticeTip.noticeinfo(actor, StringIdConst.TEXT363) return false end if firstKillData.kill.status == Const.AwardStatus.RECEIVED then noticeTip.noticeinfo(actor, StringIdConst.TEXT364) return false end local rewardCfg = ConfigDataManager.getTableValue("cfg_newarea_rankingboss","lastreward","group",group,"rankingboss",configId) this.SendReward(actor,rewardCfg,result,true) firstKillData.kill.status = Const.AwardStatus.RECEIVED end if awardType == Const.AwardType.HURT then if firstKillData.hurt.rid ~= rid then noticeTip.noticeinfo(actor, StringIdConst.TEXT363) return false end if firstKillData.hurt.status == Const.AwardStatus.RECEIVED then noticeTip.noticeinfo(actor, StringIdConst.TEXT364) return false end local rewardCfg = ConfigDataManager.getTableValue("cfg_newarea_rankingboss","mostreward","group",group,"rankingboss",configId) --jprint("个人首杀奖励配置",rewardCfg) this.SendReward(actor,rewardCfg,result,true) firstKillData.hurt.status = Const.AwardStatus.RECEIVED end --if firstKillData.hate.rid == rid and firstKillData.hate.status == Const.AwardStatus.NOT_RECEIVE then -- local rewardCfg = ConfigDataManager.getTableValue("cfg_newarea_rankingboss","killreward","group",type,"rankingboss",configId) -- this.SendReward(actor,rewardCfg,result) -- firstKillData.hate.status = Const.AwardStatus.RECEIVE --end if table.isNullOrEmpty(result) then noticeTip.noticeinfo(actor, StringIdConst.TEXT365) return false end --奖励弹框 sendluamsg(actor, LuaMessageIdToClient.COMMON_REWARD_PANEL, result) return true end ---更新个人首杀数据 function this.UpdatePersonalFirstKill(actor,group,configId) local firstKillInfo = this.GetPersonalFirstKill(actor) local personalRewardCfg = ConfigDataManager.getTableValue("cfg_newarea_rankingboss", "personalreward", "group", group,"rankingboss", configId) if string.isNullOrEmpty(personalRewardCfg) then return false end local firstKillGroup = firstKillInfo[group] if table.isNullOrEmpty(firstKillGroup) then firstKillGroup = {} end local firstKillStatus = firstKillGroup[configId] if firstKillStatus ~= nil then return false end firstKillGroup[configId] = Const.AwardStatus.NOT_RECEIVE firstKillInfo[group] = firstKillGroup --保存个人数据 this.SavePersonalFirstKill(actor,firstKillInfo) --jprint("更新个人首杀数据",firstKillInfo) this.PersonalFirstKillChange(actor,group,configId,Const.AwardStatus.NOT_RECEIVE) return true end ---领取个人首杀奖励 function OpenServerAct.ReceivePersonalFirstKill(actor,msgData) jprint("领取个人首杀奖励",msgData) local group = tonumber(msgData["group"]) local configId = tonumber(msgData["configId"]) local personalRewardCfg = ConfigDataManager.getTableValue("cfg_newarea_rankingboss", "personalreward", "group", group,"rankingboss", configId) if string.isNullOrEmpty(personalRewardCfg) then noticeTip.noticeinfo(actor, StringIdConst.TEXT366) return end local firstKillInfo = this.GetPersonalFirstKill(actor) local firstKillGroup = firstKillInfo[group] if table.isNullOrEmpty(firstKillGroup) then noticeTip.noticeinfo(actor, StringIdConst.TEXT362) return end local firstKillStatus = firstKillGroup[configId] if firstKillStatus == nil then noticeTip.noticeinfo(actor, StringIdConst.TEXT362) return end if firstKillStatus == Const.AwardStatus.RECEIVED then noticeTip.noticeinfo(actor, StringIdConst.TEXT364) return end --发奖励 local result = {} this.SendReward(actor,personalRewardCfg,result,true) firstKillGroup[configId] = Const.AwardStatus.RECEIVED firstKillInfo[group] = firstKillGroup --保存个人数据 this.SavePersonalFirstKill(actor,firstKillInfo) --弹窗 sendluamsg(actor, LuaMessageIdToClient.COMMON_REWARD_PANEL, result) this.PersonalFirstKillChange(actor,group,configId,Const.AwardStatus.RECEIVED) end ---更新装备首爆数据 function OpenServerAct.UpdateEquipFirstDropRank(actor,itemCfgId) OpenServerAct.UpdateRankValue(actor, OpenServerAct.StageRank.EQUIP_FIRST_DROP, itemCfgId) end ---更新排行数据 function OpenServerAct.UpdateRankValue(actor, rankType, newValue) --local success, errorInfo = xpcall(this.UpdateRankValue, debug.traceback, actor, rankType, newValue) --gameDebug.assertPrint(success, "开服活动排行刷新异常:", actor, rankType, newValue, errorInfo) end function this.UpdateRankValue(actor, rankType, newValue) if newValue < 1 then return end local rankCfgList = ConfigDataManager.getTable("cfg_newarea_rankingreward", "group", rankType) if table.isNullOrEmpty(rankCfgList) then return end --校验排行是否结束 local actEnd = this.IsEnd(rankType) if actEnd then return end local change = this.GetNewRankChange() local globalRankInfo = this.GetGlobalRankInfo() --记录奖励排行 local update1 = this.RecordAwardRank(actor, rankType, newValue, rankCfgList, globalRankInfo.award_rank, change.award_rank) --记录实时排行数据 update3 = this.RecordSortRank(actor, rankType, newValue, globalRankInfo.sort_rank) --记录玩家个人数据 local update3 = this.UpdateRankPersonalReward(actor, rankType, newValue, globalRankInfo.personal_rank_record, change.personal_rank_record) if not update1 and not update3 and not update3 then return end this.SaveGlobalRankInfo(globalRankInfo) this.RankValueChange(actor,rankType,change) ---刷新 jprint("更新排行数据",update1,update2,update3,actor,rankType,change) end function this.GetNewRankChange() local change = { award_rank = {}, --sort_rank = {}, personal_rank_record = {} } return change end ---记录奖励排行数据 function this.RecordAwardRank(actor,rankType,newValue,rankCfgList,awardRank,change) local realTimeRank = OpenServerAct.RealTimeRank if table.contains(realTimeRank,rankType) then return false end local rankList = awardRank[rankType] if rankList == nil then rankList = {} end local rid = getbaseinfo(actor, "rid") local update = false for _, rankCfg in pairs(rankCfgList) do local goalValue = tonumber(rankCfg["tasktype"]) local rankData = this.BuildRankAward(actor, rid, rankType, goalValue, newValue, rankList) if rankData ~= nil then change[goalValue] = rankData update = true end end awardRank[rankType] = rankList return update end ---构建排行奖励记录 function this.BuildRankAward(actor,rid, rankType, goalValue, newValue, rankList) local goalRank= rankList[goalValue] if goalRank == nil then goalRank = {} end local rankSize = table.count(goalRank) local rankLimit = this.GetRankRewardLimit(rankType, goalValue) if rankSize >= rankLimit then return nil end local rankData = this.GetAwardRankData(rid, goalRank) if rankData ~= nil then return nil end ---装备首曝特殊处理 if rankType == OpenServerAct.StageRank.EQUIP_FIRST_DROP and newValue ~= goalValue then return nil end if rankType ~= OpenServerAct.StageRank.EQUIP_FIRST_DROP and newValue < goalValue then return nil end local roleName = getbaseinfo(actor, "rolename") rankData = { rid = rid, rank_no = rankSize + 1, name = roleName, status = Const.AwardStatus.NOT_RECEIVE } table.insert(goalRank, rankData) rankList[goalValue] = goalRank return rankData end function this.GetAwardRankData(rid,goalRank) if table.isNullOrEmpty(goalRank) then return nil end for _, rankData in pairs(goalRank) do if rankData.rid == rid then return rankData end end return nil end ---记录实时排行数据 function this.RecordSortRank(actor,rankType,newValue,sortRankData) local realTimeRank = OpenServerAct.RealTimeRank if not table.contains(realTimeRank, rankType) then return false end local rankList = sortRankData[rankType] if rankList == nil then rankList = {} end local rid = getbaseinfo(actor, "rid") local rankData = rankList[rid] if rankData ~= nil and newValue <= rankData.value then return false end local nowTime = tonumber((getbaseinfo("nowsec"))) local roleName = getbaseinfo(actor, "rolename") rankData = { rid = rid, value = newValue, name = roleName, time = nowTime } rankList[rid] = rankData sortRankData[rankType] = rankList --local sortRank = this.FlushRankRealTimeRank(rankType, rankList) --jprint("记录实时排行数据",actor,rankType,sortRank) return true end ---记录个人排名 function this.UpdateRankPersonalReward(actor,rankType,newValue,personalRankData,change) local rankCfgList = ConfigDataManager.getTable("cfg_newarea_personalreward", "group", rankType) if table.isNullOrEmpty(rankCfgList) then return false end local rankList = personalRankData[rankType] if rankList == nil then rankList = {} end local rid = getbaseinfo(actor, "rid") local update = false for _, rankCfg in pairs(rankCfgList) do local limitArray = string.split(rankCfg["tasktype"], "#") local goalValue = tonumber(limitArray[1]) local rankLimit = tonumber(limitArray[2]) local goalRank = rankList[goalValue] if goalRank == nil then goalRank = {} end local rankSize = table.count(goalRank) local ok = this.CanRecordPersonalRank(rid, goalRank, rankType, newValue, goalValue, rankSize, rankLimit) if ok then table.insert(goalRank, rid) rankList[goalValue] = goalRank --记录玩家个人数据 local goalInfo = this.RecordePersonalRankReward(actor, rankType, goalValue, rankSize + 1) change[goalValue] = { rid = rid, goal_info = goalInfo, rank_size = rankSize + 1, } update = true end end if update then personalRankData[rankType] = rankList end return update end function this.CanRecordPersonalRank(rid,goalRank,rankType,newValue,goalValue,rankSize,rankLimit) if table.contains(goalRank, rid) then return false end if rankType == OpenServerAct.StageRank.EQUIP_FIRST_DROP and newValue ~= goalValue then return false end if rankType ~= OpenServerAct.StageRank.EQUIP_FIRST_DROP and newValue < goalValue then return false end if rankSize >= rankLimit then return false end return true end ---记录玩家个人奖励 function this.RecordePersonalRankReward(actor,rankType,goalValue,rankNo) ---玩家记录 local rankPersonalReward = this.GetNewAreaPersonalReward(actor) local subRankReward = rankPersonalReward[rankType] if subRankReward == nil then subRankReward = {} end local goalInfo = subRankReward[goalValue] if not table.isNullOrEmpty(goalInfo) then return nil end ---排行目标信息 goalInfo = { ---排名 rank = rankNo, ---个人奖励状态 status = Const.AwardStatus.NOT_RECEIVE, } subRankReward[goalValue] = goalInfo rankPersonalReward[rankType] = subRankReward this.SaveNewAreaPersonalReward(actor,rankPersonalReward) --jprint("更新个人排名",actor,rankType,subRankReward) return goalInfo end function OpenServerAct.FlushSortRank() local nowTime = tonumber((getbaseinfo("nowsec"))) if nowTime - LAST_FLUSH_TIME < REFRESH_INTERVAL then return end this.FlushSortRank() end function this.FlushSortRank() local globalRankInfo = this.GetGlobalRankInfo() if table.isNullOrEmpty(globalRankInfo) then return end local sortRankList = globalRankInfo.sort_rank if table.isNullOrEmpty(sortRankList) then return end local realTimeRank = OpenServerAct.RealTimeRank for rankType, rankList in pairs(sortRankList) do local actEnd = this.IsEnd(rankType) if not actEnd then if table.contains(realTimeRank, rankType) then this.FlushRankRealTimeRank(rankType, rankList) end end end end ---刷新实时排行 function this.FlushRankRealTimeRank(rankType,rankList) local sortRank = {} if table.isNullOrEmpty(rankList) then return sortRank end for _, rankData in pairs(rankList) do table.insert(sortRank, rankData) end table.sort(sortRank, this.SortRule) local rankLimit = this.GetGlobalRankLimit() local rankCount = table.count(sortRank) local rankSize = math.min(rankCount, rankLimit) local newRank = {} newRank = table.getTopN(rankSize, sortRank) REAL_TIME_RANK[rankType] = sortRank return sortRank end ---排序规则 function this.SortRule(objA, objB) if objA.value == objB.value then return objA.time < objB.time -- 如果value相同,则按time升序 else return objA.value > objB.value -- 否则按value降序 end end ---仅按时间排序 function this.TimeSort(objA, objB) return objA.time < objB.time end function openserveracttest(actor,msgData) OpenServerAct.SendSubRankInfo(actor,tonumber(msgData)) end ---发送排行榜信息 function OpenServerAct.SendSubRankInfo(actor,msgData) --jprint("请求排行数据",msgData) this.SendSubRankInfo(actor,tonumber(msgData)) end function this.SendSubRankInfo(actor,rankType) local globalRankInfo = this.GetGlobalRankInfo() local myValue = this.GetSubRankValue(actor,rankType) ---回包结构 local subRankRes = { rank_type = rankType, my_value = myValue, rank_list = {}, } --封装排行数据 local rankListRes = this.BuildRankListRes(actor,rankType,globalRankInfo) subRankRes.rank_list = rankListRes ---通知客户端 jprint("发送排行数据",subRankRes) sendluamsg(actor, LuaMessageIdToClient.OPEN_SERVER_ACT_TYPE_RANK_INFO, subRankRes) end ---构建排行数据回包 function this.BuildRankListRes(actor,rankType,globalRankInfo) local sortRank, myRank = this.GetShowSortRank(actor,rankType) local rankListRes = { ---奖励排行数据 award_rank = globalRankInfo.award_rank[rankType], ---实时排行数据 sort_rank = sortRank, ---个人冲榜奖励数据 personal_rank = {}, ---我的排名 my_rank = myRank, } local personalRankRecord = globalRankInfo.personal_rank_record[rankType] --玩家个人奖励信息 local personalRewardInfo = this.GetNewAreaPersonalReward(actor) local rankRewardInfo = personalRewardInfo[rankType] if rankRewardInfo == nil then rankRewardInfo = {} end local personalRank = {} if not table.isNullOrEmpty(personalRankRecord) then for goalValue, goalRank in pairs(personalRankRecord) do local myInfo = rankRewardInfo[goalValue] personalRank[goalValue] = { rank_size = table.count(goalRank), my_info = myInfo } end end rankListRes.personal_rank = personalRank return rankListRes end function this.GetShowSortRank(actor,rankType) local rid = tonumber(getbaseinfo(actor, "rid")) local sortRank = this.GetSortRankInfo(rankType) local newRank = {} local myRank = 0 if not table.isNullOrEmpty(sortRank) then local rankLimit = this.GetRankRewardLimit(rankType) local rankCount = table.count(sortRank) local rankSize = math.min(rankCount, rankLimit) newRank = table.getTopN(rankSize, sortRank) for rankNo, rankData in pairs(sortRank) do if rankData.rid == rid then myRank = rankNo end end end return newRank, myRank end function this.GetSortRankInfo(rankType) local sortRank = REAL_TIME_RANK[rankType] if table.isNullOrEmpty(sortRank) then local globalRankInfo = this.GetGlobalRankInfo() if not table.isNullOrEmpty(globalRankInfo.sort_rank) then local rankList = globalRankInfo.sort_rank[rankType] sortRank = this.FlushRankRealTimeRank(rankType, rankList) end end return sortRank end function OpenServerAct.SettlementRank() local nowHour = tonumber((getbaseinfo("hour"))) local settlementHour = this.GetGlobalRankAwardEmailTime() if nowHour ~= settlementHour then return end local status = this.GetRankAwardMailStatus() if status == Const.AwardStatus.RECEIVED then return end this.SettlementRank() end ---结算排行 function this.SettlementRank() local update = false local realTimeRank = OpenServerAct.RealTimeRank for _, rankType in pairs(realTimeRank) do local actClose = this.IsClose(rankType) if not actClose then local sortRank = this.GetSortRankInfo(rankType) if not table.isNullOrEmpty(sortRank) then local newRank = {} local rankLimit = this.GetRankRewardLimit(rankType) local rankCount = table.count(sortRank) local rankSize = math.min(rankCount, rankLimit) newRank = table.getTopN(rankSize, sortRank) for rankNo, rankData in pairs(newRank) do this.SendSettlementEmail(rankNo,rankType,rankData) end update = true end end end if update then this.SaveRankAwardMailStatus(Const.AwardStatus.RECEIVED) end end function this.SendSettlementEmail(rankNo,rankType,rankData) local rid = rankData.rid local rewardRet = {} this.GetSubRankAward(nil,rankType, rankNo,rewardRet) if table.isNullOrEmpty(rewardRet) then return end local actName = ConfigDataManager.getTableValue("cfg_newarea_ranking", "name","id", rankType) jprint("发送开服冲榜奖励邮件",rankType,rankData,actName,rewardRet) --sendconfigmailbyrid(rid, mail_id, rewardRet, actNames) local title = "开服活动" local content = "恭喜您在"..actName.."活动中排名第"..rankNo sendmail(rid,title,content,rewardRet) end ---领奖gm测试 function receivesubrankrewardtest(actor,rankType,goalValue) local msgData = { rankType = rankType, goalValue = goalValue } this.ReceiveRankAward(actor, msgData,0) end ---一键领取 function OpenServerAct.ReceivePlayerRankReward(actor, msgData) this.ReceiveRankAward(actor, msgData,Const.RankAward.default) end ---领取排行奖励 function OpenServerAct.ReceiveGlobalRankReward(actor, msgData) --this.ReceiveRankAward(actor, msgData,Const.RankAward.rank) end ---领取个人奖励 function OpenServerAct.ReceiveNewAreaPersonalReward(actor, msgData) this.ReceiveRankAward(actor, msgData,Const.RankAward.personal) end ---领取奖励 function this.ReceiveRankAward(actor, msgData,receiveType) jprint("玩家请求领取开服冲榜奖励",actor,msgData,receiveType) local rankType = tonumber(msgData["rankType"]) local goalValue = tonumber(msgData["goalValue"]) local actClose = this.IsClose(rankType) if actClose then noticeTip.noticeinfo(actor, StringIdConst.TEXT367) return end local rewardRet = {} local retData = {} --一键领取 if receiveType == Const.RankAward.default then retData = this.OneKeyReceiveRankReward(actor, rankType, goalValue,rewardRet) end --排行奖励 --if receiveType == Const.RankAward.rank then -- retData = this.ReceiveGlobalRankReward(actor, rankType, goalValue,rewardRet) --end --个人奖励 if receiveType == Const.RankAward.personal then retData = this.ReceiveNewAreaPersonalReward(actor, rankType, goalValue,rewardRet) end if table.isNullOrEmpty(retData) then tipinfo(actor,"无奖励可领取") return end local change = { award_type = receiveType, data = retData } --弹窗 sendluamsg(actor, LuaMessageIdToClient.COMMON_REWARD_PANEL, rewardRet) this.RankRewardChange(actor, rankType,goalValue,change) jprint("玩家领取冲榜奖励",actor, rankType,goalValue,change) end --一键领取 function this.OneKeyReceiveRankReward(actor, rankType, goalValue,rewardRet) --全服排行奖励 --local rankRet = this.ReceiveGlobalRankReward(actor, rankType, goalValue, rewardRet) --领取个人排行奖励 local personalRet = this.ReceiveNewAreaPersonalReward(actor, rankType, goalValue, rewardRet) if table.isNullOrEmpty(personalRet) then return nil end local retData = { personal = personalRet } return retData end --function this.ReceiveGlobalRankReward(actor, rankType, goalValue,rewardRet) -- local globalRankInfo = this.GetGlobalRankInfo() -- local awardRank = globalRankInfo.award_rank -- if table.isNullOrEmpty(awardRank) then -- return nil -- end -- local subRank = awardRank[rankType] -- if table.isNullOrEmpty(subRank) then -- return nil -- end -- local goalRank= subRank[goalValue] -- if table.isNullOrEmpty(goalRank) then -- return nil -- end -- local rid = getbaseinfo(actor,"rid") -- local rankData = this.GetAwardRankData(rid, goalRank) -- if table.isNullOrEmpty(rankData) then -- return nil -- end -- if rankData.status == Const.AwardStatus.RECEIVED then -- return nil -- end -- local ok = this.GetSubRankAward(actor, rankType, rankData.rank_no, goalValue,rewardRet) -- if not ok then -- return nil -- end -- rankData.status = Const.AwardStatus.RECEIVED -- goalRank[rankData.rank_no] = rankData -- subRank[goalValue] = goalRank -- awardRank[rankType] = subRank -- globalRankInfo.award_rank = awardRank -- this.SaveGlobalRankInfo(globalRankInfo) -- return rankData --end ---获取排行奖励 function this.GetSubRankAward(actor,rankType, rankNo,rewardRet) local rankCfgList = ConfigDataManager.getTable("cfg_newarea_rankingreward", "group", rankType) if table.isNullOrEmpty(rankCfgList) then return end for _, rankCfg in pairs(rankCfgList) do --local limitValue = rankCfg["tasktype"] --if not string.isNullOrEmpty(limitValue) and tonumber(limitValue) == goalValue then local rankLimit = rankCfg["ranking"] local limitArray = string.split(rankLimit, "#") if rankNo >= tonumber(limitArray[1]) and rankNo <= tonumber(limitArray[2]) then --发奖励 local rewardCfg = rankCfg["taskreward"] this.SendReward(actor,rewardCfg,rewardRet,false) break end --end end end ----领取个人挑战奖励 function this.ReceiveNewAreaPersonalReward(actor, rankType, goalValue,rewardRet) local cfgList = ConfigDataManager.getTable("cfg_newarea_personalreward", "group", rankType) if table.isNullOrEmpty(cfgList) then return nil end local personalRewardInfo = this.GetNewAreaPersonalReward(actor) local subRank = personalRewardInfo[rankType] if table.isNullOrEmpty(subRank) then return nil end local rankData = subRank[goalValue] if table.isNullOrEmpty(rankData) then return nil end if rankData.status == Const.AwardStatus.RECEIVED then return nil end local success = false for _, config in pairs(cfgList) do local limitArray = string.split(config["tasktype"], "#") local goal = tonumber(limitArray[1]) local rankLimit = tonumber(limitArray[2]) if rankData.rank <= rankLimit and goal == goalValue then local rewardCfg = config["taskreward"] this.SendReward(actor,rewardCfg,rewardRet,true) rankData.status = Const.AwardStatus.RECEIVED success = true break end end if not success then return nil end subRank[goalValue] = rankData personalRewardInfo[rankType] = subRank this.SaveNewAreaPersonalReward(actor,personalRewardInfo) return rankData end function this.SendReward(actor,rewardCfg,awardMap,intoBag) if string.isNullOrEmpty(rewardCfg) then return end local bind = ConfigDataManager.getTableValue("cfg_bind", "bind", "id", BIND_CFG) local itemArray = string.split(rewardCfg, "|") for _, param in pairs(itemArray) do local cfgArray = string.split(param, "#") local itemId = tonumber(cfgArray[1]) local itemNum = tonumber(cfgArray[2]) if intoBag == true then additemtobag(actor, itemId, itemNum,bind,9999,'开服活动') end --奖励入包 --记录 local oldCount = awardMap[itemId] if oldCount == nil then oldCount = 0 end awardMap[itemId] = oldCount + itemNum end end function checkplayeropenserverrewardtest(actor) this.CheckPlayerReward(actor) end ---检测玩家未领取的奖励 function this.CheckPlayerReward(actor) local resultGroup = {} --检测怪物首杀 this.CheckFirstKillAward(actor,resultGroup) --检测排行奖励 this.CheckRankReward(actor,resultGroup) if table.isNullOrEmpty(resultGroup) then return end jprint("检测到未领取奖励",resultGroup) local actNames = "" for _, name in pairs(resultGroup) do actNames = actNames..name.."," end --发提示邮件 --sendconfigmailbyrid(rid, mail_id, nil, actNames) end function this.RecordGroup(resultGroup,group) local actName = resultGroup[group] if not string.isNullOrEmpty(actName) then return end actName = ConfigDataManager.getTableValue("cfg_newarea_ranking", "name","id", group) resultGroup[group] = actName end ---检测怪物首杀 function this.CheckFirstKillAward(actor,resultGroup) local personalFirstKill = this.GetPersonalFirstKill(actor) if table.isNullOrEmpty(personalFirstKill) then return end local globalFirstKill = this.GetGlobalFirstKill() local firstKillGroup = OpenServerAct.FirstKill for _, group in pairs(firstKillGroup) do local actClose = this.IsClose(group) if not actClose then --检测全服首杀 local ok = this.CheckGlobalFirstKillReward(group, globalFirstKill) if not ok then ok = this.CheckPersonalFirstKill(group,personalFirstKill) end if ok then this.RecordGroup(resultGroup,group) end end end end ---检测玩家个人首杀奖励 function this.CheckPersonalFirstKill(group,personalFirstKill) if table.isNullOrEmpty(personalFirstKill) then return false end local groupInfo = personalFirstKill[group] if table.isNullOrEmpty(groupInfo) then return false end for _, status in pairs(groupInfo) do if status == Const.AwardStatus.NOT_RECEIVE then return true end end return false end ---检测玩家全服首杀奖励 function this.CheckGlobalFirstKillReward(group,globalFirstKill) local groupInfo = globalFirstKill[group] if table.isNullOrEmpty(groupInfo) then return false end for _, firstKillData in pairs(groupInfo) do if firstKillData.hurt.rid == rid and firstKillData.hurt.status == Const.AwardStatus.NOT_RECEIVE then return true end if firstKillData.kill.rid == rid and firstKillData.kill.status == Const.AwardStatus.NOT_RECEIVE then return true end end return false end ---检测玩家排行榜奖励 function this.CheckRankReward(actor,resultGroup) --个人奖励 local personalReward = this.GetNewAreaPersonalReward(actor) if table.isNullOrEmpty(personalReward) then return end local globalRankInfo = this.GetGlobalRankInfo() local rid = getbaseinfo(actor, "rid") local stageRank = OpenServerAct.StageRank local realTimeRank = OpenServerAct.RealTimeRank for _, rankType in pairs(stageRank) do local actClose = this.IsClose(rankType) if not actClose then local ok = this.CheckPersonalReward(rankType, personalReward) if not ok then ok = this.CheckGlobalRank(rid,rankType,globalRankInfo) end if ok then this.RecordGroup(resultGroup,rankType) end end end for _, rankType in pairs(realTimeRank) do local actClose = this.IsClose(rankType) if not actClose then local ok = this.CheckPersonalReward(rankType, personalReward) if not ok then ok = this.CheckGlobalRank(rid,rankType,globalRankInfo) end if ok then this.RecordGroup(resultGroup,rankType) end end end end ---检测玩家个人排行奖励 function this.CheckPersonalReward(rankType,personalReward) local subRankInfo = personalReward[rankType] if table.isNullOrEmpty(subRankInfo) then return false end for goalValue, goalData in pairs(subRankInfo) do if goalData.status == Const.AwardStatus.NOT_RECEIVE then return true end end return false end ---检测玩家全服排行奖励 function this.CheckGlobalRank(rid,rankType,globalRankInfo) local awardRankInfo = globalRankInfo.award_rank if table.isNullOrEmpty(awardRankInfo) then return false end local subRankInfo = awardRankInfo[rankType] if table.isNullOrEmpty(subRankInfo) then return false end for goalValue, goalRank in pairs(subRankInfo) do for _, rankData in pairs(goalRank) do if rankData.rid == rid and rankData.status == Const.AwardStatus.NOT_RECEIVE then return true end end end return false end function gettasktypenumtest(actor) local count = this.GetRankRewardLimit(20004, 3) jprint("排行配置数量",count) end function getserveropentimetest(actor) local openTime = getbaseinfo(actor, "serveropentime") local formatTime = os.date("%Y-%m-%d %X", openTime / 1000) tipinfo(actor,"开服时间:"..formatTime) end