local ArenaData = class("ArenaData", BaseData) -- 竞技场 function ArenaData:ctor() self.data.isDirty = false end function ArenaData:clear() self.lastArenaGiftId = nil self.curArenaGiftId = nil self.giftExpireAt = nil end function ArenaData:init(data) data = data or GConst.EMPTY_TABLE -- self.season = data.season_number -- self.score = data.current_score self.season = 1 self.score = 1000 self.lastScore = data.last_score self.lastChallengeCount = data.last_challenge_count-- 上赛季挑战次数 self.seasonRewardGot = data.settle_reward_season-- 最近领取过奖励的赛季 self.todayMatchCount = data.today_match_count self.matchInfo = data.rival_info self.matchSuccessTime = data.match_success_at // 1000-- 匹配成功时间,超过配置时间后,匹配对象过期,需要重新匹配 self.matchFreeCdEndTime = data.match_success_cd_end_at // 1000-- 免费匹配cd结束时间,<=0表示无cd,>0表示cd剩余时间 self.todayAdRematchCount = data.today_ad_count-- 今日看广告跳匹配cd次数 self.todayWinAdBoxCount = data.ad_box_win_reward_count-- 今日胜利宝箱次数 self.todayLoseAdBoxCount = data.ad_box_lose_reward_count-- 今日失败宝箱次数 self.maxScore = data.highest_score_in_history-- 历史最高积分 self.gotGradingRewardIds = data.stage_gift_id-- 已领取的段位奖励id self:updateTotalFightCount(data) -- 初始化rank配置 self.cfgRank = self:getRankCfg(self.season) -- 初始化time配置 self.cfgTime = self:getTimeCfg(self.season) self.curGradingId = self:getGradingIdFromScore(self.score) -- 当前所在段位id DataManager.FormationData:initArena(data.attack_array_heroes, data.defend_array_heroes) DataManager.PlayerData:initArena(data.today_ticket_buy_count, data.today_ticket_ad_count) -- 未找到相应赛季数据 if not self:hasServerData() then GFunc.showToast(I18N:getGlobalText(I18N.GlobalConst.ARENA_DESC_30)) end DataManager:registerCrossDayFunc("ArenaData", function() self:onDayChanged() end) self:setDirty() end function ArenaData:initGiftInfo(actArenaGift, isInit) if not actArenaGift then return end if self.lastArenaGiftId ~= actArenaGift.current_gift_id and not isInit then self.lastArenaGiftId = nil else self.lastArenaGiftId = actArenaGift.current_gift_id end self.curArenaGiftId = actArenaGift.current_gift_id self.giftExpireAt = GFunc.formatTimeStep(actArenaGift.gift_expire_at) end function ArenaData:needShowPopGift() return self.lastArenaGiftId ~= self.curArenaGiftId end function ArenaData:cleaShowPopGift() self.lastArenaGiftId = self.curArenaGiftId end function ArenaData:getGiftId() if GFunc.isShenhe() then -- 审核状态不显示 return end if not self.curArenaGiftId or self.curArenaGiftId <= 0 then return end if self:getGiftRemainTime() <= 0 then return end return self.curArenaGiftId end function ArenaData:getGiftRemainTime() if not self.giftExpireAt then return 0 end return self.giftExpireAt - Time:getServerTime() end function ArenaData:onBoughtGift(giftId) if giftId ~= self.curArenaGiftId then return end self.lastArenaGiftId = nil self.curArenaGiftId = nil self.giftExpireAt = nil end function ArenaData:setDirty() self.data.isDirty = not self.data.isDirty end -- 通用 ---------------------------------------------------------------------- -- 获取赛季rank配置 function ArenaData:getRankCfg(season) local result = {} for id, data in pairs(ConfigManager:getConfig("arena_rank")) do if data.season == season then result[id] = data end end return result end -- 获取赛季time配置 function ArenaData:getTimeCfg(season) local result = table.find(ConfigManager:getConfig("arena_time"), function(value) return value.season == season end) return result end -- 是否开启,checkData:是否判断数据 function ArenaData:isOpen(checkData) if not ModuleManager:getIsOpen(ModuleManager.MODULE_KEY.ARENA, true) then return false end if checkData and not self:hasServerData() then return false end return true end -- 是否有服务器数据 function ArenaData:hasServerData() return self.season and self:getRankCfg(self.season) end -- 是否在赛季结算中 function ArenaData:isInSeasonSettlementTime() return self:getRemainSeasonTime() > 0 and self:getRemainSeasonSettlementTime() < 0 end -- 是否在赛季时间段中 function ArenaData:isInSeasonTime() return self:getRemainSeasonTime() > 0 and self:getRemainSeasonSettlementTime() > 0 end -- 获取当前为第几赛季 function ArenaData:getSeason() return self.season end -- 获取当前赛季段位id列表(升序) function ArenaData:getGradingIdList() local result = table.keys(self.cfgRank) table.sort(result) return result end -- 获取赛季剩余时间(秒) function ArenaData:getRemainSeasonTime() local endTime = Time:getCertainTimeByStr(self.cfgTime.end_time) return endTime - Time:getServerTime() end -- 获取赛季结算的剩余时间(秒) function ArenaData:getRemainSeasonSettlementTime() -- 赛季结束前30分钟结算 local lockTime = Time:getCertainTimeByStr(self.cfgTime.end_time) - 30 * 60 return lockTime - Time:getServerTime() end -- 获取赛季段位结算奖励信息 function ArenaData:getSeasonRewards(id) local cfg = ConfigManager:getConfig("arena_rank") if cfg[id] == nil then Logger.logError("未找到段位[%d]相关数据", id) return nil end return cfg[id].season_reward end -- 获取当前赛季最低段位积分 function ArenaData:getSeasonGradingMinScore() local result = 0 if self.cfgRank then for id, data in pairs(self.cfgRank) do if result == 0 or result > data.score then result = data.score end end end return result end -- 获取积分所对应的段位id function ArenaData:getGradingIdFromScore(score, isLastSeason) if score == nil or score < 0 then return nil end local gradingId,gradingInfo = nil local cfg = self.cfgRank if isLastSeason then cfg = self:getRankCfg(self.season - 1) end if cfg == nil then -- 活动没开特殊处理 cfg = self:getRankCfg(1) end local ids = table.keys(cfg) table.sort(ids) for index, id in ipairs(ids) do if score >= cfg[id].score and (gradingInfo == nil or gradingInfo.score < cfg[id].score) then gradingId, gradingInfo = id, cfg[id] end end return gradingId end -- 获取所在段位的积分 cur - min function ArenaData:getGradingScore(score) return score - self:getGradingMinScore(score) end -- 获取所在段位的最低积分 function ArenaData:getGradingMinScore(score) local id = self:getGradingIdFromScore(score) if not self.cfgRank[id] then id = table.sort(table.keys(self.cfgRank)) end return self.cfgRank[id].score end -- 获取所在段位的最高积分 full function ArenaData:getGradingMaxScore(score) local gradingId = self:getGradingIdFromScore(score) local ids = self:getGradingIdList() local curIdx = table.indexof(ids, gradingId) if curIdx and curIdx + 1 <= #ids then return self.cfgRank[ids[curIdx + 1]].score end end -- 获取所在段位的总积分 function ArenaData:getGradingScoreTotal(score) local max = self:getGradingMaxScore(score) local min = self:getGradingMinScore(score) if max and min then return max - min else return nil end end -- 获取段位图标名(大段位区分) function ArenaData:getGradingIconName(id) local cfg = ConfigManager:getConfig("arena_rank") if cfg[id] == nil then Logger.logError("未找到段位[%d]相关数据", id) return nil end return cfg[id].rank_icon end -- 获取段位小段图标(大段中的小段区分) function ArenaData:getGradingNumName(id) local cfg = ConfigManager:getConfig("arena_rank") if cfg[id] == nil then Logger.logError("未找到段位[%d]相关数据", id) return nil end return cfg[id].rank_show end -- 获取段位名称 function ArenaData:getGradingName(id) local cfg = ConfigManager:getConfig("arena_rank") if id == nil or cfg[id] == nil then Logger.logError("未找到段位[%d]相关数据", id) return nil end return I18N:getGlobalText(cfg[id].name_txt) end -- 获取重新刷新匹配时间(秒) function ArenaData:getRematchRefreshTime() return GFunc.getConstIntValue("arena_refresh_time") * 60 end -- 获取重新匹配每天最大广告次数 function ArenaData:getRematchAdDailyMaxNum() return GFunc.getConstIntValue("arena_refresh_ad_times") end -- 获取重新匹配钻石消耗 function ArenaData:getRematchConstGem() return GFunc.getConstIntValue("arena_refresh_cost") end -- 获取匹配信息最多存在时间(秒) function ArenaData:getMatchInfoMaxTime() return GFunc.getConstIntValue("arena_info_time") * 60 * 60 end -- 获取战斗消耗 function ArenaData:getFightCostNum() return GFunc.getRewardNum(GFunc.getConstReward("arena_fight_cost")) end -- 入场券是否足够 function ArenaData:isEnoughTicket() return self:getFightCostNum() <= DataManager.BagData.ItemData:getItemNumById(GConst.ItemConst.ITEM_ID_ARENA_TICKET) end -- 排行榜 ---------------------------------------------------------------------- -- 排行榜玩家总数 function ArenaData:getRankCount() if self.rankList then return #self.rankList else return 0 end end -- 获取排行榜第n名数据 function ArenaData:getRankData(rank) local info = table.find(self.rankList, function (value) return value.rank == rank end) if info == nil then Logger.logError("没有找到排行榜第%d名数据", rank) end return info end -- 本地是否有排行榜该玩家编队数据 function ArenaData:hasRankFormation(id) return self.rankFormation ~= nil and self.rankFormation[id] ~= nil end -- 获取排行榜玩家编队信息 function ArenaData:getRankFormation(id) return self.rankFormation[id] end -- 匹配 ---------------------------------------------------------------------- -- 获取匹配玩家信息 function ArenaData:getMatchInfo() if EDITOR_MODE then Logger.logHighlight("当前匹配玩家信息") Logger.printTable(self.matchInfo) end if Time:getServerTime() - self.matchSuccessTime > self:getMatchInfoMaxTime() then -- 超过时间需要重新匹配 return nil end if self.matchInfo == nil then return nil end return self.matchInfo end -- 匹配玩家剩余存在时间 function ArenaData:getMatchExistRemainTime() return self:getMatchInfoMaxTime() - (Time:getServerTime() - self.matchSuccessTime) end -- 个人 ---------------------------------------------------------------------- -- 获取历史最高段位积分 function ArenaData:getMaxScore() return self.maxScore or self:getScore() end -- 获取当前段位积分 function ArenaData:getScore() return self.score end -- 获取当前段位id function ArenaData:getGradingId() return self.curGradingId end -- 获取当前段位 function ArenaData:getFormartMaxGrading() local id = self:getGradingIdFromScore(self.maxScore) or self.curGradingId if not id then id = 0 end id = id % 100 -- 取余数 return id end -- 获取自己的排名 function ArenaData:getRank() return self.rank end -- 获取最近战况 function ArenaData:getRecentBattleByIdx(index) if self.recentBattle == nil then return nil end return self.recentBattle[index] end -- 获取免费重新匹配cd, 大于0代表在cd中,小于等于0代表cd冷却已好,可以免费Rematch function ArenaData:getFreeRematchCd() if self.matchFreeCdEndTime <= 0 then -- cd已经冷却 return self.matchFreeCdEndTime end return self.matchFreeCdEndTime - Time:getServerTime() end -- 是否能看视频重新匹配 function ArenaData:canAdRematch() return self:getFreeRematchCd() > 0 and self.todayAdRematchCount < self:getRematchAdDailyMaxNum() end -- 获取上赛季段位id function ArenaData:getLastGradingId() local lastRank = self:getRankCfg(self.season - 1) local seasonId,grading = nil for id, data in pairs(lastRank) do if self.lastScore >= data.score and (grading == nil or grading.score < data.score) then seasonId, grading = id, data end end return seasonId end -- 是否有可领取的上赛季奖励 function ArenaData:hasSeasonReward() if self.lastChallengeCount <= 0 then return false end if self.seasonRewardGot == self.season - 1 then return false end return true end -- 是否有入口红点 function ArenaData:hasEntranceRedDot() return DataManager.BagData.ItemData:getItemNumById(GConst.ItemConst.ITEM_ID_ARENA_TICKET) > 0 or self:hasSeasonReward() or self:hasGradingRewardRedDot() end -- 广告宝箱 ---------------------------------------------------------------------- -- 获取当前段位ad宝箱奖励 function ArenaData:getAdBoxRewards(isWin) if isWin then return self.cfgRank[self.curGradingId].win_adbox else return self.cfgRank[self.curGradingId].lose_adbox end end -- 是否有广告宝箱 function ArenaData:hasAdBox(isWin, checkCount) if isWin then if checkCount and (checkCount % GFunc.getConstIntValue("arena_win_adbox")) == 0 then local todayMax = GFunc.getConstIntValue("arena_win_adbox_limit") return self.todayWinAdBoxCount < todayMax end else if checkCount and (checkCount % GFunc.getConstIntValue("arena_lose_adbox")) == 0 then local todayMax = GFunc.getConstIntValue("arena_lose_adbox_limit") return self.todayLoseAdBoxCount < todayMax end end return false end -- 升段奖励 ---------------------------------------------------------------------- -- 获取段位奖励配置 function ArenaData:getGradingRewardCfg() if self.gradingRewardCfg == nil then self.gradingRewardCfg = ConfigManager:getConfig("arena_gift") end return self.gradingRewardCfg end -- 获取段位道具奖励 function ArenaData:getGradingRewardsItem(id) return self:getGradingRewardCfg()[id].reward end -- 获取段位英雄奖励, nil为没有 function ArenaData:getGradingRewardsHero(id) return self:getGradingRewardCfg()[id].unlock_hero end -- 获取当前列表定位所在档位的index function ArenaData:getCurTargetIndex() -- 判断最低奖励可领取 for id, data in ipairs(self:getGradingRewardCfg()) do if self:canGetGradingReward(id) and not self:isReceivedGradingReward(id) then return id end end return self:getCurGradingRewardId() end -- 获取当前所在段位奖励的id function ArenaData:getCurGradingRewardId() local curScore = self:getScore() for id, data in ipairs(self:getGradingRewardCfg()) do local prog = self:getGradingRewardProgressByScore(id, curScore) if prog >= 0 and prog < 1 then return id end end return 1 end -- 段位奖励是否可领取 function ArenaData:canGetGradingReward(id) return self:getMaxScore() >= self:getGradingRewardCfg()[id].score end -- 段位奖励是否已领取 function ArenaData:isReceivedGradingReward(id) if self.gotGradingRewardIds == nil then return false end return table.containValue(self.gotGradingRewardIds, id) end -- 获取积分对应的段位奖励档位进度 function ArenaData:getGradingRewardProgressByScore(id, score) local cfg = self:getGradingRewardCfg() local point = cfg[id].score local rangeMin = 0 local rangeMax = 0 if id - 1 > 0 then rangeMin = point - math.floor((point - cfg[id - 1].score) / 2) else rangeMin = self:getSeasonGradingMinScore() end if id + 1 <= #cfg then rangeMax = point + math.floor((cfg[id + 1].score - point) / 2) else rangeMax = point end -- Logger.logHighlight(id.."档位范围:"..rangeMin.."->"..rangeMax) if id == 1 then -- 第一个档位特殊处理 local prog = 0.5 if score > point then local half = ((score - point) / (rangeMax - point)) * 0.5 prog = prog + half end return prog end if score >= rangeMax then -- 超过进度条 return 1 elseif score < rangeMin then --低于进度条 return -1 elseif score == rangeMin then -- 进度最低值 return 0 else -- 在进度条范围内 return (score - rangeMin) / (rangeMax - rangeMin) end end -- 是否有段位奖励入口红点 function ArenaData:hasGradingRewardRedDot() -- 有奖励可领取 for id, data in pairs(self:getGradingRewardCfg()) do if self:canGetGradingReward(id) and not self:isReceivedGradingReward(id) then return true end end return false end -- 奖励段位是否是段位分界线 function ArenaData:isGradingMin(id) local score = self:getGradingRewardCfg()[id].score for id, data in pairs(self.cfgRank) do if score == data.score then return true end end return false end local GRADING_REWARD_COMMON_SIZE = 220 local GRADING_REWARD_GRADING_SIZE = 460 local GRADING_REWARD_UNLOCK_SIZE = 570 -- 获取段位奖励项的高 function ArenaData:getGradingRewardItemHeight(id) if self:getGradingRewardCfg()[id].unlock_hero ~= nil then -- 有解锁的英雄 return GRADING_REWARD_UNLOCK_SIZE elseif self:isGradingMin(id) then -- 是段位分界线 return GRADING_REWARD_GRADING_SIZE else -- 普通奖励 return GRADING_REWARD_COMMON_SIZE end end -- 获取当前列表定位所在档位的高度 function ArenaData:getCurTargetPosY() -- 判断最低奖励可领取 local totalHeight = 0 for id, data in ipairs(self:getGradingRewardCfg()) do if self:canGetGradingReward(id) and not self:isReceivedGradingReward(id) then -- Logger.logHighlight(id) return totalHeight end totalHeight = totalHeight + self:getGradingRewardItemHeight(id) end -- 判断当前档位 totalHeight = 0 local curScore = self:getScore() for id, data in ipairs(self:getGradingRewardCfg()) do local prog = self:getGradingRewardProgressByScore(id, curScore) if prog >= 0 and prog < 1 then return totalHeight end totalHeight = totalHeight + self:getGradingRewardItemHeight(id) end return 0 end -- 事件处理 ---------------------------------------------------------------------- function ArenaData:onDayChanged() self.todayWinAdBoxCount = 0 self.todayLoseAdBoxCount = 0 end -- 获取到排行榜数据 function ArenaData:onRankDataReceived(rank, list) self.rank = rank self.rankList = list end -- 获取到排行榜编队信息 function ArenaData:onRankFormationReceived(id, formation) if self.rankFormation == nil then self.rankFormation = {} end self.rankFormation[id] = formation self:setDirty() end -- 获取到最近战况数据 function ArenaData:onRecentBattleReceived(recentBattle) table.sort(recentBattle, function(a, b) -- 由新到旧 return a.occur_at > b.occur_at end) self.recentBattle = recentBattle end -- 获取到匹配数据 function ArenaData:onMatchInfoReceived(match) self.matchInfo = match self.matchSuccessTime = Time:getServerTime() self.matchFreeCdEndTime = Time:getServerTime() + self:getRematchRefreshTime() self:setDirty() end -- 结算战斗数据 function ArenaData:onBattleResultReceived(score, settlement, result) self.matchInfo = nil -- 战斗记录改变 if self.recentBattle == nil then self.recentBattle = {} end table.remove(self.recentBattle, #self.recentBattle) table.insert(self.recentBattle, 1, settlement) -- 积分改变 self.score = score self.curGradingId = self:getGradingIdFromScore(self.score) local beforeMaxGrading = self.maxScore self.maxScore = result.highest_score_in_history if self:getGradingIdFromScore(beforeMaxGrading) ~= self:getGradingIdFromScore(self.maxScore) then DataManager.HeroData:checkIfCanShowHeroUnlockDan(self:getFormartMaxGrading()) end if beforeMaxGrading < self.maxScore then ModuleManager.TaskManager:addTaskProgress(GConst.TaskConst.TASK_TYPE.X_ARENA_GRADING, self.maxScore - beforeMaxGrading) end self:setDirty() end function ArenaData:updateTotalFightCount(data) self.totalWinCount = data.total_win_count or 0 -- 总胜利次数 self.totalLoseCount = data.total_lose_count or 0 -- 总失败次数 self.totalFightCount = self.totalWinCount + self.totalLoseCount end function ArenaData:getTotalFightCount() return self.totalFightCount or 0 end -- 已领取上赛季奖励 function ArenaData:onLastSeasonRewardReceived() self.seasonRewardGot = self.season - 1 self:setDirty() end -- 跳过匹配cd function ArenaData:onOverFreeRematchCD(isAd) self.matchFreeCdEndTime = -1 if isAd then self.todayAdRematchCount = self.todayAdRematchCount + 1 end self:setDirty() end -- 赛季改变 function ArenaData:onSeasonChanged() self.matchInfo = nil self:setDirty() end -- 领取段位奖励 function ArenaData:onGradingRewardReceived(ids) self.gotGradingRewardIds = table.addArray(self.gotGradingRewardIds, ids) self:setDirty() end return ArenaData