From 11c9a3b5846401523e4dafc17f2a074a712730da Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 11 三月 2026 18:27:10 +0800
Subject: [PATCH] 526 【挑战】PVP群英榜-后端(本服群英榜;优化机器人表支持按功能加载不同的机器人;)
---
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py | 53 -
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Qunying.py | 82 +++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py | 34
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py | 52 ++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py | 255 +++++++++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py | 53 -
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py | 179 +++++-
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py | 1
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py | 73 ++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py | 3
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py | 3
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py | 15
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini | 12
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py | 6
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py | 41 +
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py | 6
PySysDB/PySysDBPY.h | 15
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py | 2
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py | 2
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py | 9
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Qunying.py | 599 +++++++++++++++++++++++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py | 20
22 files changed, 1,387 insertions(+), 128 deletions(-)
diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index adf6e63..05b66d7 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -2008,6 +2008,17 @@
dict Attr; //属性
};
+//群英榜分区表
+struct QunyingCross
+{
+ char _AppID; //AppID
+ WORD _ZoneID; //分区ID
+ DWORD CrossServerID; //跨服服务器ID
+ list ServerIDList; //互通服务器ID列表
+ BYTE SplitServerCnt; //按X个相邻服分割
+ BYTE MatchServerCnt; //分割区服内X个服随机匹配一组
+};
+
//跨服公会表
struct FamilyCross
{
@@ -2195,5 +2206,9 @@
{
DWORD _ID; //机器人ID,同玩家ID
char RobotName;
+ BYTE RealmLV; //指定官职
+ DWORD TempNum; //功能模版
+ DWORD TempValue1; //功能值1
+ DWORD TempValue2; //功能值2
char ViewCache; //机器人缓存
};
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index a70516d..035e03a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -710,6 +710,18 @@
PacketSubCMD_1=0x09
PacketCallFunc_1=OnArenaMatch
+;群英榜
+[GameLogic_Qunying]
+ScriptName = Player\GameLogic_Qunying.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 1
+
+PacketCMD_1=0xB2
+PacketSubCMD_1=0x10
+PacketCallFunc_1=OnQunyingMatch
+
;古宝
[PlayerGubao]
ScriptName = Player\PlayerGubao.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 3297e46..b06ccd3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -1894,6 +1894,8 @@
Def_FBMapID_Tianzi = 30020 # 天子考验
Def_FBMapID_Dingjunge = 30030 # 定军阁
+Def_FBMapID_Qunying = 32000 # 群英榜
+
#线路未过关时免费的地图
UnPassFreeMapIDList = [Def_FBMapID_Zhanchui, Def_FBMapID_Dingjunge]
#按星级记录过关的地图
@@ -1908,7 +1910,9 @@
ExclusiveBatAttrMapIDList = [Def_FBMapID_Dingjunge]
#地图功能专用预设方案,如果没有配置的功能则默认使用主线方案
MapAtkBatPresetTypeDict = {}
-MapDefBatPresetTypeDict = {Def_FBMapID_ArenaBattle:ShareDefine.BatPreset_ArenaDef}
+MapDefBatPresetTypeDict = {Def_FBMapID_ArenaBattle:ShareDefine.BatPreset_ArenaDef,
+ Def_FBMapID_Qunying:ShareDefine.BatPreset_QunyingDef,
+ }
#注册上传跨服服务器数据后直接进入跨服服务器的地图
RegisterEnter_CrossServerMapIDList = []
@@ -1983,6 +1987,7 @@
'Zhanchui':[Def_FBMapID_Zhanchui],
'Tianzi':[Def_FBMapID_Tianzi],
'Dingjunge':[Def_FBMapID_Dingjunge],
+ 'Qunying':[Def_FBMapID_Qunying],
}
#特殊副本ID, 由系统分配, 进入时候不验证IsMapCopyFull
@@ -3632,6 +3637,12 @@
Def_PDict_ArenaScore = "ArenaScore" # 当前积分
Def_PDict_ArenaWinCnt = "ArenaWinCnt" # 累计胜利次数
+#群英榜
+Def_PDict_QunyingRefreshCnt = "QunyingRefreshCnt" # 本周已刷新匹配次数
+Def_PDict_QunyingRecoverTime = "QunyingRecoverTime" # 上次恢复挑战令时间戳
+Def_PDict_QunyingRankHighest = "QunyingRankHighest" # 历史最高名次
+Def_PDict_QunyingRankSuccAward = "QunyingRankSuccAward" # 历史最高名次成就领奖记录
+
#古宝
Def_PDict_GubaoInfo = "Gubao_%s" # 古宝信息,参数(古宝ID),特殊效果层*100000 + 等级*100 + 星级
@@ -4562,6 +4573,11 @@
ntMax
) = range(27)
+# 机器人功能模版
+(
+RobotTempNum_Comm, # 通用模版 0
+RobotTempNum_Qunying, # 群英榜专用 1
+) = range(2)
# 回合卡牌
(
@@ -4685,7 +4701,7 @@
Def_RewardType_LineupRecommend, # 阵容推荐奖励 4
Def_RewardType_LVAward, # 玩家等级奖励5
Def_RewardType_BeautyLVAward, # 红颜等级奖励 6
-Def_RewardType_7, # 每日任务修行点奖励7
+Def_RewardType_QunyingRankHighest, # 群英榜历史最高名次奖励 7
Def_RewardType_FirstCharge, # 首充礼包奖励8
Def_RewardType_OSACelebrationPointAward, # 开服庆典积分阶段奖励 9
Def_RewardType_ActHeroAppearStarFreeAward, # 武将登场升星计划免费奖励 10
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 2ef3d6c..90f9699 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -10955,6 +10955,58 @@
#------------------------------------------------------
+# B2 10 群英榜匹配玩家 #tagCSQunyingMatch
+
+class tagCSQunyingMatch(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("IsRefresh", c_ubyte), # 0-打开界面无匹配数据时查询,1-强制刷新匹配列表
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xB2
+ self.SubCmd = 0x10
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.Cmd = 0xB2
+ self.SubCmd = 0x10
+ self.IsRefresh = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCSQunyingMatch)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// B2 10 群英榜匹配玩家 //tagCSQunyingMatch:
+ Cmd:%s,
+ SubCmd:%s,
+ IsRefresh:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.IsRefresh
+ )
+ return DumpString
+
+
+m_NAtagCSQunyingMatch=tagCSQunyingMatch()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCSQunyingMatch.Cmd,m_NAtagCSQunyingMatch.SubCmd))] = m_NAtagCSQunyingMatch
+
+
+#------------------------------------------------------
# B2 07 重置加点 #tagCMResetAttrPoint
class tagCMResetAttrPoint(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 6071124..d0f7884 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -14398,6 +14398,261 @@
#------------------------------------------------------
+# A9 24 群英榜匹配玩家列表 #tagSCQunyingMatchList
+
+class tagSCQunyingMatchInfo(Structure):
+ Rank = 0 #(WORD Rank)//排名,从1开始
+ PlayerID = 0 #(DWORD PlayerID)//目标玩家ID
+ PlayerName = "" #(char PlayerName[33])
+ LV = 0 #(WORD LV)// 玩家等级
+ RealmLV = 0 #(WORD RealmLV)//境界,机器人读境界表取等级对应境界
+ FightPower = 0 #(DWORD FightPower)//战力求余亿部分
+ FightPowerEx = 0 #(DWORD FightPowerEx)//战力整除亿部分
+ Face = 0 #(DWORD Face)//基本脸型
+ FacePic = 0 #(DWORD FacePic)//头像框
+ TitleID = 0 #(DWORD TitleID)//称号
+ ModelMark = 0 #(DWORD ModelMark)//变形模型mark
+ EquipShowSwitch = 0 #(DWORD EquipShowSwitch)//其他外观信息
+ ServerID = 0 #(DWORD ServerID)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.Rank,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.PlayerName,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.LV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.RealmLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TitleID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.ModelMark,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.EquipShowSwitch,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.Rank = 0
+ self.PlayerID = 0
+ self.PlayerName = ""
+ self.LV = 0
+ self.RealmLV = 0
+ self.FightPower = 0
+ self.FightPowerEx = 0
+ self.Face = 0
+ self.FacePic = 0
+ self.TitleID = 0
+ self.ModelMark = 0
+ self.EquipShowSwitch = 0
+ self.ServerID = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 2
+ length += 4
+ length += 33
+ length += 2
+ length += 2
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteWORD(data, self.Rank)
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteString(data, 33, self.PlayerName)
+ data = CommFunc.WriteWORD(data, self.LV)
+ data = CommFunc.WriteWORD(data, self.RealmLV)
+ data = CommFunc.WriteDWORD(data, self.FightPower)
+ data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+ data = CommFunc.WriteDWORD(data, self.Face)
+ data = CommFunc.WriteDWORD(data, self.FacePic)
+ data = CommFunc.WriteDWORD(data, self.TitleID)
+ data = CommFunc.WriteDWORD(data, self.ModelMark)
+ data = CommFunc.WriteDWORD(data, self.EquipShowSwitch)
+ data = CommFunc.WriteDWORD(data, self.ServerID)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Rank:%d,
+ PlayerID:%d,
+ PlayerName:%s,
+ LV:%d,
+ RealmLV:%d,
+ FightPower:%d,
+ FightPowerEx:%d,
+ Face:%d,
+ FacePic:%d,
+ TitleID:%d,
+ ModelMark:%d,
+ EquipShowSwitch:%d,
+ ServerID:%d
+ '''\
+ %(
+ self.Rank,
+ self.PlayerID,
+ self.PlayerName,
+ self.LV,
+ self.RealmLV,
+ self.FightPower,
+ self.FightPowerEx,
+ self.Face,
+ self.FacePic,
+ self.TitleID,
+ self.ModelMark,
+ self.EquipShowSwitch,
+ self.ServerID
+ )
+ return DumpString
+
+
+class tagSCQunyingMatchList(Structure):
+ Head = tagHead()
+ MatchCount = 0 #(BYTE MatchCount)
+ MatchList = list() #(vector<tagSCQunyingMatchInfo> MatchList)// 匹配列表,从高分到低分
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xA9
+ self.Head.SubCmd = 0x24
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.MatchCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.MatchCount):
+ temMatchList = tagSCQunyingMatchInfo()
+ _pos = temMatchList.ReadData(_lpData, _pos)
+ self.MatchList.append(temMatchList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xA9
+ self.Head.SubCmd = 0x24
+ self.MatchCount = 0
+ self.MatchList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ for i in range(self.MatchCount):
+ length += self.MatchList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.MatchCount)
+ for i in range(self.MatchCount):
+ data = CommFunc.WriteString(data, self.MatchList[i].GetLength(), self.MatchList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ MatchCount:%d,
+ MatchList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.MatchCount,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagSCQunyingMatchList=tagSCQunyingMatchList()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCQunyingMatchList.Head.Cmd,m_NAtagSCQunyingMatchList.Head.SubCmd))] = m_NAtagSCQunyingMatchList
+
+
+#------------------------------------------------------
+# A9 25 群英榜玩家信息 #tagSCQunyingPlayerInfo
+
+class tagSCQunyingPlayerInfo(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("RefreshCnt", c_int), # 本周已刷新匹配次数
+ ("LastRecoverTime", c_int), # 上次免费恢复挑战令时间戳,为0时可不用倒计时
+ ("RankHighest", c_ushort), # 历史最高名次,第1名为最高
+ ("RankSuccAward", c_int), # 历史最高名次成就领奖记录,按奖励记录索引位运算记录是否已领取
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xA9
+ self.SubCmd = 0x25
+ return
+
+ def ReadData(self, stringData, _pos=0, _len=0):
+ self.Clear()
+ memmove(addressof(self), stringData[_pos:], self.GetLength())
+ return _pos + self.GetLength()
+
+ def Clear(self):
+ self.Cmd = 0xA9
+ self.SubCmd = 0x25
+ self.RefreshCnt = 0
+ self.LastRecoverTime = 0
+ self.RankHighest = 0
+ self.RankSuccAward = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagSCQunyingPlayerInfo)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// A9 25 群英榜玩家信息 //tagSCQunyingPlayerInfo:
+ Cmd:%s,
+ SubCmd:%s,
+ RefreshCnt:%d,
+ LastRecoverTime:%d,
+ RankHighest:%d,
+ RankSuccAward:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.RefreshCnt,
+ self.LastRecoverTime,
+ self.RankHighest,
+ self.RankSuccAward
+ )
+ return DumpString
+
+
+m_NAtagSCQunyingPlayerInfo=tagSCQunyingPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCQunyingPlayerInfo.Cmd,m_NAtagSCQunyingPlayerInfo.SubCmd))] = m_NAtagSCQunyingPlayerInfo
+
+
+#------------------------------------------------------
# A9 21 角色改名结果 #tagSCRenameResult
class tagSCRenameResult(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py
index 2818ac5..64d5ff9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/DB/StructData/DBBillboard.py
@@ -24,6 +24,7 @@
import CommFunc
import json
+import time
class BillboardData():
## 榜单数据
@@ -110,6 +111,8 @@
copyData.SetTime(self.GetTime())
return copyData
+TempBillData = BillboardData()
+
class Billboard():
## 某个排行榜类
@@ -120,8 +123,13 @@
self.__billboardList = [] # [BillboardData, ...]
self.__idIndexDict = {} # {id:index, ...}
self.__idOrderDict = {} # {id:名次, ...}
- self.__orderRuleList = None # 指定排名所需值规则列表 [[order, needCmpValue], ...]
self.__sortDelay = False # 是否需要延迟排序
+ self.__orderRuleList = None # 指定排名所需值规则列表 [[order, needCmpValue], ...]
+
+ # 【层级模式】机器人填充数据模式,一般如果机器人数据量比较大的情况下实用该模式,如群英榜
+ # 层级模式下,因为机器人数量一般比较大,比如1万,为了节约内存占用及遍历排序等效率,填充的机器人数据不插入实际的 __billboardList 里
+ self.__orderRuleByLayer = False # 按固定层级模式,第1层即第1名,CmpValue直接使用名次值,方便排序用,由功能自行管理好CmpValue值
+ self.__layerIDList = [] # 层级ID列表,顺序即排名,索引0为第1名,ID包含填充的机器人ID,初始的数据由功能按规则设置填充的机器人ID
return
def GetType(self): return self.__billboardType
@@ -143,10 +151,15 @@
def SortData(self):
GameWorld.DebugLog("榜单排序: billboardType=%s,groupValue1=%s,groupValue2=%s,dataCount=%s"
% (self.__billboardType, self.__groupValue1, self.__groupValue2, len(self.__billboardList)))
- self.__billboardList.sort(key=lambda b: (b.GetCmpValue(), b.GetCmpValue2(), b.GetCmpValue3(), -b.GetTime()), reverse=True)
+ if self.__orderRuleByLayer:
+ self.__billboardList.sort(key=lambda b: (-b.GetCmpValue(), -b.GetTime()), reverse=True)
+ else:
+ self.__billboardList.sort(key=lambda b: (b.GetCmpValue(), b.GetCmpValue2(), b.GetCmpValue3(), -b.GetTime()), reverse=True)
self.__idOrderDict = {} # 排序后重置,下次查询时更新并缓存
self.__idIndexDict = {}
self.__sortDelay = False
+ if self.__orderRuleByLayer:
+ self.__fixAndFillLayer()
return
def SetSortDelay(self):
@@ -161,7 +174,7 @@
if not self.__sortDelay:
return
self.SortData()
- return
+ return True
def AddNewBillboardData(self, dataID):
newData = None
@@ -273,12 +286,66 @@
billboardIndex += 1
for order, billboardData in enumerate(self.__billboardList, 1):
self.__idIndexDict[billboardData.GetID()] = order - 1
+ # 按层级固定排位的
+ elif self.__orderRuleByLayer:
+ if not self.SortDelayDo():
+ self.__fixAndFillLayer()
else:
for order, billboardData in enumerate(self.__billboardList, 1):
self.__idOrderDict[billboardData.GetID()] = order
self.__idIndexDict[billboardData.GetID()] = order - 1
return self.__idOrderDict
+ def IsOrderRuleByLayer(self): return self.__orderRuleByLayer
+ def SetOrderRuleByLayer(self, layerRobotIDList):
+ '''设置排名规则为层级模式,即一个名次一个坑位层级,该模式支持机器人填充数据
+ 该模式下 CmpValue 固定为 MaxCount - 名次 + 1
+ @param layerRobotIDList: 填充的机器人ID排名列表
+ '''
+ self.__orderRuleByLayer = True
+ self.__layerIDList = layerRobotIDList
+ self.SortData() # 强制排序处理
+ return
+ def SetLayerIDList(self, layerIDList): self.__layerIDList = layerIDList
+ def GetLayerIDList(self): return self.__layerIDList
+ def __fixAndFillLayer(self):
+ ## 检查修正并填充满最终层级ID顺序
+ maxCount = self.GetMaxCount()
+ layerIDCnt = len(self.__layerIDList)
+ if layerIDCnt < maxCount:
+ self.__layerIDList.extend([0]*(maxCount-layerIDCnt)) # 先用0填充,确保长度一致
+
+ # 先检查修正真实榜单数据的排名值,确保唯一
+ orderIDDict = {}
+ for index, billboardData in enumerate(self.__billboardList):
+ dataID = billboardData.GetID()
+ order = billboardData.GetCmpValue()
+ if order > maxCount:
+ # 超过的默认不上榜,后面的数据不再处理,外层的数据使用替换的模式,故理论上不会有多余的数据,这里暂做个防范
+ break
+ if order <= 0:
+ # 没有名次数据的也不上榜,但先跳过继续处理后面的数据
+ continue
+
+ while 1 <= order <= maxCount:
+ if order not in orderIDDict:
+ orderIDDict[order] = dataID
+ self.__idOrderDict[dataID] = order
+ self.__idIndexDict[dataID] = index
+ break
+ # 重复的数据修正层级比较值,确保唯一
+ order += 1
+ billboardData.SetCmpValue(order)
+
+ for index, layerID in enumerate(self.__layerIDList):
+ order = index + 1
+ dataID = layerID
+ if order in orderIDDict:
+ dataID = orderIDDict[order]
+ self.__layerIDList[index] = dataID
+
+ return
+
def SetOrderRuleList(self, orderRuleList):
## 排名所需值规则列表
# @param orderRuleList: 排名所需值规则列表 [[order, needCmpValue], ...]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py
index ceb798d..cf018cb 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Billboard.py
@@ -29,7 +29,7 @@
GameWorld.DebugAnswer(curPlayer, "输出排行榜数据: Billboard p 类型 [分组值1 值2 从x名 到x名]")
GameWorld.DebugAnswer(curPlayer, "注:如果没有特殊说明,本服榜单分组值均为0,跨服榜单分组值1为分区ID,分组2为0")
- for billboardType in ShareDefine.BillboardTypeList:
+ for billboardType in ShareDefine.BillboardTypeAllList:
bName = ShareDefine.BillboardNameDict.get(billboardType, billboardType)
GameWorld.DebugAnswer(curPlayer, "(%s) %s" % (billboardType, bName))
@@ -89,7 +89,9 @@
billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
curDataCount = billboardObj.GetCount()
maxDataCount = billboardObj.GetMaxCount()
-
+ isLayerMode = billboardObj.IsOrderRuleByLayer()
+ if isLayerMode:
+ cmpValue1 = min(cmpValue1, maxDataCount)
count = min(count, maxDataCount - curDataCount)
FakeName = GameWorld.GbkToCode("主公")
@@ -103,9 +105,12 @@
name1 = dataPlayerName
cmpValue = dataCmpValue1
cmpValue2 = dataCmpValue2
- PlayerBillboard.UpdateBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2,
- cmpValue, cmpValue2, cmpValue3, groupValue2, id2, False,
- value3=value3, value4=value4, value5=value5)
+ if isLayerMode:
+ PlayerBillboard.UpdateBillboardLayer(dataID, billboardType, cmpValue, groupValue1, False)
+ else:
+ PlayerBillboard.UpdateBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2,
+ cmpValue, cmpValue2, cmpValue3, groupValue2, id2, False,
+ value3=value3, value4=value4, value5=value5)
billboardObj.SortData()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Qunying.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Qunying.py
new file mode 100644
index 0000000..455b503
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Qunying.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Qunying
+#
+# @todo:群英榜
+# @author hxp
+# @date 2026-03-11
+# @version 1.0
+#
+# 详细描述: 群英榜
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2026-03-11 19:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import GameLogic_Qunying
+import PlayerBillboard
+import PlayerControl
+import DBDataMgr
+import ChConfig
+
+def OnExec(curPlayer, msgList):
+ if not msgList:
+ GameWorld.DebugAnswer(curPlayer, "重置群英数据: Qunying 0")
+ GameWorld.DebugAnswer(curPlayer, "设置所在名次: Qunying 名次")
+ GameWorld.DebugAnswer(curPlayer, "设置历史最高: Qunying h 名次 [重置奖励]")
+ GameWorld.DebugAnswer(curPlayer, "设置刷新次数: Qunying r 次数")
+ GameWorld.DebugAnswer(curPlayer, "输出名次数据: Qunying p [从x名开始 数量 ]")
+ return
+
+ playerID = curPlayer.GetPlayerID()
+
+ value1 = msgList[0]
+ if value1 == "p":
+ billboardMgr = DBDataMgr.GetBillboardMgr()
+ billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Qunying)
+ if not billBoard:
+ return
+ billBoard.SortDelayDo()
+ layerIDList = billBoard.GetLayerIDList()
+ fromRank = max(1, msgList[1] if len(msgList) > 1 else 1)
+ dataCnt = min(msgList[2] if len(msgList) > 2 else 10, 20)
+ toRank = min(len(layerIDList), fromRank + dataCnt)
+ GameWorld.DebugAnswer(curPlayer, "榜单总数据:%s/%s,idCnt=%s" % (billBoard.GetCount(), billBoard.GetMaxCount(), len(layerIDList)))
+ for rank in range(fromRank, toRank + 1):
+ dataID = layerIDList[rank - 1]
+ GameWorld.DebugAnswer(curPlayer, "名次%s, ID:%s" % (rank, dataID))
+ return
+
+ if value1 <= 0:
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRefreshCnt, 0)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRankHighest, 0)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRankSuccAward, 0)
+ GameWorld.DebugAnswer(curPlayer, "重置成功!")
+
+ elif value1 == "h":
+ rankHighest = msgList[1] if len(msgList) > 1 else 0
+ resetAward = msgList[2] if len(msgList) > 2 else 0
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRankHighest, rankHighest)
+ if resetAward:
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRankSuccAward, 0)
+ GameWorld.DebugAnswer(curPlayer, "设置历史最高: %s" % rankHighest)
+
+ elif value1 == "r":
+ refreshCnt = msgList[1] if len(msgList) > 1 else 0
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRefreshCnt, refreshCnt)
+ GameWorld.DebugAnswer(curPlayer, "设置刷新次数: %s" % refreshCnt)
+
+ elif value1 > 0:
+ cmpValue = value1
+ if PlayerBillboard.UpdateBillboardLayer(playerID, ShareDefine.Def_BT_Qunying, cmpValue):
+ GameWorld.DebugAnswer(curPlayer, "设置所在名次成功: %s" % cmpValue)
+ else:
+ GameWorld.DebugAnswer(curPlayer, "设置所在名次只能为1~最大名次")
+ return
+
+ GameLogic_Qunying.Sync_QunyingInfo(curPlayer)
+ return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
index d62bc5b..bcc222c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
@@ -993,37 +993,32 @@
PlayerControl.PlayerLeaveFB(curPlayer)
return
-## 副本每周逻辑
-# @param tick 当前时间
-# @return None or False
-# @remarks 函数详细说明.
-def OnWeek(tick):
- do_FBLogic_ID = __GetFBLogic_MapID(GameWorld.GetMap().GetMapID())
-
- callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (do_FBLogic_ID, "OnWeek"))
-
- if callFunc == None:
- return False
-
- #执行副本逻辑
- callFunc(tick)
+def OnWeek():
+ for key, mapIDList in ChConfig.Def_FB_MapID.items():
+ if not mapIDList:
+ continue
+ callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (key, "OnWeek"))
+ if callFunc:
+ callFunc()
return
-## 副本每日逻辑
-# @param tick 当前时间
-# @return None or False
-# @remarks 函数详细说明.
-def OnDay(tick):
- do_FBLogic_ID = __GetFBLogic_MapID(GameWorld.GetMap().GetMapID())
-
- callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (do_FBLogic_ID, "OnDay"))
-
- if callFunc == None:
- #GameWorld.Log("副本逻辑不可使用 GameLogic_%d"%(mapID))
- return False
-
- #执行副本逻辑
- callFunc(tick)
+def OnDay():
+ for key, mapIDList in ChConfig.Def_FB_MapID.items():
+ if not mapIDList:
+ continue
+ callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (key, "OnDay"))
+ if callFunc:
+ callFunc()
+ return
+
+## 副本每周逻辑-玩家, 不管玩家是否在该副本地图中都会触发
+def OnFBPlayerOnWeek(curPlayer, onWeekType):
+ for key, mapIDList in ChConfig.Def_FB_MapID.items():
+ if not mapIDList:
+ continue
+ callFunc = GameWorld.GetExecFunc(FBProcess, "GameLogic_%s.%s" % (key, "OnFBPlayerOnWeek"))
+ if callFunc:
+ callFunc(curPlayer)
return
## 副本每日逻辑-玩家, 不管玩家是否在该副本地图中都会触发
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
index 48e7665..9519666 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
@@ -1559,6 +1559,9 @@
return True
def FBOnWeek(curPlayer, onWeekType):
+ if onWeekType != ShareDefine.Def_OnEventType:
+ return
+ FBLogic.OnFBPlayerOnWeek(curPlayer, onWeekType)
return
def FBOnDay(curPlayer, onDayType):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Qunying.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Qunying.py
new file mode 100644
index 0000000..cb18592
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_Qunying.py
@@ -0,0 +1,599 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GameWorldLogic.FBProcess.GameLogic_Qunying
+#
+# @todo:群英榜
+# @author hxp
+# @date 2026-03-11
+# @version 1.0
+#
+# 详细描述: 群英榜
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2026-03-11 19:00"""
+#-------------------------------------------------------------------------------
+
+import DBDataMgr
+import GameWorld
+import TurnAttack
+import ShareDefine
+import PlayerControl
+import IpyGameDataPY
+import PlayerBillboard
+import PlayerViewCache
+import ChPyNetSendPack
+import NetPackCommon
+import ItemControler
+import GameFuncComm
+import PyGameData
+import FBCommon
+import ChConfig
+
+import random
+import time
+
+# 记录攻击类型
+RecAtkType_Atk = 1 # 发起攻击
+RecAtkType_Def = 2 # 被攻击的
+
+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():
+ serverDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_ServerDay) + 1
+ serverDayNeed = IpyGameDataPY.GetFuncCfg("QunyingSet", 1)
+ if serverDayNeed and serverDay < serverDayNeed:
+ GameWorld.DebugLog("开服天不足本周不重置群英榜! serverDay=%s < %s" % (serverDay, serverDayNeed))
+ return
+ DoQunyingReset()
+ return
+
+def OnDay():
+ billboardAwardDict = IpyGameDataPY.GetFuncEvalCfg("QunyingAward", 1, {})
+ PlayerBillboard.DoGiveBillboardAwardByMail(ShareDefine.Def_BT_Qunying, "QunyingDay", billboardAwardDict, "QunyingDay", isClearData=False)
+ return
+
+def OnServerStart():
+ __fillRobot()
+ return
+
+def DoQunyingReset():
+ ''' 赛季重置
+ '''
+ GameWorld.Log("=============== 重置群英榜 ===============")
+
+ PyGameData.g_qunyingPlayerMatchDict = {}
+
+ # 结算上赛季排行奖励
+ billboardAwardDict = IpyGameDataPY.GetFuncEvalCfg("QunyingAward", 2, {})
+ PlayerBillboard.DoGiveBillboardAwardByMail(ShareDefine.Def_BT_Qunying, "QunyingWeek", billboardAwardDict, "QunyingWeek", isClearData=False)
+
+ # 重置排行榜
+ DBDataMgr.GetBillboardMgr().RemoveBillboard(ShareDefine.Def_BT_Qunying)
+ __fillRobot()
+
+ GameWorld.Log("==========================================")
+ return True
+
+def __fillRobot():
+ ## 填充满机器人
+ billboardMgr = DBDataMgr.GetBillboardMgr()
+ billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Qunying)
+ maxCount = billBoard.GetMaxCount() # 机器人填充数默认使用榜单最大数
+
+ robotFPSortList = PlayerViewCache.GetRobotFightPowerSortList(ChConfig.RobotTempNum_Qunying)
+ robotDict = {} # {(rankA, rankB):[robotID], ...}
+ for _, robotID in robotFPSortList:
+ robotIpyData = IpyGameDataPY.GetIpyGameData("Robot", robotID)
+ if not robotIpyData:
+ continue
+ tempValue1 = robotIpyData.GetTempValue1()
+ tempValue2 = robotIpyData.GetTempValue2()
+ rankKey = (tempValue1, tempValue2)
+ if rankKey not in robotDict:
+ robotDict[rankKey] = []
+ robotList = robotDict[rankKey]
+ robotList.append(robotIpyData.GetID())
+
+ layerRobotIDList = []
+ robotKeyList = robotDict.keys()
+ robotKeyList.sort() # 按名次排序处理
+ for robotKey in robotKeyList:
+ rankA, rankB = robotKey
+ robotIDList = robotDict[robotKey]
+ random.shuffle(robotIDList)
+ robotCnt = len(robotIDList)
+ needRobotCnt = rankB - rankA + 1
+ for _ in range(needRobotCnt / robotCnt):
+ layerRobotIDList += robotIDList
+ for index in range(needRobotCnt % robotCnt):
+ layerRobotIDList.append(robotIDList[index])
+ layerRobotIDList = layerRobotIDList[:maxCount]
+ GameWorld.DebugLog("填充群英榜机器人: maxCount=%s,fillRobotIDLen=%s" % (maxCount, len(layerRobotIDList)))
+ billBoard.SetOrderRuleByLayer(layerRobotIDList)
+ return
+
+## ------------------------------------------------------------------------------------------------
+
+def DoQunyingOpen(curPlayer):
+ storeMax = IpyGameDataPY.GetFuncCfg("QunyingChallenge", 1)
+ PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_QunyingTicket, storeMax, "QunyingOpen")
+ Sync_QunyingInfo(curPlayer) # 开启功能
+ return
+
+def OnFBPlayerOnWeek(curPlayer):
+ if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Qunying):
+ return
+ serverDay = DBDataMgr.GetEventTrigMgr().GetValue(ShareDefine.Def_ServerDay) + 1
+ serverDayNeed = IpyGameDataPY.GetFuncCfg("QunyingSet", 1)
+ # 玩家重置有个问题,玩家的过周并不一定是周一触发,具体看玩家什么时候登录
+ # 那么可能存在周二玩家才登录,然后满足了重置条件,导致触发了玩家个人的赛季重置
+ # 目前只有刷新次数需要重置,暂时不考虑这个问题,这种情况一般只有新服才可能出现
+ # 【注】如之后有需要重置比较严谨的数据,则需要按赛季ID对比不一样才能重置
+ if serverDayNeed and serverDay < serverDayNeed:
+ GameWorld.DebugLog("开服天不足本周不重置玩家群英榜! serverDay=%s < %s" % (serverDay, serverDayNeed), curPlayer.GetPlayerID())
+ return
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRefreshCnt, 0)
+ Sync_QunyingInfo(curPlayer) # 赛季重置
+ return
+
+def OnFBPlayerOnLogin(curPlayer):
+ if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Qunying):
+ return
+ Sync_QunyingInfo(curPlayer) # 登录
+ return
+
+def __checkAtkQunyingPlayer(curPlayer, tagID, tagRank):
+ '''检查可否攻击目标
+ '''
+ playerID = curPlayer.GetPlayerID()
+ if not tagID or playerID == tagID:
+ return
+
+ matchRankList = PyGameData.g_qunyingPlayerMatchDict.get(playerID, [])
+ if tagRank not in matchRankList:
+ GameWorld.DebugLog("群英榜不可攻击不在匹配列表里的目标名次! tagID=%s not in matchRankList=%s" % (tagID, matchRankList), playerID)
+ return
+
+ # 验证名次是否还与前端的一致
+ billboardMgr = DBDataMgr.GetBillboardMgr()
+ billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Qunying)
+ if not billBoard:
+ return
+ layerIDList = billBoard.GetLayerIDList()
+
+ tagIndex = tagRank - 1
+ tagIDNow = 0
+ if 0 <= tagIndex < len(layerIDList):
+ tagIDNow = layerIDList[tagIndex]
+ if tagID != tagIDNow:
+ GameWorld.DebugLog("群英榜攻击时目标名次玩家ID不一致! tagRank=%s,tagID=%s != tagIDNow=%s" % (tagRank, tagID, tagIDNow), playerID)
+ PlayerControl.NotifyCode(curPlayer, "QunyingTagRankIDErr") # 目标玩家名次已改变
+ DoQunyingMatchRefresh(curPlayer, True, isSys=True)
+ return
+
+ return True
+
+def OnTurnFightRequest(curPlayer, mapID, funcLineID, tagType, tagID, valueList):
+ ## 回合战斗请求
+
+ if not valueList:
+ return
+
+ tagRank = valueList[0] # 目标名次
+ quickCnt = valueList[1] if len(valueList) > 1 else 0 # 速战次数
+
+ # 速战
+ if quickCnt > 0:
+ __doQuickFight(curPlayer, mapID, tagID, quickCnt)
+ return
+
+ if not __checkAtkQunyingPlayer(curPlayer, tagID, tagRank):
+ return
+
+ if not PlayerControl.HaveMoney(curPlayer, ShareDefine.TYPE_Price_QunyingTicket, 1):
+ return
+
+ return True, funcLineID
+
+def __doQuickFight(curPlayer, mapID, tagID, quickCnt):
+ '''执行速战,必胜、只给固定战斗奖励,名次不变
+ '''
+ GameWorld.DebugLog("群英榜速战: tagID=%s,quickCnt=%s" % (tagID, quickCnt))
+ if quickCnt <= 0:
+ return
+
+ if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_QunyingTicket, quickCnt, "Qunying"):
+ return
+
+ awardItemDict = {}
+ for item in IpyGameDataPY.GetFuncEvalCfg("QunyingChallenge", 3):
+ itemID, itemCount = item[:2]
+ awardItemDict[itemID] = awardItemDict.get(itemID, 0) + itemCount * quickCnt
+ awardItemList = [[itemID, itemCount] for itemID, itemCount in awardItemDict.items()]
+
+ ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["Qunying", False, {}], isNotifyAward=False)
+
+ lineID = 0
+ isPass = 1
+ jsonItemList = []
+ for itemInfo in awardItemList:
+ itemDict = {"ItemID":itemInfo[0], "Count":itemInfo[1]}
+ jsonItemList.append(itemDict)
+ overDict = {FBCommon.Over_itemInfo:jsonItemList, FBCommon.Over_isSweep:1, "tagID":tagID, "quickCnt":quickCnt}
+ FBCommon.NotifyFBOver(curPlayer, mapID, lineID, isPass, overDict)
+ return
+
+def OnTurnFightAward(curPlayer, guid, mapID, funcLineID, winFaction, statMsg, dateStr, reqData, awardDict):
+ ## 回合战斗结算奖励
+ if not curPlayer:
+ return
+
+ playerID = curPlayer.GetPlayerID()
+ tagPlayerID = reqData[1]
+ valueList = reqData[2]
+ tagRank = valueList[0] # 目标名次
+ isWin = winFaction == ChConfig.Def_FactionA
+
+ GameWorld.DebugLog("结算群英榜战斗! isWin=%s,tagPlayerID=%s,tagRank=%s" % (isWin, tagPlayerID, tagRank), playerID)
+ canAtkRet = __checkAtkQunyingPlayer(curPlayer, tagPlayerID, tagRank)
+ if not canAtkRet:
+ return
+
+ billboardMgr = DBDataMgr.GetBillboardMgr()
+ billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Qunying)
+ idRankDict = billBoard.GetIDOrderDict()
+ curRank = idRankDict.get(playerID, 0)
+
+ updRank = 0
+ awardItemList = []
+ if isWin:
+ # 胜利时固定奖励
+ awardItemList = IpyGameDataPY.GetFuncEvalCfg("QunyingChallenge", 3)
+ cmpValue = tagRank
+ if PlayerBillboard.UpdateBillboardLayer(playerID, ShareDefine.Def_BT_Qunying, cmpValue):
+ updRank = tagRank
+ else:
+ GameWorld.DebugLog(" 更新榜单失败", playerID)
+
+ awardDict.update({FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(awardItemList), "tagPlayerID":tagPlayerID, "updRank":updRank, "curRank":curRank})
+
+ GameWorld.DebugLog(" tagPlayerID=%s,isWin=%s,awardItemList=%s" % (tagPlayerID, isWin, awardItemList), playerID)
+ if not PlayerControl.PayMoney(curPlayer, ShareDefine.TYPE_Price_QunyingTicket, 1):
+ return
+
+ if isWin:
+ ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["Qunying", False, {}], isNotifyAward=False)
+
+ rankHighest = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRankHighest)
+ if not rankHighest or (1 <= tagRank < rankHighest):
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRankHighest, tagRank)
+ GameWorld.DebugLog(" 更新历史最高排名! tagRank=%s" % tagRank, playerID)
+ Sync_QunyingInfo(curPlayer) # 更新最高排名
+
+ __updQunyingBatRecord(curPlayer, tagPlayerID, isWin, curRank, tagRank)
+
+ # 战斗结束系统强制刷新匹配
+ DoQunyingMatchRefresh(curPlayer, True, isSys=True)
+ return
+
+def __updQunyingBatRecord(curPlayer, tagPlayerID, isWin, curRank, tagRank):
+ ## 更新战斗相关日志、榜单等
+
+ playerID = curPlayer.GetPlayerID()
+ maxCount = 20
+
+ tagViewCache = PlayerViewCache.FindViewCache(tagPlayerID)
+
+ gameRecMgr = DBDataMgr.GetGameRecMgr()
+ atkRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_QunyingRecord, playerID)
+ recData = atkRecMgr.AddRecData(maxCount)
+ SetRecAtkType(recData, RecAtkType_Atk)
+ SetRecTagPlayerID(recData, tagPlayerID)
+ SetRecIsWin(recData, isWin)
+ SetRecFace(recData, tagViewCache.GetFace() if tagViewCache else 0)
+ SetRecFacePic(recData, tagViewCache.GetFacePic() if tagViewCache else 0)
+ SetRecRealmLV(recData, tagViewCache.GetRealmLV() if tagViewCache else 1)
+ SetRecLV(recData, tagViewCache.GetLV() if tagViewCache else 1)
+ # 名字、自己名次、对方名次
+ tagPlayerName = tagViewCache.GetPlayerName() if tagViewCache else ""
+ recData.SetUserData({"Name":tagPlayerName, "CurRank":curRank, "TagRank":tagRank})
+
+ # 被击方
+ if tagPlayerID < ShareDefine.RealPlayerIDStart:
+ #GameWorld.DebugLog("目标非真实玩家不处理! tagPlayerID=%s" % tagPlayerID, playerID)
+ return
+
+ # 由于非榜单上的玩家不会被匹配到,所以被匹配到的可以理解为一定有战斗记录,因为要上榜必须战斗过
+ defRecMgr = gameRecMgr.GetRecTypeIDMgr(ShareDefine.Def_GameRecType_QunyingRecord, tagPlayerID)
+ if not defRecMgr.GetCount():
+ GameWorld.DebugLog("目标没有对战记录不处理! tagPlayerID=%s" % tagPlayerID, playerID)
+ return
+
+ finalRecData = defRecMgr.At(defRecMgr.GetCount() - 1)
+ if not GameWorld.CheckTimeIsSameWeek(finalRecData.GetTime()):
+ GameWorld.DebugLog("目标本周没有对战记录不处理! tagPlayerID=%s" % tagPlayerID, playerID)
+ return
+
+ recData = defRecMgr.AddRecData(maxCount)
+ SetRecAtkType(recData, RecAtkType_Def)
+ SetRecTagPlayerID(recData, playerID)
+ SetRecIsWin(recData, not isWin)
+ SetRecFace(recData, curPlayer.GetFace())
+ SetRecFacePic(recData, curPlayer.GetFacePic())
+ SetRecRealmLV(recData, curPlayer.GetOfficialRank())
+ SetRecLV(recData, curPlayer.GetLV())
+ # 名字、自己名次、对方名次
+ recData.SetUserData({"Name":curPlayer.GetPlayerName(), "CurRank":tagRank, "TagRank":curRank})
+ return
+
+def GetQunyingRankHighestAward(curPlayer):
+ rankHighest = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRankHighest)
+ awardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRankSuccAward)
+ if not rankHighest:
+ return
+ GameWorld.DebugLog("领取群英榜历史最高排名成就奖励! rankHighest=%s,awardRecord=%s" % (rankHighest, awardRecord))
+ # 首次达到x名成就奖励 {"名次":[[物品ID, 个数], ...], ...}
+ rankAwardDict = IpyGameDataPY.GetFuncEvalCfg("QunyingAward", 3, {})
+ # 首次达到x名成就奖励记录索引 {"名次":记录索引, ...},记录索引从0开始递增,上线后不能修改
+ rankIndexDict = IpyGameDataPY.GetFuncEvalCfg("QunyingAward", 4, {})
+ awardItemDict = {}
+ for rankStr, itemList in rankAwardDict.items():
+ rank = int(rankStr)
+ if rankHighest > rank:
+ GameWorld.DebugLog(" 未达到: rank=%s" % rank)
+ continue
+ if rankStr not in rankIndexDict:
+ continue
+ index = rankIndexDict[rankStr]
+ if awardRecord&pow(2, index):
+ GameWorld.DebugLog(" 已领取: rank=%s" % rank)
+ continue
+ awardRecord |= pow(2, index)
+ for itemInfo in itemList:
+ itemID, itemCount = itemInfo[:2]
+ awardItemDict[itemID] = awardItemDict.get(itemID, 0) + itemCount
+ GameWorld.DebugLog(" 可领取: rank=%s,%s,%s" % (rank, itemList, awardItemDict))
+ awardItemList = [[itemID, itemCount] for itemID, itemCount in awardItemDict.items()]
+
+ GameWorld.DebugLog(" awardRecord=%s,awardRecord=%s" % (awardRecord, awardItemList))
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRankSuccAward, awardRecord)
+ ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["QunyingRankHighest", False, {}])
+ Sync_QunyingInfo(curPlayer) # 领奖
+ return
+
+def OnProcess(curPlayer):
+ CheckQunyingTicketRecover(curPlayer)
+ return
+
+def CheckQunyingTicketRecover(curPlayer):
+ ## 检查挑战令恢复
+ storeMax = IpyGameDataPY.GetFuncCfg("QunyingChallenge", 1)
+ curTicket = PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_QunyingTicket)
+ lastRecoverTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRecoverTime)
+ if curTicket >= storeMax:
+ if lastRecoverTime:
+ GameWorld.DebugLog("群英挑战令已满!")
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRecoverTime, 0)
+ Sync_QunyingInfo(curPlayer) # 挑战令恢复满
+ return
+
+ curTime = int(time.time())
+ passSeconds = curTime - lastRecoverTime
+ if not lastRecoverTime or passSeconds < 0:
+ GameWorld.DebugLog("重设群英挑战令恢复时间!")
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRecoverTime, curTime)
+ Sync_QunyingInfo(curPlayer)
+ return
+
+ cdSeconds = IpyGameDataPY.GetFuncCfg("QunyingChallenge", 2) * 60
+ if passSeconds < cdSeconds:
+ #GameWorld.DebugLog("群英挑战令恢复CD中: passSeconds=%s < %s, lastRecoverTime=%s" % (passSeconds, cdSeconds, GameWorld.ChangeTimeNumToStr(lastRecoverTime)))
+ return
+ recoverCnt = passSeconds / cdSeconds
+ recoverCnt = min(recoverCnt, storeMax - curTicket)
+ updRecoverTime = curTime - passSeconds % cdSeconds
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRecoverTime, updRecoverTime)
+ GameWorld.DebugLog("恢复群英挑战令: %s,passSeconds=%s,上次恢复:%s" % (recoverCnt, passSeconds, GameWorld.ChangeTimeNumToStr(lastRecoverTime)))
+ PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_QunyingTicket, recoverCnt)
+ if PlayerControl.GetMoney(curPlayer, ShareDefine.TYPE_Price_QunyingTicket) >= storeMax:
+ GameWorld.DebugLog("已满!")
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRecoverTime, 0)
+ Sync_QunyingInfo(curPlayer)
+ return
+
+#// B2 10 群英榜匹配玩家 #tagCSQunyingMatch
+#
+#struct tagCSQunyingMatch
+#{
+# tagHead Head;
+# BYTE IsRefresh; // 0-打开界面时查询,1-强制刷新匹配列表
+#};
+def OnQunyingMatch(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ isRefresh = clientData.IsRefresh
+ DoQunyingMatchRefresh(curPlayer, isRefresh)
+ return
+
+def DoQunyingMatchRefresh(curPlayer, isRefresh, isSys=False):
+ ## 玩家刷新匹配对手
+ playerID = curPlayer.GetPlayerID()
+ GameWorld.DebugLog("群英榜玩家刷新匹配列表: isRefresh=%s,isSys=%s" % (isRefresh, isSys), playerID)
+
+ billboardMgr = DBDataMgr.GetBillboardMgr()
+ billBoard = billboardMgr.GetBillboard(ShareDefine.Def_BT_Qunying)
+ if not billBoard:
+ return
+ layerIDList = billBoard.GetLayerIDList()
+ idRankDict = billBoard.GetIDOrderDict()
+ layerIDCnt = len(layerIDList)
+ playerRank = idRankDict.get(playerID, layerIDCnt + 1) # 未上榜默认最大名次 + 1
+
+ # 匹配对象缓存
+ if playerID not in PyGameData.g_qunyingPlayerMatchDict:
+ PyGameData.g_qunyingPlayerMatchDict[playerID] = []
+ matchRankList = PyGameData.g_qunyingPlayerMatchDict[playerID]
+ if not isRefresh and matchRankList:
+ # 非刷新的并且已经有记录的直接同步
+ GameWorld.DebugLog(" 非刷新且有数据,直接同步! matchRankList=%s" % matchRankList, playerID)
+ __SyncQunyingMatchList(curPlayer, matchRankList, layerIDList)
+ return
+
+ # 匹配可挑战目标规则 {玩家名次:[[名次差值, 匹配x个], ...], ...} 名次差值支持正负
+ matchRuleDict = IpyGameDataPY.GetFuncEvalCfg("QunyingMatch", 1, {})
+ rankList = matchRuleDict.keys()
+ rankList.sort()
+ matchRuleList = []
+ for rank in rankList:
+ if playerRank <= rank:
+ matchRuleList = matchRuleDict[rank]
+ break
+ if not matchRuleList:
+ matchRuleList = matchRuleDict[rankList[-1]] # 没有默认取最后一档
+
+ matchRuleList.sort()
+ GameWorld.DebugLog(" layerIDCnt=%s,playerRank=%s,matchRuleList=%s" % (layerIDCnt, playerRank, matchRuleList), playerID)
+ if not matchRuleList:
+ return
+
+ if isRefresh and not isSys:
+ refreshMax = IpyGameDataPY.GetFuncCfg("QunyingMatch", 3)
+ if refreshMax:
+ refreshCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRefreshCnt)
+ if refreshCnt >= refreshMax:
+ GameWorld.DebugLog(" 已达最大刷新次数! refreshCnt=%s >= %s" % (refreshCnt, refreshMax), playerID)
+ return
+ costMoney, moneyValue = IpyGameDataPY.GetFuncEvalCfg("QunyingMatch", 2)
+ if not costMoney or not moneyValue or not PlayerControl.PayMoney(curPlayer, costMoney, moneyValue, "Qunying"):
+ return
+ if refreshMax:
+ refreshCnt += 1
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_QunyingRefreshCnt, refreshCnt)
+ Sync_QunyingInfo(curPlayer) # 刷新匹配
+
+ matchRankList = [] # 因为有填充机器人,机器人ID可能重复,固按名次位置匹配 [rank, ...]
+ if 1 <= playerRank <= layerIDCnt:
+ matchRankList.append(playerRank) # 玩家有上榜时默认要包含玩家自己
+ # [[名次差值, 匹配x个], ...]
+ # 第一名时匹配示例: [[50, 4]]
+ # 未上榜时匹配示例:[[-500, 5]]
+ # 榜单中时匹配示例:[[-300, 1], [-200, 1], [-100, 1],[100, 1]]
+ for mIndex, matchRule in enumerate(matchRuleList):
+ rankDiff, matchCnt = matchRule
+ nextDiff = None
+ if mIndex < len(matchRuleList) - 1:
+ nextDiff = matchRuleList[mIndex + 1][0]
+
+ if mIndex == 0:
+ if rankDiff >= 0: # 第1个就开始匹配后面的,直接从玩家后一名开始,否则直接从与玩家名次的差值开始
+ fromRank = playerRank + 1
+ else:
+ fromRank = playerRank + rankDiff
+
+ # 非最后一档的情况
+ if nextDiff != None:
+ if rankDiff < 0 and nextDiff >= 0:
+ toRank = playerRank - 1 # 差值正负变更,默认以玩家名次分档
+ else:
+ toRank = fromRank + (nextDiff - rankDiff) - 1 # ~ 与下一档的差值
+
+ # 最后一档
+ else:
+ if rankDiff < 0:
+ toRank = layerIDCnt
+ else:
+ toRank = fromRank + rankDiff - 1
+
+ fromRank = max(fromRank, 1)
+ toRank = min(toRank, layerIDCnt)
+ if fromRank > toRank:
+ GameWorld.ErrLog("匹配规则异常! mIndex=%s,fromRank=%s,toRank=%s,%s" % (mIndex, fromRank, toRank, matchRuleList))
+ break
+
+ randRankList = range(fromRank, toRank + 1)
+ random.shuffle(randRankList)
+ rankCnt = len(randRankList)
+ mCnt = 0
+ # 不用验证目标ID,允许匹配重复的ID,只要匹配的目标名次不重复即可
+ for randRank in randRankList:
+ if randRank in matchRankList:
+ continue
+ tagID = layerIDList[randRank - 1]
+ GameWorld.DebugLog(" 匹配名次: %s ~ %s,%s名,randRank=%s,tagID=%s" % (fromRank, toRank, rankCnt, randRank, tagID), playerID)
+ matchRankList.append(randRank)
+ mCnt += 1
+ if mCnt >= matchCnt:
+ break
+
+ if toRank == playerRank - 1:
+ fromRank = toRank + 2
+ else:
+ fromRank = toRank + 1
+
+ if fromRank > layerIDCnt:
+ break
+
+ matchRankList.sort()
+ GameWorld.DebugLog(" 匹配名次结果: matchRankList=%s" % (matchRankList), playerID)
+ PyGameData.g_qunyingPlayerMatchDict[playerID] = matchRankList
+ __SyncQunyingMatchList(curPlayer, matchRankList, layerIDList)
+ return
+
+def __SyncQunyingMatchList(curPlayer, matchRankList, layerIDList):
+ ## 同步匹配列表
+ layerIDCnt = len(layerIDList)
+ clientPack = ChPyNetSendPack.tagSCQunyingMatchList()
+ clientPack.MatchList = []
+ for rank in matchRankList:
+ if rank <= 0 or rank > layerIDCnt:
+ continue
+ matchID = layerIDList[rank - 1]
+ viewCache = PlayerViewCache.FindBattleViewCache(matchID)
+ if not viewCache:
+ continue
+ matchInfo = ChPyNetSendPack.tagSCQunyingMatchInfo()
+ matchInfo.Rank = rank
+ matchInfo.PlayerID = matchID
+ if viewCache:
+ fightPower = TurnAttack.GetCacheLineupFightPower(viewCache, ShareDefine.BatPreset_QunyingDef)
+ matchInfo.PlayerName = viewCache.GetPlayerName()
+ matchInfo.RealmLV = viewCache.GetRealmLV()
+ matchInfo.LV = viewCache.GetLV()
+ matchInfo.Face = viewCache.GetFace()
+ matchInfo.FacePic = viewCache.GetFacePic()
+ matchInfo.FightPower = fightPower % ChConfig.Def_PerPointValue
+ matchInfo.FightPowerEx = fightPower / ChConfig.Def_PerPointValue
+ matchInfo.TitleID = viewCache.GetTitleID()
+ matchInfo.ModelMark = viewCache.GetModelMark()
+ matchInfo.EquipShowSwitch = viewCache.GetEquipShowSwitch()
+ matchInfo.ServerID = viewCache.GetServerID()
+ else:
+ matchInfo.PlayerName = "p%s" % matchID
+ clientPack.MatchList.append(matchInfo)
+ clientPack.MatchCount = len(clientPack.MatchList)
+ NetPackCommon.SendFakePack(curPlayer, clientPack)
+ return
+
+def Sync_QunyingInfo(curPlayer):
+ clientPack = ChPyNetSendPack.tagSCQunyingPlayerInfo()
+ clientPack.RefreshCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRefreshCnt)
+ clientPack.LastRecoverTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRecoverTime)
+ clientPack.RankHighest = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRankHighest)
+ clientPack.RankSuccAward = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_QunyingRankSuccAward)
+ NetPackCommon.SendFakePack(curPlayer, clientPack)
+ return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
index 75862a7..4e8750f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldEvent.py
@@ -25,8 +25,8 @@
import IPY_GameWorld
import DataRecordPack
import PlayerEventCounter
+import GameLogic_Qunying
import GameWorldAction
-import PlayerViewCache
import PlayerControl
import NetPackCommon
import PlayerOnline
@@ -90,7 +90,7 @@
DBDataMgr.OnServerStart() # 优先加载公共数据
#ItemCommon.InitPyItem() # 改为放 InitItem 加载
LoadDBPlayer()
- PlayerViewCache.LoadRobot()
+ #PlayerViewCache.LoadRobot()
PyGameData.g_initGameTime = int(time.time()) # 放到加载数据之后
# 检查跨服中心唯一性
@@ -111,7 +111,7 @@
__DoMixServerInit()
# 其他功能初始化
-
+ GameLogic_Qunying.OnServerStart()
# 最后触发检查是否完全启动成功
PyGameData.g_initGameWorldOK = True
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 710ec5e..8bab621 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1613,6 +1613,15 @@
("dict", "Attr", 0),
),
+ "QunyingCross":(
+ ("char", "AppID", 1),
+ ("WORD", "ZoneID", 1),
+ ("DWORD", "CrossServerID", 0),
+ ("list", "ServerIDList", 0),
+ ("BYTE", "SplitServerCnt", 0),
+ ("BYTE", "MatchServerCnt", 0),
+ ),
+
"FamilyCross":(
("char", "AppID", 1),
("WORD", "ZoneID", 1),
@@ -1749,6 +1758,10 @@
"Robot":(
("DWORD", "ID", 1),
("char", "RobotName", 0),
+ ("BYTE", "RealmLV", 0),
+ ("DWORD", "TempNum", 0),
+ ("DWORD", "TempValue1", 0),
+ ("DWORD", "TempValue2", 0),
("char", "ViewCache", 0),
),
}
@@ -4087,6 +4100,20 @@
def GetCostItem(self): return self.attrTuple[3] # 消耗材料 dict
def GetAttr(self): return self.attrTuple[4] # 属性 dict
+# 群英榜分区表
+class IPY_QunyingCross():
+
+ def __init__(self):
+ self.attrTuple = None
+ return
+
+ def GetAppID(self): return self.attrTuple[0] # AppID char
+ def GetZoneID(self): return self.attrTuple[1] # 分区ID WORD
+ def GetCrossServerID(self): return self.attrTuple[2] # 跨服服务器ID DWORD
+ def GetServerIDList(self): return self.attrTuple[3] # 互通服务器ID列表 list
+ def GetSplitServerCnt(self): return self.attrTuple[4] # 按X个相邻服分割 BYTE
+ def GetMatchServerCnt(self): return self.attrTuple[5] # 分割区服内X个服随机匹配一组 BYTE
+
# 跨服公会表
class IPY_FamilyCross():
@@ -4319,7 +4346,11 @@
def GetID(self): return self.attrTuple[0] # 机器人ID,同玩家ID DWORD
def GetRobotName(self): return self.attrTuple[1] # char
- def GetViewCache(self): return self.attrTuple[2] # 机器人缓存 char
+ def GetRealmLV(self): return self.attrTuple[2] # 指定官职 BYTE
+ def GetTempNum(self): return self.attrTuple[3] # 功能模版 DWORD
+ def GetTempValue1(self): return self.attrTuple[4] # 功能值1 DWORD
+ def GetTempValue2(self): return self.attrTuple[5] # 功能值2 DWORD
+ def GetViewCache(self): return self.attrTuple[6] # 机器人缓存 char
def Log(msg, playerID=0, par=0):
@@ -4527,6 +4558,7 @@
self.__LoadFileData("EquipShenEvolve", onlyCheck)
self.__LoadFileData("EquipStarUp", onlyCheck)
self.__LoadFileData("EquipPlusEvolve", onlyCheck)
+ self.__LoadFileData("QunyingCross", onlyCheck)
self.__LoadFileData("FamilyCross", onlyCheck)
self.__LoadFileData("Family", onlyCheck)
self.__LoadFileData("FamilyEmblem", onlyCheck)
@@ -5821,6 +5853,13 @@
self.CheckLoadData("EquipPlusEvolve")
return self.ipyEquipPlusEvolveCache[index]
+ def GetQunyingCrossCount(self):
+ self.CheckLoadData("QunyingCross")
+ return self.ipyQunyingCrossLen
+ def GetQunyingCrossByIndex(self, index):
+ self.CheckLoadData("QunyingCross")
+ return self.ipyQunyingCrossCache[index]
+
def GetFamilyCrossCount(self):
self.CheckLoadData("FamilyCross")
return self.ipyFamilyCrossLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index 7223172..b604704 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -56,6 +56,7 @@
import PlayerActManyDayRecharge
import PlayerActSingleRecharge
import OpenServerActivity
+import GameLogic_Qunying
import ChNetSendPack
import PlayerArena
import PyGameData
@@ -770,7 +771,7 @@
PlayerControl.SendMailByKey("MixServer1", [playerID], addItemList, gold=gold, silver=silver, detail=detailDict)
# 同步排行榜
- PlayerBillboard.UpdatePlayerBillboardOnLeaveServer(curPlayer, isAll=True)
+ #PlayerBillboard.UpdatePlayerBillboardOnLeaveServer(curPlayer, isAll=True)
return
#---------------------------------------------------------------------
@@ -3147,6 +3148,9 @@
# 领取活动签到奖励 70
elif rewardType == ChConfig.Def_RewardType_ActSignAward:
PlayerActSign.OnGetActSignAward(curPlayer, dataEx, dataExStr)
+ # 群英榜历史最高名次奖励 7
+ elif rewardType == ChConfig.Def_RewardType_QunyingRankHighest:
+ GameLogic_Qunying.GetQunyingRankHighestAward(curPlayer)
# 首充礼包奖励
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
index 3538cfe..96a507b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/GameFuncComm.py
@@ -30,6 +30,7 @@
import FunctionNPCCommon
import PlayerActBuyCountGift
import OpenServerActivity
+import GameLogic_Qunying
import PlayerActTask
import ItemControler
import PlayerMingge
@@ -43,6 +44,7 @@
# 功能开启需执行的函数{功能ID:执行函数, ...} 函数需返回是否激活成功, 功能开启有需要处理功能逻辑的这里增加函数调用配置即可
FuncOpenLogicDict = {
ShareDefine.GameFuncID_Arena:lambda curObj:PlayerArena.DoArenaOpen(curObj),
+ ShareDefine.GameFuncID_Qunying:lambda curObj:GameLogic_Qunying.DoQunyingOpen(curObj),
ShareDefine.GameFuncID_Shop:lambda curObj:FunctionNPCCommon.DoShopOpen(curObj),
ShareDefine.GameFuncID_Horse:lambda curObj:PlayerHorse.DoHorseOpen(curObj),
ShareDefine.GameFuncID_Travel:lambda curObj:PlayerTravel.DoTravelOpen(curObj),
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
index 72fdac1..ccacc87 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerBillboard.py
@@ -19,8 +19,10 @@
import ShareDefine
import PlayerControl
import ChPyNetSendPack
+import PlayerViewCache
import NetPackCommon
import IpyGameDataPY
+import DBBillboard
import PlayerMail
import DBDataMgr
@@ -54,7 +56,7 @@
def BillboardOnLogin(curPlayer):
# 上线默认同步排行榜
- UpdatePlayerBillboardOnLeaveServer(curPlayer) #排行榜已实时更新,故上线不再同步
+ #UpdatePlayerBillboardOnLeaveServer(curPlayer) #排行榜已实时更新,故上线不再同步
return
def GetBillboardOperateInfo(curPlayer):
@@ -63,14 +65,6 @@
return platform
def GetBillboardJob(curPlayer): return curPlayer.GetJob()
-
-def UpdatePlayerBillboardOnLeaveServer(curPlayer, isAll=False):
- ##下线更新玩家排行榜
- if GameWorld.IsCrossServer():
- # 跨服服务器不用更新本服榜
- return
-
- return
def UpdatePlayerBillboardName(curPlayer):
## 更新排行榜中的玩家名字记录
@@ -92,20 +86,6 @@
# 跨服榜更新, 待处理
return
-def UpdatePlayerFPTotalBillboard(curPlayer, isForceUpdate=False, isCheckRule=True):
- ##更新玩家总战斗力
- return
-
-#def __CanPlayerBillboardComm(curPlayer):
-# ## 玩家可否上榜通用检查
-# if not GameWorld.IsNormalPlayer(curPlayer):
-# return False
-# #if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Billboard):
-# # GameWorld.DebugLog("排行榜未开启,无法上榜!curLV=%s" % (curPlayer.GetLV()), curPlayer.GetPlayerID())
-# # return False
-#
-# return True
-
def UpdatePlayerBillboard(curPlayer, bType, cmpValue, cmpValue2=0, cmpValue3=0, autoSort=False, groupValue1=0, **kwargs):
## 更新玩家排行榜
@@ -126,6 +106,102 @@
UpdateBillboard(bType, groupValue1, playerID, playerName, playerOpInfo, playerJob, value1, value2,
cmpValue, cmpValue2, cmpValue3, autoSort=autoSort, **kwargs)
return
+
+def __updPlayerBillViewInfo(billData):
+ playerID = billData.GetID()
+ curCache = PlayerViewCache.FindViewCache(playerID)
+ if not curCache:
+ return
+ billData.SetName1(curCache.GetPlayerName())
+ billData.SetName2(curCache.GetAccID())
+ billData.SetType2(curCache.GetJob())
+ billData.SetValue1(curCache.GetRealmLV())
+ billData.SetValue2(curCache.GetTitleID())
+ billData.SetValue3(curCache.GetFace())
+ billData.SetValue4(curCache.GetFacePic())
+ billData.SetValue5(curCache.GetModelMark())
+ billData.SetValue6(curCache.GetEquipShowSwitch())
+ return
+
+def UpdateBillboardLayer(dataID, billboardType, cmpValue, groupValue1=0, autoSort=True):
+ ## 更新榜单所在的层级,一般用于层级模式的榜单,层级模式默认与目标交换名次
+ if GameWorld.IsCrossServer():
+ if billboardType not in ShareDefine.CrossBillboardTypeList:
+ return
+ else:
+ if billboardType not in ShareDefine.BillboardTypeList:
+ return
+
+ if not dataID:
+ return
+
+ groupValue2 = 0
+ billboardMgr = DBDataMgr.GetBillboardMgr()
+ billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
+ layerIDList = billboardObj.GetLayerIDList()
+ layerIDCnt = len(layerIDList)
+ if cmpValue <= 0 or cmpValue > layerIDCnt:
+ GameWorld.ErrLog("更新层级榜单名次异常! dataID=%s,billboardType=%s,cmpValue=%s,layerIDCnt=%s" % (dataID, billboardType, cmpValue, layerIDCnt), dataID)
+ return
+ tagIndex = cmpValue - 1
+ tagID = layerIDList[tagIndex]
+ if dataID == tagID:
+ return True
+ tagBillData = billboardObj.FindByID(tagID) # 当是填充的机器人时不存在数据
+ curBillData = billboardObj.FindByID(dataID)
+
+ curTime = int(time.time())
+
+ # 未上榜的替换上榜的
+ if not curBillData:
+ if tagBillData:
+ curBillData = tagBillData
+ curBillData.Clear()
+ tagBillData = None
+ else:
+ curBillData = billboardObj.AddNewBillboardData(dataID)
+
+ # 上榜的直接交换
+ else:
+ curCmpValue = curBillData.GetCmpValue()
+ if curCmpValue <= cmpValue:
+ GameWorld.DebugLog("层级榜单名次值没有提高不更新榜单! curCmpValue=%s <= %s" % (curCmpValue, cmpValue), dataID)
+ return
+ layerIDList[curCmpValue - 1] = tagID
+
+ if tagBillData:
+ tagBillData.SetCmpValue(curCmpValue)
+ tagBillData.SetTime(curTime)
+
+ layerIDList[cmpValue - 1] = dataID
+ billboardObj.SetLayerIDList(layerIDList)
+ curBillData.SetID(dataID)
+ curBillData.SetCmpValue(cmpValue)
+ curBillData.SetTime(curTime)
+
+ __updPlayerBillViewInfo(curBillData)
+
+ GameWorld.DebugLog("更新排行层值: billboardType=%s,groupValue1=%s,dataID=%s,cmpValue=%s,tagID=%s"
+ % (billboardType, groupValue1, dataID, cmpValue, tagID), dataID)
+ if autoSort:
+ billboardObj.SortData()
+ return True
+
+def SetTempDataByViewCache(playerID, billType, groupValue1=0, groupValue2=0, cmpValue=0):
+ ## 根据玩家缓存更新临时榜单数据,一般用于填充机器人
+ TempBillData = DBBillboard.TempBillData
+ TempBillData.Clear()
+ TempBillData.SetType(billType)
+ TempBillData.SetGroupValue1(groupValue1)
+ TempBillData.SetGroupValue2(groupValue2)
+ if not playerID:
+ return TempBillData
+
+ TempBillData.SetID(playerID)
+ TempBillData.SetCmpValue(cmpValue)
+ __updPlayerBillViewInfo(TempBillData)
+
+ return TempBillData
def UpdateBillboardByID(dataID, billboardType, cmpValue, cmpValue2=0, cmpValue3=0, autoSort=False):
## 直接根据榜单ID修改榜单排行相关值,其他值不修改
@@ -197,6 +273,9 @@
billboardMgr = DBDataMgr.GetBillboardMgr()
billboardObj = billboardMgr.GetBillboard(billboardType, groupValue1, groupValue2)
+ if billboardObj.IsOrderRuleByLayer():
+ # 该模式不处理,请使用 UpdateBillboardLayer
+ return
billboardData = billboardObj.FindByID(dataID)
isNewData = False
if not billboardData:
@@ -269,11 +348,6 @@
return
return lastBillBoardData
-def UpdatePlayerCrossBillboard(curPlayer, bType, groupValue1, cmpValue, cmpValue2=0, cmpValue3=0, value1=0, value2=0,
- groupValue2=0, **kwargs):
- ## 在本服直接更新玩家跨服排行榜,发送到跨服,之后扩展
- return
-
#// A1 30 查看榜单 #tagCMViewBillboard
#
#struct tagCMViewBillboard
@@ -309,7 +383,12 @@
billboardObj.SortDelayDo()
idOrderDict = billboardObj.GetIDOrderDict()
count = billboardObj.GetCount()
-
+ isLayerMode = billboardObj.IsOrderRuleByLayer() # 层级模式有机器人填充,默认为最大,实际榜单数据中没有机器人数据
+ layerIDList = []
+ if isLayerMode:
+ layerIDList = billboardObj.GetLayerIDList()
+ count = len(layerIDList)
+
maxIndex = count - 1
startIndex = max(min(startIndex, maxIndex), 0)
viewCnt = 20 if not viewCnt else min(viewCnt, 100) # 默认20,最多100
@@ -320,7 +399,13 @@
# 查看viewID前后名次
if viewID:
viewBFCnt = 3 # 查看ViewID返回前后数据条数,一般设置为奇数
- viewIDIndex = billboardObj.IndexOfByID(viewID)
+ viewIDIndex = -1
+ if isLayerMode:
+ billboardData = billboardObj.FindByID(viewID)
+ if billboardData:
+ viewIDIndex = billboardData.GetCmpValue() - 1
+ else:
+ viewIDIndex = billboardObj.IndexOfByID(viewID)
if viewIDIndex != -1:
# 前x后x
viewIDStartIndex = max(0, viewIDIndex - viewBFCnt / 2)
@@ -334,10 +419,24 @@
clientPack.DataTotal = count
clientPack.PageDataList = []
for index in viewRange:
- billboardData = billboardObj.At(index)
+ if index >= count:
+ break
+ billboardData = None
+ if isLayerMode:
+ rank = index + 1
+ dataID = layerIDList[index]
+ billboardData = billboardObj.FindByID(dataID)
+ if not billboardData:
+ cmpValue = rank
+ billboardData = SetTempDataByViewCache(dataID, bbType, groupValue1, groupValue2, cmpValue)
+ else:
+ billboardData = billboardObj.At(index)
+ rank = idOrderDict.get(billboardData.GetID(), 0)
+ if not billboardData:
+ continue
viewData = ChPyNetSendPack.tagMCViewBillboardData()
viewData.Index = index
- viewData.Rank = idOrderDict.get(billboardData.GetID(), 0)
+ viewData.Rank = rank
viewData.ID = billboardData.GetID()
viewData.ID2 = billboardData.GetID2()
viewData.Name1 = billboardData.GetName1()
@@ -362,10 +461,22 @@
clientPack.ViewID = viewID
clientPack.ViewIDDataList = []
for index in viewIDRange:
- billboardData = billboardObj.At(index)
+ billboardData = None
+ if isLayerMode:
+ rank = index + 1
+ dataID = layerIDList[index]
+ billboardData = billboardObj.FindByID(dataID)
+ if not billboardData:
+ cmpValue = rank
+ billboardData = SetTempDataByViewCache(dataID, bbType, groupValue1, groupValue2, cmpValue)
+ else:
+ billboardData = billboardObj.At(index)
+ rank = idOrderDict.get(billboardData.GetID(), 0)
+ if not billboardData:
+ continue
viewData = ChPyNetSendPack.tagMCViewBillboardData()
viewData.Index = index
- viewData.Rank = idOrderDict.get(billboardData.GetID(), 0)
+ viewData.Rank = rank
viewData.ID = billboardData.GetID()
viewData.ID2 = billboardData.GetID2()
viewData.Name1 = billboardData.GetName1()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 0b9de40..b219a6d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -1113,7 +1113,7 @@
playerControl.RefreshAllState()
#玩家下线更新排行榜
- PlayerBillboard.UpdatePlayerBillboardOnLeaveServer(curPlayer) #排行榜已实时更新,故下线不再同步
+ #PlayerBillboard.UpdatePlayerBillboardOnLeaveServer(curPlayer) #排行榜已实时更新,故下线不再同步
#玩家下线通知gameserver记录缓存(放在下线更新排行榜之后,方便Gameserver判断是否需要存入数据库中)
PlayerViewCache.OnPlayerLogout(curPlayer)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index d0181ea..cc038a9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -33,7 +33,6 @@
import PlayerActivity
import FBCommon
import ChItem
-import GameLogic_Tianzi
import PlayerGoldInvest
import PlayerActTask
import PlayerActBuyCountGift
@@ -75,14 +74,11 @@
def DoLogic_OnDay(tick):
GameWorld.Log("MapServer -> OnDay!")
- #副本OnDay事件响应
- #FBLogic.OnDay(tick)
OpenServerActivity.OnDay()
- #仙盟
+ FBLogic.OnDay()
PlayerFamily.FamilyOnDay()
PlayerArena.OnDay()
- GameLogic_Tianzi.OnDay()
PlayerOfflineSupport.OnDay()
playerManager = GameWorld.GetPlayerManager()
@@ -128,6 +124,7 @@
def DoLogic_OnWeek(tick):
GameWorld.Log("MapServer -> OnWeek!")
+ FBLogic.OnWeek()
PlayerArena.OnWeek()
playerManager = GameWorld.GetPlayerManager()
@@ -139,8 +136,6 @@
PlayerOnWeek(curPlayer)
- #副本OnWeek事件响应
- FBLogic.OnWeek(tick)
return
def DoLogic_OnMonth(tick):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
index 1f41466..2a06406 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
@@ -23,6 +23,7 @@
import ChItem
import PlayerGMOper
import OperControlManager
+import GameLogic_Qunying
import ShareDefine
import ReadChConfig
import IpyGameDataPY
@@ -1043,6 +1044,8 @@
PlayerGoldRush.OnProcess(curPlayer)
#游历
PlayerTravel.OnProcess(curPlayer)
+ #群英榜
+ GameLogic_Qunying.OnProcess(curPlayer)
return
def ProcessPlayerMinute(curPlayer, tick):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
index ab10733..2891192 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCache.py
@@ -452,36 +452,31 @@
}
return robotDict
-def LoadRobot():
- ## 加载机器人缓存,在服务器启动、重读配置时加载
- robotFPSortList = []
- viewCacheMgr = DBDataMgr.GetPlayerViewCacheMgr()
- ipyDataMgr = IpyGameDataPY.IPY_Data()
- for index in range(ipyDataMgr.GetRobotCount()):
- ipyData = ipyDataMgr.GetRobotByIndex(index)
- robotPlayerID = ipyData.GetID()
- curCache = viewCacheMgr.GetPlayerViewCache(robotPlayerID)
- if not curCache:
- curCache = viewCacheMgr.AddPlayerViewCache(robotPlayerID)
- if not curCache:
- continue
- UpdRobotViewCache(curCache, robotPlayerID, ipyData)
- robotFPSortList.append([curCache.GetFightPowerTotal(), robotPlayerID])
- robotFPSortList.sort(reverse=True) # 战力倒序排序
- IpyGameDataPY.SetConfigEx("robotFPSortList", robotFPSortList)
- GameWorld.Log("加载机器人战力排序: %s, %s" % (len(robotFPSortList), robotFPSortList))
- return robotFPSortList
-
-def GetRobotFightPowerSortList():
+def GetRobotFightPowerSortList(tempNum=0):
## 机器人战力倒序排序列表
# @return: 倒序排序列表 [[战力, 机器人ID], ...],外部使用可随机修改,不会打乱原始排序
- sortList = []
- robotFPSortList = IpyGameDataPY.GetConfigEx("robotFPSortList")
+ robotFPSortList = IpyGameDataPY.GetConfigEx("robotFPSortList%s" % tempNum)
if not robotFPSortList:
- robotFPSortList = LoadRobot()
- if robotFPSortList:
- sortList += robotFPSortList
- return sortList
+ robotFPSortList = []
+ viewCacheMgr = DBDataMgr.GetPlayerViewCacheMgr()
+ ipyDataMgr = IpyGameDataPY.IPY_Data()
+ for index in range(ipyDataMgr.GetRobotCount()):
+ ipyData = ipyDataMgr.GetRobotByIndex(index)
+ if ipyData.GetTempNum() != tempNum:
+ continue
+ robotPlayerID = ipyData.GetID()
+ curCache = viewCacheMgr.GetPlayerViewCache(robotPlayerID)
+ if not curCache:
+ curCache = viewCacheMgr.AddPlayerViewCache(robotPlayerID)
+ if not curCache:
+ continue
+ UpdRobotViewCache(curCache, robotPlayerID, ipyData)
+ robotFPSortList.append([curCache.GetFightPowerTotal(), robotPlayerID])
+ robotFPSortList.sort(reverse=True) # 战力倒序排序
+ IpyGameDataPY.SetConfigEx("robotFPSortList%s" % tempNum, robotFPSortList)
+ GameWorld.Log("加载机器人战力排序: tempNum=%s,%s, %s" % (tempNum, len(robotFPSortList), robotFPSortList))
+
+ return robotFPSortList
def UpdRobotViewCache(curCache, robotID, robotIpyData=None):
## 更新机器人查看缓存
@@ -495,11 +490,11 @@
return
#curCache.SetAccID(dbPlayer.AccID)
-
+ realmLV = robotIpyData.GetRealmLV()
curCache.SetPlayerName(GameWorld.GbkToCode(robotIpyData.GetRobotName()))
curCache.SetLV(robotInfo.get("LV", 1))
curCache.SetJob(robotInfo.get("Job", 1))
- curCache.SetRealmLV(robotInfo.get("RealmLV", 0))
+ curCache.SetRealmLV(realmLV if realmLV else robotInfo.get("RealmLV", 0))
curCache.SetFace(robotInfo.get("Face", 0))
curCache.SetFacePic(robotInfo.get("FacePic", 0))
curCache.SetTitleID(robotInfo.get("TitleID", 0))
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index baa0492..a6e1d69 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -46,6 +46,7 @@
g_broadCastList = [] # 后台gm广播
g_arenaPlayerMatchDict = {} # 本服竞技场玩家匹配记录缓存 {playerID:[tagPlayerID, ...], ...}
+g_qunyingPlayerMatchDict = {} # 群英榜玩家匹配记录缓存,该功能允许重复的机器人ID,所以记录匹配名次 {playerID:[rank, ...], ...}
g_beautyEffTypeDict = {} # 红颜特殊效果缓存 {playerID:{effType:[effValue, effTypeValue], ...}, ...}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index d8c6a8a..d319445 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -329,7 +329,8 @@
Def_BT_OSA_HeroTrain, # 开服武将冲榜 7
Def_BT_OSA_BeautyTrain, # 开服红颜冲榜 8
Def_BT_OSA_MinggeTrain, # 开服命格冲榜 9
-) = range(0, 10)
+Def_BT_Qunying, # 群英榜积分周榜 10
+) = range(0, 11)
''' 跨服排行榜类型, 从 150 开始,最大条数在功能配置表 CrossBillboardSet 配置,没配默认100
与本服榜单存储的是不一样的数据库表格,理论上类型可以和本服榜单类型重复,为了做下区分防误导,跨服榜单从 150 开始
@@ -337,7 +338,7 @@
本服榜单表(tagDBBillboard)
'''
CrossBillboardTypeList = (
-Def_CBT_ActCTG, # 跨服运营活动 - 充值榜 150
+Def_CBT_Qunying, # 跨服群英榜积分周榜 - 150
) = range(150, 150 + 1)
BillboardTypeAllList = BillboardTypeList + CrossBillboardTypeList
@@ -345,7 +346,8 @@
BillboardNameDict = {Def_BT_MainLevel:"主线过关榜", Def_BT_Arena:"演武场积分周榜", Def_BT_Tianzi:"天子考验伤害榜",
Def_BT_OSA_MainLevel:"开服关卡榜", Def_BT_OSA_HeroCall:"开服招募榜", Def_BT_Dingjunge:"定军阁过关榜",
Def_BT_OSA_HeroTrain:"开服武将冲榜", Def_BT_OSA_BeautyTrain:"开服红颜冲榜", Def_BT_OSA_MinggeTrain:"开服命格冲榜",
- Def_BT_ActHeroAppear:"武将登场招募榜(分组值1-ActNum)",
+ Def_BT_ActHeroAppear:"武将登场招募榜(分组值1-ActNum)", Def_BT_Qunying:"群英榜积分周榜",
+ Def_CBT_Qunying:"跨服群英榜积分周榜(分组值1-zoneID)",
}
#仙盟榜单类型
@@ -596,7 +598,9 @@
CDBPlayerRefresh_ArenaTicket, # 挑战券 286
CDBPlayerRefresh_TehuiPoint, # 特惠印绶 287
CDBPlayerRefresh_OSAPoint, # 开服庆典积分 288
-) = range(146, 289)
+CDBPlayerRefresh_QunyingTicket, # 群英榜挑战令 289
+CDBPlayerRefresh_QunyingPoint, # 群英榜积分 290
+) = range(146, 291)
TYPE_Price_Gold_Paper_Money = 5 # 金钱类型,(先用礼券,再用金子)
TYPE_Price_FamilyExp = 6 # 战盟经验
@@ -640,13 +644,15 @@
TYPE_Price_ArenaTicket = 53 # 演武场挑战券
TYPE_Price_TehuiPoint = 54 # 特惠印绶
TYPE_Price_OSAPoint = 55 # 开服庆典积分
+TYPE_Price_QunyingTicket = 56 # 群英榜挑战令
+TYPE_Price_QunyingPoint = 57 # 群英榜积分
TYPE_Price_PayCoinDay = 98 # 代币时效,每日过天重置
TYPE_Price_PayCoin = 99 # 代币
#key可用于遍历所有货币,value仅GM相关会用到
MoneyNameDict = {
1:"金币", 15:"公会贡献币", 41:"战锤", 42:"将星玉髓", 43:"将魂", 51:"招募积分", 52:"淘金令", 53:"挑战券", 54:"特惠印绶",
- 55:"可用开服庆典积分",
+ 55:"可用开服庆典积分", 56:"群英榜挑战令", 57:"群英榜积分",
98:"代币时效", 99:"代币"
}
#MoneyNameDict = {
@@ -672,6 +678,8 @@
TYPE_Price_ArenaTicket:CDBPlayerRefresh_ArenaTicket,
TYPE_Price_TehuiPoint:CDBPlayerRefresh_TehuiPoint,
TYPE_Price_OSAPoint:CDBPlayerRefresh_OSAPoint,
+ TYPE_Price_QunyingTicket:CDBPlayerRefresh_QunyingTicket,
+ TYPE_Price_QunyingPoint:CDBPlayerRefresh_QunyingPoint,
TYPE_Price_PayCoinDay:CDBPlayerRefresh_PayCoinDay,
#TYPE_Price_Rune:CDBPlayerRefresh_Rune,
#TYPE_Price_RuneSplinters:CDBPlayerRefresh_RuneSplinters,
@@ -714,9 +722,7 @@
GameFuncID_OSA_HeroTrain = 59 # 开服武将冲榜
GameFuncID_OSA_BeautyTrain = 60 # 开服红颜冲榜
GameFuncID_OSA_MinggeTrain = 61 # 开服命格冲榜
-
-# 以下为暂时无用的
-GameFuncID_Pet = -1 # 宠物,灵宠 6
+GameFuncID_Qunying = 62 # 群英榜
#背包类型
(
@@ -785,13 +791,14 @@
Def_GameRecType_BatPreset, # 战斗方案预设额外存储信息,playerID 309
Def_GameRecType_Setting, # 前端自定义存储的设置内容,playerID 310
Def_GameRecType_Treasure, # 寻宝记录,treasureType 311
- ) = range(300, 1 + 311)
+ Def_GameRecType_QunyingRecord, # 群英榜玩家挑战记录,playerID 312
+ ) = range(300, 1 + 312)
#通用信息记录新 - 字典key配置,如果有配置,则可额外按对应记录Value值存储字典,方便快速取值,可配置Value编号 1~8,配空默认 Value1
Def_GameRecValueKeyDict = {
Def_GameRecType_Xiangong:[1],
}
#仅查看自己的记录
-Def_ViewGameRecSelfList = [Def_GameRecType_ArenaRecord, Def_GameRecType_BatPreset, Def_GameRecType_Setting]
+Def_ViewGameRecSelfList = [Def_GameRecType_ArenaRecord, Def_GameRecType_BatPreset, Def_GameRecType_Setting, Def_GameRecType_QunyingRecord]
#UserData不使用json的记录类型
UserDataNOJsonRecTypeList = []
@@ -1199,12 +1206,13 @@
BatPresetList = (
BatPreset_Main, # 主线战斗 1
BatPreset_ArenaDef, # 演武场防守 2
-) = range(1, 1 + 2)
+BatPreset_QunyingDef, # 群英榜防守 3
+) = range(1, 1 + 3)
# 需要缓存的战斗功能预设,一般只要主线+防守功能预设,主动攻击的PVE功能可以不用,如某个副本的主动攻击预设
-NeedCacheBatPresetList = [BatPreset_Main, BatPreset_ArenaDef]
+NeedCacheBatPresetList = [BatPreset_Main, BatPreset_ArenaDef, BatPreset_QunyingDef]
-BatPresetName = {BatPreset_Main:"主线", BatPreset_ArenaDef:"演武场防守"}
+BatPresetName = {BatPreset_Main:"主线", BatPreset_ArenaDef:"演武场防守", BatPreset_QunyingDef:"群英榜防守"}
# 功能预设定义
FuncPresetList = (
--
Gitblit v1.8.0