| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- --[[
- 作者: 无心
- 日期: 2025-08-24
- 功能介绍:
- 本文件为线路管理(LineManager)模块,主要负责处理与游戏多线路相关的逻辑,包括获取玩家当前线路、地图、线路策略配置等功能。
- 该模块为游戏服务器提供多线路分流、线路策略、进入条件等相关的辅助方法。
- --]] LineManager = {}
- LineManager.init = function()
- end
- --- 获取玩家当前线路ID
- --- @param actor table 玩家对象
- --- @return number 当前线路ID
- function LineManager.getCurrentLine(actor)
- return getbaseinfo(actor, "line")
- end
- --- 获取玩家当前地图ID
- --- @param actor table 玩家对象
- --- @return number 当前地图ID
- function LineManager.getCurrentMapId(actor)
- return getbaseinfo(actor, "mapid")
- end
- -- 公共方法:根据actor和字段名获取线路策略配置表中的字段值
- function LineManager.getLinePolicyField(actor, fieldName)
- local lineId = LineManager.getCurrentLine(actor)
- local mapId = LineManager.getCurrentMapId(actor)
- local linePolicyConfig = ConfigDataManager.getTableValue("cfg_map_line", "line_policy_config", "id", mapId)
- -- info(string.format("MS LineManager.getLinePolicyField: 获取线路策略配置信息=%s", linePolicyConfig))
- if not linePolicyConfig or linePolicyConfig == "" then
- return nil
- end
- local foundPolicyId = nil
- for _, mapping in ipairs(string.split(linePolicyConfig, "|")) do
- local parts = string.split(mapping, "#")
- if #parts == 2 then
- local configLineId = tonumber(parts[1])
- local policyId = tonumber(parts[2])
- if configLineId == lineId then
- foundPolicyId = policyId
- break
- end
- end
- end
- -- info(string.format("MS LineManager.getLinePolicyField: 获取线路策略配置id = %s", foundPolicyId))
- if not foundPolicyId then
- return nil
- end
- local value = ConfigDataManager.getTableValue("cfg_line_policy", fieldName, "id", foundPolicyId)
- -- info(string.format("MS LineManager.getLinePolicyField: 获取线路策略配置字段[%s]=%s", fieldName, value))
- return value
- end
- -- 通过公共方法获取经验倍率
- function LineManager.GetLineExpRate(actor)
- local expRate = LineManager.getLinePolicyField(actor, "expRate")
- return tonumber(expRate) or 100
- end
- -- 通过公共方法获取掉落倍率
- function LineManager.getDropRate(actor)
- local dropRate = LineManager.getLinePolicyField(actor, "dropRate")
- -- info(string.format("MS LineManager >>> 配置文件 -> 获取地图基础爆率加成完成 线路爆率=%s", tostring(dropRate)))
- return tonumber(dropRate) or 100
- end
- --- 获取线路经验倍率
- --- @param actor table 玩家对象
- --- @return number 经验倍率
- function LineManager.getExpRate(actor)
- local expRate = LineManager.getLinePolicyField(actor, "expRate")
- return tonumber(expRate) or 100
- end
- --- 检查线路是否允许PK
- --- @param actor table 玩家对象
- --- @return boolean
- function LineManager.isPvpEnabled(actor)
- local pvpEnabled = LineManager.getLinePolicyField(actor, "pvpEnabled")
- return tonumber(pvpEnabled) == 1
- end
- --- 检查线路是否允许交易
- --- @param actor table 玩家对象
- --- @return boolean
- function LineManager.isTradeEnabled(actor)
- local tradeEnabled = LineManager.getLinePolicyField(actor, "tradeEnabled")
- return tonumber(tradeEnabled) == 1
- end
- --- 检查线路是否开放古战场
- --- @param actor table 玩家对象
- --- @return boolean
- function LineManager.isAncientBattleEnabled(actor)
- local ancientBattleEnabled = LineManager.getLinePolicyField(actor, "ancientBattleEnabled")
- return tonumber(ancientBattleEnabled) == 1
- end
- --- 检查线路是否开放活动
- --- @param actor table 玩家对象
- --- @return boolean
- function LineManager.isActivityEnabled(actor)
- local activityEnabled = LineManager.getLinePolicyField(actor, "activityEnabled")
- return tonumber(activityEnabled) == 1
- end
- --- 检查线路是否允许怪物
- --- @param actor table 玩家对象
- --- @return boolean
- function LineManager.isMonsterEnabled(actor)
- local monsterEnabled = LineManager.getLinePolicyField(actor, "monsterEnabled")
- return tonumber(monsterEnabled) == 1
- end
- function LineManager.takeoffequip(actor)
- local mapId = getbaseinfo(actor, "map")
- local wear_conditions = ConfigDataManager.getTableValue("cfg_map_line", "wear_conditions", "id", mapId)
- if string.isNullOrEmpty(wear_conditions) then
- return
- end
- local checkResult, tip = LineManager.CheckCanEnterLineMap(actor, mapId, 1)
- if checkResult ~= nil and checkResult == false then
- APISetInt(actor, "IS_TAKEOFF_EQUIP_TRANSFET", 1)
- tipinfo(actor, tip)
- maptransfer(actor, 135, 128 , 1001, 1, 0)
- end
- end
- --- 检查玩家是否可以进入指定线路地图
- --- @param actor table 玩家对象
- --- @param targetLine number 目标线路ID
- --- @param targetMap number 目标地图ID
- --- @return boolean, string 是否可以进入,原因
- function LineManager.CheckCanEnterLineMap(actor, targetMapId, targetLine)
- -- 获取目标地图和线路的线路策略配置字段
- local function getLinePolicyFieldForTarget(mapId, lineId, fieldName)
- local linePolicyConfig = ConfigDataManager.getTableValue("cfg_map_line", "line_policy_config", "id", mapId)
- if not linePolicyConfig or linePolicyConfig == "" then
- return nil
- end
- local foundPolicyId = nil
- for _, mapping in ipairs(string.split(linePolicyConfig, "|")) do
- local parts = string.split(mapping, "#")
- if #parts == 2 then
- local configLineId = tonumber(parts[1])
- local policyId = tonumber(parts[2])
- if configLineId == lineId then
- foundPolicyId = policyId
- break
- end
- end
- end
- if not foundPolicyId then
- return nil
- end
- local value = ConfigDataManager.getTableValue("cfg_line_policy", fieldName, "id", foundPolicyId)
- return value
- end
- local wear_conditions = ConfigDataManager.getTableValue("cfg_map_line", "wear_conditions", "id", targetMapId)
- if not string.isNullOrEmpty(wear_conditions) then
- local equips = getputonequipinfo(actor)
- local conditions = string.split(wear_conditions, "|")
- local isPass = table.count(conditions) <= 0
- local strTip = ""
- local notNecessaryMax = 0
- local notNecessaryPass = 0
- for _, v in ipairs(conditions) do
- local condition = string.split(v, "#")
- local type = condition[1]
- local equip = condition[2]
- local isNecessary = tonumber(condition[3])
- local tip = condition[4]
- local isPassTmp = false
- if type == "1" then
- local allposs = string.split(equip, "&")
- local isWear = nil
- for _, vpos in ipairs(allposs) do
- local hasWear, v = table.findByCondi(equips, function(a)
- local pos = gameequip.pos(a.equipindex)
- if a.equipindex > 70000 and tonumber(vpos) >= 10000 then
- pos = pos + 9984
- end
- return pos == tonumber(vpos);
- end)
- if tonumber(vpos) == 10003 then
- local allmount = getallmount(actor)
- local isWear2 = table.findByCondi(allmount, function(a)
- return a.wear == 1 or a.auto == 1
- end)
- hasWear = isWear2
- end
- if hasWear == nil then
- isWear = nil
- break
- else
- isWear = hasWear
- end
- end
- isPassTmp = isWear ~= nil
- elseif type == "2" then
- local hasWear, v = table.findByCondi(equips, function(a)
- return a.cfgid == tonumber(equip);
- end)
- isPassTmp = hasWear ~= nil
- elseif type == "3" then
- local hasWear, v = table.findByCondi(equips, function(a)
- return a.cfgid == tonumber(equip);
- end)
- local count = getbagitemcountbyid(actor, tonumber(equip))
- isPassTmp = not (hasWear == nil and count == 0)
- elseif type == "4" then
- local totalLv = 0
- for kk, vv in pairs(equips) do
- local lv = EquipFunc.getEquipStrengthLevel(actor, vv.id)
- totalLv = totalLv + lv
- end
- isPassTmp = not (totalLv < tonumber(equip))
- end
- if isNecessary == 1 then
- if isPassTmp ~= true then
- strTip = tip
- isPass = false
- break
- else
- isPass = isPassTmp
- end
- end
- if isNecessary == 0 then
- notNecessaryMax = notNecessaryMax + 1
- if isPassTmp == true then
- isPass = true
- notNecessaryPass = notNecessaryPass + 1
- else
- strTip = tip
- end
- end
- end
- if isPass ~= true then
- -- tipinfo(actor, strTip)
- return false, strTip
- elseif notNecessaryMax > 0 and notNecessaryPass <= 0 then
- -- tipinfo(actor, strTip)
- return false, strTip
- end
- end
- local tradeCardRequired = tonumber(getLinePolicyFieldForTarget(targetMapId, targetLine, "TradeCard")) or 0
- local enjoyPrivilegeRequired = tonumber(getLinePolicyFieldForTarget(targetMapId, targetLine, "EnjoyPrivilege")) or 0
- local unionLevelRequired = tonumber(getLinePolicyFieldForTarget(targetMapId, targetLine, "UnionLevel")) or 0
- local vipLevelRequired = tonumber(getLinePolicyFieldForTarget(targetMapId, targetLine, "VipLevel")) or 0
- -- info("MS LineManager.CheckCanEnterLineMap-> ", targetMapId, targetLine, tradeCardRequired, enjoyPrivilegeRequired,
- -- unionLevelRequired, vipLevelRequired)
- -- 1. 检查是否需要交易卡
- if tradeCardRequired > 0 then
- if not LineManager.hasTradeCard(actor) then
- tipinfo(actor, "需要交易卡")
- return false, "需要交易卡"
- end
- end
- -- 2. 检查是否需要畅玩特权
- if enjoyPrivilegeRequired > 0 then
- if not PrivilegeMonth.hasEnjoyPrivilege(actor) then
- tipinfo(actor, "需要畅玩特权")
- return false, "需要畅玩特权"
- end
- end
- -- 3. 检查战盟等级
- if unionLevelRequired > 0 then
- if not LineManager.checkUnionLevel(actor, unionLevelRequired) then
- tipinfo(actor, string.format("战盟等级不足,需要%d级", unionLevelRequired))
- return false, string.format("战盟等级不足,需要%d级", unionLevelRequired)
- end
- end
- -- 4. 检查VIP等级
- if vipLevelRequired > 0 then
- if not LineManager.checkVipLevel(actor, vipLevelRequired) then
- tipinfo(actor, string.format("VIP等级不足,需要%d级", vipLevelRequired))
- return false, string.format("VIP等级不足,需要%d级", vipLevelRequired)
- end
- end
- -- 所有条件都满足
- return true, "可以进入"
- end
- --- 检查玩家进入指定线路地图所需道具
- --- @param actor table 玩家对象
- --- @param itemsNeedIndex number 所需道具idx
- --- @param targetMapId number 目标地图ID
- --- @return boolean, string 是否可以进入,原因
- function LineManager.CheckEnterLineMapItemsNeed(actor, targetMapId, itemsNeedIndex)
- local mapId = tonumber(getbaseinfo(actor, "mapid"))
- if mapId == targetMapId then
- return true, ""
- end
- local joinMapNeedSelect = {} -- 选择需要道具
- local joinMapNeed = {} -- 必须需要道具
- local strTip = ""
- local items_need = ConfigDataManager.getTableValue("cfg_map_line", "items_need", "id", targetMapId)
- if not string.isNullOrEmpty(items_need) then
- local conditionArr = string.split(items_need, "|")
- for _, conditionData in ipairs(conditionArr) do
- local conditionStr = string.split(conditionData, "#")
- strTip = conditionStr[3]
- if tonumber(conditionStr[2]) == 0 then
- local itemArr = string.split(conditionStr[1], "&")
- if table.count(itemArr) > 1 then
- table.insert(joinMapNeedSelect, {itemId = tonumber(itemArr[1]), itemNum = tonumber(itemArr[2])})
- end
- else
- local itemArr = string.split(conditionStr[1], "&")
- if table.count(itemArr) > 1 then
- table.insert(joinMapNeed, {itemId = tonumber(itemArr[1]), itemNum = tonumber(itemArr[2])})
- end
- end
- end
- end
- local itemNeed = joinMapNeedSelect[itemsNeedIndex]
- if table.count(joinMapNeedSelect) > 0 then
- if itemNeed == nil then
- tipinfo(actor, "材料扣除失败")
- return false, strTip
- end
- else
- return true, ""
- end
- -- 整合所需道具
- local itemsNeed = {}
- if itemNeed ~= nil then
- table.insert(itemsNeed, {itemId = itemNeed.itemId, itemNum = itemNeed.itemNum})
- end
- for _,item in ipairs(joinMapNeed) do
- table.insert(itemsNeed, {itemId = item.itemId, itemNum = item.itemNum})
- end
- -- 传送至地图所需道具扣除
- for _, item in ipairs(itemsNeed) do
- local result = removeitemfrombag(actor, item.itemId, item.itemNum, 0, 9999, "传送古战场消耗")
- if not result then
- tipinfo(actor, "扣除道具失败")
- return false, strTip
- end
- end
- return true, ""
- end
- --- 检查是否有交易卡(优化版本)
- --- @param actor table 玩家对象
- --- @return boolean
- function LineManager.hasTradeCard(actor)
- -- 这里需要根据实际的交易卡道具ID进行判断
- local tradeCardId = 70700001 -- 假设的交易卡道具ID,需要根据实际配置调整
- return Bag.hasItem(actor, tradeCardId, 1)
- end
- --- 检查VIP等级(优化版本)
- --- @param actor table 玩家对象
- --- @param requiredLevel number 要求的VIP等级
- --- @return boolean
- function LineManager.checkVipLevel(actor, requiredLevel)
- -- 这里需要根据实际的VIP系统进行判断
- -- local vipLevel = getplaydef(actor, "VIP_LEVEL") or 0
- -- return tonumber(vipLevel) >= requiredLevel
- return true
- end
- --- 检查战盟等级(优化版本)
- --- @param actor table 玩家对象
- --- @param requiredLevel number 要求的战盟等级
- --- @return boolean
- function LineManager.checkUnionLevel(actor, requiredLevel)
- -- 这里需要根据实际的战盟系统进行判断
- -- local unionLevel = getplaydef(actor, "UNION_LEVEL") or 0
- -- return tonumber(unionLevel) >= requiredLevel
- return true
- end
- --- 应用掉落倍率
- --- @param actor table 玩家对象
- --- @param baseDropRate number 基础掉落率
- --- @return number 实际掉落率
- function LineManager.applyDropRate(actor, baseDropRate)
- -- 获取线路爆率
- local lineDropRate = LineManager.getDropRate(actor)
- -- info(string.format("MS LineManager >>> 开始获取地图基础爆率加成 基础掉落率=%s", tostring(baseDropRate)))
- -- info(string.format("MS LineManager >>> 获取地图基础爆率加成完成 线路爆率=%s", tostring(lineDropRate)))
- -- 计算实际掉落率
- local actualDropRate = baseDropRate * (lineDropRate / 100)
- -- info(string.format("MS LineManager >>> 玩家掉落倍率调整:倍率=%s, 基础掉落率=%s, 实际掉落率=%s", tostring(lineDropRate), tostring(baseDropRate), tostring(actualDropRate)))
- return actualDropRate
- end
- --- 应用经验倍率
- --- @param actor table 玩家对象
- --- @param baseExp number 基础经验
- --- @return number 实际经验
- function LineManager.applyExpRate(actor, baseExp)
- local lineExpRate = LineManager.GetLineExpRate(actor)
- if not lineExpRate then
- -- info(string.format("MS LineManager.applyExpRate 检测没有线路策略: actor=%s, currentLine=%d, lineExpRate=nil", actor:toString(), currentLine))
- return baseExp
- end
- -- 计算实际经验
- local actualExp = baseExp * (tonumber(lineExpRate) / 100)
- return actualExp
- end
|