|
|
@@ -1,6 +1,9 @@
|
|
|
-----------------------------------------------------------------
|
|
|
--- 巅峰战场核心逻辑
|
|
|
-----------------------------------------------------------------
|
|
|
+--------------------------------
|
|
|
+-- 文件名 : ServerCommerceActPeakBettle.lua
|
|
|
+-- 文件说明 : 巅峰战场
|
|
|
+-- 创建时间 : 2025/11/13
|
|
|
+-- 创建人 : WWF
|
|
|
+--------------------------------
|
|
|
|
|
|
local Util = require("common.Util")
|
|
|
local Lang = require("common.Lang")
|
|
|
@@ -17,98 +20,408 @@ local RoleLogic = require("role.RoleLogic")
|
|
|
local RoleDBLogic = require("role.RoleDBLogic")
|
|
|
local MailManager = require("mail.MailManager")
|
|
|
local MailExcel = require("excel.mail")
|
|
|
-local PeakBattlefieldDB = require("peakBattlefield.PeakBattlefieldDB")
|
|
|
-local PeakBattlefieldDefine = require("peakBattlefield.PeakBattlefieldDefine")
|
|
|
-local YunYingLogic = require("yunying.YunYingLogic")
|
|
|
-local AbsActLogic = require("absAct.AbsActLogic")
|
|
|
+local ServerCommerceManager = require("serverCommerce.ServerCommerceManager")
|
|
|
+local ServerCommerceActDefine = require("serverCommerce.ServerCommerceActDefine")
|
|
|
|
|
|
-- Excel配置表
|
|
|
local PeakBattlefieldRewardExcel = require("excel.peakbattlefieldReward")
|
|
|
|
|
|
--- 战场之魂活动ID(从常量定义中获取)
|
|
|
-local BATTLEFIELD_SOUL_FUNC_ID = PeakBattlefieldDefine.BATTLEFIELD_SOUL_FUNC_ID
|
|
|
-local BATTLEFIELD_SOUL_PANEL_ID = PeakBattlefieldDefine.BATTLEFIELD_SOUL_PANEL_ID
|
|
|
+-- 巅峰战场常量定义
|
|
|
+local INIT_RANK = 999
|
|
|
+local MATCH_RANK_MIN_OFFSET = 50 -- 向下偏移
|
|
|
+local MATCH_RANK_MAX_OFFSET = 10 -- 向上偏移
|
|
|
+local MATCH_RANK_MIN = 1 -- 最小排名
|
|
|
+local MATCH_RANK_MAX = 999 -- 最大排名
|
|
|
+local OPPONENT_LIST_SIZE = 5
|
|
|
+local DAILY_FREE_CHALLENGE_CNT = 5
|
|
|
+local CHALLENGE_COST_ITEM_ID = 115
|
|
|
+local CHALLENGE_COST_ITEM_CNT = 3
|
|
|
+local REWARD_ID_WIN = 1001 -- 战胜奖励
|
|
|
+local REWARD_ID_LOSE = 1002 -- 战败奖励
|
|
|
+local INIT_HERO_CNT_PER_CAMP = 5
|
|
|
+local MAIL_ID_DEFEAT = 1 -- 战败通知邮件ID
|
|
|
+local MAIL_ID_RANK_REWARD = 0 -- 排名奖励邮件ID
|
|
|
|
|
|
-local CombatDefine = require("combat.CombatDefine")
|
|
|
--- 战斗类型(需要添加到 CombatDefine 中,或使用 Excel 配置)
|
|
|
-local COMBAT_TYPE_PEAK_BATTLEFIELD = CombatDefine.COMBAT_TYPE35 or 35 -- 巅峰战场战斗类型
|
|
|
-
|
|
|
--- 获取战场之魂活动时间
|
|
|
-local function getBattlefieldSoulTime(human)
|
|
|
- -- 方法1:如果知道战场之魂的funcID,直接获取
|
|
|
- if BATTLEFIELD_SOUL_FUNC_ID then
|
|
|
- local state, endTime, startTime = AbsActLogic.isStarted(human, BATTLEFIELD_SOUL_FUNC_ID)
|
|
|
- if state and endTime and startTime then
|
|
|
- return startTime, endTime
|
|
|
- end
|
|
|
+-- 战斗类型
|
|
|
+local COMBAT_TYPE_PEAK_BATTLEFIELD = CombatDefine.COMBAT_TYPE35 or 35
|
|
|
+
|
|
|
+-- 数据库相关
|
|
|
+local LuaMongo = _G.lua_mongo
|
|
|
+local DB = require("common.DB")
|
|
|
+
|
|
|
+-- 排名映射:uuid -> rank
|
|
|
+local UUID_2_RANK = {}
|
|
|
+-- 排名数据:rank -> data
|
|
|
+local RANK_2_DATA = {}
|
|
|
+
|
|
|
+-- 查询条件
|
|
|
+local QueryByUuid = {_id = nil}
|
|
|
+
|
|
|
+----------------------------------------- 内部处理开始 -------------------------------------
|
|
|
+
|
|
|
+-- 获取玩家排名
|
|
|
+local function getRank(uuid)
|
|
|
+ local rank = UUID_2_RANK[uuid]
|
|
|
+ return rank or 0
|
|
|
+end
|
|
|
+
|
|
|
+-- 获取玩家数据
|
|
|
+local function getData(uuid)
|
|
|
+ local rank = UUID_2_RANK[uuid]
|
|
|
+ if not rank then return end
|
|
|
+ return RANK_2_DATA[rank]
|
|
|
+end
|
|
|
+
|
|
|
+-- 获取对手列表
|
|
|
+local function getOpponentList(uuid)
|
|
|
+ local data = getData(uuid)
|
|
|
+ if not data then return {} end
|
|
|
+ return data.opponentList or {}
|
|
|
+end
|
|
|
+
|
|
|
+-- 获取已解锁英雄列表
|
|
|
+local function getUnlockedHeroes(uuid)
|
|
|
+ local data = getData(uuid)
|
|
|
+ if not data then return {} end
|
|
|
+ return data.unlockedHeroes or {}
|
|
|
+end
|
|
|
+
|
|
|
+-- 获取每日免费挑战次数
|
|
|
+local function getFreeChallengeCnt(uuid)
|
|
|
+ local data = getData(uuid)
|
|
|
+ if not data then return DAILY_FREE_CHALLENGE_CNT end
|
|
|
+
|
|
|
+ -- 检查是否需要重置(跨天)
|
|
|
+ local lastResetTime = data.lastResetTime or 0
|
|
|
+ if not Util.isSameDay(lastResetTime, os.time()) then
|
|
|
+ return DAILY_FREE_CHALLENGE_CNT
|
|
|
end
|
|
|
|
|
|
- -- 方法2:通过panelID查找(如果巅峰战场是战场之魂的子标签页)
|
|
|
- if BATTLEFIELD_SOUL_PANEL_ID then
|
|
|
- -- 通过panelID查找yyID(需要YunYingLogic提供getActIDByPanelID函数)
|
|
|
- -- 注意:YunYingLogic中getActIDByPanelID是local函数,可能需要添加公共接口
|
|
|
- -- 或者直接遍历ID2YYInfo查找
|
|
|
- for yyID, YYInfo in pairs(YunYingLogic.ID2YYInfo or {}) do
|
|
|
- if YYInfo and YYInfo.config and YYInfo.config.panelID == BATTLEFIELD_SOUL_PANEL_ID then
|
|
|
- if YYInfo.config.funcs then
|
|
|
- for i = 1, #YYInfo.config.funcs do
|
|
|
- local funcID = YYInfo.config.funcs[i]
|
|
|
- local state, endTime, startTime = AbsActLogic.isStarted(human, funcID)
|
|
|
- if state and endTime and startTime then
|
|
|
- return startTime, endTime
|
|
|
- end
|
|
|
- end
|
|
|
- end
|
|
|
- end
|
|
|
- end
|
|
|
+ return data.freeChallengeCnt or DAILY_FREE_CHALLENGE_CNT
|
|
|
+end
|
|
|
+
|
|
|
+-- 消耗免费挑战次数
|
|
|
+local function consumeFreeChallenge(uuid)
|
|
|
+ local data = getData(uuid)
|
|
|
+ if not data then return false end
|
|
|
+
|
|
|
+ local lastResetTime = data.lastResetTime or 0
|
|
|
+ local freeCnt = getFreeChallengeCnt(uuid)
|
|
|
+
|
|
|
+ if freeCnt <= 0 then
|
|
|
+ return false
|
|
|
end
|
|
|
|
|
|
- -- 方法3:从配置中获取(如果配置中有realStartTime和realEndTime)
|
|
|
- if BATTLEFIELD_SOUL_FUNC_ID then
|
|
|
- local funcConfig = YunYingLogic.getFuncConfig(BATTLEFIELD_SOUL_FUNC_ID)
|
|
|
- if funcConfig and funcConfig.realStartTime and funcConfig.realEndTime then
|
|
|
- local now = os.time()
|
|
|
- if now >= funcConfig.realStartTime and now < funcConfig.realEndTime then
|
|
|
- return funcConfig.realStartTime, funcConfig.realEndTime
|
|
|
- end
|
|
|
+ -- 跨天重置
|
|
|
+ if not Util.isSameDay(lastResetTime, os.time()) then
|
|
|
+ data.freeChallengeCnt = DAILY_FREE_CHALLENGE_CNT
|
|
|
+ data.lastResetTime = os.time()
|
|
|
+ end
|
|
|
+
|
|
|
+ data.freeChallengeCnt = (data.freeChallengeCnt or DAILY_FREE_CHALLENGE_CNT) - 1
|
|
|
+ updateData(data)
|
|
|
+ return true
|
|
|
+end
|
|
|
+
|
|
|
+-- 排名比较函数(排名越小越靠前)
|
|
|
+local function rankCmp(a, b)
|
|
|
+ if a.rank ~= b.rank then
|
|
|
+ return a.rank < b.rank
|
|
|
+ end
|
|
|
+ return (a.time or 0) < (b.time or 0)
|
|
|
+end
|
|
|
+
|
|
|
+-- 排序排名
|
|
|
+local function sortRank()
|
|
|
+ if #RANK_2_DATA > 1 then
|
|
|
+ table.sort(RANK_2_DATA, rankCmp)
|
|
|
+ end
|
|
|
+ for rank = 1, #RANK_2_DATA do
|
|
|
+ local uuid = RANK_2_DATA[rank]._id
|
|
|
+ UUID_2_RANK[uuid] = rank
|
|
|
+ RANK_2_DATA[rank].rank = rank
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+-- 添加玩家
|
|
|
+local function addPlayer(human)
|
|
|
+ local rank = UUID_2_RANK[human.db._id]
|
|
|
+ if rank then return end
|
|
|
+
|
|
|
+ local data = {}
|
|
|
+ data._id = human.db._id
|
|
|
+ data.rank = INIT_RANK
|
|
|
+ data.opponentList = {}
|
|
|
+ data.unlockedHeroes = {}
|
|
|
+ data.freeChallengeCnt = DAILY_FREE_CHALLENGE_CNT
|
|
|
+ data.lastResetTime = os.time()
|
|
|
+ data.time = os.time()
|
|
|
+ data.name = human.db.name or ""
|
|
|
+ data.lv = human.db.lv or 1
|
|
|
+ data.head = human.db.head or 0
|
|
|
+ data.zhandouli = human.db.zhandouli or 0
|
|
|
+
|
|
|
+ LuaMongo.insert(DB.db_peak_battlefield, data)
|
|
|
+
|
|
|
+ RANK_2_DATA[#RANK_2_DATA + 1] = data
|
|
|
+ sortRank()
|
|
|
+end
|
|
|
+
|
|
|
+-- 交换排名(挑战胜利时)
|
|
|
+local function swapRank(atkUuid, defUuid)
|
|
|
+ local atkRank = UUID_2_RANK[atkUuid]
|
|
|
+ local defRank = UUID_2_RANK[defUuid]
|
|
|
+
|
|
|
+ if not atkRank or not defRank then return end
|
|
|
+
|
|
|
+ local atkData = RANK_2_DATA[atkRank]
|
|
|
+ local defData = RANK_2_DATA[defRank]
|
|
|
+
|
|
|
+ if not atkData or not defData then return end
|
|
|
+
|
|
|
+ -- 交换排名
|
|
|
+ local tempRank = atkData.rank
|
|
|
+ atkData.rank = defData.rank
|
|
|
+ defData.rank = tempRank
|
|
|
+
|
|
|
+ atkData.time = os.time()
|
|
|
+ defData.time = os.time()
|
|
|
+
|
|
|
+ -- 清空对手列表(需要重新匹配)
|
|
|
+ atkData.opponentList = {}
|
|
|
+ defData.opponentList = {}
|
|
|
+
|
|
|
+ updateData(atkData)
|
|
|
+ updateData(defData)
|
|
|
+
|
|
|
+ sortRank()
|
|
|
+end
|
|
|
+
|
|
|
+-- 设置对手列表
|
|
|
+local function setOpponentList(uuid, opponentList)
|
|
|
+ local data = getData(uuid)
|
|
|
+ if not data then return end
|
|
|
+
|
|
|
+ data.opponentList = opponentList or {}
|
|
|
+ updateData(data)
|
|
|
+end
|
|
|
+
|
|
|
+-- 更新已解锁英雄
|
|
|
+local function updateUnlockedHeroes(uuid, heroList)
|
|
|
+ local data = getData(uuid)
|
|
|
+ if not data then return end
|
|
|
+
|
|
|
+ data.unlockedHeroes = heroList or {}
|
|
|
+ updateData(data)
|
|
|
+end
|
|
|
+
|
|
|
+-- 更新数据库
|
|
|
+local function updateData(data)
|
|
|
+ QueryByUuid._id = data._id
|
|
|
+ LuaMongo.update(DB.db_peak_battlefield, QueryByUuid, data)
|
|
|
+end
|
|
|
+
|
|
|
+-- 获取排名范围内的玩家(用于匹配)
|
|
|
+local function getPlayersInRankRange(minRank, maxRank, excludeUuid)
|
|
|
+ local result = {}
|
|
|
+ excludeUuid = excludeUuid or ""
|
|
|
+
|
|
|
+ for rank = 1, #RANK_2_DATA do
|
|
|
+ local data = RANK_2_DATA[rank]
|
|
|
+ if data.rank >= minRank and data.rank <= maxRank and data._id ~= excludeUuid then
|
|
|
+ result[#result + 1] = data
|
|
|
end
|
|
|
end
|
|
|
|
|
|
- -- 默认返回nil,表示无法获取活动时间
|
|
|
- return nil, nil
|
|
|
+ return result
|
|
|
end
|
|
|
|
|
|
-- 获取活动剩余时间(秒)
|
|
|
-local function getActivityLeftTime(human)
|
|
|
- local startTime, endTime = getBattlefieldSoulTime(human)
|
|
|
- if not endTime then
|
|
|
+local function getActivityLeftTime()
|
|
|
+ local nStartTime, nEndTime = ServerCommerceManager.CommerceAct_GetOpenAndEndTime()
|
|
|
+ if not nEndTime or nEndTime == 0 then
|
|
|
return 0
|
|
|
end
|
|
|
|
|
|
local now = os.time()
|
|
|
- local leftTime = math.max(endTime - now, 0)
|
|
|
+ local leftTime = math.max(nEndTime - now, 0)
|
|
|
return leftTime
|
|
|
end
|
|
|
|
|
|
+-- 生成对手列表
|
|
|
+local function generateOpponents(uuid, rank)
|
|
|
+ if rank <= 0 then
|
|
|
+ rank = INIT_RANK
|
|
|
+ end
|
|
|
+
|
|
|
+ local minRank = math.max(rank - MATCH_RANK_MIN_OFFSET, MATCH_RANK_MIN)
|
|
|
+ local maxRank = math.min(rank + MATCH_RANK_MAX_OFFSET, MATCH_RANK_MAX)
|
|
|
+
|
|
|
+ local candidates = getPlayersInRankRange(minRank, maxRank, uuid)
|
|
|
+
|
|
|
+ -- 随机选择5个对手
|
|
|
+ local opponentList = {}
|
|
|
+ local selected = {}
|
|
|
+ local needCnt = OPPONENT_LIST_SIZE
|
|
|
+
|
|
|
+ if #candidates > 0 then
|
|
|
+ for i = 1, math.min(needCnt, #candidates) do
|
|
|
+ local idx = math.random(1, #candidates)
|
|
|
+ while selected[idx] do
|
|
|
+ idx = math.random(1, #candidates)
|
|
|
+ end
|
|
|
+ selected[idx] = true
|
|
|
+ opponentList[#opponentList + 1] = {
|
|
|
+ uuid = candidates[idx]._id,
|
|
|
+ rank = candidates[idx].rank
|
|
|
+ }
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ return opponentList
|
|
|
+end
|
|
|
+
|
|
|
+-- 检查并解锁英雄(使用系统英雄表,按阵营解锁)
|
|
|
+local function checkAndUnlockHeroes(human, rank)
|
|
|
+ local HeroExcel = require("excel.hero").hero
|
|
|
+
|
|
|
+ local currentUnlocked = getUnlockedHeroes(human.db._id)
|
|
|
+ local newUnlocked = {}
|
|
|
+
|
|
|
+ -- 根据排名解锁英雄:初始排名时解锁每个阵营的初始英雄
|
|
|
+ if rank <= INIT_RANK then
|
|
|
+ -- 使用 CombatDefine 中的阵营定义
|
|
|
+ local camps = {
|
|
|
+ CombatDefine.CAMP_TYPE1, -- 恶魔(人族)
|
|
|
+ CombatDefine.CAMP_TYPE2, -- 圣堂(妖族)
|
|
|
+ CombatDefine.CAMP_TYPE3 -- 不死(兽族)
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, camp in ipairs(camps) do
|
|
|
+ -- 从HeroExcel中获取该阵营的所有英雄
|
|
|
+ local campHeroes = {}
|
|
|
+ for heroId, heroConfig in pairs(HeroExcel) do
|
|
|
+ if heroConfig.camp == camp then
|
|
|
+ campHeroes[#campHeroes + 1] = heroId
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 随机选择初始数量的英雄
|
|
|
+ if #campHeroes > 0 then
|
|
|
+ local count = INIT_HERO_CNT_PER_CAMP
|
|
|
+ local maxSelect = math.min(count, #campHeroes)
|
|
|
+ for i = 1, maxSelect do
|
|
|
+ local idx = math.random(1, #campHeroes)
|
|
|
+ local heroId = campHeroes[idx]
|
|
|
+
|
|
|
+ -- 检查是否已解锁
|
|
|
+ local found = false
|
|
|
+ for k = 1, #currentUnlocked do
|
|
|
+ if currentUnlocked[k] == heroId then
|
|
|
+ found = true
|
|
|
+ break
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ if not found then
|
|
|
+ newUnlocked[#newUnlocked + 1] = heroId
|
|
|
+ currentUnlocked[#currentUnlocked + 1] = heroId
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 移除已选择的英雄,避免重复
|
|
|
+ table.remove(campHeroes, idx)
|
|
|
+ if #campHeroes == 0 then break end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ if #newUnlocked > 0 then
|
|
|
+ updateUnlockedHeroes(human.db._id, currentUnlocked)
|
|
|
+ -- 发送提示
|
|
|
+ Broadcast.sendErr(human, "解锁新英雄!")
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+-- 发送战败邮件
|
|
|
+local function sendDefeatMail(defeatedUuid, attackerUuid, newRank)
|
|
|
+ local attackerDb = RoleDBLogic.getDb(attackerUuid)
|
|
|
+ if not attackerDb then return end
|
|
|
+
|
|
|
+ -- 获取邮件配置
|
|
|
+ local mailID = MAIL_ID_DEFEAT
|
|
|
+ if not mailID or mailID == 0 then
|
|
|
+ return
|
|
|
+ end
|
|
|
+
|
|
|
+ local mailConfig = MailExcel.mail[mailID]
|
|
|
+ if not mailConfig then
|
|
|
+ print("[sendDefeatMail] 邮件配置不存在,mailID=" .. (mailID or 0))
|
|
|
+ return
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 格式化邮件内容
|
|
|
+ local content = Util.format(mailConfig.content or "", attackerDb.name or "", newRank)
|
|
|
+
|
|
|
+ -- 发送邮件
|
|
|
+ MailManager.add(MailManager.SYSTEM, defeatedUuid, mailConfig.title or "巅峰战区赛", content, nil, mailConfig.senderName or "系统")
|
|
|
+end
|
|
|
+
|
|
|
+----------------------------------------- 外部调用 -------------------------------------
|
|
|
+
|
|
|
+-- 起服初始化
|
|
|
+function Init()
|
|
|
+ -- 从数据库加载所有玩家数据
|
|
|
+ local cursor = LuaMongo.find(DB.db_peak_battlefield, {})
|
|
|
+ if cursor then
|
|
|
+ RANK_2_DATA = {}
|
|
|
+ UUID_2_RANK = {}
|
|
|
+
|
|
|
+ local data = LuaMongo.next(cursor)
|
|
|
+ while data do
|
|
|
+ RANK_2_DATA[#RANK_2_DATA + 1] = data
|
|
|
+ data = LuaMongo.next(cursor)
|
|
|
+ end
|
|
|
+
|
|
|
+ sortRank()
|
|
|
+ print("[ServerCommerceActPeakBettle - Init] 巅峰战场数据加载完成")
|
|
|
+ end
|
|
|
+ return true
|
|
|
+end
|
|
|
+
|
|
|
+-- 活动结束
|
|
|
+function End()
|
|
|
+ -- 活动结束后可以重置数据(如果需要)
|
|
|
+end
|
|
|
+
|
|
|
+-- 重置玩家数据
|
|
|
+function ResetData(human)
|
|
|
+ if not human then
|
|
|
+ return
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+----------------------------------------- 客户端请求 -------------------------------------
|
|
|
+
|
|
|
-- 查询巅峰战场数据
|
|
|
-function query(human)
|
|
|
+function CommerceActPeakBettle_Query(human)
|
|
|
-- 确保玩家已加入
|
|
|
- if not PeakBattlefieldDB.getData(human.db._id) then
|
|
|
- PeakBattlefieldDB.addPlayer(human)
|
|
|
+ if not getData(human.db._id) then
|
|
|
+ addPlayer(human)
|
|
|
end
|
|
|
|
|
|
- local data = PeakBattlefieldDB.getData(human.db._id)
|
|
|
+ local data = getData(human.db._id)
|
|
|
if not data then return end
|
|
|
|
|
|
- local rank = PeakBattlefieldDB.getRank(human.db._id)
|
|
|
- local freeCnt = PeakBattlefieldDB.getFreeChallengeCnt(human.db._id)
|
|
|
- local opponentList = PeakBattlefieldDB.getOpponentList(human.db._id)
|
|
|
- local unlockedHeroes = PeakBattlefieldDB.getUnlockedHeroes(human.db._id)
|
|
|
+ local rank = getRank(human.db._id)
|
|
|
+ local freeCnt = getFreeChallengeCnt(human.db._id)
|
|
|
+ local opponentList = getOpponentList(human.db._id)
|
|
|
+ local unlockedHeroes = getUnlockedHeroes(human.db._id)
|
|
|
|
|
|
-- 如果没有对手列表,生成对手
|
|
|
if not opponentList or #opponentList == 0 then
|
|
|
opponentList = generateOpponents(human.db._id, rank)
|
|
|
- PeakBattlefieldDB.setOpponentList(human.db._id, opponentList)
|
|
|
+ setOpponentList(human.db._id, opponentList)
|
|
|
end
|
|
|
|
|
|
local msgRet = Msg.gc.GC_PEAK_BATTLEFIELD_QUERY
|
|
|
@@ -118,9 +431,9 @@ function query(human)
|
|
|
-- 填充对手列表
|
|
|
local len = 0
|
|
|
for i = 1, #opponentList do
|
|
|
- if len >= PeakBattlefieldDefine.OPPONENT_LIST_SIZE then break end
|
|
|
+ if len >= OPPONENT_LIST_SIZE then break end
|
|
|
local opponent = opponentList[i]
|
|
|
- local opponentData = PeakBattlefieldDB.getData(opponent.uuid)
|
|
|
+ local opponentData = getData(opponent.uuid)
|
|
|
if opponentData then
|
|
|
len = len + 1
|
|
|
local net = msgRet.opponentList[len]
|
|
|
@@ -151,57 +464,24 @@ function query(human)
|
|
|
end
|
|
|
msgRet.unlockedHeroes[0] = len
|
|
|
|
|
|
- -- 活动剩余时间(从战场之魂活动获取)
|
|
|
- msgRet.leftTime = getActivityLeftTime(human)
|
|
|
+ -- 活动剩余时间
|
|
|
+ msgRet.leftTime = getActivityLeftTime()
|
|
|
|
|
|
Msg.send(msgRet, human.fd)
|
|
|
end
|
|
|
|
|
|
--- 生成对手列表
|
|
|
-function generateOpponents(uuid, rank)
|
|
|
- if rank <= 0 then
|
|
|
- rank = PeakBattlefieldDefine.INIT_RANK
|
|
|
- end
|
|
|
-
|
|
|
- local minRank = math.max(rank - PeakBattlefieldDefine.MATCH_RANK_MIN_OFFSET, PeakBattlefieldDefine.MATCH_RANK_MIN)
|
|
|
- local maxRank = math.min(rank + PeakBattlefieldDefine.MATCH_RANK_MAX_OFFSET, PeakBattlefieldDefine.MATCH_RANK_MAX)
|
|
|
-
|
|
|
- local candidates = PeakBattlefieldDB.getPlayersInRankRange(minRank, maxRank, uuid)
|
|
|
-
|
|
|
- -- 随机选择5个对手
|
|
|
- local opponentList = {}
|
|
|
- local selected = {}
|
|
|
- local needCnt = PeakBattlefieldDefine.OPPONENT_LIST_SIZE
|
|
|
-
|
|
|
- if #candidates > 0 then
|
|
|
- for i = 1, math.min(needCnt, #candidates) do
|
|
|
- local idx = math.random(1, #candidates)
|
|
|
- while selected[idx] do
|
|
|
- idx = math.random(1, #candidates)
|
|
|
- end
|
|
|
- selected[idx] = true
|
|
|
- opponentList[#opponentList + 1] = {
|
|
|
- uuid = candidates[idx]._id,
|
|
|
- rank = candidates[idx].rank
|
|
|
- }
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- return opponentList
|
|
|
-end
|
|
|
-
|
|
|
-- 刷新对手列表
|
|
|
-function refreshOpponents(human)
|
|
|
- local rank = PeakBattlefieldDB.getRank(human.db._id)
|
|
|
+function CommerceActPeakBettle_Refresh(human)
|
|
|
+ local rank = getRank(human.db._id)
|
|
|
local opponentList = generateOpponents(human.db._id, rank)
|
|
|
- PeakBattlefieldDB.setOpponentList(human.db._id, opponentList)
|
|
|
+ setOpponentList(human.db._id, opponentList)
|
|
|
|
|
|
local msgRet = Msg.gc.GC_PEAK_BATTLEFIELD_REFRESH
|
|
|
local len = 0
|
|
|
for i = 1, #opponentList do
|
|
|
- if len >= PeakBattlefieldDefine.OPPONENT_LIST_SIZE then break end
|
|
|
+ if len >= OPPONENT_LIST_SIZE then break end
|
|
|
local opponent = opponentList[i]
|
|
|
- local opponentData = PeakBattlefieldDB.getData(opponent.uuid)
|
|
|
+ local opponentData = getData(opponent.uuid)
|
|
|
if opponentData then
|
|
|
len = len + 1
|
|
|
local net = msgRet.opponentList[len]
|
|
|
@@ -225,9 +505,9 @@ function refreshOpponents(human)
|
|
|
end
|
|
|
|
|
|
-- 挑战对手
|
|
|
-function challenge(human, opponentUuid)
|
|
|
+function CommerceActPeakBettle_Challenge(human, opponentUuid)
|
|
|
-- 检查对手是否在对手列表中
|
|
|
- local opponentList = PeakBattlefieldDB.getOpponentList(human.db._id)
|
|
|
+ local opponentList = getOpponentList(human.db._id)
|
|
|
local found = false
|
|
|
for i = 1, #opponentList do
|
|
|
if opponentList[i].uuid == opponentUuid then
|
|
|
@@ -241,18 +521,18 @@ function challenge(human, opponentUuid)
|
|
|
end
|
|
|
|
|
|
-- 检查挑战次数
|
|
|
- local freeCnt = PeakBattlefieldDB.getFreeChallengeCnt(human.db._id)
|
|
|
+ local freeCnt = getFreeChallengeCnt(human.db._id)
|
|
|
if freeCnt > 0 then
|
|
|
-- 使用免费次数
|
|
|
- if not PeakBattlefieldDB.consumeFreeChallenge(human.db._id) then
|
|
|
+ if not consumeFreeChallenge(human.db._id) then
|
|
|
return Broadcast.sendErr(human, "免费挑战次数不足")
|
|
|
end
|
|
|
else
|
|
|
-- 消耗道具
|
|
|
- if not BagLogic.checkItem(human, PeakBattlefieldDefine.CHALLENGE_COST_ITEM_ID, PeakBattlefieldDefine.CHALLENGE_COST_ITEM_CNT) then
|
|
|
+ if not BagLogic.checkItem(human, CHALLENGE_COST_ITEM_ID, CHALLENGE_COST_ITEM_CNT) then
|
|
|
return Broadcast.sendErr(human, "挑战券不足")
|
|
|
end
|
|
|
- BagLogic.delItem(human, PeakBattlefieldDefine.CHALLENGE_COST_ITEM_ID, PeakBattlefieldDefine.CHALLENGE_COST_ITEM_CNT, "peak_battlefield_challenge")
|
|
|
+ BagLogic.delItem(human, CHALLENGE_COST_ITEM_ID, CHALLENGE_COST_ITEM_CNT, "peak_battlefield_challenge")
|
|
|
end
|
|
|
|
|
|
-- 启动战斗
|
|
|
@@ -261,32 +541,29 @@ function challenge(human, opponentUuid)
|
|
|
combatType = COMBAT_TYPE_PEAK_BATTLEFIELD
|
|
|
}
|
|
|
|
|
|
- -- 获取对手的防守阵容(需要根据实际需求实现)
|
|
|
- -- 这里假设使用系统提供的英雄数据
|
|
|
- -- 注意:需要确保在 Excel 配置中注册了战斗类型和模块
|
|
|
CombatLogic.combatBegin(human, nil, {opponentUuid = opponentUuid}, COMBAT_TYPE_PEAK_BATTLEFIELD, cbParam, false)
|
|
|
end
|
|
|
|
|
|
-- 战斗结束回调
|
|
|
-function onFightEnd(human, result, combatType, cbParam, combatInfo, param)
|
|
|
+function CommerceActPeakBettle_OnFightEnd(human, result, combatType, cbParam, combatInfo, param)
|
|
|
if combatType ~= COMBAT_TYPE_PEAK_BATTLEFIELD then return end
|
|
|
if not cbParam or not cbParam.opponentUuid then return end
|
|
|
|
|
|
local opponentUuid = cbParam.opponentUuid
|
|
|
local isWin = (result == CombatDefine.RESULT_WIN)
|
|
|
|
|
|
- local oldRank = PeakBattlefieldDB.getRank(human.db._id)
|
|
|
+ local oldRank = getRank(human.db._id)
|
|
|
local newRank = oldRank
|
|
|
|
|
|
-- 胜利:交换排名
|
|
|
if isWin then
|
|
|
- PeakBattlefieldDB.swapRank(human.db._id, opponentUuid)
|
|
|
- newRank = PeakBattlefieldDB.getRank(human.db._id)
|
|
|
+ swapRank(human.db._id, opponentUuid)
|
|
|
+ newRank = getRank(human.db._id)
|
|
|
|
|
|
-- 刷新对手列表
|
|
|
- local rank = PeakBattlefieldDB.getRank(human.db._id)
|
|
|
+ local rank = getRank(human.db._id)
|
|
|
local opponentList = generateOpponents(human.db._id, rank)
|
|
|
- PeakBattlefieldDB.setOpponentList(human.db._id, opponentList)
|
|
|
+ setOpponentList(human.db._id, opponentList)
|
|
|
|
|
|
-- 检查英雄解锁
|
|
|
checkAndUnlockHeroes(human, newRank)
|
|
|
@@ -298,7 +575,7 @@ function onFightEnd(human, result, combatType, cbParam, combatInfo, param)
|
|
|
end
|
|
|
|
|
|
-- 发放奖励(挑战奖励,rewardType=1)
|
|
|
- local rewardId = isWin and PeakBattlefieldDefine.REWARD_ID_WIN or PeakBattlefieldDefine.REWARD_ID_LOSE
|
|
|
+ local rewardId = isWin and REWARD_ID_WIN or REWARD_ID_LOSE
|
|
|
local rewardConfig = PeakBattlefieldRewardExcel.rankReward[rewardId]
|
|
|
if rewardConfig and rewardConfig.rewardType == 1 and rewardConfig.reward then
|
|
|
BagLogic.addItemList(human, rewardConfig.reward, "peak_battlefield_challenge")
|
|
|
@@ -321,12 +598,12 @@ function onFightEnd(human, result, combatType, cbParam, combatInfo, param)
|
|
|
|
|
|
-- 胜利时发送新的对手列表
|
|
|
if isWin then
|
|
|
- local opponentList = PeakBattlefieldDB.getOpponentList(human.db._id)
|
|
|
+ local opponentList = getOpponentList(human.db._id)
|
|
|
local len = 0
|
|
|
for i = 1, #opponentList do
|
|
|
- if len >= PeakBattlefieldDefine.OPPONENT_LIST_SIZE then break end
|
|
|
+ if len >= OPPONENT_LIST_SIZE then break end
|
|
|
local opponent = opponentList[i]
|
|
|
- local opponentData = PeakBattlefieldDB.getData(opponent.uuid)
|
|
|
+ local opponentData = getData(opponent.uuid)
|
|
|
if opponentData then
|
|
|
len = len + 1
|
|
|
local net = msgRet.opponentList[len]
|
|
|
@@ -352,103 +629,9 @@ function onFightEnd(human, result, combatType, cbParam, combatInfo, param)
|
|
|
Msg.send(msgRet, human.fd)
|
|
|
end
|
|
|
|
|
|
--- 检查并解锁英雄(使用系统英雄表,按阵营解锁)
|
|
|
-function checkAndUnlockHeroes(human, rank)
|
|
|
- local HeroExcel = require("excel.hero").hero
|
|
|
- local CombatDefine = require("combat.CombatDefine")
|
|
|
-
|
|
|
- local currentUnlocked = PeakBattlefieldDB.getUnlockedHeroes(human.db._id)
|
|
|
- local newUnlocked = {}
|
|
|
-
|
|
|
- -- 根据排名解锁英雄:初始排名时解锁每个阵营的初始英雄
|
|
|
- -- 可以根据排名区间扩展更多解锁逻辑
|
|
|
- if rank <= PeakBattlefieldDefine.INIT_RANK then
|
|
|
- -- 使用 CombatDefine 中的阵营定义
|
|
|
- local camps = {
|
|
|
- CombatDefine.CAMP_TYPE1, -- 恶魔(人族)
|
|
|
- CombatDefine.CAMP_TYPE2, -- 圣堂(妖族)
|
|
|
- CombatDefine.CAMP_TYPE3 -- 不死(兽族)
|
|
|
- }
|
|
|
-
|
|
|
- for _, camp in ipairs(camps) do
|
|
|
- -- 从HeroExcel中获取该阵营的所有英雄
|
|
|
- local campHeroes = {}
|
|
|
- for heroId, heroConfig in pairs(HeroExcel) do
|
|
|
- if heroConfig.camp == camp then
|
|
|
- campHeroes[#campHeroes + 1] = heroId
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- -- 随机选择初始数量的英雄
|
|
|
- if #campHeroes > 0 then
|
|
|
- local count = PeakBattlefieldDefine.INIT_HERO_CNT_PER_CAMP
|
|
|
- local maxSelect = math.min(count, #campHeroes)
|
|
|
- for i = 1, maxSelect do
|
|
|
- local idx = math.random(1, #campHeroes)
|
|
|
- local heroId = campHeroes[idx]
|
|
|
-
|
|
|
- -- 检查是否已解锁
|
|
|
- local found = false
|
|
|
- for k = 1, #currentUnlocked do
|
|
|
- if currentUnlocked[k] == heroId then
|
|
|
- found = true
|
|
|
- break
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- if not found then
|
|
|
- newUnlocked[#newUnlocked + 1] = heroId
|
|
|
- currentUnlocked[#currentUnlocked + 1] = heroId
|
|
|
- end
|
|
|
-
|
|
|
- -- 移除已选择的英雄,避免重复
|
|
|
- table.remove(campHeroes, idx)
|
|
|
- if #campHeroes == 0 then break end
|
|
|
- end
|
|
|
- end
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
- -- 可以根据排名区间添加更多解锁逻辑
|
|
|
- -- 例如:排名前100时解锁更多英雄等
|
|
|
-
|
|
|
- if #newUnlocked > 0 then
|
|
|
- PeakBattlefieldDB.updateUnlockedHeroes(human.db._id, currentUnlocked)
|
|
|
- -- 发送提示
|
|
|
- Broadcast.sendErr(human, "解锁新英雄!")
|
|
|
- end
|
|
|
-end
|
|
|
-
|
|
|
--- 发送战败邮件
|
|
|
-function sendDefeatMail(defeatedUuid, attackerUuid, newRank)
|
|
|
- local attackerDb = RoleDBLogic.getDb(attackerUuid)
|
|
|
- if not attackerDb then return end
|
|
|
-
|
|
|
- -- 获取邮件配置(需要在邮件配置表中添加对应的邮件ID)
|
|
|
- local mailID = PeakBattlefieldDefine.MAIL_ID_DEFEAT
|
|
|
- if not mailID or mailID == 0 then
|
|
|
- -- 如果没有配置邮件ID,跳过发送
|
|
|
- return
|
|
|
- end
|
|
|
-
|
|
|
- local mailConfig = MailExcel.mail[mailID]
|
|
|
- if not mailConfig then
|
|
|
- -- 邮件配置不存在,记录日志但不影响游戏流程
|
|
|
- print("[sendDefeatMail] 邮件配置不存在,mailID=" .. (mailID or 0))
|
|
|
- return
|
|
|
- end
|
|
|
-
|
|
|
- -- 格式化邮件内容:使用 Util.format,参数顺序对应邮件内容中的 {1} {2}
|
|
|
- -- {1}=攻击者名字, {2}=新排名
|
|
|
- local content = Util.format(mailConfig.content or "", attackerDb.name or "", newRank)
|
|
|
-
|
|
|
- -- 发送邮件
|
|
|
- MailManager.add(MailManager.SYSTEM, defeatedUuid, mailConfig.title or "巅峰战区赛", content, nil, mailConfig.senderName or "系统")
|
|
|
-end
|
|
|
-
|
|
|
-- 查询排名奖励
|
|
|
-function rankRewardQuery(human)
|
|
|
- local rank = PeakBattlefieldDB.getRank(human.db._id)
|
|
|
+function CommerceActPeakBettle_RankRewardQuery(human)
|
|
|
+ local rank = getRank(human.db._id)
|
|
|
|
|
|
local msgRet = Msg.gc.GC_PEAK_BATTLEFIELD_RANK_REWARD_QUERY
|
|
|
msgRet.rank = rank
|
|
|
@@ -478,14 +661,13 @@ function rankRewardQuery(human)
|
|
|
end
|
|
|
|
|
|
-- 活动结算(活动结束时发放排名奖励)
|
|
|
--- 需要在活动结束的定时器中调用,或通过活动结束回调触发
|
|
|
-function onActivityEnd()
|
|
|
+function CommerceActPeakBettle_OnActivityEnd()
|
|
|
-- 获取所有玩家数据
|
|
|
- if not PeakBattlefieldDB.RANK_2_DATA then return end
|
|
|
+ if not RANK_2_DATA then return end
|
|
|
|
|
|
-- 遍历所有排名,发放奖励
|
|
|
- for rank = 1, #PeakBattlefieldDB.RANK_2_DATA do
|
|
|
- local data = PeakBattlefieldDB.RANK_2_DATA[rank]
|
|
|
+ for rank = 1, #RANK_2_DATA do
|
|
|
+ local data = RANK_2_DATA[rank]
|
|
|
if data and data._id then
|
|
|
-- 根据排名查找对应的奖励配置(只处理排名奖励 rewardType=2或3)
|
|
|
if PeakBattlefieldRewardExcel.rankReward then
|
|
|
@@ -497,8 +679,7 @@ function onActivityEnd()
|
|
|
local rankMax = config.rank[2]
|
|
|
if rank >= rankMin and rank <= rankMax then
|
|
|
-- 发放排名奖励(通过邮件)
|
|
|
- -- 需要在邮件配置表中添加排名奖励邮件ID
|
|
|
- local mailID = PeakBattlefieldDefine.MAIL_ID_RANK_REWARD
|
|
|
+ local mailID = MAIL_ID_RANK_REWARD
|
|
|
if mailID and mailID > 0 then
|
|
|
local mailConfig = MailExcel.mail[mailID]
|
|
|
if mailConfig and config.reward then
|
|
|
@@ -514,21 +695,25 @@ function onActivityEnd()
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
-
|
|
|
- -- 活动结束后可以重置数据(如果需要)
|
|
|
- -- PeakBattlefieldDB.resetData()
|
|
|
end
|
|
|
|
|
|
--- 检查活动是否结束,如果结束则触发结算
|
|
|
--- 可以在定时器中调用,或在查询时检查
|
|
|
-function checkActivityEnd(human)
|
|
|
- local startTime, endTime = getBattlefieldSoulTime(human)
|
|
|
- if not endTime then return false end
|
|
|
-
|
|
|
- local now = os.time()
|
|
|
- -- 检查是否刚过活动结束时间(避免重复结算)
|
|
|
- -- 这里需要记录上次结算时间,避免重复结算
|
|
|
- -- 暂时返回是否已结束
|
|
|
- return now >= endTime
|
|
|
+-- 检查红点
|
|
|
+function isRed(human)
|
|
|
+ -- 可以根据需要实现红点逻辑
|
|
|
+ return false
|
|
|
+end
|
|
|
+
|
|
|
+----------------------------------------- 战斗模块接口 -------------------------------------
|
|
|
+-- 供战斗模块使用的公共接口
|
|
|
+
|
|
|
+-- 获取玩家数据(供战斗模块使用)
|
|
|
+function GetData(uuid)
|
|
|
+ return getData(uuid)
|
|
|
+end
|
|
|
+
|
|
|
+-- 检查对手是否存在(供战斗模块使用)
|
|
|
+function CheckOpponent(opponentUuid)
|
|
|
+ local data = getData(opponentUuid)
|
|
|
+ return data ~= nil
|
|
|
end
|
|
|
|