hxp
8 天以前 bd9dce2d66b5086712596b8dac6d9116be65bafd
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerArena.py
@@ -22,6 +22,7 @@
import PlayerControl
import IpyGameDataPY
import ChPyNetSendPack
import PlayerGoldInvest
import PlayerViewCache
import NetPackCommon
import PyGameData
@@ -166,6 +167,8 @@
    return
def DoArenaOpen(curPlayer):
    storeMax = IpyGameDataPY.GetFuncCfg("ArenaSet", 3)
    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_ArenaTicket, storeMax, "ArenaOpen")
    __DoArenaSeasonReset(curPlayer)
    return
@@ -179,11 +182,11 @@
def GetArenaTicketStoreMax(curPlayer):
    ## 获取挑战券存储上限
    baseCnt = IpyGameDataPY.GetFuncCfg("ArenaSet", 3)
    storeMax = IpyGameDataPY.GetFuncCfg("ArenaSet", 3)
    
    # 其他特权提升上限
    storeMax += PlayerGoldInvest.GetArenaTicketMax(curPlayer)
    
    storeMax = baseCnt
    return storeMax
#// B2 09 演武场匹配玩家 #tagCSArenaMatch
@@ -211,12 +214,12 @@
    playerID = curPlayer.GetPlayerID()
    playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
    matchScoreList = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 1)
    needMatchCount = len(matchScoreList)
    
    GameWorld.DebugLog("竞技场玩家刷新匹配列表: isRefresh=%s,playerScore=%s,gmMatchIDList=%s,isSys=%s" % (isRefresh, playerScore, gmMatchIDList, isSys), playerID)
    GameWorld.DebugLog("    matchScoreList=%s" % (matchScoreList), playerID)
    GameWorld.DebugLog("needMatchCount=%s,matchScoreList=%s" % (needMatchCount, matchScoreList), playerID)
    
    # 匹配对象缓存
    needMatchCount = len(matchScoreList)
    if playerID not in PyGameData.g_arenaPlayerMatchDict:
        PyGameData.g_arenaPlayerMatchDict[playerID] = []
    matchIDList = PyGameData.g_arenaPlayerMatchDict[playerID]
@@ -232,110 +235,193 @@
        if not costMoney or not moneyValue or not PlayerControl.PayMoney(curPlayer, costMoney, moneyValue, "Arena"):
            return
        
    billboardMgr = DBDataMgr.GetBillboardMgr()
    billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Arena)
    if not billBoard:
        return
    maxOrder = billBoard.GetCount()
    playerOrder = billBoard.IndexOfByID(playerID) + 1  # 玩家在排行榜中的名次,没有名次为-1
    matchRobotCntDict = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 3)
    if playerOrder > 0:
        matchRobotRange = GameWorld.GetOrderValueByDict(matchRobotCntDict, playerOrder)
        matchRobotCnt = random.randint(matchRobotRange[0], matchRobotRange[1])
    else:
        matchRobotCnt = needMatchCount
    matchPlayerCnt = needMatchCount - matchRobotCnt
    GameWorld.DebugLog("    maxOrder=%s,playerOrder=%s,matchRobotCnt=%s,matchPlayerCnt=%s" % (maxOrder, playerOrder, matchRobotCnt, matchPlayerCnt), playerID)
    fromLowerCnt, matchPerRank = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 2)
    toOrder = playerOrder + fromLowerCnt * matchPerRank # 从低名次往高名次匹配
    GameWorld.DebugLog("    fromLowerCnt=%s,matchPerRank=%s,toOrder=%s" % (fromLowerCnt, matchPerRank, toOrder), playerID)
    matchIDList = [] # 最终匹配的玩家ID列表
    matchOrderList = [] # 匹配到的名次
    for _ in range(matchPlayerCnt):
        fromOrder = max(1, toOrder - matchPerRank)
        if toOrder <= fromOrder:
            break
        orderList = range(fromOrder, toOrder)
        random.shuffle(orderList)
        if playerOrder in orderList:
            orderList.remove(playerOrder) # 不包含自己
        if not orderList:
            break
    viewCacheDict = {}
    robotFPCoefficient =  IpyGameDataPY.GetFuncCfg("ArenaMatchRobot", 1) # 必定匹配机器人的玩家战力系数,玩家战力*该系数<=机器人最高战力时必定匹配机器人
    playerFightPower = PlayerControl.GetFightPower(curPlayer)
    robotFPSortList = PlayerViewCache.GetRobotFightPowerSortList()
    robotFightPowerMax = robotFPSortList[0][0] if robotFPSortList else 0
    robotCntTotal = len(robotFPSortList)
    GameWorld.DebugLog("玩家战力=%s,机器人最大战力=%s,匹配机器人战力系数=%s,机器人总数=%s"
                       % (playerFightPower, robotFightPowerMax, robotFPCoefficient, robotCntTotal), playerID)
    reFightPower = playerFightPower * robotFPCoefficient # 参考战力
    if reFightPower <= robotFightPowerMax:
        # 匹配机器人相对玩家战力百分比范围列表  [[相对玩家战力百分比A, B], ..],支持负数,如-30就是机器人比玩家低30%战力,10就是机器人比玩家高10%战力
        matchRobotFPPerList = IpyGameDataPY.GetFuncEvalCfg("ArenaMatchRobot", 2)
        GameWorld.DebugLog("全部匹配机器人: %s, reFightPower=%s <= %s" % (matchRobotFPPerList, reFightPower, robotFightPowerMax), playerID)
        loopIndex = 0
        for fpPerRange in matchRobotFPPerList[::-1]: # 从高战力往低战力匹配
            fpPerA, fpPerB = fpPerRange
            GameWorld.DebugLog("    处理匹配机器人战力段: fpPerA=%s,fpPerB=%s,loopIndex=%s" % (fpPerA, fpPerB, loopIndex), playerID)
            if loopIndex >= robotCntTotal:
                continue
            robotFPIDList = []
            for robotIndex in range(loopIndex, robotCntTotal):
                robotFightPower, robotID = robotFPSortList[robotIndex]
                fpPer = (robotFightPower / float(playerFightPower) - 1) * 100
                if fpPer < fpPerA:
                    GameWorld.DebugLog("        比低百分比还小的战力跳出,进入下一段匹配逻辑: %s,robotID=%s,robotFightPower=%s,fpPer=%s < %s"
                                       % (robotIndex, robotID, robotFightPower, fpPer, fpPerA), playerID)
                    break
                loopIndex = robotIndex + 1
                if fpPer > fpPerB:
                    #GameWorld.DebugLog("        比高百分比还大的战力跳过,不匹配: %s,robotID=%s,robotFightPower=%s,fpPer=%s > %s"
                    #                   % (robotIndex, robotID, robotFightPower, fpPer, fpPerB), playerID)
                    continue
                robotFPIDList.append([robotFightPower, robotID])
                #GameWorld.DebugLog("        战力在匹配段范围内,可匹配: %s,robotID=%s,robotFightPower=%s,%s <= fpPer(%s) <= %s"
                #                   % (robotIndex, robotID, robotFightPower, fpPerA, fpPer, fpPerB), playerID)
            if not robotFPIDList:
                GameWorld.DebugLog("        该战力范围段没有符合的机器人!", playerID)
                continue
            random.shuffle(robotFPIDList)
            robotFightPower, robotID = robotFPIDList[0]
            matchIDList.append(robotID)
            GameWorld.DebugLog("        匹配机器人: robotID=%s,robotFightPower=%s" % (robotID, robotFightPower), playerID)
        if len(matchIDList) < needMatchCount:
            GameWorld.DebugLog("    可匹配的机器人还不够,从剩下未遍历的机器人内匹配: loopIndex=%s" % loopIndex, playerID)
            if loopIndex < robotCntTotal:
                randIndexList = range(loopIndex, robotCntTotal)
                random.shuffle(randIndexList)
                matchIndexList = randIndexList[:needMatchCount-len(matchIDList)]
                matchIndexList.sort()
                for robotIndex in matchIndexList:
                    robotFightPower, robotID = robotFPSortList[robotIndex]
                    matchIDList.append(robotID)
                    GameWorld.DebugLog("        匹配机器人: robotID=%s,robotFightPower=%s" % (robotID, robotFightPower), playerID)
    else:
        # 匹配真人
        GameWorld.DebugLog("匹配真人: reFightPower=%s > %s" % (reFightPower, robotFightPowerMax), playerID)
        billboardMgr = DBDataMgr.GetBillboardMgr()
        billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Arena)
        if not billBoard:
            return
        
        if fromOrder == 1:
        maxOrder = billBoard.GetCount()
        playerOrder = billBoard.IndexOfByID(playerID) + 1  # 玩家在排行榜中的名次,没有名次为-1
        leastRobotCnt = IpyGameDataPY.GetFuncCfg("ArenaMatchRobot", 3)
        matchPlayerCnt = needMatchCount - leastRobotCnt
        GameWorld.DebugLog("    maxOrder=%s,playerOrder=%s,matchPlayerCnt=%s,leastRobotCnt=%s" % (maxOrder, playerOrder, matchPlayerCnt, leastRobotCnt), playerID)
        fromLowerCnt, matchPerRank = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 2)
        toOrder = playerOrder + fromLowerCnt * matchPerRank # 从低名次往高名次匹配
        GameWorld.DebugLog("    fromLowerCnt=%s,matchPerRank=%s,toOrder=%s" % (fromLowerCnt, matchPerRank, toOrder), playerID)
        for _ in range(matchPlayerCnt):
            fromOrder = max(1, toOrder - matchPerRank)
            if toOrder <= fromOrder:
                break
            orderList = range(fromOrder, toOrder)
            random.shuffle(orderList)
            if playerOrder in orderList:
                orderList.remove(playerOrder) # 不包含自己
            if not orderList:
                break
            for order in orderList:
                if order > maxOrder:
                    continue
                billData = billBoard.At(order - 1)
                tagID = billData.GetID()
                viewCache = PlayerViewCache.FindBattleViewCache(tagID)
                if not viewCache:
                    GameWorld.DebugLog("    无战斗缓存的玩家不匹配: tagID=%s,order=%s,fromOrder=%s,toOrder=%s" % (tagID, order, fromOrder, toOrder), playerID)
                    continue
                matchOrderList.append(order)
                if len(matchOrderList) >= matchPlayerCnt:
                    break
        else:
            order = orderList[0]
            if order <= maxOrder:
                matchOrderList.append(order)
                viewCacheDict[tagID] = viewCache
                
        GameWorld.DebugLog("    匹配玩家: fromOrder=%s,toOrder=%s,matchOrderList=%s" % (fromOrder, toOrder, matchOrderList), playerID)
        toOrder = fromOrder - 1
                if fromOrder == 1:
                    if len(matchOrderList) >= matchPlayerCnt:
                        break
                else:
                    break
            GameWorld.DebugLog("    匹配玩家: fromOrder=%s,toOrder=%s,matchOrderList=%s" % (fromOrder, toOrder, matchOrderList), playerID)
            toOrder = fromOrder - 1
        matchOrderList.sort()
        for matchOrder in matchOrderList:
            if matchOrder > maxOrder or matchOrder <= 0:
                break
            billData = billBoard.At(matchOrder - 1)
            tagID = billData.GetID()
            matchIDList.append(tagID)
        GameWorld.DebugLog("    匹配榜单结果: matchIDList=%s,matchOrderList=%s" % (matchIDList, matchOrderList), playerID)
        
    # GM指定匹配测试
    if gmMatchIDList != None and curPlayer.GetGMLevel():
        for gmMatchID in gmMatchIDList:
            if gmMatchID == playerID:
                GameWorld.DebugAnswer(curPlayer, "目标ID不能是自己!无法匹配!%s" % gmMatchID)
                GameWorld.DebugAnswer(curPlayer, "不能匹配自己!%s" % gmMatchID)
                continue
            
            gmMatchOrder = billBoard.IndexOfByID(gmMatchID) + 1
            if gmMatchOrder <= 0:
                GameWorld.DebugAnswer(curPlayer, "目标ID不在榜单上!无法匹配!%s" % gmMatchID)
            if gmMatchID in matchIDList:
                continue
            GameWorld.DebugAnswer(curPlayer, "指定匹配ID(%s),order(%s)" % (gmMatchID, gmMatchOrder))
            if gmMatchID not in matchOrderList:
                matchOrderList.insert(0, gmMatchOrder)
            viewCache = PlayerViewCache.FindBattleViewCache(gmMatchID)
            if not viewCache:
                GameWorld.DebugAnswer(curPlayer, "没有战斗缓存目标不匹配!%s" % gmMatchID)
                continue
            GameWorld.DebugAnswer(curPlayer, "指定匹配ID(%s)" % (gmMatchID))
            matchIDList.append(gmMatchID)
            viewCacheDict[gmMatchID] = viewCache
        matchOrderList = matchOrderList[:needMatchCount]
    matchOrderList.sort()
    matchIDList = [] # 最终匹配的玩家ID列表
    for matchOrder in matchOrderList:
        if matchOrder > maxOrder or matchOrder <= 0:
            break
        billData = billBoard.At(matchOrder - 1)
        matchIDList.append(billData.GetID())
        GameWorld.DebugLog("    指定匹配结果: matchIDList=%s" % (matchIDList), playerID)
        
    needRobotCnt = needMatchCount - len(matchIDList)
    GameWorld.DebugLog("    匹配榜单结果: matchIDList=%s,matchOrderList=%s,needRobotCnt=%s" % (matchIDList, matchOrderList, needRobotCnt), playerID)
    ipyDataMgr = IpyGameDataPY.IPY_Data()
    robotMax = ipyDataMgr.GetRobotCount()
    GameWorld.DebugLog("    最终还需机器人数=%s" % (needRobotCnt), playerID)
    robotFPIDList = []
    doCnt = 100
    while doCnt > 0 and needRobotCnt > 0 and robotMax:
    while doCnt > 0 and needRobotCnt > 0 and robotCntTotal:
        doCnt -= 1
        robotIndex = random.randint(0, robotMax - 1)
        robotIpyData = ipyDataMgr.GetRobotByIndex(robotIndex)
        robotID = robotIpyData.GetID()
        robotIndex = random.randint(0, robotCntTotal - 1)
        robotFightPower, robotID = robotFPSortList[robotIndex]
        if robotID not in matchIDList:
            matchIDList.append(robotID)
            robotFPIDList.append([robotFightPower, robotID])
            needRobotCnt -= 1
    if robotFPIDList:
        robotFPIDList.sort(reverse=True)
        #GameWorld.DebugLog("    补充机器人战力ID排序=%s" % (robotFPIDList), playerID)
        for _, robotID in robotFPIDList:
            if robotID in matchIDList:
                matchIDList.remove(robotID)
                matchIDList.append(robotID)
    GameWorld.DebugLog("    最终匹配结果: matchIDList=%s" % matchIDList, playerID)
    
    PyGameData.g_arenaPlayerMatchDict[playerID] = matchIDList
    __SyncMatchList(curPlayer, matchIDList)
    __SyncMatchList(curPlayer, matchIDList, viewCacheDict)
    return
def __SyncMatchList(curPlayer, matchIDList):
def __SyncMatchList(curPlayer, matchIDList, viewCacheDict={}):
    ## 同步匹配列表
    clientPack = ChPyNetSendPack.tagSCArenaMatchList()
    clientPack.MatchList = []
    for matchID in matchIDList:
        viewCache = PlayerViewCache.FindViewCache(matchID)
        if matchID in viewCacheDict:
            viewCache = viewCacheDict[matchID]
        else:
            viewCache = PlayerViewCache.FindBattleViewCache(matchID)
        if not viewCache:
            continue
        matchInfo = ChPyNetSendPack.tagSCArenaMatchInfo()
        matchInfo.PlayerID = matchID
        if viewCache:
            matchInfo.PlayerName = viewCache.GetPlayerName()
            matchInfo.RealmLV = viewCache.GetRealmLV()
            matchInfo.LV = viewCache.GetLV()
            matchInfo.Face = viewCache.GetFace()
            matchInfo.FacePic = viewCache.GetFacePic()
            matchInfo.FightPower = viewCache.GetFightPower()
            matchInfo.FightPowerEx = viewCache.GetFightPowerEx()
            matchInfo.TitleID = viewCache.GetTitleID()
        else:
            matchInfo.PlayerName = "p%s" % matchID
        clientPack.MatchList.append(matchInfo)
@@ -346,5 +432,6 @@
def Sync_ArenaInfo(curPlayer):
    clientPack = ChPyNetSendPack.tagSCArenaPlayerInfo()
    clientPack.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
    clientPack.WinCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaWinCnt)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return