c1_lua/lua/app/userdata/arena/arena_data.lua
2025-06-29 13:37:33 +08:00

773 lines
22 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.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