| | |
| | | #
|
| | | ##@package Player.PlayerArena
|
| | | #
|
| | | # @todo:竞技场 - 本服
|
| | | # @todo:演武场
|
| | | # @author hxp
|
| | | # @date 2020-12-07
|
| | | # @date 2025-09-12
|
| | | # @version 1.0
|
| | | #
|
| | | # 详细描述: 竞技场 - 本服
|
| | | # 详细描述: 演武场
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2020-12-07 19:30"""
|
| | | #"""Version = 2025-09-12 10:30"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import DBDataMgr
|
| | | import PlayerMail
|
| | | import ShareDefine
|
| | | import GameFuncComm
|
| | | import PlayerControl
|
| | | import IpyGameDataPY
|
| | | import ChPyNetSendPack
|
| | | import PlayerViewCache
|
| | | import NetPackCommon
|
| | | import PyGameData
|
| | | import GameWorld
|
| | | import ChConfig
|
| | | import FBCommon
|
| | | import IPY_GameWorld
|
| | | import ItemControler
|
| | | import EventShell
|
| | | import PlayerActTask
|
| | | import PlayerWeekParty
|
| | | import PlayerFeastTravel
|
| | | import PlayerActivity
|
| | | import PlayerSuccess
|
| | | import PlayerGubao
|
| | | import random
|
| | |
|
| | | def DoArenaOpen(curPlayer):
|
| | | ## 竞技场功能开启
|
| | | __DoArenaSeasonReset(curPlayer)
|
| | | # 记录攻击类型
|
| | | RecAtkType_Atk = 1 # 发起攻击
|
| | | RecAtkType_Def = 2 # 被攻击的
|
| | |
|
| | | def GetRecUpdScore(recData): return recData.GetValue1() # 更新积分
|
| | | def SetRecUpdScore(recData, score): return recData.SetValue1(score)
|
| | | def GetRecAtkType(recData): return recData.GetValue2() # 攻击类型 1-发起攻击的,2-被攻击的
|
| | | def SetRecAtkType(recData, atkType): return recData.SetValue2(atkType)
|
| | | def GetRecTagPlayerID(recData): return recData.GetValue3() # 相对攻击类型的目标玩家ID
|
| | | def SetRecTagPlayerID(recData, tagPlayerID): return recData.SetValue3(tagPlayerID)
|
| | | def GetRecIsWin(recData): return recData.GetValue4() # 是否获胜 1-获胜;2-失败
|
| | | def SetRecIsWin(recData, isWin): return recData.SetValue4(1 if isWin else 0)
|
| | | def GetRecFace(recData): return recData.GetValue5() # 目标头像
|
| | | def SetRecFace(recData, face): return recData.SetValue5(face)
|
| | | def GetRecFacePic(recData): return recData.GetValue6()
|
| | | def SetRecFacePic(recData, facePic): return recData.SetValue6(facePic)
|
| | | def GetRecRealmLV(recData): return recData.GetValue7()
|
| | | def SetRecRealmLV(recData, realmLV): return recData.SetValue7(realmLV)
|
| | | def GetRecLV(recData): return recData.GetValue8()
|
| | | def SetRecLV(recData, tagLV): return recData.SetValue8(tagLV)
|
| | | #SetUserData 名字、变更积分 +-、战力
|
| | |
|
| | | def OnWeek():
|
| | | DoArenaReset()
|
| | | return
|
| | |
|
| | | def OnDay():
|
| | | __DoGiveBillboardAward("Day")
|
| | | return
|
| | |
|
| | | def DoArenaReset():
|
| | | ''' 赛季重置
|
| | | '''
|
| | | GameWorld.Log("=============== 重置竞技场 ===============")
|
| | | |
| | | PyGameData.g_arenaPlayerMatchDict = {}
|
| | | |
| | | # 结算上赛季排行奖励
|
| | | __DoGiveBillboardAward("Week")
|
| | | |
| | | # 重置排行榜
|
| | | DBDataMgr.GetBillboardMgr().RemoveBillboard(ShareDefine.Def_BT_Arena)
|
| | | # 重置记录
|
| | | #DBDataMgr.GetGameRecMgr().DelDataByType(ShareDefine.Def_GameRecType_ArenaRecord) # 挑战记录不重置
|
| | | |
| | | GameWorld.Log("==========================================")
|
| | | return True
|
| | |
|
| | | def __DoGiveBillboardAward(awardType):
|
| | | ## 竞技场结算排行奖励, 每日、赛季通用
|
| | | |
| | | GameWorld.Log("=== 竞技场结算排行奖励! === %s" % awardType)
|
| | | |
| | | billboardMgr = DBDataMgr.GetBillboardMgr()
|
| | | billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Arena)
|
| | | if not billBoard:
|
| | | return
|
| | | |
| | | if awardType == "Day":
|
| | | billboradAwardDict = IpyGameDataPY.GetFuncEvalCfg("ArenaBillboradAward", 1, {})
|
| | | elif awardType == "Week":
|
| | | billboradAwardDict = IpyGameDataPY.GetFuncEvalCfg("ArenaBillboradAward", 2, {})
|
| | | else:
|
| | | return
|
| | | |
| | | orderList = [int(orderStr) for orderStr in billboradAwardDict.keys()]
|
| | | orderList.sort()
|
| | | GameWorld.Log(" 奖励名次列表: %s" % orderList)
|
| | | |
| | | awardOrder = orderList[0]
|
| | | orderPlayerIDDict = {}
|
| | | billboardCount, billboardMaxCount = billBoard.GetCount(), billBoard.GetMaxCount()
|
| | | GameWorld.Log(" 榜单数据数! billboardCount=%s,billboardMaxCount=%s" % (billboardCount, billboardMaxCount))
|
| | | for index in xrange(billboardCount):
|
| | | billBoardData = billBoard.At(index)
|
| | | if not billBoardData:
|
| | | continue
|
| | | order = index + 1
|
| | | |
| | | if order > awardOrder:
|
| | | nextOrderIndex = orderList.index(awardOrder) + 1
|
| | | if nextOrderIndex >= len(orderList):
|
| | | break
|
| | | awardOrder = orderList[nextOrderIndex]
|
| | | |
| | | playerID = billBoardData.GetID()
|
| | | if playerID < ShareDefine.RealPlayerIDStart:
|
| | | # 非真人不处理
|
| | | continue
|
| | | |
| | | orderPlayerIDDict[playerID] = [order, awardOrder]
|
| | | |
| | | paramList = [order]
|
| | | awardList = billboradAwardDict[str(awardOrder)]
|
| | | PlayerMail.SendMailByKey("ArenaBillboardAward%s" % awardType, playerID, awardList, paramList)
|
| | | |
| | | GameWorld.Log(" 奖励玩家名次信息: %s" % orderPlayerIDDict)
|
| | | return
|
| | |
|
| | | def OnLogin(curPlayer):
|
| | | if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Arena):
|
| | | return
|
| | | OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
|
| | | if not OSSeasonState:
|
| | | __DoArenaSeasonReset(curPlayer)
|
| | | else:
|
| | | Sync_ArenaInfo(curPlayer)
|
| | | __loginUpdPlayerScore(curPlayer)
|
| | | Sync_ArenaInfo(curPlayer)
|
| | | return
|
| | |
|
| | | def __loginUpdPlayerScore(curPlayer):
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | recMgr = DBDataMgr.GetGameRecMgr()
|
| | | recIDMgr = recMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_ArenaRecord, playerID)
|
| | | if not recIDMgr.GetCount():
|
| | | return
|
| | | finalRecData = recIDMgr.At(recIDMgr.GetCount() - 1)
|
| | | recTime = finalRecData.GetTime()
|
| | | if not GameWorld.CheckTimeIsSameWeek(recTime):
|
| | | GameWorld.Log("玩家上线演武场记录积分非本周不更新! recTime=%s" % GameWorld.ChangeTimeNumToStr(recTime), playerID)
|
| | | return
|
| | | updScore = GetRecUpdScore(finalRecData)
|
| | | befScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
|
| | | GameWorld.Log("玩家上线更新演武场积分: befScore=%s,updScore=%s,recTime=%s" % (befScore, updScore, GameWorld.ChangeTimeNumToStr(recTime)), playerID)
|
| | | return
|
| | |
|
| | | def OnDayEx(curPlayer):
|
| | | if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Arena):
|
| | | return
|
| | | |
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaItemAddCount, 0)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleCountDay, 0)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, 0)
|
| | | Sync_ArenaInfo(curPlayer)
|
| | | |
| | | openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
|
| | | customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1)
|
| | | if openServerDay <= customMaxServerDay:
|
| | | GameWorld.DebugLog("OnDayEx时竞技场开服定制赛季进行中,不处理! openServerDay=%s <= %s" % (openServerDay, customMaxServerDay))
|
| | | return
|
| | | |
| | | OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
|
| | | if OSSeasonState > 1:
|
| | | GameWorld.DebugLog("OnDayEx时竞技场开服定制赛季已结算过,不处理! OSSeasonState=%s" % (OSSeasonState))
|
| | | return
|
| | | |
| | | __DoArenaSeasonReset(curPlayer)
|
| | | return
|
| | |
|
| | | def OnWeekEx(curPlayer):
|
| | | if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Arena):
|
| | | return
|
| | | |
| | | openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
|
| | | customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1)
|
| | | if openServerDay <= customMaxServerDay:
|
| | | GameWorld.DebugLog("OnWeekEx时在开服定制天内,不处理竞技场赛季重置! openServerDay=%s <= %s" % (openServerDay, customMaxServerDay))
|
| | | return
|
| | | |
| | | OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
|
| | | if not OSSeasonState or OSSeasonState == 1 or OSSeasonState == openServerDay:
|
| | | GameWorld.DebugLog("OnWeekEx时竞技场开服定制赛季进行中或同一天结算,不处理重置! openServerDay=%s,OSSeasonState=%s" % (openServerDay, OSSeasonState)) |
| | | return
|
| | | |
| | | __DoArenaSeasonReset(curPlayer)
|
| | | return
|
| | |
|
| | | def DoArenaOpen(curPlayer):
|
| | | __DoArenaSeasonReset(curPlayer)
|
| | | return
|
| | |
|
| | | def __DoArenaSeasonReset(curPlayer):
|
| | | ## 玩家重置竞技场
|
| | | |
| | | OSSeasonState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaOSSeasonState)
|
| | | openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
|
| | | |
| | | customMaxServerDay = IpyGameDataPY.GetFuncCfg("OperationAction", 1)
|
| | | if openServerDay <= customMaxServerDay and OSSeasonState != 0:
|
| | | GameWorld.DebugLog("开服定制天内不能重置!")
|
| | | return
|
| | | |
| | | setScoreMin, setScoreMax, refScoreMax = IpyGameDataPY.GetFuncEvalCfg("ArenaSet", 2)
|
| | | setScore = setScoreMin
|
| | | if openServerDay <= customMaxServerDay and OSSeasonState == 0:
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaOSSeasonState, 1)
|
| | | GameWorld.DebugLog("竞技场开服定制赛季! setScore=%s" % setScore)
|
| | | else:
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaOSSeasonState, customMaxServerDay + 1)
|
| | | |
| | | preSeasonscore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | if preSeasonscore <= setScoreMin:
|
| | | setScore = setScoreMin
|
| | | elif preSeasonscore >= refScoreMax:
|
| | | setScore = setScoreMax
|
| | | else:
|
| | | # 按比例降低积分,都减去最低分的差值算比例
|
| | | calcScore = preSeasonscore - setScoreMin
|
| | | setScore = setScoreMin + int(calcScore * (setScoreMax - setScoreMin) / float(refScoreMax - setScoreMin))
|
| | | |
| | | GameWorld.DebugLog("竞技场赛季重置! preSeasonscore=%s,setScore=%s" % (preSeasonscore, setScore))
|
| | | |
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, setScore)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaItemAddCount, 0)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleCountDay, 0)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, 0)
|
| | | Sync_ArenaInfo(curPlayer, True)
|
| | | initScore = IpyGameDataPY.GetFuncCfg("ArenaSet", 1)
|
| | | GameWorld.DebugLog("竞技场赛季重置!initScore=%s" % (initScore))
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, initScore)
|
| | | Sync_ArenaInfo(curPlayer)
|
| | | return
|
| | |
|
| | | def CheckArenaBattleCount(curPlayer):
|
| | | ## 验证是否还有对战次数
|
| | | todayBattleCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleCountDay)
|
| | | itemAddCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaItemAddCount)
|
| | | dayFreeCount = IpyGameDataPY.GetFuncCfg("ArenaSet", 3)
|
| | | return todayBattleCount < (dayFreeCount + itemAddCount)
|
| | | def GetArenaTicketStoreMax(curPlayer):
|
| | | ## 获取挑战券存储上限
|
| | | baseCnt = IpyGameDataPY.GetFuncCfg("ArenaSet", 3)
|
| | | |
| | | # 其他特权提升上限
|
| | | |
| | | storeMax = baseCnt
|
| | | return storeMax
|
| | |
|
| | | #// B2 09 竞技场匹配玩家 #tagCMArenaMatch
|
| | | #// B2 09 演武场匹配玩家 #tagCSArenaMatch
|
| | | #
|
| | | #struct tagCMArenaMatch
|
| | | #struct tagCSArenaMatch
|
| | | #{
|
| | | # tagHead Head;
|
| | | # BYTE IsRefresh; // 0-打开界面无匹配数据时时查询,1-强制刷新匹配列表
|
| | | # BYTE IsRefresh; // 0-打开界面无匹配数据时查询,1-强制刷新匹配列表
|
| | | #};
|
| | | def OnArenaMatch(index, clientData, tick):
|
| | | curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
| | | isRefresh = clientData.IsRefresh
|
| | | |
| | | playerID = curPlayer.GetPlayerID()
|
| | | refreshCountLimit = IpyGameDataPY.GetFuncCfg("ArenaSet", 5)
|
| | | if isRefresh and refreshCountLimit:
|
| | | refreshCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaMatchRefreshCount)
|
| | | if refreshCount >= refreshCountLimit:
|
| | | GameWorld.DebugLog("竞技场刷新匹配玩家次数已满!refreshCount=%s >= %s" % (refreshCount, refreshCountLimit), playerID)
|
| | | return
|
| | | |
| | | if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_Arena, tick):
|
| | | GameWorld.DebugLog("竞技场匹配操作CD中...", playerID)
|
| | | PlayerControl.NotifyCode(curPlayer, "RequestLater")
|
| | | return
|
| | | |
| | | playerLV = curPlayer.GetLV()
|
| | | playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | msgInfo = str(["MatchRefresh", {"isRefresh":isRefresh, "playerLV":playerLV, "playerScore":playerScore}])
|
| | | GameWorld.DebugLog("竞技场发送GameServer匹配: %s" % msgInfo, playerID)
|
| | | GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "Arena", msgInfo, len(msgInfo))
|
| | | DoArenaMatchRefresh(curPlayer, isRefresh)
|
| | | return
|
| | |
|
| | | def GMArenaMatch(curPlayer, gmMatchIDList):
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | playerLV = curPlayer.GetLV()
|
| | | playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | msgInfo = str(["MatchRefresh", {"isRefresh":1, "playerLV":playerLV, "playerScore":playerScore, "gmMatchIDList":gmMatchIDList}])
|
| | | GameWorld.DebugLog("竞技场发送GameServer匹配: %s" % msgInfo, playerID)
|
| | | GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "Arena", msgInfo, len(msgInfo))
|
| | | ## GM直接匹配
|
| | | isRefresh = True
|
| | | DoArenaMatchRefresh(curPlayer, isRefresh, gmMatchIDList)
|
| | | return
|
| | |
|
| | | #// B2 10 竞技场挑战玩家 #tagCMArenaBattle
|
| | | #
|
| | | #struct tagCMArenaBattle
|
| | | #{
|
| | | # tagHead Head;
|
| | | # DWORD TagPlayerID; // 目标玩家ID或机器人ID
|
| | | # BYTE Result; // 0-进入自定义场景发送通知后端;1-胜利(后端处理,暂时不需要发送此状态);2-失败(前端被对手击杀需要发送此状态)
|
| | | #};
|
| | | def OnArenaBattle(index, clientData, tick):
|
| | | curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
|
| | | def DoArenaMatchRefresh(curPlayer, isRefresh, gmMatchIDList=None, isSys=False):
|
| | | ## 玩家刷新匹配对手
|
| | | |
| | | playerID = curPlayer.GetPlayerID()
|
| | | tagPlayerID = clientData.TagPlayerID
|
| | | result = clientData.Result
|
| | | playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | matchScoreList = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 1)
|
| | |
|
| | | GameWorld.DebugLog("竞技场挑战玩家! tagPlayerID=%s,result=%s" % (tagPlayerID, result), playerID)
|
| | | if not tagPlayerID:
|
| | | GameWorld.DebugLog("竞技场玩家刷新匹配列表: isRefresh=%s,playerScore=%s,gmMatchIDList=%s,isSys=%s" % (isRefresh, playerScore, gmMatchIDList, isSys), playerID)
|
| | | GameWorld.DebugLog(" matchScoreList=%s" % (matchScoreList), playerID)
|
| | | |
| | | # 匹配对象缓存
|
| | | needMatchCount = len(matchScoreList)
|
| | | if playerID not in PyGameData.g_arenaPlayerMatchDict:
|
| | | PyGameData.g_arenaPlayerMatchDict[playerID] = []
|
| | | matchIDList = PyGameData.g_arenaPlayerMatchDict[playerID]
|
| | | if len(matchIDList) > needMatchCount:
|
| | | matchIDList = matchIDList[:needMatchCount] # 删除多余的个数,一般都是相同的,除非修改匹配数重读配置
|
| | | if not isRefresh and len(matchIDList) == needMatchCount:
|
| | | # 非刷新的并且已经有记录的直接同步
|
| | | GameWorld.DebugLog(" 非刷新且有数据,直接同步!", playerID)
|
| | | __SyncMatchList(curPlayer, matchIDList)
|
| | | return
|
| | | |
| | | if not result:
|
| | | GameWorld.DebugLog("更新竞技场对战对手ID! tagPlayerID=%s" % tagPlayerID, playerID)
|
| | | # 记录对手ID
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleTagID, tagPlayerID)
|
| | | return
|
| | | |
| | | if tagPlayerID >= 10000:
|
| | | if result:
|
| | | GameWorld.DebugLog("真人由后端镜像PK决定胜负! tagPlayerID=%s" % tagPlayerID, playerID)
|
| | | if isRefresh and not gmMatchIDList and not isSys:
|
| | | costMoney, moneyValue = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 4)
|
| | | if not costMoney or not moneyValue or not PlayerControl.PayMoney(curPlayer, costMoney, moneyValue, "Arena"):
|
| | | return
|
| | |
|
| | | isWin = 1 if result == 1 else 0
|
| | | # # 木桩被击杀,后端判断,其他前端同步
|
| | | # if isWin:
|
| | | # GameWorld.ErrLog("前端不能同步竞技场胜利状态!", playerID)
|
| | | # return
|
| | | |
| | | recTagPlayerID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleTagID)
|
| | | if tagPlayerID != recTagPlayerID:
|
| | | GameWorld.ErrLog("竞技场结算时对手ID不一致! tagPlayerID(%s) != recTagPlayerID(%s)" % (tagPlayerID, recTagPlayerID), playerID)
|
| | | __DoArenaBattleOver(curPlayer)
|
| | | billboardMgr = DBDataMgr.GetBillboardMgr()
|
| | | billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Arena)
|
| | | if not billBoard:
|
| | | return
|
| | | maxOrder = billBoard.GetCount()
|
| | | playerOrder = billBoard.IndexOfByID(playerID) + 1 # 玩家在排行榜中的名次,没有名次为-1
|
| | |
|
| | | # 失败结算入口: 前端同步
|
| | | SendGameServer_ArenaBattleOver(curPlayer, isWin)
|
| | | return
|
| | |
|
| | | def OnKillBattleNPC(curPlayer, curNPC):
|
| | | # ## 击杀对手,前端本,使用木桩NPC作为对手
|
| | | # |
| | | # if curNPC.GetGameObjType() != IPY_GameWorld.gotNPC or curNPC.GetType() not in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:
|
| | | # GameWorld.DebugLog("击杀非木桩NPC,不结算!")
|
| | | # return
|
| | | # |
| | | # # 胜利结算入口:后端验证击杀对手
|
| | | # tagPlayerID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleTagID)
|
| | | # GameWorld.DebugLog("竞技场击杀对手! tagPlayerID=%s" % tagPlayerID, curPlayer.GetPlayerID())
|
| | | # isWin = 1
|
| | | # SendGameServer_ArenaBattleOver(curPlayer, isWin)
|
| | | return
|
| | |
|
| | | def SendGameServer_ArenaBattleOver(curPlayer, isWin):
|
| | | ## 发送GameServer通知战斗结算
|
| | | 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)
|
| | |
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | tagPlayerID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleTagID)
|
| | | if not tagPlayerID:
|
| | | GameWorld.ErrLog("竞技场结算时没有对手ID!", playerID)
|
| | | __DoArenaBattleOver(curPlayer)
|
| | | return
|
| | | |
| | | if not CheckArenaBattleCount(curPlayer):
|
| | | GameWorld.ErrLog("竞技场已经没有对战次数!", playerID)
|
| | | __DoArenaBattleOver(curPlayer)
|
| | | return
|
| | | |
| | | tick = GameWorld.GetGameWorld().GetTick()
|
| | | if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_Arena, tick):
|
| | | GameWorld.ErrLog("结算竞技场CD中!tagPlayerID=%s" % tagPlayerID, playerID)
|
| | | return
|
| | | |
| | | playerLV = curPlayer.GetLV()
|
| | | playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | msgInfo = str(["BattleResult", {"tagPlayerID":tagPlayerID, "isWin":isWin, "playerLV":playerLV, "playerScore":playerScore, |
| | | "realmLV":curPlayer.GetOfficialRank(), "fightPower":PlayerControl.GetFightPower(curPlayer)}])
|
| | | GameWorld.DebugLog("竞技场发送GameServer结算: %s" % msgInfo, playerID)
|
| | | GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, "Arena", msgInfo, len(msgInfo))
|
| | | return
|
| | |
|
| | | def __DoArenaBattleOver(curPlayer, retDict={}):
|
| | | ## 主动战斗结算奖励
|
| | | # @param isOK: True时才结算奖励,防止某些异常情况无法结算通知前端FBOver,导致卡副本
|
| | | |
| | | GameWorld.DebugLog("结算竞技场对战奖励! retDict=%s" % retDict)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleTagID, 0)
|
| | | |
| | | isOK = retDict.get("isOK", False)
|
| | | isWin = retDict.get("isWin", 0)
|
| | | if not isOK:
|
| | | # 一直异常的情况直接同步结束包,防止不结算卡副本
|
| | | FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_ArenaBattle, 0, isWin)
|
| | | return
|
| | | |
| | | #GameServer MapServer 同步有一定时间差,本功能存在被动挑战引发积分变动的情况,
|
| | | #curScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | addScore = retDict["addScore"]
|
| | | updScore = retDict["updScore"]
|
| | | curOrder = retDict["curOrder"]
|
| | | updOrder = retDict["updOrder"]
|
| | | offlineRecTime = retDict.get("offlineRecTime", 0)
|
| | | |
| | | # 扣次数
|
| | | if not offlineRecTime or GameWorld.CheckTimeIsSameServerDayEx(offlineRecTime):
|
| | | todayBattleCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleCountDay) + 1
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaBattleCountDay, todayBattleCount)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, 0)
|
| | | fromLowerCnt, matchPerRank = IpyGameDataPY.GetFuncEvalCfg("ArenaMatch", 2)
|
| | | toOrder = playerOrder + fromLowerCnt * matchPerRank # 从低名次往高名次匹配
|
| | | GameWorld.DebugLog(" fromLowerCnt=%s,matchPerRank=%s,toOrder=%s" % (fromLowerCnt, matchPerRank, toOrder), playerID)
|
| | | 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
|
| | |
|
| | | # 更新积分
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
|
| | | highestScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaHighestScore)
|
| | | if updScore > highestScore:
|
| | | highestScore = updScore
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaHighestScore, highestScore)
|
| | | GameWorld.DebugLog(" 更新竞技场历史最高分! %s" % highestScore)
|
| | | if fromOrder == 1:
|
| | | for order in orderList:
|
| | | if order > maxOrder:
|
| | | continue
|
| | | matchOrderList.append(order)
|
| | | if len(matchOrderList) >= matchPlayerCnt:
|
| | | break
|
| | | else:
|
| | | order = orderList[0]
|
| | | if order <= maxOrder:
|
| | | matchOrderList.append(order)
|
| | | |
| | | GameWorld.DebugLog(" 匹配玩家: fromOrder=%s,toOrder=%s,matchOrderList=%s" % (fromOrder, toOrder, matchOrderList), playerID)
|
| | | toOrder = fromOrder - 1
|
| | |
|
| | | # 胜利给额外奖励
|
| | | itemList = retDict.get("awardItemList", [])
|
| | | ItemControler.GivePlayerItemOrMail(curPlayer, itemList)
|
| | | jsonItemList = FBCommon.GetJsonItemList(itemList)
|
| | | |
| | | overDict = {FBCommon.Over_itemInfo:jsonItemList, "addScore":addScore, "updScore":updScore, "curOrder":curOrder, "updOrder":updOrder}
|
| | | FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_ArenaBattle, 0, isWin, overDict)
|
| | | Sync_ArenaInfo(curPlayer)
|
| | | |
| | | # 触发任务
|
| | | EventShell.EventRespons_ArenaBattleOver(curPlayer)
|
| | | EventShell.EventRespons_ArenaHighestScore(curPlayer)
|
| | | |
| | | PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_Arena, 1)
|
| | | PlayerFeastTravel.AddFeastTravelTaskValue(curPlayer, ChConfig.Def_FeastTravel_Arena, 1)
|
| | | PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_Arena, 1)
|
| | | PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Arena, 1)
|
| | | PlayerGubao.AddGubaoItemEffValue(curPlayer, PlayerGubao.GubaoEffType_Arena, 1)
|
| | | PlayerActTask.AddActTaskValue(curPlayer, ChConfig.ActTaskType_Arena)
|
| | | return
|
| | |
|
| | | def __DoUpdateArenaScore(curPlayer, cmdDict={}):
|
| | | ''' 玩家直接更新积分,有以下几种情况,都是被挑战的,只更新积分
|
| | | 1. 被动挑战在线时直接更新积分
|
| | | 2. 离线/脱机时被挑战,上线后同步最新积分
|
| | | '''
|
| | | |
| | | playerScore = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | updScore = cmdDict.get("updScore", playerScore)
|
| | | if updScore == playerScore:
|
| | | return
|
| | | |
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaScore, updScore)
|
| | | Sync_ArenaInfo(curPlayer)
|
| | | return
|
| | |
|
| | | def GameServer_ArenaResult(curPlayer, msgList, tick):
|
| | | if not msgList:
|
| | | return
|
| | | |
| | | cmd = msgList[0]
|
| | | cmdDict = msgList[1] if len(msgList) > 1 else {}
|
| | | retDict = msgList[2] if len(msgList) > 2 else {}
|
| | | |
| | | # 刷新匹配
|
| | | if cmd == "MatchRefresh":
|
| | | isRefresh = cmdDict.get("isRefresh", False)
|
| | | refreshCountLimit = IpyGameDataPY.GetFuncCfg("ArenaSet", 5)
|
| | | if isRefresh and refreshCountLimit:
|
| | | updRefreshCount = min(250, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaMatchRefreshCount) + 1)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ArenaMatchRefreshCount, updRefreshCount)
|
| | | GameWorld.DebugLog("更新竞技场刷新匹配次数! updRefreshCount=%s" % updRefreshCount)
|
| | | Sync_ArenaInfo(curPlayer)
|
| | | # GM指定匹配测试
|
| | | if gmMatchIDList != None and curPlayer.GetGMLevel():
|
| | | for gmMatchID in gmMatchIDList:
|
| | | if gmMatchID == playerID:
|
| | | GameWorld.DebugAnswer(curPlayer, "目标ID不能是自己!无法匹配!%s" % gmMatchID)
|
| | | continue
|
| | |
|
| | | # 主动对战结果
|
| | | elif cmd == "BattleResult":
|
| | | __DoArenaBattleOver(curPlayer, retDict)
|
| | | gmMatchOrder = billBoard.IndexOfByID(gmMatchID) + 1
|
| | | if gmMatchOrder <= 0:
|
| | | GameWorld.DebugAnswer(curPlayer, "目标ID不在榜单上!无法匹配!%s" % gmMatchID)
|
| | | continue
|
| | | GameWorld.DebugAnswer(curPlayer, "指定匹配ID(%s),order(%s)" % (gmMatchID, gmMatchOrder))
|
| | | if gmMatchID not in matchOrderList:
|
| | | matchOrderList.insert(0, gmMatchOrder)
|
| | | matchOrderList = matchOrderList[:needMatchCount]
|
| | |
|
| | | # 被动挑战更新积分
|
| | | elif cmd == "UpdScore":
|
| | | __DoUpdateArenaScore(curPlayer, cmdDict)
|
| | | matchOrderList.sort()
|
| | | matchIDList = [] # 最终匹配的玩家ID列表
|
| | | for matchOrder in matchOrderList:
|
| | | if matchOrder > maxOrder or matchOrder <= 0:
|
| | | break
|
| | | billData = billBoard.At(matchOrder - 1)
|
| | | matchIDList.append(billData.GetID())
|
| | |
|
| | | needRobotCnt = needMatchCount - len(matchIDList)
|
| | | GameWorld.DebugLog(" 匹配榜单结果: matchIDList=%s,matchOrderList=%s,needRobotCnt=%s" % (matchIDList, matchOrderList, needRobotCnt), playerID)
|
| | | ipyDataMgr = IpyGameDataPY.IPY_Data()
|
| | | robotMax = ipyDataMgr.GetRobotCount()
|
| | | doCnt = 100
|
| | | while doCnt > 0 and needRobotCnt > 0 and robotMax:
|
| | | doCnt -= 1
|
| | | robotIndex = random.randint(0, robotMax - 1)
|
| | | robotIpyData = ipyDataMgr.GetRobotByIndex(robotIndex)
|
| | | robotID = robotIpyData.GetID()
|
| | | if robotID not in matchIDList:
|
| | | matchIDList.append(robotID)
|
| | | needRobotCnt -= 1
|
| | | GameWorld.DebugLog(" 最终匹配结果: matchIDList=%s" % matchIDList, playerID)
|
| | | |
| | | PyGameData.g_arenaPlayerMatchDict[playerID] = matchIDList
|
| | | __SyncMatchList(curPlayer, matchIDList)
|
| | | return
|
| | |
|
| | | def Sync_ArenaInfo(curPlayer, isReset=False):
|
| | | clientPack = ChPyNetSendPack.tagMCArenaPlayerInfo()
|
| | | clientPack.IsReset = 1 if isReset else 0
|
| | | clientPack.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | clientPack.BattleCountToday = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaBattleCountDay)
|
| | | clientPack.MatchRefreshCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaMatchRefreshCount)
|
| | | clientPack.ItemAddBattleCountToday = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaItemAddCount)
|
| | | def __SyncMatchList(curPlayer, matchIDList):
|
| | | ## 同步匹配列表
|
| | | clientPack = ChPyNetSendPack.tagSCArenaMatchList()
|
| | | clientPack.MatchList = []
|
| | | for matchID in matchIDList:
|
| | | viewCache = PlayerViewCache.FindViewCache(matchID)
|
| | | matchInfo = ChPyNetSendPack.tagSCArenaMatchInfo()
|
| | | matchInfo.PlayerID = matchID
|
| | | if viewCache:
|
| | | matchInfo.PlayerName = viewCache.GetPlayerName()
|
| | | matchInfo.RealmLV = viewCache.GetRealmLV()
|
| | | matchInfo.Face = viewCache.GetFace()
|
| | | matchInfo.FacePic = viewCache.GetFacePic()
|
| | | matchInfo.FightPower = viewCache.GetFightPower()
|
| | | matchInfo.FightPowerEx = viewCache.GetFightPowerEx()
|
| | | else:
|
| | | matchInfo.PlayerName = "p%s" % matchID
|
| | | clientPack.MatchList.append(matchInfo)
|
| | | clientPack.MatchCount = len(clientPack.MatchList)
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack)
|
| | | return
|
| | |
|
| | | def Sync_ArenaInfo(curPlayer):
|
| | | clientPack = ChPyNetSendPack.tagSCArenaPlayerInfo()
|
| | | clientPack.Score = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ArenaScore)
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack)
|
| | | return
|