From b3c6d36f5ae851f09a3c2e73494ff19956b06fb0 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 11 四月 2025 16:56:14 +0800
Subject: [PATCH] 10367 【越南】【英语】【BT】【砍树】仙盟攻城战-服务端(跨服仙盟支持;后台查询区服仙盟支持;活动时间流程支持;攻城战主活动功能完整流程:公示、分组、战备、战斗、榜单、竞猜、领奖等;)
---
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py | 2902 ++++++++++++++++++
ServerPython/CoreServerGroup/GameServer/Script/NetPackCommon.py | 30
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py | 161 +
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py | 251 +
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py | 1824 +++++++++++
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py | 251 +
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py | 1824 +++++++++++
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py | 4
ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py | 92
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActFamilyGCZ.py | 525 +++
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py | 32
ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py | 1
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py | 150
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py | 5
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_GetFamilyByServerID.py | 83
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py | 21
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini | 11
ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py | 16
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py | 45
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py | 21
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py | 11
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py | 13
ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py | 7
ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py | 4
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py | 12
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py | 3
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py | 29
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py | 406 ++
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py | 9
ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py | 5
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini | 20
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/CreateFamily.py | 146
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/FamilyGCZ.py | 75
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py | 41
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyGCZ.py | 47
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py | 4
ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py | 35
PySysDB/PySysDBG.h | 64
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py | 16
39 files changed, 9,077 insertions(+), 119 deletions(-)
diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index 6f49190..a1339f2 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -792,6 +792,70 @@
dict ScoreAwardEx; //达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...}
};
+
+//活动时间流程表
+
+struct tagActTimeFlow
+{
+ DWORD _FlowID;
+ BYTE StartDay; //开始天
+ BYTE StartHour; //开始时
+ BYTE StartMinute; //开始分
+ BYTE EndDay; //结束天
+ BYTE EndHour; //结束时
+ BYTE EndMinute; //结束分
+ WORD StateValue; //状态值
+};
+
+//活动榜单奖励模版表
+
+struct tagActBillboardAwardTemp
+{
+ DWORD _TemplateID; //模板编号
+ BYTE Rank; //名次
+ DWORD NeedValue; //上榜所需值
+ dict ValueAwardEx; //达标值额外奖励 {值:[[物品ID,个数,是否拍品], ...], ...}
+ list AwardItemList; //奖励物品列表[[物品ID,个数,是否拍品], ...]
+ list LeaderAwardItemList; //仙盟榜盟主奖励物品信息列表[[物品ID,个数,是否拍品], ...]
+ list EliteAwardItemList; //仙盟榜精英奖励物品信息列表[[物品ID,个数,是否拍品], ...]
+};
+
+//活动竞猜表
+
+struct tagActGuess
+{
+ DWORD _TemplateID; //模板编号
+ DWORD AwardID; //奖励ID
+ list RightRankList; //猜对名次列表
+ list AwardItemList; //对应奖励列表 [[物品ID,个数,是否拍品], ...]
+};
+
+//仙盟攻城战活动表
+
+struct tagCrossActFamilyGCZ
+{
+ DWORD _CfgID; //配置ID
+ char ActGroupName; //活动组名(同组活动的名字需相同)
+ BYTE ZoneID; //组内分组编号
+ list ServerIDRangeList; //活动的服务器ID范围列表 [[serverIDA, serverIDB], ...]
+ char StartDate; //开启日期
+ char EndDate; //结束日期
+ BYTE JoinFamilyCnt; //参与仙盟数
+ WORD ActFlowID; //活动流程ID,对应H.活动时间流程表
+ WORD GuessTemplateID; //竞猜奖励模版,对应H.活动竞猜表
+ WORD PersonalTemplateID; //个人伤害排行奖励模版,对应H.活动榜单奖励模版表
+ WORD FamilyTemplateID; //仙盟积分排行奖励模版,对应H.活动榜单奖励模版表
+};
+
+//仙盟攻城战大本营等级表
+
+struct tagCrossActFamilyGCZCampLV
+{
+ DWORD _CampLV; //大本营等级
+ DWORD LVUPNeedExp; //升下一级所需经验
+ DWORD AddHPPer; //生命累计总加成百分比
+};
+
//仙匣秘境活动时间表
struct tagActXianXiaMJ
diff --git a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
index 6e9965f..2f79136 100644
--- a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
+++ b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
@@ -566,6 +566,17 @@
PacketSubCMD_1=0x07
PacketCallFunc_1=OnVoiceChat
+[CrossFamilyGCZ]
+ScriptName = GameWorldLogic\CrossFamilyGCZ.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 1
+
+PacketCMD_1=0xC0
+PacketSubCMD_1=0x26
+PacketCallFunc_1=OnFamilyGCZQuery
+
[GameWorship]
ScriptName = GameWorldLogic\GameWorship.py
Writer = hxp
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
index 2b69f4f..390086e 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -381,6 +381,7 @@
Def_WorldKey_CrossPKZoneSeasonState = "CrossPKZoneSeasonState_%s" #跨服PK赛区赛季状态,跨服服务器控制,参数(zoneID)0-未开启,1-开启中,2-已结束
Def_WorldKey_CrossPKBillboardSyncTick = "CrossPKBillboardSyncTick_%s_%s" #跨服PK本赛季排行榜同步tick,参数(zoneID, seasonID)
Def_WorldKey_CrossSetPlayerAttrTick = "CrossSetPlayerAttrTick" #同步设置跨服玩家属性值tick
+Def_WorldKey_SyncFamilyAllToCross = "SyncFamilyAllToCross" #本次启动是否已经同步过所有仙盟到跨服服务器
#---------------------------------------------------------------------
#个人时间间隔
TYPE_Player_Tick_Requestkey = 0 # 玩家请求处理间隔
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index 2163321..dec4787 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -5089,6 +5089,70 @@
#------------------------------------------------------
+# C0 26 仙盟攻城战查询 #tagCGFamilyGCZQuery
+
+class tagCGFamilyGCZQuery(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("QueryType", c_ubyte), #查询类型:1-成员捐献值;2-进入城池场景;3-退出城池场景;4-进入城池;5-退出城池;6-战报;7-分组仙盟成员伤害;
+ ("BatType", c_ubyte), #指定战场类型,需要发送的查询类型: 2、4
+ ("GroupNum", c_ubyte), #指定分组编号,需要发送的查询类型: 2、4
+ ("FamilyID", c_int), #指定仙盟ID或城池ID,查自己盟的可不发,需要发的类型:2、4、6、7
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC0
+ self.SubCmd = 0x26
+ 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 = 0xC0
+ self.SubCmd = 0x26
+ self.QueryType = 0
+ self.BatType = 0
+ self.GroupNum = 0
+ self.FamilyID = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCGFamilyGCZQuery)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 26 仙盟攻城战查询 //tagCGFamilyGCZQuery:
+ Cmd:%s,
+ SubCmd:%s,
+ QueryType:%d,
+ BatType:%d,
+ GroupNum:%d,
+ FamilyID:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.QueryType,
+ self.BatType,
+ self.GroupNum,
+ self.FamilyID
+ )
+ return DumpString
+
+
+m_NAtagCGFamilyGCZQuery=tagCGFamilyGCZQuery()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGFamilyGCZQuery.Cmd,m_NAtagCGFamilyGCZQuery.SubCmd))] = m_NAtagCGFamilyGCZQuery
+
+
+#------------------------------------------------------
# C0 03 强制退出跨服状态 #tagCGForceQuitCrossState
class tagCGForceQuitCrossState(Structure):
@@ -5245,8 +5309,8 @@
("Cmd", c_ubyte),
("SubCmd", c_ubyte),
("Type", c_ubyte), #榜单类型
- ("GroupValue1", c_ubyte), # 分组值1
- ("GroupValue2", c_ubyte), # 分组值2,与分组值1组合归为同组榜单数据
+ ("GroupValue1", c_int), # 分组值1
+ ("GroupValue2", c_int), # 分组值2,与分组值1组合归为同组榜单数据
("StartIndex", c_int), #查看的起始名次索引, 默认0
("WatchCnt", c_ubyte), #查看条数,默认20,最大不超过100
("WatchID", c_int), #查看指定ID名次前后,如玩家ID、家族ID等
@@ -23599,6 +23663,189 @@
#------------------------------------------------------
+# C1 25 仙盟攻城战攻击 #tagCMFamilyGCZAtk
+
+class tagCMFamilyGCZAtk(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("AtkType", c_ubyte), #攻击类型: 1-普通单攻;2-技能单攻;3-技能群攻;
+ ("TagCityID", c_int), #目标城池ID,一般是仙盟ID或者特殊城池ID如修罗城城池,普攻单攻需指定目标,群攻技能发0
+ ("TagGuardID", c_int), #目标守卫ID,一般是玩家ID或者特殊守卫ID如修罗城守卫,普攻单攻需指定目标,技能攻击发0
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC1
+ 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 = 0xC1
+ self.SubCmd = 0x25
+ self.AtkType = 0
+ self.TagCityID = 0
+ self.TagGuardID = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCMFamilyGCZAtk)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C1 25 仙盟攻城战攻击 //tagCMFamilyGCZAtk:
+ Cmd:%s,
+ SubCmd:%s,
+ AtkType:%d,
+ TagCityID:%d,
+ TagGuardID:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.AtkType,
+ self.TagCityID,
+ self.TagGuardID
+ )
+ return DumpString
+
+
+m_NAtagCMFamilyGCZAtk=tagCMFamilyGCZAtk()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFamilyGCZAtk.Cmd,m_NAtagCMFamilyGCZAtk.SubCmd))] = m_NAtagCMFamilyGCZAtk
+
+
+#------------------------------------------------------
+# C1 24 仙盟攻城战捐献 #tagCMFamilyGCZContribution
+
+class tagCMFamilyGCZContribution(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("ContributionType", c_ubyte), #捐献类型: 0-低级;1-高级
+ ("UseCount", c_int), #物品捐献时使用个数
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC1
+ self.SubCmd = 0x24
+ 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 = 0xC1
+ self.SubCmd = 0x24
+ self.ContributionType = 0
+ self.UseCount = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCMFamilyGCZContribution)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C1 24 仙盟攻城战捐献 //tagCMFamilyGCZContribution:
+ Cmd:%s,
+ SubCmd:%s,
+ ContributionType:%d,
+ UseCount:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.ContributionType,
+ self.UseCount
+ )
+ return DumpString
+
+
+m_NAtagCMFamilyGCZContribution=tagCMFamilyGCZContribution()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFamilyGCZContribution.Cmd,m_NAtagCMFamilyGCZContribution.SubCmd))] = m_NAtagCMFamilyGCZContribution
+
+
+#------------------------------------------------------
+# C1 26 仙盟攻城战竞猜 #tagCMFamilyGCZGuess
+
+class tagCMFamilyGCZGuess(Structure):
+ Head = tagHead()
+ SelectCnt = 0 #(BYTE SelectCnt)
+ SelectFamilyIDList = list() #(vector<DWORD> SelectFamilyIDList)// 竞猜选择的仙盟ID排名顺序
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC1
+ self.Head.SubCmd = 0x26
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.SelectCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.SelectCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.SelectFamilyIDList.append(value)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC1
+ self.Head.SubCmd = 0x26
+ self.SelectCnt = 0
+ self.SelectFamilyIDList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 4 * self.SelectCnt
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.SelectCnt)
+ for i in range(self.SelectCnt):
+ data = CommFunc.WriteDWORD(data, self.SelectFamilyIDList[i])
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ SelectCnt:%d,
+ SelectFamilyIDList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.SelectCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagCMFamilyGCZGuess=tagCMFamilyGCZGuess()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFamilyGCZGuess.Head.Cmd,m_NAtagCMFamilyGCZGuess.Head.SubCmd))] = m_NAtagCMFamilyGCZGuess
+
+
+#------------------------------------------------------
# C1 10 幸运云购购买 #tagCMLuckyCloudBuy
class tagCMLuckyCloudBuy(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 9e7d65d..58ed11c 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -17027,8 +17027,8 @@
class tagGCCrossBillboardInfo(Structure):
Head = tagHead()
Type = 0 #(BYTE Type)//榜单类型
- GroupValue1 = 0 #(BYTE GroupValue1)// 分组值1
- GroupValue2 = 0 #(BYTE GroupValue2)// 分组值2,与分组值1组合归为同组榜单数据
+ GroupValue1 = 0 #(DWORD GroupValue1)// 分组值1
+ GroupValue2 = 0 #(DWORD GroupValue2)// 分组值2,与分组值1组合归为同组榜单数据
WatchID = 0 #(DWORD WatchID)//查看指定ID名次前后,如玩家ID、家族ID等
BillboardCount = 0 #(BYTE BillboardCount)
CrossBillboardDataList = list() #(vector<tagGCCrossBillboardData> CrossBillboardDataList)
@@ -17044,8 +17044,8 @@
self.Clear()
_pos = self.Head.ReadData(_lpData, _pos)
self.Type,_pos = CommFunc.ReadBYTE(_lpData, _pos)
- self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
- self.GroupValue2,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupValue1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.GroupValue2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
self.WatchID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
self.BillboardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
for i in range(self.BillboardCount):
@@ -17071,8 +17071,8 @@
length = 0
length += self.Head.GetLength()
length += 1
- length += 1
- length += 1
+ length += 4
+ length += 4
length += 4
length += 1
for i in range(self.BillboardCount):
@@ -17084,8 +17084,8 @@
data = ''
data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
data = CommFunc.WriteBYTE(data, self.Type)
- data = CommFunc.WriteBYTE(data, self.GroupValue1)
- data = CommFunc.WriteBYTE(data, self.GroupValue2)
+ data = CommFunc.WriteDWORD(data, self.GroupValue1)
+ data = CommFunc.WriteDWORD(data, self.GroupValue2)
data = CommFunc.WriteDWORD(data, self.WatchID)
data = CommFunc.WriteBYTE(data, self.BillboardCount)
for i in range(self.BillboardCount):
@@ -18518,6 +18518,1750 @@
m_NAtagGCCrossZoneInfo=tagGCCrossZoneInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossZoneInfo.Cmd,m_NAtagGCCrossZoneInfo.SubCmd))] = m_NAtagGCCrossZoneInfo
+
+
+#------------------------------------------------------
+# C0 24 仙盟攻城战活动信息 #tagGCFamilyGCZActInfo
+
+class tagGCFamilyGCZActFamily(Structure):
+ FamilyID = 0 #(DWORD FamilyID)
+ Name = "" #(char Name[33])//参与仙盟名字
+ LV = 0 #(BYTE LV)//仙盟等级
+ ServerID = 0 #(DWORD ServerID)//仙盟所属区服ID
+ EmblemID = 0 #(DWORD EmblemID)//徽章ID
+ FightPower = 0 #(DWORD FightPower)//仙盟总战力,求余亿部分
+ FightPowerEx = 0 #(DWORD FightPowerEx)//仙盟总战力,整除亿部分
+ LeaderID = 0 #(DWORD LeaderID)//盟主ID
+ LeaderName = "" #(char LeaderName[33])//盟主名
+ LeaderFace = 0 #(DWORD LeaderFace)
+ LeaderFacePic = 0 #(DWORD LeaderFacePic)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.LV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.EmblemID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.LeaderID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.LeaderName,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.LeaderFace,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.LeaderFacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.FamilyID = 0
+ self.Name = ""
+ self.LV = 0
+ self.ServerID = 0
+ self.EmblemID = 0
+ self.FightPower = 0
+ self.FightPowerEx = 0
+ self.LeaderID = 0
+ self.LeaderName = ""
+ self.LeaderFace = 0
+ self.LeaderFacePic = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 33
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteBYTE(data, self.LV)
+ data = CommFunc.WriteDWORD(data, self.ServerID)
+ data = CommFunc.WriteDWORD(data, self.EmblemID)
+ data = CommFunc.WriteDWORD(data, self.FightPower)
+ data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+ data = CommFunc.WriteDWORD(data, self.LeaderID)
+ data = CommFunc.WriteString(data, 33, self.LeaderName)
+ data = CommFunc.WriteDWORD(data, self.LeaderFace)
+ data = CommFunc.WriteDWORD(data, self.LeaderFacePic)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ FamilyID:%d,
+ Name:%s,
+ LV:%d,
+ ServerID:%d,
+ EmblemID:%d,
+ FightPower:%d,
+ FightPowerEx:%d,
+ LeaderID:%d,
+ LeaderName:%s,
+ LeaderFace:%d,
+ LeaderFacePic:%d
+ '''\
+ %(
+ self.FamilyID,
+ self.Name,
+ self.LV,
+ self.ServerID,
+ self.EmblemID,
+ self.FightPower,
+ self.FightPowerEx,
+ self.LeaderID,
+ self.LeaderName,
+ self.LeaderFace,
+ self.LeaderFacePic
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZActInfo(Structure):
+ Head = tagHead()
+ ServerInfoLen = 0 #(BYTE ServerInfoLen)
+ ServerIDRangeInfo = "" #(String ServerIDRangeInfo)//开放该活动的服务器ID范围列表,json格式 [[IDA, IDB], ...], [] 为全服
+ ZoneID = 0 #(BYTE ZoneID)// 活动分区ID,公示期为0
+ ActID = 0 #(DWORD ActID)// 活动ID,代表某一次活动的唯一ID,前端如果有活动相关的本地记录可以通过验证此ID变更进行重置
+ StartDate = "" #(char StartDate[10])// 开始日期 y-m-d
+ EndtDate = "" #(char EndtDate[10])// 结束日期 y-m-d
+ JoinFamilyCnt = 0 #(BYTE JoinFamilyCnt)// 参与仙盟数
+ ActFlowID = 0 #(WORD ActFlowID)// 活动流程ID,对应H.活动时间流程表中的编号,前端根据跨服时间自行计算当前所处流程状态
+ GuessTemplateID = 0 #(WORD GuessTemplateID)// 竞猜奖励模版,对应H.活动竞猜表,前端自行读表展示
+ PersonalTemplateID = 0 #(WORD PersonalTemplateID)// 个人伤害排行奖励模版,对应H.活动榜单奖励模版表,前端自行读表展示
+ FamilyTemplateID = 0 #(WORD FamilyTemplateID)// 仙盟积分排行奖励模版,对应H.活动榜单奖励模版表,前端自行读表展示
+ StateError = 0 #(BYTE StateError)// 活动流程状态是否异常,如果不为0代表活动已异常,前端自行决定是不显示活动还是活动页面做提示
+ FamilyCount = 0 #(BYTE FamilyCount)
+ ActFamilyList = list() #(vector<tagGCFamilyGCZActFamily> ActFamilyList)//本分区参与的仙盟名单
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x24
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ServerInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ServerIDRangeInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ServerInfoLen)
+ self.ZoneID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ActID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.JoinFamilyCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ActFlowID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.GuessTemplateID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.PersonalTemplateID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.FamilyTemplateID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.StateError,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.FamilyCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FamilyCount):
+ temActFamilyList = tagGCFamilyGCZActFamily()
+ _pos = temActFamilyList.ReadData(_lpData, _pos)
+ self.ActFamilyList.append(temActFamilyList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x24
+ self.ServerInfoLen = 0
+ self.ServerIDRangeInfo = ""
+ self.ZoneID = 0
+ self.ActID = 0
+ self.StartDate = ""
+ self.EndtDate = ""
+ self.JoinFamilyCnt = 0
+ self.ActFlowID = 0
+ self.GuessTemplateID = 0
+ self.PersonalTemplateID = 0
+ self.FamilyTemplateID = 0
+ self.StateError = 0
+ self.FamilyCount = 0
+ self.ActFamilyList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += len(self.ServerIDRangeInfo)
+ length += 1
+ length += 4
+ length += 10
+ length += 10
+ length += 1
+ length += 2
+ length += 2
+ length += 2
+ length += 2
+ length += 1
+ length += 1
+ for i in range(self.FamilyCount):
+ length += self.ActFamilyList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ServerInfoLen)
+ data = CommFunc.WriteString(data, self.ServerInfoLen, self.ServerIDRangeInfo)
+ data = CommFunc.WriteBYTE(data, self.ZoneID)
+ data = CommFunc.WriteDWORD(data, self.ActID)
+ data = CommFunc.WriteString(data, 10, self.StartDate)
+ data = CommFunc.WriteString(data, 10, self.EndtDate)
+ data = CommFunc.WriteBYTE(data, self.JoinFamilyCnt)
+ data = CommFunc.WriteWORD(data, self.ActFlowID)
+ data = CommFunc.WriteWORD(data, self.GuessTemplateID)
+ data = CommFunc.WriteWORD(data, self.PersonalTemplateID)
+ data = CommFunc.WriteWORD(data, self.FamilyTemplateID)
+ data = CommFunc.WriteBYTE(data, self.StateError)
+ data = CommFunc.WriteBYTE(data, self.FamilyCount)
+ for i in range(self.FamilyCount):
+ data = CommFunc.WriteString(data, self.ActFamilyList[i].GetLength(), self.ActFamilyList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ServerInfoLen:%d,
+ ServerIDRangeInfo:%s,
+ ZoneID:%d,
+ ActID:%d,
+ StartDate:%s,
+ EndtDate:%s,
+ JoinFamilyCnt:%d,
+ ActFlowID:%d,
+ GuessTemplateID:%d,
+ PersonalTemplateID:%d,
+ FamilyTemplateID:%d,
+ StateError:%d,
+ FamilyCount:%d,
+ ActFamilyList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ServerInfoLen,
+ self.ServerIDRangeInfo,
+ self.ZoneID,
+ self.ActID,
+ self.StartDate,
+ self.EndtDate,
+ self.JoinFamilyCnt,
+ self.ActFlowID,
+ self.GuessTemplateID,
+ self.PersonalTemplateID,
+ self.FamilyTemplateID,
+ self.StateError,
+ self.FamilyCount,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZActInfo=tagGCFamilyGCZActInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZActInfo.Head.Cmd,m_NAtagGCFamilyGCZActInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZActInfo
+
+
+#------------------------------------------------------
+# C0 29 仙盟攻城战城池战斗信息 #tagGCFamilyGCZBatCityInfo
+
+class tagGCFamilyGCZBatCityInfo(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("CityID", c_int), #城池ID
+ ("CityLV", c_ubyte), #城池等级
+ ("FamilyID", c_int), #所属仙盟ID,可能为0
+ ("GuardID", c_int), #当前防守成员ID,为0时表示没有防守成员了,城池已被击毁
+ ("HP", c_int), #防守成员剩余生命,求余亿部分,剩余生命为0时代表该防守成员被击败
+ ("HPEx", c_int), #防守成员剩余生命,整除亿部分
+ ("HPMax", c_int), #防守成员最大生命,求余亿部分
+ ("HPMaxEx", c_int), #防守成员最大生命,整除亿部分
+ ("AtkPlayerID", c_int), #发起攻击的玩家ID,可能为0,判断是否自己的ID进行相应的攻击表现
+ ("AtkRet", c_ubyte), #攻击结果,仅在攻击玩家ID不为0时有效,0--成功;1-目标已被击杀;2-城池已被摧毁;3-其他
+ ("KillCnt", c_ubyte), #本次攻击击杀防守人员数
+ ("HurtValue", c_int), #伤害飘血,求余亿部分
+ ("HurtValueEx", c_int), #伤害飘血,整除亿部分
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC0
+ self.SubCmd = 0x29
+ 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 = 0xC0
+ self.SubCmd = 0x29
+ self.CityID = 0
+ self.CityLV = 0
+ self.FamilyID = 0
+ self.GuardID = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.AtkPlayerID = 0
+ self.AtkRet = 0
+ self.KillCnt = 0
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatCityInfo)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 29 仙盟攻城战城池战斗信息 //tagGCFamilyGCZBatCityInfo:
+ Cmd:%s,
+ SubCmd:%s,
+ CityID:%d,
+ CityLV:%d,
+ FamilyID:%d,
+ GuardID:%d,
+ HP:%d,
+ HPEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ AtkPlayerID:%d,
+ AtkRet:%d,
+ KillCnt:%d,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.CityID,
+ self.CityLV,
+ self.FamilyID,
+ self.GuardID,
+ self.HP,
+ self.HPEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.AtkPlayerID,
+ self.AtkRet,
+ self.KillCnt,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatCityInfo=tagGCFamilyGCZBatCityInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatCityInfo.Cmd,m_NAtagGCFamilyGCZBatCityInfo.SubCmd))] = m_NAtagGCFamilyGCZBatCityInfo
+
+
+#------------------------------------------------------
+# C0 25 仙盟攻城战轮次分组信息 #tagGCFamilyGCZBatGroupInfo
+
+class tagGCFamilyGCZBatGroup(Structure):
+ GroupNum = 0 #(BYTE GroupNum)// 分组编号,从1开始,对应A
+ FamilyIDCnt = 0 #(BYTE FamilyIDCnt)
+ FamilyIDList = list() #(vector<DWORD> FamilyIDList)// 仙盟ID列表,前端可以通过判断参与的仙盟ID是否在某个分组里面验证有没有战场参赛资格
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.GroupNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.FamilyIDCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FamilyIDCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.FamilyIDList.append(value)
+ return _pos
+
+ def Clear(self):
+ self.GroupNum = 0
+ self.FamilyIDCnt = 0
+ self.FamilyIDList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ length += 4 * self.FamilyIDCnt
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.GroupNum)
+ data = CommFunc.WriteBYTE(data, self.FamilyIDCnt)
+ for i in range(self.FamilyIDCnt):
+ data = CommFunc.WriteDWORD(data, self.FamilyIDList[i])
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ GroupNum:%d,
+ FamilyIDCnt:%d,
+ FamilyIDList:%s
+ '''\
+ %(
+ self.GroupNum,
+ self.FamilyIDCnt,
+ "..."
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBat(Structure):
+ BatType = 0 #(BYTE BatType)// 战场类型 1-初级;2-中级;3-高级;
+ GroupCnt = 0 #(BYTE GroupCnt)// 分组数
+ GroupList = list() #(vector<tagGCFamilyGCZBatGroup> GroupList)// 分组列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.BatType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.GroupCnt):
+ temGroupList = tagGCFamilyGCZBatGroup()
+ _pos = temGroupList.ReadData(_lpData, _pos)
+ self.GroupList.append(temGroupList)
+ return _pos
+
+ def Clear(self):
+ self.BatType = 0
+ self.GroupCnt = 0
+ self.GroupList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ for i in range(self.GroupCnt):
+ length += self.GroupList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.BatType)
+ data = CommFunc.WriteBYTE(data, self.GroupCnt)
+ for i in range(self.GroupCnt):
+ data = CommFunc.WriteString(data, self.GroupList[i].GetLength(), self.GroupList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ BatType:%d,
+ GroupCnt:%d,
+ GroupList:%s
+ '''\
+ %(
+ self.BatType,
+ self.GroupCnt,
+ "..."
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatGroupInfo(Structure):
+ Head = tagHead()
+ RoundNum = 0 #(BYTE RoundNum)// 第x轮的分组,从1开始,没有在对应轮次战场分组里的视为没有该轮次的参赛资格
+ BatTypeCnt = 0 #(BYTE BatTypeCnt)// 战场类型数
+ BatList = list() #(vector<tagGCFamilyGCZBat> BatList)//战场列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x25
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.RoundNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.BatTypeCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.BatTypeCnt):
+ temBatList = tagGCFamilyGCZBat()
+ _pos = temBatList.ReadData(_lpData, _pos)
+ self.BatList.append(temBatList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x25
+ self.RoundNum = 0
+ self.BatTypeCnt = 0
+ self.BatList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 1
+ for i in range(self.BatTypeCnt):
+ length += self.BatList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.RoundNum)
+ data = CommFunc.WriteBYTE(data, self.BatTypeCnt)
+ for i in range(self.BatTypeCnt):
+ data = CommFunc.WriteString(data, self.BatList[i].GetLength(), self.BatList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ RoundNum:%d,
+ BatTypeCnt:%d,
+ BatList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.RoundNum,
+ self.BatTypeCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatGroupInfo=tagGCFamilyGCZBatGroupInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatGroupInfo.Head.Cmd,m_NAtagGCFamilyGCZBatGroupInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZBatGroupInfo
+
+
+#------------------------------------------------------
+# C0 30 仙盟攻城战战斗战报 #tagGCFamilyGCZBatReport
+
+class tagGCFamilyGCZBatRepHurt(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("TagFamilyID", c_int), #目标仙盟ID
+ ("HurtValue", c_int), #输出伤害,求余亿部分
+ ("HurtValueEx", c_int), #输出伤害,整除亿部分
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.TagFamilyID = 0
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatRepHurt)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 30 仙盟攻城战战斗战报 //tagGCFamilyGCZBatReport:
+ TagFamilyID:%d,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.TagFamilyID,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatReport(Structure):
+ Head = tagHead()
+ FamilyID = 0 #(DWORD FamilyID)// 战报仙盟ID
+ DefRepCnt = 0 #(BYTE DefRepCnt)
+ DefRepList = list() #(vector<tagGCFamilyGCZBatRepHurt> DefRepList)// 防守战报
+ AtkRepCnt = 0 #(BYTE AtkRepCnt)
+ AtkRepList = list() #(vector<tagGCFamilyGCZBatRepHurt> AtkRepList)// 进攻战报
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x30
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.DefRepCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.DefRepCnt):
+ temDefRepList = tagGCFamilyGCZBatRepHurt()
+ _pos = temDefRepList.ReadData(_lpData, _pos)
+ self.DefRepList.append(temDefRepList)
+ self.AtkRepCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.AtkRepCnt):
+ temAtkRepList = tagGCFamilyGCZBatRepHurt()
+ _pos = temAtkRepList.ReadData(_lpData, _pos)
+ self.AtkRepList.append(temAtkRepList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x30
+ self.FamilyID = 0
+ self.DefRepCnt = 0
+ self.DefRepList = list()
+ self.AtkRepCnt = 0
+ self.AtkRepList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 1
+ for i in range(self.DefRepCnt):
+ length += self.DefRepList[i].GetLength()
+ length += 1
+ for i in range(self.AtkRepCnt):
+ length += self.AtkRepList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteBYTE(data, self.DefRepCnt)
+ for i in range(self.DefRepCnt):
+ data = CommFunc.WriteString(data, self.DefRepList[i].GetLength(), self.DefRepList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.AtkRepCnt)
+ for i in range(self.AtkRepCnt):
+ data = CommFunc.WriteString(data, self.AtkRepList[i].GetLength(), self.AtkRepList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ FamilyID:%d,
+ DefRepCnt:%d,
+ DefRepList:%s,
+ AtkRepCnt:%d,
+ AtkRepList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.FamilyID,
+ self.DefRepCnt,
+ "...",
+ self.AtkRepCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatReport=tagGCFamilyGCZBatReport()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatReport.Head.Cmd,m_NAtagGCFamilyGCZBatReport.Head.SubCmd))] = m_NAtagGCFamilyGCZBatReport
+
+
+#------------------------------------------------------
+# C0 28 仙盟攻城战城池场景信息 #tagGCFamilyGCZBatSceneInfo
+
+class tagGCFamilyGCZBatScenePlayer(Structure):
+ PlayerID = 0 #(DWORD PlayerID)
+ Name = "" #(char Name[33])
+ Face = 0 #(DWORD Face)
+ FacePic = 0 #(DWORD FacePic)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.PlayerID = 0
+ self.Name = ""
+ self.Face = 0
+ self.FacePic = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteDWORD(data, self.Face)
+ data = CommFunc.WriteDWORD(data, self.FacePic)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ PlayerID:%d,
+ Name:%s,
+ Face:%d,
+ FacePic:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.Name,
+ self.Face,
+ self.FacePic
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatSceneHurt(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("CityID", c_int), #被攻击的城池ID
+ ("HurtValue", c_int), #伤害飘血,求余亿部分
+ ("HurtValueEx", c_int), #伤害飘血,整除亿部分
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.CityID = 0
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatSceneHurt)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 28 仙盟攻城战城池场景信息 //tagGCFamilyGCZBatSceneInfo:
+ CityID:%d,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.CityID,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatSceneCity(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("CityID", c_int), #城池ID
+ ("CityLV", c_ubyte), #城池等级
+ ("FamilyID", c_int), #所属仙盟ID,可能为0
+ ("Rank", c_ubyte), #当前名次,从1开始
+ ("HP", c_int), #剩余生命,求余亿部分,剩余生命为0时代表被摧毁
+ ("HPEx", c_int), #剩余生命,整除亿部分
+ ("HPMax", c_int), #最大生命,求余亿部分
+ ("HPMaxEx", c_int), #最大生命,整除亿部分
+ ("LastAtkedTime", c_int), #最后一次被攻击时间戳,可能为0
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.CityID = 0
+ self.CityLV = 0
+ self.FamilyID = 0
+ self.Rank = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.LastAtkedTime = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatSceneCity)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 28 仙盟攻城战城池场景信息 //tagGCFamilyGCZBatSceneInfo:
+ CityID:%d,
+ CityLV:%d,
+ FamilyID:%d,
+ Rank:%d,
+ HP:%d,
+ HPEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ LastAtkedTime:%d
+ '''\
+ %(
+ self.CityID,
+ self.CityLV,
+ self.FamilyID,
+ self.Rank,
+ self.HP,
+ self.HPEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.LastAtkedTime
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatSceneInfo(Structure):
+ Head = tagHead()
+ BatType = 0 #(BYTE BatType)// 战场类型 1-初级;2-中级;3-高级;
+ GroupNum = 0 #(BYTE GroupNum)// 分组编号,从1开始,对应A
+ TopFamilyID = 0 #(DWORD TopFamilyID)// 伤害第一仙盟ID
+ TopLeaderID = 0 #(DWORD TopLeaderID)// 伤害第一盟主ID
+ TopPlayerID = 0 #(DWORD TopPlayerID)// 伤害第一玩家ID
+ TopPlayerFamilyID = 0 #(DWORD TopPlayerFamilyID)// 伤害第一玩家仙盟ID
+ AtkPlayerID = 0 #(DWORD AtkPlayerID)// 发起攻击的玩家,可能为0,仅技能攻击时通知,普攻时仅通知血量等信息
+ AtkType = 0 #(BYTE AtkType)// 攻击类型,有发起攻击的玩家时有效
+ KillCnt = 0 #(BYTE KillCnt)// 本次攻击累计击杀数,有发起攻击的玩家时有效
+ HurtCnt = 0 #(BYTE HurtCnt)
+ HurtList = list() #(vector<tagGCFamilyGCZBatSceneHurt> HurtList)//本次攻击伤血信息,有发起攻击的玩家时有效
+ CityCnt = 0 #(BYTE CityCnt)
+ CityList = list() #(vector<tagGCFamilyGCZBatSceneCity> CityList)// 城池信息,仅通知变化的城池
+ PlayerCnt = 0 #(BYTE PlayerCnt)
+ PlayerInfoList = list() #(vector<tagGCFamilyGCZBatScenePlayer> PlayerInfoList)// 场景展示所需要用到的玩家信息,如第一玩家、使用技能玩家
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x28
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.BatType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.TopFamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TopLeaderID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TopPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TopPlayerFamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AtkPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AtkType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.KillCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.HurtCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.HurtCnt):
+ temHurtList = tagGCFamilyGCZBatSceneHurt()
+ _pos = temHurtList.ReadData(_lpData, _pos)
+ self.HurtList.append(temHurtList)
+ self.CityCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.CityCnt):
+ temCityList = tagGCFamilyGCZBatSceneCity()
+ _pos = temCityList.ReadData(_lpData, _pos)
+ self.CityList.append(temCityList)
+ self.PlayerCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.PlayerCnt):
+ temPlayerInfoList = tagGCFamilyGCZBatScenePlayer()
+ _pos = temPlayerInfoList.ReadData(_lpData, _pos)
+ self.PlayerInfoList.append(temPlayerInfoList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x28
+ self.BatType = 0
+ self.GroupNum = 0
+ self.TopFamilyID = 0
+ self.TopLeaderID = 0
+ self.TopPlayerID = 0
+ self.TopPlayerFamilyID = 0
+ self.AtkPlayerID = 0
+ self.AtkType = 0
+ self.KillCnt = 0
+ self.HurtCnt = 0
+ self.HurtList = list()
+ self.CityCnt = 0
+ self.CityList = list()
+ self.PlayerCnt = 0
+ self.PlayerInfoList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 1
+ length += 1
+ length += 1
+ for i in range(self.HurtCnt):
+ length += self.HurtList[i].GetLength()
+ length += 1
+ for i in range(self.CityCnt):
+ length += self.CityList[i].GetLength()
+ length += 1
+ for i in range(self.PlayerCnt):
+ length += self.PlayerInfoList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.BatType)
+ data = CommFunc.WriteBYTE(data, self.GroupNum)
+ data = CommFunc.WriteDWORD(data, self.TopFamilyID)
+ data = CommFunc.WriteDWORD(data, self.TopLeaderID)
+ data = CommFunc.WriteDWORD(data, self.TopPlayerID)
+ data = CommFunc.WriteDWORD(data, self.TopPlayerFamilyID)
+ data = CommFunc.WriteDWORD(data, self.AtkPlayerID)
+ data = CommFunc.WriteBYTE(data, self.AtkType)
+ data = CommFunc.WriteBYTE(data, self.KillCnt)
+ data = CommFunc.WriteBYTE(data, self.HurtCnt)
+ for i in range(self.HurtCnt):
+ data = CommFunc.WriteString(data, self.HurtList[i].GetLength(), self.HurtList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.CityCnt)
+ for i in range(self.CityCnt):
+ data = CommFunc.WriteString(data, self.CityList[i].GetLength(), self.CityList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.PlayerCnt)
+ for i in range(self.PlayerCnt):
+ data = CommFunc.WriteString(data, self.PlayerInfoList[i].GetLength(), self.PlayerInfoList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ BatType:%d,
+ GroupNum:%d,
+ TopFamilyID:%d,
+ TopLeaderID:%d,
+ TopPlayerID:%d,
+ TopPlayerFamilyID:%d,
+ AtkPlayerID:%d,
+ AtkType:%d,
+ KillCnt:%d,
+ HurtCnt:%d,
+ HurtList:%s,
+ CityCnt:%d,
+ CityList:%s,
+ PlayerCnt:%d,
+ PlayerInfoList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.BatType,
+ self.GroupNum,
+ self.TopFamilyID,
+ self.TopLeaderID,
+ self.TopPlayerID,
+ self.TopPlayerFamilyID,
+ self.AtkPlayerID,
+ self.AtkType,
+ self.KillCnt,
+ self.HurtCnt,
+ "...",
+ self.CityCnt,
+ "...",
+ self.PlayerCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatSceneInfo=tagGCFamilyGCZBatSceneInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatSceneInfo.Head.Cmd,m_NAtagGCFamilyGCZBatSceneInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZBatSceneInfo
+
+
+#------------------------------------------------------
+# C0 26 仙盟攻城战大本营信息 #tagGCFamilyGCZCampInfo
+
+class tagGCFamilyGCZCampMem(Structure):
+ PlayerID = 0 #(DWORD PlayerID)
+ Name = "" #(char Name[33])//参与玩家名字
+ FamilyLV = 0 #(BYTE FamilyLV)//参与时的家族职位
+ Face = 0 #(DWORD Face)//基本脸型
+ FacePic = 0 #(DWORD FacePic)//头像框
+ FightPower = 0 #(DWORD FightPower)//战力,求余亿部分
+ FightPowerEx = 0 #(DWORD FightPowerEx)//战力,整除亿部分
+ HP = 0 #(DWORD HP)//剩余生命,求余亿部分
+ HPEx = 0 #(DWORD HPEx)//剩余生命,整除亿部分
+ HPMax = 0 #(DWORD HPMax)//最大生命,求余亿部分
+ HPMaxEx = 0 #(DWORD HPMaxEx)//最大生命,整除亿部分
+ TotalHurt = 0 #(DWORD TotalHurt)//活动总伤害,求余亿部分,如果不在榜上则读该值
+ TotalHurtEx = 0 #(DWORD TotalHurtEx)//活动总伤害,整除亿部分
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.FamilyLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMax,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMaxEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TotalHurt,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TotalHurtEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.PlayerID = 0
+ self.Name = ""
+ self.FamilyLV = 0
+ self.Face = 0
+ self.FacePic = 0
+ self.FightPower = 0
+ self.FightPowerEx = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.TotalHurt = 0
+ self.TotalHurtEx = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteBYTE(data, self.FamilyLV)
+ data = CommFunc.WriteDWORD(data, self.Face)
+ data = CommFunc.WriteDWORD(data, self.FacePic)
+ data = CommFunc.WriteDWORD(data, self.FightPower)
+ data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+ data = CommFunc.WriteDWORD(data, self.HP)
+ data = CommFunc.WriteDWORD(data, self.HPEx)
+ data = CommFunc.WriteDWORD(data, self.HPMax)
+ data = CommFunc.WriteDWORD(data, self.HPMaxEx)
+ data = CommFunc.WriteDWORD(data, self.TotalHurt)
+ data = CommFunc.WriteDWORD(data, self.TotalHurtEx)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ PlayerID:%d,
+ Name:%s,
+ FamilyLV:%d,
+ Face:%d,
+ FacePic:%d,
+ FightPower:%d,
+ FightPowerEx:%d,
+ HP:%d,
+ HPEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ TotalHurt:%d,
+ TotalHurtEx:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.Name,
+ self.FamilyLV,
+ self.Face,
+ self.FacePic,
+ self.FightPower,
+ self.FightPowerEx,
+ self.HP,
+ self.HPEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.TotalHurt,
+ self.TotalHurtEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZCampInfo(Structure):
+ Head = tagHead()
+ FamilyID = 0 #(DWORD FamilyID)//所在活动仙盟ID,可能不是玩家当前的仙盟ID,活动以该ID为准
+ Score = 0 #(WORD Score)//活动总积分,如果不在榜上则读该值
+ CampLV = 0 #(WORD CampLV)//大本营当前等级
+ CampExp = 0 #(DWORD CampExp)//大本营当前经验
+ CityLV = 0 #(WORD CityLV)//城池属性等级,开战后可能与当前大本营等级不一样
+ HPBase = 0 #(DWORD HPBase)//基础生命,求余亿部分
+ HPBaseEx = 0 #(DWORD HPBaseEx)//基础生命,整除亿部分
+ HPMax = 0 #(DWORD HPMax)//总生命,求余亿部分
+ HPMaxEx = 0 #(DWORD HPMaxEx)//总大生命,整除亿部分
+ HP = 0 #(DWORD HP)//剩余生命,求余亿部分
+ HPEx = 0 #(DWORD HPEx)//剩余生命,整除亿部分
+ DefMemCnt = 0 #(BYTE DefMemCnt)
+ DefMemList = list() #(vector<tagGCFamilyGCZCampMem> DefMemList)//防守成员列表,有同步则差异更新,没有在防守成员里的视为没有参与资格
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x26
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Score,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.CampLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.CampExp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CityLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.HPBase,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPBaseEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMax,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMaxEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.DefMemCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.DefMemCnt):
+ temDefMemList = tagGCFamilyGCZCampMem()
+ _pos = temDefMemList.ReadData(_lpData, _pos)
+ self.DefMemList.append(temDefMemList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x26
+ self.FamilyID = 0
+ self.Score = 0
+ self.CampLV = 0
+ self.CampExp = 0
+ self.CityLV = 0
+ self.HPBase = 0
+ self.HPBaseEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.DefMemCnt = 0
+ self.DefMemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 2
+ length += 2
+ length += 4
+ length += 2
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 1
+ for i in range(self.DefMemCnt):
+ length += self.DefMemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteWORD(data, self.Score)
+ data = CommFunc.WriteWORD(data, self.CampLV)
+ data = CommFunc.WriteDWORD(data, self.CampExp)
+ data = CommFunc.WriteWORD(data, self.CityLV)
+ data = CommFunc.WriteDWORD(data, self.HPBase)
+ data = CommFunc.WriteDWORD(data, self.HPBaseEx)
+ data = CommFunc.WriteDWORD(data, self.HPMax)
+ data = CommFunc.WriteDWORD(data, self.HPMaxEx)
+ data = CommFunc.WriteDWORD(data, self.HP)
+ data = CommFunc.WriteDWORD(data, self.HPEx)
+ data = CommFunc.WriteBYTE(data, self.DefMemCnt)
+ for i in range(self.DefMemCnt):
+ data = CommFunc.WriteString(data, self.DefMemList[i].GetLength(), self.DefMemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ FamilyID:%d,
+ Score:%d,
+ CampLV:%d,
+ CampExp:%d,
+ CityLV:%d,
+ HPBase:%d,
+ HPBaseEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ HP:%d,
+ HPEx:%d,
+ DefMemCnt:%d,
+ DefMemList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.FamilyID,
+ self.Score,
+ self.CampLV,
+ self.CampExp,
+ self.CityLV,
+ self.HPBase,
+ self.HPBaseEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.HP,
+ self.HPEx,
+ self.DefMemCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZCampInfo=tagGCFamilyGCZCampInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZCampInfo.Head.Cmd,m_NAtagGCFamilyGCZCampInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZCampInfo
+
+
+#------------------------------------------------------
+# C0 27 仙盟攻城战成员贡献值信息 #tagGCFamilyGCZContributionInfo
+
+class tagGCFamilyGCZContribution(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("PlayerID", c_int),
+ ("ContributionValue", c_int), #贡献值
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.PlayerID = 0
+ self.ContributionValue = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZContribution)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 27 仙盟攻城战成员贡献值信息 //tagGCFamilyGCZContributionInfo:
+ PlayerID:%d,
+ ContributionValue:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.ContributionValue
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZContributionInfo(Structure):
+ Head = tagHead()
+ ContriCnt = 0 #(BYTE ContriCnt)
+ ContriList = list() #(vector<tagGCFamilyGCZContribution> ContriList)//成员贡献值列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x27
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ContriCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.ContriCnt):
+ temContriList = tagGCFamilyGCZContribution()
+ _pos = temContriList.ReadData(_lpData, _pos)
+ self.ContriList.append(temContriList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x27
+ self.ContriCnt = 0
+ self.ContriList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ for i in range(self.ContriCnt):
+ length += self.ContriList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ContriCnt)
+ for i in range(self.ContriCnt):
+ data = CommFunc.WriteString(data, self.ContriList[i].GetLength(), self.ContriList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ContriCnt:%d,
+ ContriList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ContriCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZContributionInfo=tagGCFamilyGCZContributionInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZContributionInfo.Head.Cmd,m_NAtagGCFamilyGCZContributionInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZContributionInfo
+
+
+#------------------------------------------------------
+# C0 31 仙盟攻城战分组仙盟成员伤害明细 #tagGCFamilyGCZGroupFamilyMemHurtInfo
+
+class tagGCFamilyGCZGroupFamilyMemHurt(Structure):
+ PlayerID = 0 #(DWORD PlayerID)
+ Name = "" #(char Name[33])//参与玩家名字
+ HurtValue = 0 #(DWORD HurtValue)//伤害,求余亿部分
+ HurtValueEx = 0 #(DWORD HurtValueEx)//伤害,整除亿部分
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.HurtValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HurtValueEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.PlayerID = 0
+ self.Name = ""
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteDWORD(data, self.HurtValue)
+ data = CommFunc.WriteDWORD(data, self.HurtValueEx)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ PlayerID:%d,
+ Name:%s,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.Name,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZGroupFamilyMemHurtInfo(Structure):
+ Head = tagHead()
+ FamilyID = 0 #(DWORD FamilyID)//查看的目标仙盟ID
+ HurtMemCnt = 0 #(BYTE HurtMemCnt)
+ HurtMemList = list() #(vector<tagGCFamilyGCZGroupFamilyMemHurt> HurtMemList)//成员伤害明细列表,只算城池被摧毁前的伤害,未排序,前端自己排序
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x31
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HurtMemCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.HurtMemCnt):
+ temHurtMemList = tagGCFamilyGCZGroupFamilyMemHurt()
+ _pos = temHurtMemList.ReadData(_lpData, _pos)
+ self.HurtMemList.append(temHurtMemList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x31
+ self.FamilyID = 0
+ self.HurtMemCnt = 0
+ self.HurtMemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 1
+ for i in range(self.HurtMemCnt):
+ length += self.HurtMemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteBYTE(data, self.HurtMemCnt)
+ for i in range(self.HurtMemCnt):
+ data = CommFunc.WriteString(data, self.HurtMemList[i].GetLength(), self.HurtMemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ FamilyID:%d,
+ HurtMemCnt:%d,
+ HurtMemList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.FamilyID,
+ self.HurtMemCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo=tagGCFamilyGCZGroupFamilyMemHurtInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo.Head.Cmd,m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo
+
+
+#------------------------------------------------------
+# C0 32 仙盟攻城战竞猜名单信息 #tagGCFamilyGCZGuessInfo
+
+class tagGCFamilyGCZGuessFamily(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("FamilyID", c_int), #备选仙盟ID
+ ("GuessValue", c_ushort), #竞猜热度值,玩家每次选择则加1,重复选择也算
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.FamilyID = 0
+ self.GuessValue = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZGuessFamily)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 32 仙盟攻城战竞猜名单信息 //tagGCFamilyGCZGuessInfo:
+ FamilyID:%d,
+ GuessValue:%d
+ '''\
+ %(
+ self.FamilyID,
+ self.GuessValue
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZGuessRight(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("AwardID", c_ubyte), #奖励ID
+ ("RightPlayerCnt", c_ushort), #猜中玩家个数
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.AwardID = 0
+ self.RightPlayerCnt = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZGuessRight)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 32 仙盟攻城战竞猜名单信息 //tagGCFamilyGCZGuessInfo:
+ AwardID:%d,
+ RightPlayerCnt:%d
+ '''\
+ %(
+ self.AwardID,
+ self.RightPlayerCnt
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZGuessInfo(Structure):
+ Head = tagHead()
+ PlayerID = 0 #(DWORD PlayerID)//竞猜玩家ID,有玩家修改竞猜时会附带该信息,如果是自己ID,则更新自己的竞猜选项,否则无视
+ SelectCnt = 0 #(BYTE SelectCnt)
+ SelectFamilyIDList = list() #(vector<DWORD> SelectFamilyIDList)//竞猜玩家选择的仙盟ID顺序
+ FinalCnt = 0 #(BYTE FinalCnt)
+ FinalFamilyIDList = list() #(vector<DWORD> FinalFamilyIDList)//最终排名顺序,仅活动排名出来后才有值
+ RightCnt = 0 #(BYTE RightCnt)
+ RightInfoList = list() #(vector<tagGCFamilyGCZGuessRight> RightInfoList)//猜中个数明细列表
+ FamilyCnt = 0 #(BYTE FamilyCnt)
+ GuessFamilyList = list() #(vector<tagGCFamilyGCZGuessFamily> GuessFamilyList)//备选仙盟名单列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x32
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.SelectCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.SelectCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.SelectFamilyIDList.append(value)
+ self.FinalCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FinalCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.FinalFamilyIDList.append(value)
+ self.RightCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.RightCnt):
+ temRightInfoList = tagGCFamilyGCZGuessRight()
+ _pos = temRightInfoList.ReadData(_lpData, _pos)
+ self.RightInfoList.append(temRightInfoList)
+ self.FamilyCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FamilyCnt):
+ temGuessFamilyList = tagGCFamilyGCZGuessFamily()
+ _pos = temGuessFamilyList.ReadData(_lpData, _pos)
+ self.GuessFamilyList.append(temGuessFamilyList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x32
+ self.PlayerID = 0
+ self.SelectCnt = 0
+ self.SelectFamilyIDList = list()
+ self.FinalCnt = 0
+ self.FinalFamilyIDList = list()
+ self.RightCnt = 0
+ self.RightInfoList = list()
+ self.FamilyCnt = 0
+ self.GuessFamilyList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 1
+ length += 4 * self.SelectCnt
+ length += 1
+ length += 4 * self.FinalCnt
+ length += 1
+ for i in range(self.RightCnt):
+ length += self.RightInfoList[i].GetLength()
+ length += 1
+ for i in range(self.FamilyCnt):
+ length += self.GuessFamilyList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteBYTE(data, self.SelectCnt)
+ for i in range(self.SelectCnt):
+ data = CommFunc.WriteDWORD(data, self.SelectFamilyIDList[i])
+ data = CommFunc.WriteBYTE(data, self.FinalCnt)
+ for i in range(self.FinalCnt):
+ data = CommFunc.WriteDWORD(data, self.FinalFamilyIDList[i])
+ data = CommFunc.WriteBYTE(data, self.RightCnt)
+ for i in range(self.RightCnt):
+ data = CommFunc.WriteString(data, self.RightInfoList[i].GetLength(), self.RightInfoList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.FamilyCnt)
+ for i in range(self.FamilyCnt):
+ data = CommFunc.WriteString(data, self.GuessFamilyList[i].GetLength(), self.GuessFamilyList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ PlayerID:%d,
+ SelectCnt:%d,
+ SelectFamilyIDList:%s,
+ FinalCnt:%d,
+ FinalFamilyIDList:%s,
+ RightCnt:%d,
+ RightInfoList:%s,
+ FamilyCnt:%d,
+ GuessFamilyList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.PlayerID,
+ self.SelectCnt,
+ "...",
+ self.FinalCnt,
+ "...",
+ self.RightCnt,
+ "...",
+ self.FamilyCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZGuessInfo=tagGCFamilyGCZGuessInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZGuessInfo.Head.Cmd,m_NAtagGCFamilyGCZGuessInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZGuessInfo
#------------------------------------------------------
@@ -57675,6 +59419,70 @@
#------------------------------------------------------
+# C1 10 仙盟攻城战玩家信息 #tagMCFamilyGCZPlayerInfo
+
+class tagMCFamilyGCZPlayerInfo(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("ContributionCnt", c_ubyte), # 轮次低级捐献已捐献次数,轮次变更时会重置
+ ("Energy", c_ubyte), # 当前可用免费体力
+ ("EnergyTime", c_int), # 上次恢复免费体力时间戳,为0时不再恢复
+ ("AwardState", c_int), # 活动奖励领取状态,按二进制位判断是否已领取,0-竞猜奖励;1-个人排行奖励;2-仙盟排名奖励;
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC1
+ 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 = 0xC1
+ self.SubCmd = 0x10
+ self.ContributionCnt = 0
+ self.Energy = 0
+ self.EnergyTime = 0
+ self.AwardState = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagMCFamilyGCZPlayerInfo)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C1 10 仙盟攻城战玩家信息 //tagMCFamilyGCZPlayerInfo:
+ Cmd:%s,
+ SubCmd:%s,
+ ContributionCnt:%d,
+ Energy:%d,
+ EnergyTime:%d,
+ AwardState:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.ContributionCnt,
+ self.Energy,
+ self.EnergyTime,
+ self.AwardState
+ )
+ return DumpString
+
+
+m_NAtagMCFamilyGCZPlayerInfo=tagMCFamilyGCZPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyGCZPlayerInfo.Cmd,m_NAtagMCFamilyGCZPlayerInfo.SubCmd))] = m_NAtagMCFamilyGCZPlayerInfo
+
+
+#------------------------------------------------------
# C1 08 幸运云购玩家信息 #tagMCLuckyCloudBuyPlayerInfo
class tagMCLuckyCloudBuyPlayerInfo(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/CreateFamily.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/CreateFamily.py
index 0d572b6..5382fb2 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/CreateFamily.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/CreateFamily.py
@@ -18,7 +18,10 @@
import ShareDefine
import PlayerFamily
import GameWorldFamilyWar
+import IPY_GameServer
+import random
+FackFamilyIDStart = 1000000000
## 执行逻辑
# @param curPlayer 当前玩家
@@ -27,11 +30,17 @@
def OnExec(curPlayer, gmList):
if not gmList:
- GameWorld.DebugAnswer(curPlayer, "CreatFamily 创建假仙盟个数 可选参数(仙盟等级 是否设置联赛名次)")
- GameWorld.DebugAnswer(curPlayer, "删除创建的假仙盟: CreatFamily 0")
+ GameWorld.DebugAnswer(curPlayer, "创建跨服假仙盟: CreatFamily c 个数 [总战力 ServerID 等级 成员数]")
+ GameWorld.DebugAnswer(curPlayer, "删除跨服假仙盟: CreatFamily c 0")
+ GameWorld.DebugAnswer(curPlayer, "创建本服假仙盟: CreatFamily 个数 [等级 设置联赛名次]")
+ GameWorld.DebugAnswer(curPlayer, "删除本服假仙盟: CreatFamily 0")
return
- creatCount = gmList[0]
+ value1 = gmList[0]
+ if value1 == "c":
+ return
+
+ creatCount = value1
if creatCount <= 0:
delFamilyList = []
familyManager = GameWorld.GetFamilyManager()
@@ -94,4 +103,135 @@
PlayerFamily.DoFamilySort()
return
+def OnGetMergeParam(curPlayer):
+ return []
+
+def OnMergeServerExec(gmList, tick):
+ ## 跨服执行命令
+ if not gmList:
+ return
+
+ value1 = gmList[0]
+ if value1 != "c":
+ return
+
+ value2 = gmList[1] if len(gmList) > 1 else 1 # 默认1个
+ if not value2:
+ __delMergeServerFackFamily()
+ return
+
+ __createMergeServerFackFamily(gmList)
+ return
+
+def __delMergeServerFackFamily():
+
+ delCnt = 0
+ familyManager = GameWorld.GetFamilyManager()
+ for i in range(familyManager.GetCount())[::-1]:
+ family = familyManager.GetAt(i)
+ if not family:
+ continue
+ if family.GetID() >= FackFamilyIDStart:
+ familyManager.DelFamily(family.GetID())
+ delCnt += 1
+
+ GameWorld.DebugAnswer(None, "成功删除跨服假仙盟: %s,剩余:%s" % (delCnt, familyManager.GetCount()))
+ return
+
+def __createMergeServerFackFamily(gmList):
+ ## c 个数 [总战力 ServerID 等级 成员数]
+
+ creatCount = gmList[1] if len(gmList) > 1 else 1 # 默认1个
+ familyFightPower = gmList[2] if len(gmList) > 2 else 10000000
+ serverID = gmList[3] if len(gmList) > 3 else random.randint(1, 200)
+ familyLV = gmList[4] if len(gmList) > 4 else 1 # 默认1级
+ memberCnt = gmList[5] if len(gmList) > 5 else random.randint(1, 10)
+
+ FakeFamilyName = "假仙盟".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
+ FakeMemberName = "假成员".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
+
+ fackFamilyID = FackFamilyIDStart # 跨服假仙盟ID从10亿开始,因为子服的仙盟ID分配是从1开始
+ fackFamilyIDMax = fackFamilyID + 10000 # 限制最大假盟数
+ fackMemID = 1 # 假成员 1~9999
+ fackMemIDMax = 9999
+ fackMemIDList = []
+ createOKCnt = 0
+ familyManager = GameWorld.GetFamilyManager()
+ for _ in range(min(creatCount, 100)):
+
+ fackFamily = familyManager.FindFamily(fackFamilyID)
+ while fackFamily and fackFamilyID < fackFamilyIDMax:
+ for m in xrange(fackFamily.GetCount()):
+ member = fackFamily.GetAt(m)
+ memID = member.GetPlayerID()
+ if memID and memID not in fackMemIDList:
+ fackMemIDList.append(memID)
+ fackFamilyID += 1
+ fackFamily = familyManager.FindFamily(fackFamilyID)
+
+ if fackFamily:
+ break
+
+ fackFamilyName = "%s%s" % (FakeFamilyName, fackFamilyID)
+ fackFamily = familyManager.AddFamilyEx(fackFamilyName, fackFamilyID)
+ fackFamilyID += 1
+ if not fackFamily:
+ continue
+
+ fackFamily.SetLV(familyLV)
+ PlayerFamily.SetFamilyTotalFightPower(fackFamily, familyFightPower)
+ PlayerFamily.SetFamilyEmblemID(fackFamily, 1)
+ fackFamily.SetServerID(serverID)
+
+ GameWorld.DebugLog("创建假仙盟: fackFamilyID=%s,serverID=%s,familyFightPower=%s,memberCnt=%s"
+ % (fackFamilyID, serverID, familyFightPower, memberCnt))
+ for _ in range(memberCnt):
+
+ while fackMemID in fackMemIDList and fackMemID < fackMemIDMax:
+ fackMemID += 1
+
+ if fackMemID in fackMemIDList:
+ break
+ fackMemName = "%s%s" % (FakeMemberName, fackMemID)
+
+ member = fackFamily.AddMemberEx(fackMemID)
+ if not member:
+ continue
+
+ member.SetName(fackMemName)
+ member.SetLV(random.randint(100, 200))
+ member.SetJob(random.randint(1, 2))
+ member.SetOfficialRank(random.randint(1, 20))
+
+ if not fackFamily.GetLeaderID():
+ member.SetFamilyLV(IPY_GameServer.fmlLeader)
+ fackFamily.SetLeaderID(fackMemID)
+ fackFamily.SetLeaderName(fackMemName)
+ fackFamily.SetLeaderOfficialRank(member.GetOfficialRank())
+
+ fackMemID += 1
+
+ # 根据成功创建的成员平均分配总战力
+ memFightPowerTotal = familyFightPower
+ memCnt = fackFamily.GetCount()
+ avgValue = memFightPowerTotal / memCnt
+ for m in range(memCnt):
+ member = fackFamily.GetAt(m)
+ memID = member.GetPlayerID()
+ fmLV = member.GetFamilyLV()
+ if m == memCnt - 1:
+ memFightPower = memFightPowerTotal
+ else:
+ memFightPower = avgValue + memCnt / 2 - m
+ memFightPowerTotal -= memFightPower
+ PlayerFamily.SetMemberFightPower(member, memFightPower)
+ GameWorld.DebugLog(" 仙盟成员: memID=%s,memFightPower=%s,fmLV=%s" % (memID, memFightPower, fmLV))
+
+ createOKCnt += 1
+ familyFightPower += 10000
+
+ GameWorld.DebugAnswer(None, "成功创建跨服假仙盟: %s,总:%s" % (creatCount, familyManager.GetCount()))
+ return
+
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_GetFamilyByServerID.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_GetFamilyByServerID.py
new file mode 100644
index 0000000..7aebf12
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/GMT_GetFamilyByServerID.py
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.GMT_GetFamilyByServerID
+#
+# @todo:查询仙盟
+# @author hxp
+# @date 2025-04-09
+# @version 1.0
+#
+# 详细描述: 查询仙盟 - 根据所属区服ID条件
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-04-09 16:00"""
+#-------------------------------------------------------------------------------
+
+import GMCommon
+import GameWorld
+import PlayerFamily
+import ChPlayer
+
+def OnExec(orderId, gmCmdDict):
+ serverIDList = eval(gmCmdDict.get("serverIDList", '[]'))
+ queryCnt = GameWorld.ToIntDef(gmCmdDict.get("queryCnt", '0') , 100)
+ GameWorld.DebugLog("GMT_GetFamilyByServerID queryCnt=%s, %s, %s" % (queryCnt, serverIDList, gmCmdDict))
+
+ isCrossServer = GameWorld.IsCrossServer()
+ familyMgr = GameWorld.GetFamilyManager()
+ if isCrossServer:
+ sortFamilyIDList, totalCnt = PlayerFamily.SortCrossFamily(serverIDList, queryCnt)
+ else:
+ sortFamilyIDList = PlayerFamily.GetSortFamilyIDList()
+ totalCnt = len(sortFamilyIDList)
+
+ retCnt = 0
+ familyList = []
+ for familyID in sortFamilyIDList:
+ if isCrossServer:
+ curFamily = familyID
+ familyID = curFamily.GetID()
+ else:
+ curFamily = familyMgr.FindFamily(familyID)
+ if not curFamily:
+ continue
+ familyList.append(GetQueryFamilyInfo(curFamily, isCrossServer))
+ retCnt += 1
+ if retCnt >= queryCnt:
+ break
+
+ #执行成功
+ retMsg = {"familyList":familyList, "totalCnt":totalCnt}
+ GMCommon.GMCommandResult(orderId, gmCmdDict, GMCommon.Def_Success, retMsg)
+ return
+
+def GetQueryFamilyInfo(curFamily, isCrossServer):
+ if curFamily == None:
+ return {}
+
+ onlineCnt = 0
+ memberCnt = curFamily.GetCount()
+ onlineMgr = ChPlayer.GetOnlinePlayerMgr()
+ for index in range(memberCnt):
+ curMember = curFamily.GetAt(index)
+ playerID = curMember.GetPlayerID()
+ if onlineMgr.IsOnline(playerID):
+ onlineCnt += 1
+
+ familyInfo = {
+ 'ID':curFamily.GetID(),
+ 'Name':curFamily.GetName(),
+ 'FightPower':PlayerFamily.GetFamilyTotalFightPower(curFamily), # 总战力
+ 'LeaderID':curFamily.GetLeaderID(),
+ 'LeaderName':curFamily.GetLeaderName(),
+ 'LV':curFamily.GetLV(),
+ 'MemberCnt':memberCnt,
+ 'OnLineCnt':onlineCnt,
+ 'ServerID':curFamily.GetServerID(),
+ }
+
+ return familyInfo
+
+
\ No newline at end of file
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
index d7ad0ea..31bad23 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -1223,6 +1223,98 @@
# 找不到的默认取最后一名
return orderDict[orderList[-1]] if isDefaultLast else defaultValue
+def GetActBillboardTempAward(playerID, billID, billRank, awardTemplateID, billValue=None, fmLV=None):
+ '''获取玩家活动榜单领奖奖励
+ @param playerID: 领奖玩家ID
+ @param billID: 上榜ID,不一定是玩家ID,比如仙盟ID
+ @param billRank: 上榜名次
+ @param awardTemplateID: 活动奖励模版ID
+ @param billValue: 榜单上榜值,None时不处理
+ @param fmLV: 活动时的仙盟成员等级,None时不处理
+ '''
+ playerAwardItemList = []
+ if not billRank:
+ return playerAwardItemList
+ ipyDataList = IpyGameDataPY.GetIpyGameDataList("ActBillboardAwardTemp", awardTemplateID)
+ if not ipyDataList:
+ ErrLog("活动榜单奖励模版找不到模版! billID=%s,billRank=%s,awardTemplateID=%s,billValue=%s,fmLV=%s"
+ % (billID, billRank, awardTemplateID, billValue, fmLV), playerID)
+ return playerAwardItemList
+
+ for ipyData in ipyDataList:
+ rank = ipyData.GetRank()
+ if billRank > rank:
+ continue
+ needValue = ipyData.GetNeedValue()
+ if needValue and billValue != None and billValue < needValue:
+ continue
+
+ awardItemList = ipyData.GetAwardItemList()
+ leaderAwardItemList = ipyData.GetLeaderAwardItemList()
+ eliteAwardItemList = ipyData.GetEliteAwardItemList()
+
+ if fmLV != None and fmLV == IPY_GameServer.fmlLeader and leaderAwardItemList:
+ playerAwardItemList += leaderAwardItemList
+ elif fmLV != None and fmLV > IPY_GameServer.fmlMember and eliteAwardItemList:
+ playerAwardItemList += eliteAwardItemList
+ else:
+ playerAwardItemList += awardItemList
+
+ valueAwardEx = ipyData.GetValueAwardEx()
+ if valueAwardEx and billValue != None:
+ valueAwardExList = valueAwardEx.keys()
+ valueAwardExList.sort()
+ awardItemExList = []
+ for valueEx in valueAwardExList:
+ if billValue < valueEx:
+ break
+ awardItemExList = valueAwardEx[valueEx] # 取最大满足条件的一档
+ playerAwardItemList += awardItemExList
+
+ return playerAwardItemList
+
+ ErrLog("活动榜单奖励模版找不到奖励! billID=%s,billRank=%s,awardTemplateID=%s,billValue=%s,fmLV=%s"
+ % (billID, billRank, awardTemplateID, billValue, fmLV), playerID)
+ return playerAwardItemList
+
+def GetActGuessRightRankAwardIDDict(guessTemplateID):
+ ## 获取活动竞猜默认猜中名次对应奖励ID信息
+ # @return: {(名次, ...):awardID, ...} 用于 StatActGuessRet 统计竞猜结果
+ rightRankAwardIDDict = {}
+ guessIpyDataList = IpyGameDataPY.GetIpyGameDataList("ActGuess", guessTemplateID)
+ if guessIpyDataList:
+ for ipyData in guessIpyDataList:
+ awardID = ipyData.GetAwardID()
+ rightRankList = ipyData.GetRightRankList()
+ rightRankAwardIDDict[tuple(rightRankList)] = awardID
+ return rightRankAwardIDDict
+
+def StatActGuessRet(playerID, playerGuessIDList, finalRankIDList, rightRankAwardIDDict, statGuessRetDict, actName=""):
+ '''统计活动竞猜结果
+ @param playerID: 参与竞猜的玩家ID
+ @param playerGuessIDList: 玩家竞猜选择的ID顺序列表
+ @param finalRankIDList: 活动最终排名顺序列表
+ @param rightRankAwardIDDict: GetActGuessRightRankAwardIDDict 返回值
+ @param statGuessRetDict: 统计结果 {awardID:[猜中的玩家ID, ...], ...}
+ @param actName: 活动名称,可选参数,输出日志用
+ '''
+ rightRankList = [] # 玩家猜中的名次列表
+ for index, finalID in enumerate(finalRankIDList):
+ rank = index + 1
+ guessID = playerGuessIDList[index] if len(playerGuessIDList) > index else 0
+ if guessID == finalID:
+ rightRankList.append(rank)
+
+ rightRankTuple = tuple(rightRankList)
+ awardID = rightRankAwardIDDict.get(rightRankTuple, 0)
+ if awardID not in statGuessRetDict:
+ statGuessRetDict[awardID] = []
+ rightPlayerIDList = statGuessRetDict[awardID]
+ rightPlayerIDList.append(playerID)
+ DebugLog(" %s统计玩家竞猜结果: playerID=%s,rightRankTuple=%s,awardID=%s,%s"
+ % (actName, playerID, rightRankTuple, awardID, len(rightPlayerIDList)))
+ return
+
##概率相关, 这个事件是否能够出现
# @param rate 基础几率
# @param maxRate 最大几率
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
index 0d1c52f..7772342 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossActionControl.py
@@ -27,6 +27,8 @@
import PlayerActGubao
import PlayerActHorsePetTrain
import PlayerActLianqi
+import PlayerDBGSEvent
+import CrossFamilyGCZ
import CrossRealmMsg
import PyGameData
import ChConfig
@@ -137,6 +139,37 @@
if zoneID != ipyZoneID:
return
return actInfo
+
+def GetCrossActInfoByZoneID(actName, zoneID):
+ ## 获取分区ID对应的跨服活动信息
+ crossActInfoDict = GetCrossActInfoDict()
+ if actName not in crossActInfoDict:
+ return
+ curActInfoDict = crossActInfoDict[actName]
+ for actInfo in curActInfoDict.values():
+ ipyDataDict = actInfo.get(ShareDefine.ActKey_IpyDataInfo, {})
+ if not ipyDataDict:
+ return
+ ipyZoneID = ipyDataDict.get("ZoneID", 0)
+ if zoneID == ipyZoneID:
+ return actInfo
+ return
+
+def GetCrossActZoneIDList(actName):
+ ## 获取跨服活动当前所有分区列表
+ crossActInfoDict = GetCrossActInfoDict()
+ if actName not in crossActInfoDict:
+ return []
+ zoneIDList = []
+ curActInfoDict = crossActInfoDict[actName]
+ for actInfo in curActInfoDict.values():
+ ipyDataDict = actInfo.get(ShareDefine.ActKey_IpyDataInfo, {})
+ if not ipyDataDict:
+ return
+ zoneID = ipyDataDict.get("ZoneID", 0)
+ if zoneID and zoneID not in zoneIDList:
+ zoneIDList.append(zoneID)
+ return zoneIDList
def GetCrossActInfoDict():
if PyGameData.g_crossActInfoDict == None:
@@ -530,6 +563,7 @@
actChangeList = []
actStateChangeList = []
sysnCrossActInfoDict = {}
+ flowStateErrorResetList = []
for actName in ShareDefine.CrossActNameList:
if actName not in actTimeInfoDict or actName not in crossActInfoDict or actName not in actCfgIDInfoDict:
continue
@@ -549,6 +583,8 @@
cfgID = ipyData.GetCfgID()
groupName = ipyData.GetActGroupName()
zoneID = ipyData.GetZoneID()
+ actFlowID = ipyData.GetActFlowID() if hasattr(ipyData, "GetActFlowID") else 0 # 活动流程ID
+ actStartDataTime = None
if cfgID not in crossActInfoDict[actName]:
crossActInfoDict[actName][cfgID] = {}
@@ -560,6 +596,7 @@
endDateTime = endList[dIndex]
if startDateTime <= curDateTime < endDateTime:
state = dIndex + 1 # 也是代表第几个时间段
+ actStartDataTime = startDateTime
break
if endList:
isEnd = (curDateTime >= endList[-1])
@@ -575,18 +612,11 @@
else:
stateJoin = ShareDefine.ActStateJoin_Start if state else ShareDefine.ActStateJoin_None
+ actID = actInfoDict.get(ShareDefine.ActKey_ID, 0)
+ templateID = actInfoDict.get(ShareDefine.ActKey_TemplateID, 0)
serverIDRangeList = actInfoDict.get(ShareDefine.ActKey_ServerIDRangeList)
- # 全服广播提示信息
- if curDateTime in notifyDict:
- if serverIDRangeList != None:
- notifyKey, paramList = notifyDict[curDateTime]
- country = 0
- serverGroupIDList = []
- crossNotifyList = []
- crossNotifyList.append([ShareDefine.CrossNotify_CrossAct, [country, notifyKey, paramList], serverIDRangeList])
- PlayerControl.CrossNotifyEx(serverGroupIDList, crossNotifyList)
-
dbInfo = actInfoDict.get(ShareDefine.ActKey_DBInfo, {})
+
dbState = dbInfo.get(ShareDefine.ActKey_State, 0)
dbStateJoin = dbInfo.get(ShareDefine.ActKey_StateJoin, 0)
dbCfgID = dbInfo.get(ShareDefine.ActKey_CfgID, 0)
@@ -598,8 +628,33 @@
if dbCfgID == cfgID and dbServerIDRangeList != serverIDRangeList:
forceReset = True
- actID = actInfoDict.get(ShareDefine.ActKey_ID, 0)
- templateID = actInfoDict.get(ShareDefine.ActKey_TemplateID, 0)
+ errStateActID = 0
+ if state and actFlowID: # 有活动流程ID的,实际状态按取活动流程对应状态
+ errStateActID = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActFlowStateError % (actName, zoneID))
+ # 已经是不同活动了,强制重置异常状态标记,防止影响新活动
+ if errStateActID and (errStateActID != actID or not dbState):
+ GameWorld.Log("按流程走的活动流程上次异常,新活动重置状态! %s,zoneID=%s,actID=%s,errStateActID=%s,dbState=%s" % (actName, zoneID, actID, errStateActID, dbState))
+ PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActFlowStateError % (actName, zoneID), 0)
+ errStateActID = 0
+
+ flowStateIndex, flowState, flowStatePre = GetActTimeFlowState(actFlowID, actStartDataTime, curDateTime)
+ # 非第一个流程状态变更的时候,要验证流程是否正确,如果异常,则流程照走,标记异常,具体异常的处理由各活动自行处理
+ if flowStateIndex > 0 and flowState != dbState and flowStatePre != dbState and not errStateActID:
+ GameWorld.ErrLog("按流程走的活动流程已异常! %s,zoneID=%s,actID=%s,flowStatePre=%s,dbState=%s" % (actName, zoneID, actID, flowStatePre, dbState))
+ PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActFlowStateError % (actName, zoneID), actID)
+ errStateActID = actID
+ state = flowState
+
+ # 全服广播提示信息
+ if curDateTime in notifyDict and not flowState and not errStateActID:
+ if serverIDRangeList != None:
+ notifyKey, paramList = notifyDict[curDateTime]
+ country = 0
+ serverGroupIDList = []
+ crossNotifyList = []
+ crossNotifyList.append([ShareDefine.CrossNotify_CrossAct, [country, notifyKey, paramList], serverIDRangeList])
+ PlayerControl.CrossNotifyEx(serverGroupIDList, crossNotifyList)
+
if not isReload and dbState == state and dbStateJoin == stateJoin and dbActID == actID and not forceReset:
#已经是这个状态了
continue
@@ -612,6 +667,9 @@
dbInfo = {ShareDefine.ActKey_ID:actID, ShareDefine.ActKey_State:state, ShareDefine.ActKey_TemplateID:templateID,
ShareDefine.ActKey_CfgID:cfgID, ShareDefine.ActKey_ServerIDRangeList:serverIDRangeList,
ShareDefine.ActKey_StateJoin:stateJoin}
+ if errStateActID:
+ actInfoDict[ShareDefine.ActKey_StateError] = errStateActID
+
actInfoDict[ShareDefine.ActKey_DBInfo] = dbInfo
#GameWorld.Log(" 活动状态同步信息: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,actInfoDict=%s" % (actName, cfgID, groupName, zoneID, actInfoDict))
if actName not in sysnCrossActInfoDict:
@@ -622,6 +680,9 @@
GameWorld.Log(" 活动ID变更: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbActID=%s -> actID=%s,forceReset=%s,dbTemplateID=%s"
% (actName, cfgID, groupName, zoneID, dbActID, actID, forceReset, dbTemplateID))
+ if errStateActID:
+ flowStateErrorResetList.append((actName, zoneID))
+
if actName == ShareDefine.CrossActName_CTGBillboard:
CrossActCTGBillboard.OnActIDChange(cfgID, dbTemplateID, state)
@@ -640,18 +701,21 @@
elif actName == ShareDefine.CrossActName_Lianqi:
PlayerActLianqi.OnCrossActIDChange(cfgID, zoneID, ipyData, state)
+ elif actName == ShareDefine.CrossActName_FamilyGCZ:
+ CrossFamilyGCZ.OnCrossActIDChange(cfgID, zoneID, ipyData, state)
+
else:
actChangeList.append([actName, ipyData, state, cfgID, groupName, zoneID, dbActID, actID, forceReset, dbTemplateID])
# 活动ID变更强制视为状态变更,防止维护前后状态一样,但其实活动ID已经不同的情况会导致无法触发状态变更
actIDChange = True
- actStateChangeList.append([actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, dbTemplateID])
+ actStateChangeList.append([actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, actID, dbTemplateID])
elif dbState != state:
actIDChange = False
GameWorld.Log(" 活动状态变更: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbState=%s -> state=%s,actIDChange=%s,dbTemplateID=%s"
% (actName, cfgID, groupName, zoneID, dbState, state, actIDChange, dbTemplateID))
- actStateChangeList.append([actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, dbTemplateID])
+ actStateChangeList.append([actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, actID, dbTemplateID])
# 活动中刷新,每次都需要刷新的逻辑,包含重读配置等
if state:
@@ -713,15 +777,67 @@
CrossActAllRecharge.OnActIDChange(ipyData, state)
for changeInfo in actStateChangeList:
- actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, dbTemplateID = changeInfo
+ actName, ipyData, dbState, state, cfgID, groupName, zoneID, actIDChange, actID, dbTemplateID = changeInfo
GameWorld.Log(" 活动状态变更: actName=%s,cfgID=%s,groupName=%s,zoneID=%s,dbState=%s -> state=%s,actIDChange=%s,dbTemplateID=%s"
% (actName, cfgID, groupName, zoneID, dbState, state, actIDChange, dbTemplateID))
if actName == ShareDefine.CrossActName_LuckyCloudBuy:
import CrossLuckyCloudBuy
CrossLuckyCloudBuy.OnLuckyCloudBuyStateChange(ipyData, actIDChange, state)
+ elif actName == ShareDefine.CrossActName_FamilyGCZ:
+ CrossFamilyGCZ.OnCrossActStateChange(ipyData, actID, dbState, state)
+ for actName, zoneID in flowStateErrorResetList:
+ GameWorld.Log("活动结束重置按流程走的活动流程异常状态! %s,zoneID=%s" % (actName, zoneID))
+ PlayerDBGSEvent.SetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActFlowStateError % (actName, zoneID), 0)
+
return
+
+def IsActFlowStateError(actName, zoneID):
+ ## 流程状态是否已异常
+ errStateActID = PlayerDBGSEvent.GetDBGSTrig_ByKey(PlayerDBGSEvent.Def_ActFlowStateError % (actName, zoneID))
+ if errStateActID:
+ GameWorld.ErrLog("活动流程状态已异常! %s,zoneID=%s,errStateActID=%s" % (actName, zoneID, errStateActID))
+ return True
+ return False
+
+def GetActTimeFlowState(actFlowID, actStartDataTime, curDateTime):
+ ## 获取活动流程ID对应当前状态
+ ipyDataList = IpyGameDataPY.GetIpyGameDataList("ActTimeFlow", actFlowID)
+ if not ipyDataList:
+ return 0
+
+ flowStatePre = 0
+ flowState = 0
+ flowStateIndex = -1
+ for index, timeIpyData in enumerate(ipyDataList):
+ #dataID = timeIpyData.GetID()
+ startDay, startHour, startMinute = timeIpyData.GetStartDay(), timeIpyData.GetStartHour(), timeIpyData.GetStartMinute()
+ endDay, endHour, endMinute = timeIpyData.GetEndDay(), timeIpyData.GetEndHour(), timeIpyData.GetEndMinute()
+
+ startSeconds = ((startDay - 1) * 24 + startHour) * 3600 + startMinute * 60
+ endSeconds = ((endDay - 1) * 24 + endHour) * 3600 + endMinute * 60
+ startDateTime = actStartDataTime + datetime.timedelta(seconds=startSeconds)
+ endDateTime = actStartDataTime + datetime.timedelta(seconds=endSeconds)
+ if curDateTime < startDateTime or curDateTime > endDateTime:
+ flowStatePre = timeIpyData.GetStateValue()
+ continue
+ flowState = timeIpyData.GetStateValue()
+ flowStateIndex = index
+ #notifyInfoDict = timeIpyData.GetNotifyInfo()
+ #if not stateError and notifyInfoDict:
+ # diffDateTime = curDateTime - startDateTime
+ # diffMinute = (diffDateTime.days * 24 * 3600 + diffDateTime.seconds) / 60 # 当前时间与开始时间相差分钟数
+ # GameWorld.DebugLog(" 广播判断: curDateTime=%s,startDateTime=%s,diffDays=%s,diffSeconds=%s,diffMinute=%s"
+ # % (curDateTime, startDateTime, diffDateTime.days, diffDateTime.seconds, diffMinute))
+ # if diffMinute in notifyInfoDict:
+ # notifyKey, paramList = notifyInfoDict[diffMinute]
+ # PlayerControl.WorldNotifyCross(serverGroupIDList, 0, notifyKey, paramList)
+ break
+
+ if not flowState:
+ flowStatePre = 0
+ return flowStateIndex, flowState, flowStatePre
def Sync_CrossActInfoToClientServer(serverGroupID=0):
''' 同步跨服运营活动信息到子服务器
@@ -761,6 +877,10 @@
GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossActInfo % actName, syncActInfoDict)
+ # 以下需要等活动信息同步给地图后才处理
+ if actName == ShareDefine.CrossActName_FamilyGCZ:
+ CrossFamilyGCZ.ClientServer_CrossActInfo()
+
# 删除非活动中的
for actName, actInfoDict in PyGameData.g_crossActInfoDict.items():
for cfgID, actInfo in actInfoDict.items():
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
index 93bbf87..d3fec6f 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossBillboard.py
@@ -19,6 +19,7 @@
import ShareDefine
import IpyGameDataPY
import CrossRealmMsg
+import PlayerViewCache
import PyGameDataStruct
import ChPyNetSendPack
import DataRecordPack
@@ -66,6 +67,27 @@
for key in self.__billboardDict.keys():
if key[0] == billboardType:
self.__billboardDict.pop(key)
+ return
+
+ def ClearBillboard(self, billboardType, groupValue1=None, groupValue2=None):
+ '''清除某个类型的榜单所有数据,可指定过滤groupValue,有流向记录
+ @param groupValue1: 不为None时验证 groupValue1 是否相同
+ @param groupValue2: 不为None时验证 groupValue2 是否相同
+ 如果groupValue1 groupValue2 都传入None,相当于清空 billboardType 类型的所有榜单数据
+ '''
+ clearList = []
+ for bType, gValue1, gValue2 in self.__billboardDict.keys():
+ if bType != billboardType:
+ continue
+ if groupValue1 != None and groupValue1 != gValue1:
+ continue
+ if groupValue2 != None and groupValue2 != gValue2:
+ continue
+ key = (bType, gValue1, gValue2)
+ clearList.append(key)
+
+ for bType, gValue1, gValue2 in clearList:
+ self.GetCrossBillboard(bType, gValue1, gValue2).ClearData()
return
# 保存数据 存数据库和realtimebackup
@@ -450,8 +472,8 @@
#{
# tagHead Head;
# BYTE Type; //榜单类型
-# BYTE GroupValue1; // 分组值1
-# BYTE GroupValue2; // 分组值2,与分组值1组合归为同组榜单数据
+# DWORD GroupValue1; // 分组值1
+# DWORD GroupValue2; // 分组值2,与分组值1组合归为同组榜单数据
# DWORD StartIndex; //查看的起始名次索引, 默认0
# BYTE WatchCnt; //查看条数,默认20,最大不超过100
# DWORD WatchID; //查看指定ID名次前后,如玩家ID、家族ID等
@@ -771,6 +793,21 @@
id2=id2, autoSort=autoSort, value3=value3, value4=value4, value5=value5)
return
+def UpdCrossBillboardPlayer(bType, playerID, groupValue1, cmpValue, cmpValue2=0, value1=0, value2=0, groupValue2=0, autoSort=True, **kwargs):
+ ## 通用的更新跨服玩家榜,GameServer直接调用
+ playerInfo = PlayerViewCache.GetShotCacheDict(playerID, "AccID", "ServerID", "Face", "FacePic")
+ name1 = playerInfo.get("Name", "")
+ name2 = playerInfo.get("AccID", "")
+ type2 = playerInfo.get("Job", 1)
+ if not value1:
+ value1 = playerInfo.get("RealmLV", 1)
+ value3 = playerInfo.get("Face", 0)
+ value4 = playerInfo.get("FacePic", 0)
+ value5 = playerInfo.get("ServerID", 0)
+ UpdCrossBillboard(bType, groupValue1, playerID, name1, name2, type2, value1, value2, cmpValue, cmpValue2,
+ autoSort=autoSort, value3=value3, value4=value4, value5=value5)
+ return
+
def UpdCrossBillboard(billboardType, groupValue1, dataID, name1, name2, type2, value1, value2, cmpValue,
cmpValue2=0, cmpValue3=0, groupValue2=0, id2=0, autoSort=True, noSortAndSync=False,
**kwargs):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py
new file mode 100644
index 0000000..0b61fe1
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossFamilyGCZ.py
@@ -0,0 +1,2902 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package CrossFamilyGCZ
+#
+# @todo:仙盟攻城战
+# @author hxp
+# @date 2025-04-09
+# @version 1.0
+#
+# 详细描述: 仙盟攻城战
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-04-09 16:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import ShareDefine
+import PlayerFamily
+import IpyGameDataPY
+import CrossRealmMsg
+import CrossBillboard
+import PlayerViewCache
+import CrossActionControl
+import PlayerCompensation
+import ChPyNetSendPack
+import NetPackCommon
+import PyDataManager
+import PlayerControl
+import PyGameData
+import ChConfig
+import ChPlayer
+
+import random
+import copy
+import time
+
+
+## 1-公示期;99-领奖期;轮次状态=轮次*10+轮次阶段;轮次阶段:1-分组战备;2-战斗;3-休战结算
+FamilyGCZState_Publicity = 1 # 公示期
+FamilyGCZState_Award = 99 # 结束领奖期
+
+# 轮次状态信息
+FamilyGCZRoundState_Group = 1 # 分组+战备
+FamilyGCZRoundState_Fight = 2 # 战斗
+FamilyGCZRoundState_Over = 3 # 休战结算
+
+# 战场类型
+BatTypeList = (
+BatType_Junior, # 初级 1
+BatType_Middle, # 中级 2
+BatType_High, # 高级 3
+) = range(1, 1 + 3)
+
+# 攻击类型
+(
+AtkType_Normal, # 普通单攻 1
+AtkType_SkillSingle, # 技能单攻 2
+AtkType_SkillArea, # 技能群攻 3
+) = range(1, 1 + 3)
+
+# 攻击结果
+(
+AtkRet_OK, # 成功 0
+AtkRet_TagDead, # 目标已被击杀 1
+AtkRet_TagBroken, # 城池已被摧毁 3
+AtkRet_Other, # 其他 3
+) = range(4)
+
+# 修罗城池ID,每个分组都允许有各自的修罗城,ID可以一样
+XiuluoCityID = 2000000000
+
+# 奖励类型
+(
+AwwardType_Guess, # 竞猜
+AwwardType_PlayerHurt, # 个人伤害排行
+AwwardType_FamilyScore, # 仙盟积分排行
+) = range(3)
+
+
+class FamilyGCZFighter(object):
+ ## 城池战斗防守人员 - 玩家、守卫战斗类
+
+ def __init__(self):
+ self.fighterID = 0
+ self.hp = 0 # 当前血量
+ self.hpMax = 0 # 最大血量
+ self.hpBase = 0 # 基础血量,不算加成
+ self.fightPower = 0 # 战斗力
+ return
+
+ def IsDead(self): return self.hp <= 0
+
+ def RefreshFighterAttr(self, hpFightPowerMulti, addHPPer):
+ self.hpBase = self.fightPower * hpFightPowerMulti
+ self.hpMax = int(self.hpBase * (100 + addHPPer) / 100.0)
+ self.hp = self.hpMax # 只要刷属性就回满血,战斗阶段会锁住不允许刷属性
+ return
+
+class FamilyGCZCityWall():
+ ## 城池
+
+ def __init__(self, zoneID=0, cityID=0, cityLV=0, familyID=0):
+ self.zoneID = zoneID
+ self.batType = 0
+ self.groupNum = 0
+ self.cityID = cityID # 城池ID
+ self.cityLV = cityLV # 城池等级,一般为锁定时的大本营等级,或指定的等级,战斗属性加成由该等级决定
+ self.familyID = familyID # 所属仙盟ID,可能无归属,如修罗城
+ self.guardMemIDList = [] # 防守战斗人员ID列表,被击杀不变
+ self.fighterIDList = [] # 防守战斗人员ID列表,按成员战力升序排,NPC守卫 + 成员,被击杀移除
+
+ self.guardNPCCount = 0 # 守卫NPC数,这里指的是非玩家的系统守卫
+ self.guardNPC = FamilyGCZFighter() # 当前NPC守卫,目前仅修罗成有用
+
+ self.attrLock = 0 # 是否锁定属性
+ self.hp = 0 # 当前血量,所有防守战斗人员hp 之和
+ self.hpMax = 0 # 最大血量,所有防守战斗人员hp hpMax 之和
+ self.hpBase = 0 # 基础血量,不算加成,所有防守战斗人员hp hpBase 之和
+ self.fightPowerTotal = 0 # 总战力
+
+ self.atkedTime = 0 # 最后一次被攻击时间戳
+ self.atkReportDict = {} # 攻击战报 {tagFamilyID:totalHurt, ...}
+ self.defReportDict = {} # 防守战报 {tagFamilyID:totalHurt, ...}
+ self.fighterHurtDict = {} # 战斗成员贡献伤害,被击毁后不会再累加 {playerID:hurtValue, ...}
+ self.inCityPlayerIDList = [] # 在战斗城池里的玩家ID列表
+ return
+
+ def ResetDefense(self, cityLV, guardMemIDList=None, guardNPCCount=0):
+ ## 城池重置防御
+ self.attrLock = 0
+ self.cityLV = cityLV
+ self.guardMemIDList = []
+ self.guardNPCCount = guardNPCCount
+ if self.guardNPCCount:
+ self.guardMemIDList += range(1, 1 + self.guardNPCCount)
+ if guardMemIDList:
+ self.guardMemIDList += guardMemIDList
+ self.atkedTime = 0
+ self.atkReportDict = {}
+ self.defReportDict = {}
+ self.fighterHurtDict = {}
+ self.inCityPlayerIDList = []
+ self.RefreshCityAttr()
+ return
+
+ def OnFightStart(self):
+ ## 战斗开始 - 锁定
+ self.RefreshCityAttr()
+ self.attrLock = 1 # 刷完属性后锁住
+ return
+
+ def IsBroken(self):
+ ## 是否被击毁
+ if self.hp <= 0 or not self.fighterIDList:
+ return True
+ return False
+
+ def GetCurGuardID(self):
+ ## 当前守卫ID
+ if not self.fighterIDList:
+ return 0
+ return self.fighterIDList[0]
+
+ def NextGuard(self):
+ ## 换下一个守卫
+ if not self.fighterIDList:
+ return 0
+ self.fighterIDList.pop(0)
+ if not self.fighterIDList:
+ return 0
+ nextGuardID = self.fighterIDList
+ if self.IsGuardNPC(nextGuardID):
+ self.guardNPC.hp = self.guardNPC.hpMax
+ GameWorld.DebugLog(" 切换下一个NPC守卫: %s, %s/%s" % (nextGuardID, self.guardNPC.hp, self.guardNPC.hpMax))
+ else:
+ GameWorld.DebugLog(" 切换下一个防守人员: %s" % nextGuardID)
+ return nextGuardID
+
+ def IsGuardNPC(self, fighterID):
+ ## 是否系统NPC守卫,加上系统NPC数验证,兼容内网假仙盟成员测试
+ return self.guardNPCCount > 0 and fighterID < 10000
+
+ def RefreshCityAttr(self, cityLV=None):
+ # @return: 是否成功刷新属性,战斗锁定时无法刷属性
+ if self.attrLock:
+ GameWorld.ErrLog("仙盟攻城战已经锁定战斗属性不能刷新! cityID=%s,familyID=%s" % (self.cityID, self.familyID))
+ return
+ if cityLV != None:
+ self.cityLV = cityLV
+ cityID = self.cityID
+ cityLV = self.cityLV
+ addHPPer = 0
+ campIpyData = IpyGameDataPY.GetIpyGameData("CrossActFamilyGCZCampLV", cityLV)
+ if campIpyData:
+ addHPPer = campIpyData.GetAddHPPer()
+
+ hpFightPowerMulti = IpyGameDataPY.GetFuncCfg("FamilyGCZCity", 1) # 成员生命是战力的x倍
+ GameWorld.DebugLog("仙盟攻城战刷新城池属性: cityID=%s,cityLV=%s,addHPPer=%s,hpFightPowerMulti=%s" % (cityID, cityLV, addHPPer, hpFightPowerMulti))
+
+ zone = GetFamilyGCZMgr().GetActZone(self.zoneID)
+
+ self.hpBase = 0
+ self.hpMax = 0
+ self.fightPowerTotal = 0
+ sortFighterIDList = []
+ for fighterID in self.guardMemIDList:
+ if self.IsGuardNPC(fighterID):
+ fighter = self.guardNPC
+ fighter.fightPower = IpyGameDataPY.GetFuncCfg("FamilyGCZXiuluo", 1)
+ else:
+ fighter = zone.GetZoneJoinMember(fighterID)
+
+ fighter.RefreshFighterAttr(hpFightPowerMulti, addHPPer)
+
+ self.hpBase += fighter.hpBase
+ self.hpMax += fighter.hpMax
+ self.fightPowerTotal += fighter.fightPower
+
+ sortFighterIDList.append([fighter.fightPower, fighterID])
+ GameWorld.DebugLog(" 成员属性: cityID=%s,fighterID=%s,fightPower=%s,hpBase=%s,hpMax=%s,cityHPMax=%s"
+ % (cityID, fighterID, fighter.fightPower, fighter.hpBase, fighter.hpMax, self.hpMax))
+
+ sortFighterIDList.sort() # 按战力升序
+ self.fighterIDList = [f[1] for f in sortFighterIDList]
+
+ self.hp = self.hpMax # 只要刷属性就回满血,战斗阶段会锁住不允许刷属性
+
+ GameWorld.DebugLog(" 城池属性: cityID=%s,cityLV=%s,fightPowerTotal=%s,hpBase=%s,hpMax=%s" % (cityID, cityLV, self.fightPowerTotal, self.hpBase, self.hpMax))
+ GameWorld.DebugLog(" 防守人员战力ID排序=%s" % sortFighterIDList)
+ GameWorld.DebugLog(" 防守人员ID排序顺序=%s" % self.fighterIDList)
+ return True
+
+ def SetPlayerInCity(self, playerID, serverGroupID):
+ if playerID in self.inCityPlayerIDList:
+ return
+ self.inCityPlayerIDList.append(playerID)
+ Sync_FamilyGCZBatCityInfo(self.zoneID, self.batType, self.groupNum, self.cityID, toPlayerServerDict={playerID:serverGroupID})
+ return
+
+ def SetPlayerOutCity(self, playerID):
+ if playerID in self.inCityPlayerIDList:
+ self.inCityPlayerIDList.remove(playerID)
+ return
+
+class FamilyGCZMember(FamilyGCZFighter):
+ ## 参与的成员
+
+ def __init__(self, zoneID=0, familyID=0, playerID=0):
+ super(FamilyGCZMember, self).__init__()
+ self.zoneID = zoneID
+ self.batType = 0
+ self.groupNum = 0
+ self.playerID = playerID
+ self.familyID = familyID # 参与时的仙盟ID
+ self.fighterID = playerID
+ self.fmLV = 0 # 参与时的仙盟职位等级
+ self.playerName = ""
+ self.job = 0
+ self.realmLV = 0
+ self.face = 0
+ self.facePic = 0
+ self.lv = 0
+ self.totalHurtValue = 0 # 活动总伤害,可能无法上榜,记录用
+ self.awardState = 0 # 活动发奖同步记录,与子服的玩家个人记录对应,该记录仅用于补发奖励用
+ return
+
+class FamilyGCZFamily():
+ ## 参与的仙盟
+
+ def __init__(self, zoneID=0, familyID=0):
+ self.zoneID = zoneID
+ self.familyID = familyID
+ self.batType = 0
+ self.groupNum = 0
+ self.campLV = 1 # 大本营等级
+ self.campExp = 0
+ self.score = 0 # 活动总积分
+
+ self.familyName = ""
+ self.lv = 0
+ self.leaderID = 0
+ self.leaderName = ""
+ self.emblemID = 0
+ self.serverID = 0
+ self.fightPowerTotal = 0
+
+ self.joinMemberIDList = [] # 参与的成员ID列表 [playerID, ...]
+ self.memAddCampExpInfo = {} # 成员贡献大本营经验信息 {playerID:addExp, ...}
+ self.cityWall = FamilyGCZCityWall(zoneID, familyID, self.campLV, familyID) # 每个盟自带一个城池
+ return
+
+ def OnRoundFamilyReset(self):
+ ## 轮次重置处理
+ self.batType = 0
+ self.groupNum = 0
+ self.cityWall.ResetDefense(self.campLV, self.joinMemberIDList)
+ self.fightPowerTotal = self.cityWall.fightPowerTotal
+ Sync_FamilyGCZCampInfo(self.zoneID, self.familyID)
+ return
+
+ def OnRoundFamilyFightStart(self):
+ ## 轮次开战
+ self.cityWall.OnFightStart()
+ self.fightPowerTotal = self.cityWall.fightPowerTotal
+ Sync_FamilyGCZCampInfo(self.zoneID, self.familyID)
+ return
+
+ def RefreshFamilyAttr(self, isNotify=True):
+ ## 刷新仙盟战斗属性
+ isOK = self.cityWall.RefreshCityAttr(self.campLV)
+ self.fightPowerTotal = self.cityWall.fightPowerTotal
+ if isNotify:
+ Sync_FamilyGCZCampInfo(self.zoneID, self.familyID)
+ return isOK
+
+ def AddCampExp(self, playerID, addCampExp, isNotify=True):
+ ## 大本营加经验
+ # @return: 是否升级
+ if playerID not in self.joinMemberIDList:
+ # 非本盟锁定成员不能加经验
+ GameWorld.ErrLog("非仙盟攻城战锁定成员无法加大本营经验! familyID=%s,playerID=%s not in %s" % (self.familyID, playerID, self.joinMemberIDList))
+ return
+
+ campLV = self.campLV
+ campExp = self.campExp
+ updCampExp = min(campExp + addCampExp, ChConfig.Def_UpperLimit_DWord)
+ updCampLV = campLV
+
+ # 满级了也不限制捐献,让玩家可以继续消耗多余的道具
+ campIpyData = IpyGameDataPY.GetIpyGameData("CrossActFamilyGCZCampLV", campLV)
+ if campIpyData and campIpyData.GetLVUPNeedExp():
+ lvupNeedExp = campIpyData.GetLVUPNeedExp()
+ if updCampExp >= lvupNeedExp and IpyGameDataPY.GetIpyGameDataNotLog("CrossActFamilyGCZCampLV", campLV + 1):
+ updCampExp -= lvupNeedExp
+ updCampLV = campLV + 1
+
+ self.campLV = updCampLV
+ self.campExp = updCampExp
+ self.memAddCampExpInfo[playerID] = self.memAddCampExpInfo.get(playerID, 0) + addCampExp
+
+ GameWorld.DebugLog("增加大本营经验: familyID=%s,playerID=%s,addCampExp=%s,campLV-Exp=%s-%s,updLV-Exp=%s-%s,playerAddExpTotal=%s"
+ % (self.familyID, playerID, addCampExp, campLV, campExp, updCampLV, updCampExp, self.memAddCampExpInfo[playerID]))
+
+ # 升级了
+ defMemIDList = [] # 加经验默认不通知防守成员属性
+ isLVUP = False
+ if campLV != updCampLV:
+ isLVUP = True
+ GameWorld.DebugLog("大本营升级了! familyID=%s,campLV=%s to %s" % (self.familyID, campLV, updCampLV))
+ if self.RefreshFamilyAttr(False):
+ defMemIDList = None # 升级后成功刷成员属性后,额外附带所有防守成员信息,战斗阶段属性是锁定的
+
+ if isNotify:
+ Sync_FamilyGCZCampInfo(self.zoneID, self.familyID, defMemIDList=defMemIDList)
+
+ return isLVUP
+
+ def GetOLMemServerGroupIDDict(self):
+ ## 获取本盟在线参与成员信息
+ olDict = {}
+ onlineMgr = ChPlayer.GetOnlinePlayerMgr()
+ for playerID in self.joinMemberIDList:
+ serverGroupID = onlineMgr.GetOLPlayerServerGroupID(playerID)
+ if serverGroupID:
+ olDict[playerID] = serverGroupID
+ return olDict
+
+class FamilyGCZBatGroup():
+ ## 战斗分组
+
+ def __init__(self, zoneID, batType, groupNum):
+ self.zoneID = zoneID
+ self.batType = batType
+ self.groupNum = groupNum
+
+ # 城池并不一定归属于某个仙盟所以由分组自行管理
+ self.cityWallDict = {} # 城池对象信息 {cityID:FamilyGCZCityWall, ...}
+ self.__cityIDList = [] # 城池ID列表,按添加顺序的列表
+ self.__topHurtPlayerID = 0 # 本组伤害第一玩家ID
+ self.__topHurtPlayerValue = 0 # 本组伤害第一玩家伤害
+ self.inBatScenePlayerIDList = [] # 在战斗场景中的玩家ID列表 [playerID, ...]
+ return
+
+ def GetTopHurtPlayerIDValue(self):
+ ## 获取本组有效伤害第一玩家,仅算城池未被摧毁前的累计伤害
+ if self.__topHurtPlayerID and self.__topHurtPlayerValue:
+ return self.__topHurtPlayerID, self.__topHurtPlayerValue
+
+ for cityID in self.cityWallDict.keys():
+ cityWall = self.GetCityWall(cityID)
+ if not cityWall:
+ continue
+ for playerID, hurtTotal in cityWall.fighterHurtDict.items():
+ if hurtTotal > self.__topHurtPlayerValue:
+ self.__topHurtPlayerID = playerID
+
+ return self.__topHurtPlayerID, self.__topHurtPlayerValue
+ def UpdTopHurtPlayerIDValue(self, topPlayerID, topHurtValue):
+ self.__topHurtPlayerID, self.__topHurtPlayerValue = topPlayerID, topHurtValue
+ return
+
+ def GetCityIDList(self):
+ if not self.__cityIDList:
+ self.__cityIDList = self.cityWallDict.keys()
+ return self.__cityIDList
+
+ def GetCityWall(self, cityID):
+ ## 获取某个城池,可能为None
+ cityWall = None
+ if cityID in self.cityWallDict:
+ cityWall = self.cityWallDict[cityID]
+ elif False: # 不可能执行,提示代码用
+ cityWall = FamilyGCZCityWall()
+ return cityWall
+
+ def GetGroupFamilyIDList(self):
+ familyIDList = []
+ for cityID in self.GetCityIDList():
+ city = self.GetCityWall(cityID)
+ if not city:
+ continue
+ familyID = city.familyID
+ if familyID not in familyIDList:
+ familyIDList.append(familyID)
+ return familyIDList
+
+ def AddGroupFamily(self, familyID):
+ ## 将仙盟分配到该分组
+ zone = GetFamilyGCZMgr().GetActZone(self.zoneID)
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ return
+ joinFamily.batType = self.batType
+ joinFamily.groupNum = self.groupNum
+ for playerID in joinFamily.joinMemberIDList:
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if not joinMember:
+ continue
+ joinMember.batType = self.batType
+ joinMember.groupNum = self.groupNum
+
+ joinFamily.cityWall.batType = self.batType
+ joinFamily.cityWall.groupNum = self.groupNum
+ cityID = joinFamily.cityWall.cityID
+ self.cityWallDict[cityID] = joinFamily.cityWall
+ if cityID not in self.__cityIDList:
+ self.__cityIDList.append(cityID)
+ return joinFamily
+
+ def CreateCityWall(self, cityID, cityLV, guardMemIDList=None, guardNPCCount=0, isAttrLock=False):
+ '''创建自定义城池,如修罗城
+ @param cityID: 自定义城池ID
+ @param cityLV: 城池等级
+ @param guardMemIDList: 布防玩家ID列表
+ @param guardNPCCount: 布防系统NPC数量
+ 城池总属性: (布防的玩家 + 布防系统NPC)属性总和
+ '''
+ guardNPCCount = min(guardNPCCount, 100)
+ newCity = FamilyGCZCityWall(self.zoneID, cityID, cityLV)
+ newCity.batType = self.batType
+ newCity.groupNum = self.groupNum
+ newCity.ResetDefense(cityLV, guardNPCCount=guardNPCCount)
+ if isAttrLock:
+ newCity.attrLock = 1
+ self.cityWallDict[cityID] = newCity
+ if cityID not in self.__cityIDList:
+ self.__cityIDList.append(cityID)
+ return newCity
+
+ def SetPlayerInScene(self, playerID, serverGroupID):
+ if playerID in self.inBatScenePlayerIDList:
+ return
+ self.inBatScenePlayerIDList.append(playerID)
+ Sync_FamilyGCZBatSceneInfo(self.zoneID, self.batType, self.groupNum, toPlayerServerDict={playerID:serverGroupID})
+ return
+
+ def SetPlayerOutScene(self, playerID):
+ if playerID in self.inBatScenePlayerIDList:
+ self.inBatScenePlayerIDList.remove(playerID)
+ return
+
+class FamilyGCZZone():
+ ## 攻城战分区
+
+ def __init__(self, zoneID):
+ self.zoneID = zoneID
+ self.joinFamilyCnt = 0
+ self.lockFamilyIDList = [] # 锁定的仙盟ID列表
+ self.joinFamilyDict = {} # 参与仙盟对象信息 {familyID:FamilyGCZFamily, ...}
+ self.joinMemberDict = {} # 参与玩家对象信息 {playerID:FamilyGCZMember, ...}
+ self.roundGroupDict = {} # 当前轮次分组信息 {batType:{groupNum:FamilyGCZBatGroup, ...}, ...}
+ self.familyGuessDict = {} # 仙盟竞猜热度信息 {familyID:value, ...}
+ self.playerGuessDict = {} # 玩家竞猜记录 {playerID:[familyID, ...], ...}
+
+ self.statGuessRetDict = None # 统计竞猜结果 {awardID:[猜中玩家ID, ...], ...}
+ self.guessFinalFamilyIDList = [] # 竞猜最终排名仙盟ID列表
+ self.inBatScenePlayerIDDict = {} # 在战斗场景中的玩家ID {(batType, groupNum):[playerID, ...], ...}
+ self.inBatCityPlayerIDDict = {} # 在战斗城池中的玩家ID {(batType, groupNum, cityID):[playerID, ...], ...}
+ return
+
+ def OnRoundReset(self):
+ ## 分区轮次重置
+ self.roundGroupDict = {}
+ self.inBatScenePlayerIDDict = {}
+ self.inBatCityPlayerIDDict = {}
+ for familyID in self.lockFamilyIDList:
+ joinFamily = self.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ continue
+ joinFamily.OnRoundFamilyReset()
+ return
+
+ def OnRoundFightStart(self):
+ ## 分区轮次开始
+ for familyID in self.lockFamilyIDList:
+ joinFamily = self.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ continue
+ joinFamily.OnRoundFamilyFightStart()
+ return
+
+ def AddBatGroup(self, batType, groupNum):
+ if batType not in self.roundGroupDict:
+ self.roundGroupDict[batType] = {}
+ groupNumDict = self.roundGroupDict[batType]
+ batGroup = FamilyGCZBatGroup(self.zoneID, batType, groupNum)
+ groupNumDict[groupNum] = batGroup
+ return batGroup
+
+ def GetBatGroup(self, batType, groupNum):
+ ## 获取某个分组,可能为None
+ if batType not in self.roundGroupDict:
+ self.roundGroupDict[batType] = {}
+ groupNumDict = self.roundGroupDict[batType]
+ batGroup = groupNumDict.get(groupNum, None)
+ if batGroup == None and False: # 不可能执行,提示代码用
+ batGroup = FamilyGCZBatGroup()
+ return batGroup
+
+ ## 获取本分区参与的仙盟ID列表,按锁定顺序的
+ def GetZoneLockFamilyIDList(self): return self.lockFamilyIDList
+ def GetZoneJoinFamily(self, familyID):
+ ## 获取本分区参与的仙盟,可能为None
+ joinFamily = None
+ if familyID in self.joinFamilyDict:
+ joinFamily = self.joinFamilyDict[familyID]
+ elif False: # 不可能执行,提示代码用
+ joinFamily = FamilyGCZFamily()
+ return joinFamily
+
+ def AddZoneJoinFamily(self, familyID):
+ ## 添加参与仙盟
+ joinFamily = None
+ if familyID in self.joinFamilyDict:
+ joinFamily = self.joinFamilyDict[familyID]
+ else:
+ joinFamily = FamilyGCZFamily(self.zoneID, familyID)
+ self.joinFamilyDict[familyID] = joinFamily
+ if familyID not in self.lockFamilyIDList:
+ self.lockFamilyIDList.append(familyID)
+ GetFamilyGCZMgr().SetFamilyIDZoneID(familyID, self.zoneID)
+ return joinFamily
+
+ def GetZoneJoinMember(self, playerID):
+ ## 获取本分区参与的玩家,可能为None
+ joinMember = None
+ if playerID in self.joinMemberDict:
+ joinMember = self.joinMemberDict[playerID]
+ elif False: # 不可能执行,提示代码用
+ joinMember = FamilyGCZMember()
+ return joinMember
+
+ def AddZoneJoinMember(self, playerID, familyID):
+ ## 添加参与成员
+ joinMember = None
+ if playerID in self.joinMemberDict:
+ joinMember = self.joinMemberDict[playerID]
+ else:
+ joinMember = FamilyGCZMember(self.zoneID, familyID, playerID)
+ self.joinMemberDict[playerID] = joinMember
+ GetFamilyGCZMgr().SetPlayerIDZoneID(playerID, self.zoneID)
+ return joinMember
+
+ def GetOLServerGroupIDDict(self):
+ ## 获取本分区在线参与成员信息
+ olDict = {}
+ for joinFamily in self.joinFamilyDict.values():
+ olDict.update(joinFamily.GetOLMemServerGroupIDDict())
+ return olDict
+
+ def SetPlayerInBatScene(self, playerID, batType=0, groupNum=0, serverGroupID=0):
+ ## 设置玩家在某个战斗场景,参数默认0为退出
+ for bType, groupDict in self.roundGroupDict.items():
+ for gNum in groupDict.keys():
+ batGroup = self.GetBatGroup(bType, gNum)
+ if not batGroup:
+ continue
+ if batType != bType or groupNum != gNum:
+ batGroup.SetPlayerOutScene(playerID)
+ else:
+ batGroup.SetPlayerInScene(playerID, serverGroupID)
+ return
+
+ def SetPlayerInBatCity(self, playerID, batType=0, groupNum=0, cityID=0, serverGroupID=0):
+ ## 设置玩家在某个战斗城池,参数默认0为退出
+ for bType, groupDict in self.roundGroupDict.items():
+ for gNum in groupDict.keys():
+ batGroup = self.GetBatGroup(bType, gNum)
+ if not batGroup:
+ continue
+ for cID in batGroup.GetCityIDList():
+ cityWall = batGroup.GetCityWall(cID)
+ if not cityWall:
+ continue
+ if batType != bType or groupNum != gNum or cityID != cID:
+ cityWall.SetPlayerOutCity(playerID)
+ else:
+ cityWall.SetPlayerInCity(playerID, serverGroupID)
+ return
+
+class FamilyGCZMgr():
+ ## 仙盟攻城战管理
+
+ def __init__(self):
+ self.zoneDict = {} # 分区信息 {zone:FamilyGCZZone, ...}
+ self.familyIDZoneIDDict = {} # 仙盟ID所在分区 {familyID:zoneID, ...}
+ self.playerIDZoneIDDict = {} # 玩家ID所在分区 {playerID:zoneID, ...}
+ return
+
+ def SetFamilyIDZoneID(self, familyID, zoneID):
+ self.familyIDZoneIDDict[familyID] = zoneID
+ return
+
+ def SetPlayerIDZoneID(self, playerID, zoneID):
+ self.playerIDZoneIDDict[playerID] = zoneID
+ return
+
+ def ClearGCZZone(self, zoneID):
+ self.zoneDict.pop(zoneID, None)
+ for familyID, fZoneID in self.familyIDZoneIDDict.items():
+ if fZoneID == zoneID:
+ self.familyIDZoneIDDict.pop(familyID)
+ for playerID, pZoneID in self.playerIDZoneIDDict.items():
+ if pZoneID == zoneID:
+ self.playerIDZoneIDDict.pop(playerID)
+ return
+
+ def GetActZone(self, zoneID):
+ ## 获取分区管理
+ zone = None
+ if zoneID in self.zoneDict:
+ zone = self.zoneDict[zoneID]
+ else:
+ zone = FamilyGCZZone(zoneID)
+ self.zoneDict[zoneID] = zone
+ return zone
+
+ def GetJoinFamily(self, familyID):
+ ## 直接获取某个参与仙盟信息
+ joinFamily = None
+ if familyID in self.familyIDZoneIDDict:
+ zoneID = self.familyIDZoneIDDict[familyID]
+ zone = self.GetActZone(zoneID)
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ elif False: # 不可能执行,提示代码用
+ joinFamily = FamilyGCZFamily()
+ return joinFamily
+
+ def GetJoinFamilyByPlayerID(self, playerID):
+ ## 直接获取某个参与仙盟信息 - 根据成员玩家ID
+ joinFamily = None
+ if playerID in self.playerIDZoneIDDict:
+ zoneID = self.playerIDZoneIDDict[playerID]
+ zone = self.GetActZone(zoneID)
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if joinMember:
+ joinFamily = zone.GetZoneJoinFamily(joinMember.familyID)
+ elif False: # 不可能执行,提示代码用
+ joinFamily = FamilyGCZFamily()
+ return joinFamily
+
+ def GetJoinMember(self, playerID):
+ ## 直接获取某个参与玩家信息
+ joinMember = None
+ if playerID in self.playerIDZoneIDDict:
+ zoneID = self.playerIDZoneIDDict[playerID]
+ zone = self.GetActZone(zoneID)
+ joinMember = zone.GetZoneJoinMember(playerID)
+ elif False: # 不可能执行,提示代码用
+ joinMember = FamilyGCZMember()
+ return joinMember
+
+def GetFamilyGCZMgr():
+ mgr = PyGameData.g_familyGCZMgr
+ if not mgr:
+ mgr = FamilyGCZMgr()
+ PyGameData.g_familyGCZMgr = mgr
+ return mgr
+
+def OnLoadPyData():
+
+ if not GameWorld.IsCrossServer():
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+
+ recDataDict = gameRecMgr.GetGameRecDataDict(ShareDefine.Def_GameRecType_FamilyGCZMgr)
+ for zoneID, zoneRecDataList in recDataDict.items():
+ if not zoneRecDataList:
+ continue
+ zoneRecData = zoneRecDataList[0] # 分区管理,每个分区只要一条记录
+ joinFamilyCnt = zoneRecData.GetValue1()
+ zoneDataDict = zoneRecData.GetUserDataDict()
+
+ gczMgr.ClearGCZZone(zoneID)
+
+ zone = gczMgr.GetActZone(zoneID)
+ zone.joinFamilyCnt = joinFamilyCnt
+ zone.lockFamilyIDList = zoneDataDict.get("lockFamilyIDList", [])
+ zone.familyGuessDict = zoneDataDict.get("familyGuessDict", {})
+ zone.playerGuessDict = zoneDataDict.get("playerGuessDict", {})
+ GameWorld.Log("加载分区记录! zoneID=%s,joinFamilyCnt=%s,lockCnt=%s,%s" % (zoneID, zone.joinFamilyCnt, len(zone.lockFamilyIDList), zone.lockFamilyIDList))
+
+ familyRecList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_FamilyGCZJoinFamily, zoneID)
+ for fNum, familyRecData in enumerate(familyRecList, 1):
+ familyID = familyRecData.GetValue1()
+ batType = familyRecData.GetValue2()
+ groupNum = familyRecData.GetValue3()
+ campLV = familyRecData.GetValue4()
+ campExp = familyRecData.GetValue5()
+ score = familyRecData.GetValue6()
+ familyDataDict = familyRecData.GetUserDataDict()
+
+ joinFamily = zone.AddZoneJoinFamily(familyID)
+ joinFamily.batType = batType
+ joinFamily.groupNum = groupNum
+ joinFamily.campLV = campLV
+ joinFamily.campExp = campExp
+ joinFamily.score = score
+ joinFamily.familyName = familyDataDict.get("familyName", "")
+ joinFamily.leaderID = familyDataDict.get("leaderID", 0)
+ joinFamily.leaderName = familyDataDict.get("leaderName", "")
+ joinFamily.lv = familyDataDict.get("lv", 0)
+ joinFamily.emblemID = familyDataDict.get("emblemID", 0)
+ joinFamily.serverID = familyDataDict.get("serverID", 0)
+ joinFamily.fightPowerTotal = familyDataDict.get("fightPowerTotal", 0)
+ joinFamily.joinMemberIDList = familyDataDict.get("joinMemberIDList", [])
+ joinFamily.memAddCampExpInfo = familyDataDict.get("memAddCampExpInfo", {})
+
+ GameWorld.Log(" 加载分区仙盟 zoneID=%s,%s,familyID=%s,campLV=%s-%s,score=%s,,memAddCampExpInfo=%s"
+ % (zoneID, fNum, familyID, joinFamily.campLV, joinFamily.campExp, joinFamily.score, joinFamily.memAddCampExpInfo))
+
+ memberRecList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_FamilyGCZJoinMember, zoneID)
+ for pNum, memberRecData in enumerate(memberRecList, 1):
+ playerID = memberRecData.GetValue1()
+ familyID = memberRecData.GetValue2()
+ batType = memberRecData.GetValue3()
+ groupNum = memberRecData.GetValue4()
+ fmLV = memberRecData.GetValue5()
+ playerDataDict = memberRecData.GetUserDataDict()
+
+ joinMember = zone.AddZoneJoinMember(playerID, familyID)
+ joinMember.batType = batType
+ joinMember.groupNum = groupNum
+ joinMember.fmLV = fmLV
+ joinMember.playerName = playerDataDict.get("playerName", "")
+ joinMember.job = playerDataDict.get("job", 1)
+ joinMember.realmLV = playerDataDict.get("realmLV", 1)
+ joinMember.face = playerDataDict.get("face", 0)
+ joinMember.facePic = playerDataDict.get("facePic", 0)
+ joinMember.lv = playerDataDict.get("lv", 1)
+ joinMember.totalHurtValue = playerDataDict.get("totalHurtValue", 0)
+ joinMember.awardState = playerDataDict.get("awardState", 0)
+ joinMember.hp = playerDataDict.get("hp", 0)
+ joinMember.hpMax = playerDataDict.get("hpMax", 0)
+ joinMember.hpBase = playerDataDict.get("hpBase", 0)
+ joinMember.fightPower = playerDataDict.get("fightPower", 0)
+
+ GameWorld.Log(" 加载分区成员 zoneID=%s,familyID=%s,%s,playerID=%s,hp=%s/%s,totalHurtValue=%s"
+ % (zoneID, familyID, pNum, playerID, joinMember.hp, joinMember.hpMax, joinMember.totalHurtValue))
+
+ cityWallRecList = gameRecMgr.GetGameRecDataList(ShareDefine.Def_GameRecType_FamilyGCZCityWall, zoneID)
+ for cNum, cityRecData in enumerate(cityWallRecList, 1):
+ cityID = cityRecData.GetValue1()
+ batType = cityRecData.GetValue2()
+ groupNum = cityRecData.GetValue3()
+ cityLV = cityRecData.GetValue4()
+ familyID = cityRecData.GetValue5()
+ attrLock = cityRecData.GetValue6()
+ cityDataDict = cityRecData.GetUserDataDict()
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ batGroup = zone.AddBatGroup(batType, groupNum)
+ if not batGroup:
+ continue
+ if familyID:
+ batGroup.AddGroupFamily(familyID)
+ else:
+ batGroup.CreateCityWall(cityID, cityLV)
+
+ city = batGroup.GetCityWall(cityID)
+ if not city:
+ continue
+
+ city.cityLV = cityLV
+ city.attrLock = attrLock
+ city.guardMemIDList = cityDataDict.get("guardMemIDList", [])
+ city.fighterIDList = cityDataDict.get("fighterIDList", [])
+ city.guardNPCCount = cityDataDict.get("guardNPCCount", 0)
+ city.hp = cityDataDict.get("hp", 0)
+ city.hpMax = cityDataDict.get("hpMax", 0)
+ city.hpBase = cityDataDict.get("hpBase", 0)
+ city.fightPowerTotal = cityDataDict.get("fightPowerTotal", 0)
+ city.atkReportDict = cityDataDict.get("atkReportDict", {})
+ city.fighterHurtDict = cityDataDict.get("fighterHurtDict", {})
+
+ GameWorld.Log(" 加载分区城池 zoneID=%s,batType=%s,batType=%s,%s,cityID=%s,familyID=%s,hp=%s/%s,fighterIDList=%s,%s"
+ % (zoneID, batType, groupNum, cNum, cityID, city.familyID, city.hp, city.hpMax, len(city.fighterIDList), city.fighterIDList))
+
+ return
+
+def OnSavePyData():
+ if not GameWorld.IsCrossServer():
+ return
+
+ gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+ gameRecMgr.DelGameRecDataByType(ShareDefine.Def_GameRecType_FamilyGCZMgr)
+ gameRecMgr.DelGameRecDataByType(ShareDefine.Def_GameRecType_FamilyGCZJoinFamily)
+ gameRecMgr.DelGameRecDataByType(ShareDefine.Def_GameRecType_FamilyGCZJoinMember)
+ gameRecMgr.DelGameRecDataByType(ShareDefine.Def_GameRecType_FamilyGCZCityWall)
+
+ gczMgr = GetFamilyGCZMgr()
+ zoneIDList = gczMgr.zoneDict.keys()
+ GameWorld.Log("保存仙盟攻城战分区记录! zoneIDList=%s" % zoneIDList)
+ for zoneID in zoneIDList:
+ if not zoneID:
+ continue
+ zone = gczMgr.GetActZone(zoneID)
+ zoneRecData = gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_FamilyGCZMgr, zoneID)
+ zoneRecData.SetValue1(zone.joinFamilyCnt)
+ lockFamilyIDList = zone.GetZoneLockFamilyIDList()
+ zoneData = {"lockFamilyIDList":lockFamilyIDList, "familyGuessDict":zone.familyGuessDict, "playerGuessDict":zone.playerGuessDict}
+ zoneRecData.SetUserData(zoneData)
+
+ GameWorld.Log("----- zoneID=%s,joinFamilyCnt=%s,lockFamilyIDList=%s,%s" % (zoneID, zone.joinFamilyCnt, len(lockFamilyIDList), lockFamilyIDList))
+
+ for batType, groupDict in zone.roundGroupDict.items():
+ for groupNum in groupDict.keys():
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ continue
+ cityIDList = batGroup.GetCityIDList()
+ for cNum, cityID in enumerate(cityIDList, 1):
+ city = batGroup.GetCityWall(cityID)
+ if not city:
+ continue
+ cityRecData = gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_FamilyGCZCityWall, zoneID)
+ cityRecData.SetValue1(cityID)
+ cityRecData.SetValue2(city.batType)
+ cityRecData.SetValue3(city.groupNum)
+ cityRecData.SetValue4(city.cityLV)
+ cityRecData.SetValue5(city.familyID)
+ cityRecData.SetValue6(city.attrLock)
+ cityData = {"guardMemIDList":city.guardMemIDList, "fighterIDList":city.fighterIDList, "guardNPCCount":city.guardNPCCount,
+ "hp":city.hp, "hpMax":city.hpMax, "hpBase":city.hpBase, "fightPowerTotal":city.fightPowerTotal,
+ "atkReportDict":city.atkReportDict, "defReportDict":city.defReportDict, "fighterHurtDict":city.fighterHurtDict}
+ cityRecData.SetUserData(cityData)
+ GameWorld.Log(" 保存分区城池 zoneID=%s,batType=%s,groupNum=%s,%s,cityID=%s,familyID=%s,attrLock=%s,hp=%s/%s,fighterIDList=%s,%s"
+ % (zoneID, batType, groupNum, cNum, cityID, city.familyID, city.attrLock, city.hp, city.hpMax, len(city.fighterIDList), city.fighterIDList))
+
+ for fNum, familyID in enumerate(lockFamilyIDList, 1):
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ continue
+ familyRecData = gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_FamilyGCZJoinFamily, zoneID)
+ familyRecData.SetValue1(familyID)
+ familyRecData.SetValue2(joinFamily.batType)
+ familyRecData.SetValue3(joinFamily.groupNum)
+ familyRecData.SetValue4(joinFamily.campLV)
+ familyRecData.SetValue5(joinFamily.campExp)
+ familyRecData.SetValue6(joinFamily.score)
+
+ familyData = {"familyName":joinFamily.familyName, "leaderID":joinFamily.leaderID, "leaderName":joinFamily.leaderName,
+ "lv":joinFamily.lv, "emblemID":joinFamily.emblemID, "serverID":joinFamily.serverID, "fightPowerTotal":joinFamily.fightPowerTotal,
+ "joinMemberIDList":joinFamily.joinMemberIDList, "memAddCampExpInfo":joinFamily.memAddCampExpInfo
+ }
+ familyRecData.SetUserData(familyData)
+ GameWorld.Log(" 保存分区仙盟 zoneID=%s,%s,familyID=%s,campLV=%s-%s,score=%s," % (zoneID, fNum, familyID, joinFamily.campLV, joinFamily.campExp, joinFamily.score))
+
+ for pNum, playerID in enumerate(joinFamily.joinMemberIDList, 1):
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if not joinMember:
+ continue
+ memberRecData = gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_FamilyGCZJoinMember, zoneID)
+ memberRecData.SetValue1(playerID)
+ memberRecData.SetValue2(familyID)
+ memberRecData.SetValue3(joinMember.batType)
+ memberRecData.SetValue4(joinMember.groupNum)
+ memberRecData.SetValue5(joinMember.fmLV)
+
+ memberData = {"playerName":joinMember.playerName, "job":joinMember.job, "realmLV":joinMember.realmLV,
+ "face":joinMember.face, "facePic":joinMember.facePic, "lv":joinMember.lv, "totalHurtValue":joinMember.totalHurtValue,
+ "awardState":joinMember.awardState,
+ "hp":joinMember.hp, "hpMax":joinMember.hpMax, "hpBase":joinMember.hpBase, "fightPower":joinMember.fightPower}
+ memberRecData.SetUserData(memberData)
+ GameWorld.Log(" 保存分区成员 zoneID=%s,familyID=%s,%s,playerID=%s,hp=%s/%s,totalHurtValue=%s"
+ % (zoneID, familyID, pNum, playerID, joinMember.hp, joinMember.hpMax, joinMember.totalHurtValue))
+
+ return
+
+def OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID):
+ ## 本服登录时跨服服务器需要处理的逻辑
+
+ zoneID, familyID = GetPlayerActJoinInfo(playerID)
+ if not zoneID:
+ return
+
+ Sync_FamilyGCZActInfo(zoneID, playerID)
+ Sync_FamilyGCZBatGroupInfo(zoneID, {playerID:serverGroupID})
+ Sync_FamilyGCZCampInfo(zoneID, familyID, {playerID:serverGroupID})
+ Sync_FamilyGCZGuessInfo(zoneID, playerID, playerID)
+ return
+
+def GetRoundState(state):
+ ## 获取轮次、状态信息
+ if state < 10 or state == FamilyGCZState_Award:
+ return 0, state
+ return state / 10, state % 10
+
+def OnCrossActIDChange(cfgID, zoneID, ipyData, state):
+ ## 跨服活动ID变更
+ DoMailReissueAward(zoneID, ipyData)
+ DelFamilyGCZZone(zoneID)
+ return
+
+def DelFamilyGCZZone(zoneID):
+ # 清空活动相关数据
+ gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+ gameRecMgr.DelGameRecDataByTypeID(ShareDefine.Def_GameRecType_FamilyGCZMgr, zoneID)
+ gameRecMgr.DelGameRecDataByTypeID(ShareDefine.Def_GameRecType_FamilyGCZJoinFamily, zoneID)
+ gameRecMgr.DelGameRecDataByTypeID(ShareDefine.Def_GameRecType_FamilyGCZJoinMember, zoneID)
+ gameRecMgr.DelGameRecDataByTypeID(ShareDefine.Def_GameRecType_FamilyGCZCityWall, zoneID)
+
+ # 清空活动相关榜单
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billboardMgr.ClearBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
+ billboardMgr.ClearBillboard(ShareDefine.Def_CBT_FamilyGCZPlayerHurt, zoneID)
+ billboardMgr.ClearBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, zoneID)
+
+ GetFamilyGCZMgr().ClearGCZZone(zoneID)
+ return
+
+def OnCrossActStateChange(ipyData, actID, dbState, state):
+ ## 跨服活动状态变更
+
+ zoneID = ipyData.GetZoneID()
+ if CrossActionControl.IsActFlowStateError(ShareDefine.CrossActName_FamilyGCZ, zoneID):
+ Sync_FamilyGCZActInfo(zoneID)
+ return
+
+ if state == FamilyGCZState_Publicity:
+ Sync_FamilyGCZActInfo(zoneID)
+ return
+
+ if state == FamilyGCZState_Award:
+ DoStartAward(zoneID)
+ return
+
+ curRound, roundState = GetRoundState(state)
+ if curRound > 0:
+ # 分组
+ if roundState == FamilyGCZRoundState_Group:
+ if curRound == 1: # 第一轮分组前锁定名单
+ DoLockActFamily(actID, ipyData)
+ DoRoundGroup(curRound, zoneID, ipyData.GetJoinFamilyCnt())
+
+ # 开始战斗
+ elif roundState == FamilyGCZRoundState_Fight:
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ zone.OnRoundFightStart()
+
+ # 结算
+ elif roundState == FamilyGCZRoundState_Over:
+ DoRoundOver(curRound, zoneID)
+
+ else:
+ pass
+
+ # 竞猜
+ DoGenerateGuess(zoneID, state)
+ return
+
+def GetPlayerActJoinInfo(playerID):
+ '''获取玩家参与的活动信息,如果返回的有分区ID及活动ID,代表一定是活动中的
+ 必须是zoneID、actID都一直才能视为同一个活动,且actState非0
+ @return: [zoneID, familyID]
+ '''
+
+ zoneID, familyID = 0, 0
+ defaultRet = (zoneID, familyID)
+
+ gczMgr = GetFamilyGCZMgr()
+ joinMember = gczMgr.GetJoinMember(playerID)
+ # 有在参赛资格名单里
+ if joinMember:
+ zoneID, familyID = joinMember.zoneID, joinMember.familyID
+ return zoneID, familyID
+
+ # 注: 公示期期间也是没有在资格里的,没有参与资格的,暂时都视为普通成员
+ # 没有在活动中参与资格里的,再按所在服ID判断资格: 当前所在盟服ID > 玩家所在服ID
+ #
+ # 参与资格的相关跨服活动本身具有一定的数据延迟容错空间,逻辑统一由跨服服务器处理
+ # 故没有在锁定资格里的玩家可能存在以下情况
+ # 1. 没有跨服查看缓存,一般为未达到跨服条件的号或已流失7天的号,可视为不参与活动
+ # 2. 玩家缓存中的仙盟ID在跨服服务器还在,但子服已经解散了,一样还是用的缓存中的仙盟ID,因为活动本身具有一定的时间差容错空间,所以不影响
+ cacheDict = PlayerViewCache.GetCachePropDataDict(PlayerViewCache.FindViewCache(playerID))
+ if not cacheDict:
+ return defaultRet
+
+ joinServerID = 0
+ familyIDNow = cacheDict.get("FamilyID", 0)
+ if familyIDNow:
+ curFamily = GameWorld.GetFamilyManager().FindFamily(familyIDNow)
+ if curFamily:
+ familyID = familyIDNow
+ joinServerID = curFamily.GetServerID()
+
+ if not joinServerID:
+ joinServerID = GameWorld.GetAccIDServerID(cacheDict.get("AccID", ""))
+
+ actInfo = CrossActionControl.GetCrossActInfoByServerGroupID(ShareDefine.CrossActName_FamilyGCZ, joinServerID)
+ if not actInfo or not actInfo.get(ShareDefine.ActKey_State):
+ # 非活动中直接返回
+ return defaultRet
+ ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)
+ if ipyDataInfo:
+ zoneID = ipyDataInfo.get("ZoneID", 0)
+ return zoneID, familyID
+
+def OnCrossJoinFamilyMemberUpd(curFamily, updMemIDList):
+ ## 本活动只更新参与活动成员战力,换仙盟的成员不更新了,以最后一次更新为准
+ if not curFamily:
+ return
+
+ familyID = curFamily.GetID()
+ gczMgr = GetFamilyGCZMgr()
+ joinFamily = gczMgr.GetJoinFamily(familyID)
+ if not joinFamily:
+ # 非锁定的仙盟不更新,可能没有参与资格或未锁定
+ return
+ zoneID = joinFamily.zoneID
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ # 非活动中不更新
+ return
+ state = actInfo.get(ShareDefine.ActKey_State)
+ if not state:
+ return
+ curRound, roundState = GetRoundState(state)
+ GameWorld.DebugLog("更新仙盟攻城战仙盟成员: familyID=%s,zoneID=%s,state=%s,curRound=%s,roundState=%s"
+ % (familyID, zoneID, state, curRound, roundState))
+
+ zone = gczMgr.GetActZone(zoneID)
+ for playerID in updMemIDList:
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if not joinMember:
+ continue
+ curMember = curFamily.FindMember(playerID)
+ if not curMember:
+ continue
+ joinMember.fightPower = max(joinMember.fightPower, PlayerFamily.GetMemberFightPower(curMember)) # 以较大战力为准
+ GameWorld.DebugLog(" playerID=%s,joinFamilyID=%s,updFightPower=%s" % (playerID, joinMember.familyID, joinMember.fightPower))
+
+ return
+
+def DoLockActFamily(actID, ipyData):
+ ## 锁定参与仙盟名单
+
+ zoneID = ipyData.GetZoneID()
+ serverIDList = ipyData.GetServerIDRangeList()
+ joinFamilyCnt = ipyData.GetJoinFamilyCnt()
+ GameWorld.Log("仙盟攻城战锁定参与仙盟名单: zoneID=%s,serverIDList=%s,joinFamilyCnt=%s" % (zoneID, serverIDList, joinFamilyCnt))
+ sortFamilyList = PlayerFamily.SortCrossFamily(serverIDList, joinFamilyCnt)[0]
+
+ DelFamilyGCZZone(zoneID)
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ zone.joinFamilyCnt = joinFamilyCnt
+
+ for num, family in enumerate(sortFamilyList, 1):
+ familyID = family.GetID()
+ serverID = family.GetServerID()
+
+ joinFamily = zone.AddZoneJoinFamily(familyID)
+ familyBaseInfo = PlayerFamily.GetCrossFamilyBaseInfo(family)
+ joinFamily.familyName = familyBaseInfo.get("Name", "")
+ joinFamily.lv = familyBaseInfo.get("LV", 0)
+ joinFamily.leaderID = familyBaseInfo.get("LeaderID", 0)
+ joinFamily.leaderName = familyBaseInfo.get("LeaderName", "")
+ joinFamily.emblemID = familyBaseInfo.get("EmblemID", 0)
+ joinFamily.serverID = familyBaseInfo.get("ServerID", 0)
+ joinFamily.fightPowerTotal = familyBaseInfo.get("FightPower", 0)
+ joinFamily.campLV = 1
+ fightPowerTotal = joinFamily.fightPowerTotal
+
+ for i in range(0, family.GetCount()):
+ member = family.GetAt(i)
+ playerID = member.GetPlayerID()
+ if not playerID:
+ continue
+
+ memBaseInfo = PlayerFamily.GetCrossFamilyMemInfo(member)
+ joinMember = zone.AddZoneJoinMember(playerID, familyID)
+ joinMember.playerName = memBaseInfo.get("Name", "")
+ joinMember.lv = memBaseInfo.get("LV", 0)
+ joinMember.job = memBaseInfo.get("Job", 0)
+ joinMember.realmLV = memBaseInfo.get("OfficialRank", 0)
+ joinMember.face = memBaseInfo.get("Face", 0)
+ joinMember.facePic = memBaseInfo.get("FacePic", 0)
+ joinMember.fightPower = memBaseInfo.get("FightPower", 0)
+ joinMember.fmLV = memBaseInfo.get("FamilyLV", 0)
+
+ joinFamily.joinMemberIDList.append(playerID)
+
+ GameWorld.Log(" %s,familyID=%s,serverID=%s,fightPowerTotal=%s,memCnt=%s,%s"
+ % (num, familyID, serverID, fightPowerTotal, len(joinFamily.joinMemberIDList), joinFamily.joinMemberIDList))
+
+ Sync_FamilyGCZActInfo(zoneID)
+ return
+
+def DoRoundGroup(curRound, zoneID, joinFamilyCnt):
+ ## 执行轮次分组
+
+ GameWorld.Log("========== 仙盟攻城战轮次分组: zoneID=%s,curRound=%s,joinFamilyCnt=%s" % (zoneID, curRound, joinFamilyCnt))
+ # 参与仙盟数对应分组及晋级规则 {参与仙盟数:{轮次:{战场类型:[组数, 前x名晋级, x名开始降级], ...}, ...}, ...}
+ FamilyGCZGroupSet = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGroupSet", 1, {})
+ if joinFamilyCnt not in FamilyGCZGroupSet:
+ return
+ roundSetDict = FamilyGCZGroupSet[joinFamilyCnt]
+ if curRound not in roundSetDict:
+ return
+ batTypeDict = roundSetDict[curRound]
+
+ groupValue1 = zoneID
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+
+ # 先处理上一轮晋级、保级、降级,需在重置前处理
+ nextBatTypeFamilyInfo = {} # 下一轮战场仙盟ID分配信息 {batType:[familyID, ...], ....}
+ preRound = curRound - 1
+ preBatTypeDict = roundSetDict.get(preRound, {})
+ for batType in BatTypeList: # 按战场类型顺序遍历处理
+ if batType not in zone.roundGroupDict:
+ continue
+ groupDict = zone.roundGroupDict[batType]
+ groupNumList = groupDict.keys()
+ groupNumList.sort()
+ preRoundSet = preBatTypeDict.get(batType, [0, 0])
+ upRank = preRoundSet[1] # 前x晋级
+ downRank = preRoundSet[2] if len(preRoundSet) > 2 else 0 # 大于等于x名降级,为0时不降级
+ GameWorld.Log("上轮战场类型分组: preRound=%s,batType=%s,upRank=%s,downRank=%s,%s" % (preRound, batType, upRank, downRank, groupNumList))
+ for groupNum in groupNumList:
+ groupValue2 = GetRoundHurtGroupID(batType, groupNum)
+ billboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, groupValue1, groupValue2)
+ billboardObj.SortData()
+ upFamilyIDList, keepFamilyIDList, downFamilyIDList = [], [], []
+ for bIndex in range(billboardObj.GetCount()):
+ billData = billboardObj.At(bIndex)
+ familyID = billData.ID
+ rank = bIndex + 1
+ if rank <= upRank:
+ nextBatType = min(BatType_High, batType + 1)
+ upFamilyIDList.append(familyID)
+ elif downRank and rank >= downRank:
+ nextBatType = max(BatType_Junior, batType - 1)
+ downFamilyIDList.append(familyID)
+ # 除了升降级的就是保级
+ else:
+ nextBatType = batType
+ keepFamilyIDList.append(familyID)
+
+ if nextBatType not in nextBatTypeFamilyInfo:
+ nextBatTypeFamilyInfo[nextBatType] = []
+ familyIDList = nextBatTypeFamilyInfo[nextBatType]
+ if familyID not in familyIDList:
+ familyIDList.append(familyID)
+ GameWorld.Log(" 升保降级zoneID=%s,batType=%s,groupNum=%s,up:%s,keep:%s,down:%s,%s"
+ % (zoneID, batType, groupNum, upFamilyIDList, keepFamilyIDList, downFamilyIDList, nextBatTypeFamilyInfo))
+
+ #每轮重新分组时,重置该分区下的轮次伤害相关榜单
+ billboardMgr.ClearBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, groupValue1)
+ zone.OnRoundReset()
+
+ for batType in BatTypeList: # 按战场类型顺序遍历处理
+ if batType not in batTypeDict:
+ # 本轮不需要此战场类型分组
+ continue
+ groupCnt = batTypeDict[batType][0] # 本轮该战场类型分组
+ if not groupCnt:
+ GameWorld.Log("本轮战场不需要分组: zoneID=%s,curRound=%s,batType=%s" % (zoneID, curRound, batType))
+ continue
+
+ batFamilyIDList = [] # 该战场的仙盟ID列表
+ if curRound == 1:
+ # 首轮分组默认取锁定名单
+ batFamilyIDList = zone.GetZoneLockFamilyIDList()
+ GameWorld.Log("首轮战场分组直接取分区锁定仙盟名单: zoneID=%s,curRound=%s,batType=%s,%s,%s" % (zoneID, curRound, batType, len(batFamilyIDList), batFamilyIDList))
+
+ # 上一轮该战场类型有比赛的
+ elif batType in nextBatTypeFamilyInfo:
+ batFamilyIDList = nextBatTypeFamilyInfo[batType]
+ GameWorld.Log("非首轮分组直接取上轮晋保降仙盟名单: zoneID=%s,curRound=%s,batType=%s,%s,%s" % (zoneID, curRound, batType, len(batFamilyIDList), batFamilyIDList))
+
+ else:
+ GameWorld.ErrLog("本轮分组可能没有仙盟名单: zoneID=%s,curRound=%s,batType=%s,%s,%s" % (zoneID, curRound, batType, len(batFamilyIDList), batFamilyIDList))
+
+ # 生成空分组,确保即使没有仙盟也有对应分组
+ for groupNum in range(1, 1 + groupCnt):
+ zone.AddBatGroup(batType, groupNum)
+
+ # 先按分组规则排序
+ groupFamilyDict = {}
+ groupFamilySortList = []
+ for familyID in batFamilyIDList:
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ continue
+ groupFamilySortList.append(joinFamily)
+ groupFamilyDict[familyID] = [joinFamily.fightPowerTotal, joinFamily.score]
+
+ # 先按总战力倒序,可扩展积分等
+ groupFamilySortList.sort(key=lambda f: (f.fightPowerTotal, f.score), reverse=True)
+ groupFamilyIDSortList = [f.familyID for f in groupFamilySortList]
+
+ GameWorld.Log("开始分组按排序后的顺序循环插入每组! 仙盟数:%s, %s, %s" % (len(groupFamilyIDSortList), groupFamilyIDSortList, groupFamilyDict))
+
+ groupNum = 0
+ for familyID in groupFamilyIDSortList:
+ groupNum += 1
+ if groupNum > groupCnt:
+ groupNum = 1
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ GameWorld.ErrLog("仙盟分组时战斗分组不存在! zoneID=%s,batType=%s,groupNum=%s,familyID=%s" % (zoneID, batType, groupNum, familyID))
+ continue
+ joinFamily = batGroup.AddGroupFamily(familyID)
+ if not joinFamily:
+ GameWorld.ErrLog("仙盟分配到战斗分组失败! zoneID=%s,batType=%s,groupNum=%s,familyID=%s" % (zoneID, batType, groupNum, familyID))
+ continue
+ UndFamilyRoundHurtBillboard(joinFamily)
+ GameWorld.Log(" 仙盟ID分组: zoneID=%s,curRound=%s,batType=%s,groupNum=%s,familyID=%s,%s" % (zoneID, curRound, batType, groupNum, familyID, groupFamilyDict[familyID]))
+
+ Sync_FamilyGCZBatGroupInfo(zoneID)
+ return
+
+def UndFamilyRoundHurtBillboard(joinFamily):
+ ## 更新仙盟轮次伤害榜单
+ if not joinFamily:
+ return
+ dataID = joinFamily.familyID
+ name1 = joinFamily.familyName
+ id2 = joinFamily.leaderID
+ name2 = joinFamily.leaderName
+ type2, value1, value2 = 0, 0, 0
+ value3 = joinFamily.emblemID
+ value5 = joinFamily.serverID
+ groupValue1 = joinFamily.zoneID
+ groupValue2 = GetRoundHurtGroupID(joinFamily.batType, joinFamily.groupNum)
+ roundTotalHurt = sum(joinFamily.cityWall.fighterHurtDict.values())
+ cmpValue = roundTotalHurt / ChConfig.Def_PerPointValue
+ cmpValue2 = roundTotalHurt % ChConfig.Def_PerPointValue
+ CrossBillboard.UpdCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, groupValue1, dataID, name1, name2, type2, value1, value2,
+ cmpValue, cmpValue2, groupValue2=groupValue2, id2=id2, autoSort=True, value3=value3, value5=value5)
+ return
+
+def DoRoundOver(curRound, zoneID):
+ ## 执行轮次结算
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ batTypeScoreInfo = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGroupSet", 2, {})
+ GameWorld.Log("========== 仙盟攻城战轮次结算: zoneID=%s,curRound=%s" % (zoneID, curRound))
+ for batType, groupDict in zone.roundGroupDict.items():
+ rankScoreInfo = batTypeScoreInfo.get(str(batType), {})
+ if not rankScoreInfo:
+ GameWorld.ErrLog("仙盟攻城战战场类型没有配置名次积分! batType=%s" % batType)
+ rankScoreDict = {int(k):v for k, v in rankScoreInfo.items()}
+ groupNumList = groupDict.keys()
+ GameWorld.Log("zoneID=%s,batType=%s,groupCnt=%s,rankScoreDict=%s" % (zoneID, batType, len(groupNumList), rankScoreDict))
+ for groupNum in groupNumList:
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ continue
+
+ groupValue2 = GetRoundHurtGroupID(batType, groupNum)
+ billboardObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, zoneID, groupValue2)
+ billboardObj.SortData()
+ GameWorld.Log("zoneID=%s,batType=%s,groupNum=%s,roundHurtFamilyCnt=%s" % (zoneID, batType, groupNum, billboardObj.GetCount()))
+ for bIndex in range(billboardObj.GetCount()):
+ billData = billboardObj.At(bIndex)
+ familyID = billData.ID
+ hurtValue = billData.CmpValue
+ hurtValueEx = billData.CmpValue2
+ hurtValueTotal = hurtValue * ChConfig.Def_PerPointValue + hurtValueEx
+ rank = bIndex + 1
+ addScore = GameWorld.GetOrderValueByDict(rankScoreDict, rank, False, 0)
+
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ continue
+ joinFamily.score += addScore
+ GameWorld.Log(" zoneID=%s,batType=%s,groupNum=%s,rank=%s,familyID=%s,addScore=%s,updScore=%s,hurtValueTotal=%s"
+ % (zoneID, batType, groupNum, rank, familyID, addScore, joinFamily.score, hurtValueTotal))
+
+ dataID = joinFamily.familyID
+ name1 = joinFamily.familyName
+ id2 = joinFamily.leaderID
+ name2 = joinFamily.leaderName
+ type2, value1, value2 = 0, 0, 0
+ value3 = joinFamily.emblemID
+ value5 = joinFamily.serverID
+ cmpValue = joinFamily.score
+ CrossBillboard.UpdCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID, dataID, name1, name2, type2, value1, value2,
+ cmpValue, id2=id2, autoSort=False, value3=value3, value5=value5)
+
+ # 都加完积分后统一排序
+ familyScoreBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
+ familyScoreBillObj.SortData()
+
+ playerHurtBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZPlayerHurt, zoneID)
+ playerHurtBillObj.SortData()
+ return
+
+def DoGenerateGuess(zoneID, state):
+ ## 生成竞猜数据
+ if state not in IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGuess", 1):
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+
+ guessRankMax = IpyGameDataPY.GetFuncCfg("FamilyGCZGuess", 2)
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ scoreBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
+ for index in range(guessRankMax):
+ billData = scoreBillObj.At(index)
+ familyID = billData.ID
+ if familyID not in zone.familyGuessDict:
+ zone.familyGuessDict[familyID] = 0
+ GameWorld.Log("仙盟攻城战生成竞猜备选名单: zoneID=%s,index=%s,familyID=%s" % (zoneID, index, familyID))
+
+ Sync_FamilyGCZGuessInfo(zoneID)
+ return
+
+def DoStartAward(zoneID):
+ ## 开始领奖
+
+ # 下发竞猜统计结果
+ Sync_FamilyGCZGuessInfo(zoneID)
+ return
+
+def GetRoundHurtGroupID(batType, groupNum): return batType * 100 + groupNum
+def GetRoundHurtGroupIDInfo(groupValue2):
+ batType = groupValue2 / 100
+ groupNum = groupValue2 % 100
+ return batType, groupNum
+
+def Send_CrossServerMsg_FamilyGCZ(actMsgType, msgInfo, serverGroupIDList=None):
+ msgInfo["ActMsgType"] = actMsgType
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_FamilyGCZ, msgInfo, serverGroupIDList)
+ return
+
+#def GetMaxRound(joinFamilyCnt):
+# ## 获取最大轮次
+# FamilyGCZGroupSet = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGroupSet", 1, {})
+# if joinFamilyCnt not in FamilyGCZGroupSet:
+# return 0
+# roundSetDict = FamilyGCZGroupSet[joinFamilyCnt]
+# if not roundSetDict:
+# return 0
+# return max(roundSetDict)
+
+def ClientServerMsg_FamilyGCZ(serverGroupID, msgData):
+ ActMsgType = msgData["ActMsgType"]
+
+ # 加经验
+ if ActMsgType == "AddCampExp":
+ __clientServer_AddCampExp(msgData)
+
+ elif ActMsgType == "Query":
+ # 查询类型:1-成员捐献值;2-进入城池场景;3-退出城池场景;4-进入城池;5-退出城池;6-战报;7-分组仙盟成员伤害
+ # "ActMsgType":"Query", "playerID":playerID, "queryType":queryType, "batType":batType, "groupNum":groupNum, "familyID":familyID
+ queryType = msgData["queryType"]
+ playerID = msgData["playerID"]
+ batType = msgData["batType"]
+ groupNum = msgData["groupNum"]
+ tagFamilyID = msgData["familyID"]
+ gczMgr = GetFamilyGCZMgr()
+ joinMember = gczMgr.GetJoinMember(playerID)
+ if not joinMember:
+ return
+ zoneID = joinMember.zoneID
+ zone = gczMgr.GetActZone(zoneID)
+
+ if queryType == 1: # 成员捐献值
+ __clientServer_QueryContributionInfo(playerID, serverGroupID, msgData)
+ elif queryType == 2: # 进入城池场景
+ zone.SetPlayerInBatScene(playerID, batType, groupNum, serverGroupID)
+ elif queryType == 3: # 退出城池场景
+ zone.SetPlayerInBatScene(playerID)
+ elif queryType == 4: # 进入城池
+ zone.SetPlayerInBatCity(playerID, batType, groupNum, tagFamilyID, serverGroupID)
+ elif queryType == 5: # 退出城池
+ zone.SetPlayerInBatCity(playerID)
+ elif queryType == 6: # 战报
+ repFamilyID = tagFamilyID if tagFamilyID else joinMember.familyID
+ __clientServer_QueryBatReport(playerID, serverGroupID, repFamilyID)
+ elif queryType == 7: # 分组仙盟成员伤害
+ repFamilyID = tagFamilyID if tagFamilyID else joinMember.familyID
+ __clientServer_QueryGroupFamilyMemHurt(playerID, serverGroupID, zoneID, repFamilyID)
+
+ elif ActMsgType == "GCZAtk":
+ __clientServer_Atk(serverGroupID, msgData)
+
+ elif ActMsgType == "Guess":
+ __clientServer_Guess(serverGroupID, msgData)
+
+ elif ActMsgType == "GetAward":
+ __clientServer_GetAward(serverGroupID, msgData)
+
+ elif ActMsgType == "GMCMD":
+ __clientServer_GMCMD(serverGroupID, msgData)
+
+ return
+
+def __clientServer_AddCampExp(msgData):
+ playerID = msgData["playerID"]
+ addCampExp = msgData["addCampExp"]
+
+ gczMgr = GetFamilyGCZMgr()
+ joinMember = gczMgr.GetJoinMember(playerID)
+ if not joinMember:
+ GameWorld.ErrLog("非仙盟攻城战参赛成员无法加经验!", playerID)
+ return
+ familyID = joinMember.familyID
+ joinFamily = gczMgr.GetJoinFamily(familyID)
+ if not joinFamily:
+ GameWorld.ErrLog("非仙盟攻城战参赛仙盟无法加经验! familyID=%s" % familyID, playerID)
+ return
+ joinFamily.AddCampExp(playerID, addCampExp)
+ return
+
+def __clientServer_GMCMD(serverGroupID, msgData):
+ ''' GM命令,方便开发测试用
+ '''
+ playerID = msgData["playerID"]
+ msgList = msgData["msgList"]
+
+ gczMgr = GetFamilyGCZMgr()
+ joinMember = gczMgr.GetJoinMember(playerID)
+ if not joinMember:
+ GameWorld.ErrLog("非仙盟攻城战参赛成员!", playerID)
+ return
+ zoneID = joinMember.zoneID
+ familyID = joinMember.familyID
+ zone = gczMgr.GetActZone(zoneID)
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ GameWorld.ErrLog("非仙盟攻城战参赛仙盟! familyID=%s" % familyID, playerID)
+ return
+ batType, groupNum = joinMember.batType, joinMember.groupNum
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "没有战斗分组:batType-group:%s-%s" % (batType, groupNum))
+ return
+
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ state = actInfo.get(ShareDefine.ActKey_State)
+ if not state:
+ return
+ curRound, roundState = GetRoundState(state)
+
+ value0 = msgList[0]
+ if value0 in ["a", "h", "k"]:
+ if not curRound or (curRound and roundState != FamilyGCZRoundState_Fight):
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "非战斗阶段!state=%s" % (state))
+ return
+
+ #攻击城池: FamilyGCZ a 城池ID [攻击次数 仙盟ID]
+ if value0 == "a":
+ tagCityID = msgList[1] if len(msgList) > 1 else 0
+ atkCntTotal = msgList[2] if len(msgList) > 2 else 1
+ atkFamilyID = msgList[3] if len(msgList) > 3 else familyID
+ atkMemberID = 0
+ if atkFamilyID == familyID:
+ atkJoinFamily = joinFamily
+ if atkCntTotal == 1:
+ atkMemberID = playerID
+ else:
+ atkJoinFamily = zone.GetZoneJoinFamily(atkFamilyID)
+ if not atkJoinFamily:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "攻击方不存在:%s" % atkFamilyID)
+ return
+ curCityID = atkJoinFamily.cityWall.cityID
+ tagCity = batGroup.GetCityWall(tagCityID)
+ if not tagCity:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "目标城池不存在:%s" % (tagCityID))
+ return
+ atkOK = __DoGMAtkCity(playerID, serverGroupID, zoneID, curRound, batType, groupNum, curCityID, tagCityID, atkCntTotal, 0, atkMemberID)
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "atkOK:%s,remainHP:%s" % (atkOK, tagCity.hp))
+
+ #攻击城池: FamilyGCZ a 城池ID 剩余血量 [攻击方人数 仙盟ID]
+ elif value0 == "h":
+ tagCityID = msgList[1] if len(msgList) > 1 else 0
+ remainHP = msgList[2] if len(msgList) > 2 else 0
+ atkCntTotal = msgList[3] if len(msgList) > 3 else 0
+ atkFamilyID = msgList[4] if len(msgList) > 4 else familyID
+ atkMemberID = 0
+ if atkFamilyID == familyID:
+ atkJoinFamily = joinFamily
+ if atkCntTotal == 1:
+ atkMemberID = playerID
+ else:
+ atkJoinFamily = zone.GetZoneJoinFamily(atkFamilyID)
+ if not atkJoinFamily:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "攻击方不存在:%s" % atkFamilyID)
+ return
+ curCityID = atkJoinFamily.cityWall.cityID
+ tagCity = batGroup.GetCityWall(tagCityID)
+ if not tagCity:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "目标城池不存在:%s" % (tagCityID))
+ return
+ if tagCity.hp <= remainHP:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "剩余血量不能超过当前血量:%s" % (tagCity.hp))
+ return
+ hurtValueTotal = tagCity.hp - remainHP
+ atkOK = __DoGMAtkCity(playerID, serverGroupID, zoneID, curRound, batType, groupNum, curCityID, tagCityID, 0, hurtValueTotal, atkMemberID)
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "atkOK:%s,remainHP:%s" % (atkOK, tagCity.hp))
+
+ #击毁城池: FamilyGCZ k [城池ID 攻击方仙盟ID]
+ elif value0 == "k":
+ tagCityID = msgList[1] if len(msgList) > 1 else 0
+ atkFamilyID = msgList[2] if len(msgList) > 2 else familyID
+ atkJoinFamily = zone.GetZoneJoinFamily(atkFamilyID)
+ if not atkJoinFamily:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "攻击方不存在:%s" % atkFamilyID)
+ return
+ curCityID = atkJoinFamily.cityWall.cityID
+ #随机一个城池击毁
+ if not tagCityID:
+ cityIDList = batGroup.GetCityIDList()
+ else:
+ cityIDList = [tagCityID]
+ tagCity = None
+ for cityID in cityIDList[::-1]:
+ city = batGroup.GetCityWall(cityID)
+ if not city:
+ continue
+ if city.IsBroken() or cityID in [XiuluoCityID, atkFamilyID]:
+ continue
+ tagCity = city
+ break
+ if not tagCity:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "没有可击毁的城池了!")
+ return
+ tagCityID = tagCity.cityID
+ hurtValueTotal = tagCity.hp
+ atkOK = __DoGMAtkCity(playerID, serverGroupID, zoneID, curRound, batType, groupNum, curCityID, tagCityID, 0, hurtValueTotal)
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "killOK:%s,目标:%s,攻击方:%s" % (atkOK, tagCityID, curCityID))
+
+ #输出城池: FamilyGCZ p [战场类型 分组编号]
+ elif value0 == "p":
+ bType = msgList[1] if len(msgList) > 1 else batType
+ gNum = msgList[2] if len(msgList) > 2 else groupNum
+ __GMPrintGroupCity(zoneID, bType, gNum, playerID, serverGroupID)
+
+ #山寨竞猜: FamilyGCZ g 人数 [竞猜ID1 ID2 ID3]
+ elif value0 == "g":
+ guessCnt = msgList[1] if len(msgList) > 1 else 1
+ guessFamilyIDList = msgList[2:]
+ __DoGMGuess(zoneID, state, guessCnt, guessFamilyIDList, playerID, serverGroupID)
+
+ #成员捐献: FamilyGCZ x 经验 [成员数]
+ elif value0 == "x":
+ addCampExp = msgList[1] if len(msgList) > 1 else 1
+ memCnt = msgList[2] if len(msgList) > 2 else 1
+ if memCnt > 1:
+ memIDList = copy.deepcopy(joinFamily.joinMemberIDList)
+ random.shuffle(memIDList)
+ playerIDList = memIDList[:memCnt]
+ else:
+ playerIDList = [playerID]
+
+ for memID in playerIDList:
+ joinFamily.AddCampExp(memID, addCampExp, False)
+
+ Sync_FamilyGCZCampInfo(joinFamily.zoneID, joinFamily.familyID)
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "成员捐献:人数(%s)x%s:campLV(%s),Exp(%s)" % (len(playerIDList), addCampExp, joinFamily.campLV, joinFamily.campExp))
+
+ #设大本营: FamilyGCZ c 等级 [经验]
+ elif value0 == "c":
+ campLV = msgList[1] if len(msgList) > 1 else joinFamily.campLV
+ campExp = msgList[2] if len(msgList) > 2 else joinFamily.campExp
+ if campLV and not IpyGameDataPY.GetIpyGameData("CrossActFamilyGCZCampLV", campLV):
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "大本营没有该等级:%s" % campExp)
+ return
+ joinFamily.campLV = campLV
+ joinFamily.campExp = campExp
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "设置大本营等级:%s,Exp:%s" % (campLV, campExp))
+ joinFamily.RefreshFamilyAttr()
+
+ return
+
+def __GMPrintGroupCity(zoneID, batType, groupNum, playerID, serverGroupID):
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ cityIDList = batGroup.GetCityIDList()
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "---分区(%s)分组类型(%s)组(%s)城池数(%s)" % (zoneID, batType, groupNum, len(cityIDList)))
+ for cNum, cityID in enumerate(cityIDList, 1):
+ city = batGroup.GetCityWall(cityID)
+ if not city:
+ continue
+ broken = "已击毁" if city.IsBroken() else ""
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "城池%02d:%s,防守人员ID:%s,人数:%s/%s"
+ % (cNum, cityID, city.GetCurGuardID(), len(city.fighterIDList), len(city.guardMemIDList)))
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, " HP: %s/%s %s" % (city.hp, city.hpMax, broken))
+ return
+
+def __DoGMAtkCity(gmPlayerID, serverGroupID, zoneID, curRound, batType, groupNum, curCityID, tagCityID, atkCntTotal=0, hurtValueTotal=0, atkMemberID=0):
+ '''GM攻击城池
+ @param curCityID: 攻击方城池ID
+ @param tagCityID: 防守方城池ID
+ @param atkCntTotal: 大于0时指定总攻击次数
+ @param hurtValueTotal: 大于0时指定总伤害
+ @param atkMemberID: 发起攻击的成员ID,如果为0则所有成员平摊攻击
+ '''
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ if curCityID == tagCityID:
+ GameWorld.DebugAnswerCross(gmPlayerID, serverGroupID, "不能攻击自己的城池")
+ return
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ return
+ curCity = batGroup.GetCityWall(curCityID)
+ tagCity = batGroup.GetCityWall(tagCityID)
+ if not curCity:
+ GameWorld.DebugAnswerCross(gmPlayerID, serverGroupID, "攻击方不存在:%s" % curCityID)
+ return
+ if not tagCity:
+ GameWorld.DebugAnswerCross(gmPlayerID, serverGroupID, "被攻击方不存在:%s" % tagCityID)
+ return
+ curFamilyID = curCity.familyID
+ tagFamilyID = tagCity.familyID
+ curJoinFamily = zone.GetZoneJoinFamily(curFamilyID)
+ if not curJoinFamily:
+ GameWorld.DebugAnswerCross(gmPlayerID, serverGroupID, "无归属仙盟城池不能发起攻击")
+ return
+
+ GameWorld.DebugLog("GM攻击城池: zoneID=%s,batType=%s,groupNum=%s,curCityID=%s,tagCityID=%s,atkCntTotal=%s,hurtValueTotal=%s,atkMemberID=%s"
+ % (zoneID, batType, groupNum, curCityID, tagCityID, atkCntTotal, hurtValueTotal, atkMemberID))
+
+ remainHurtTotal = 0
+ memHurtDict = {}
+ atkMemIDList = [atkMemberID] if (atkMemberID and atkMemberID in curJoinFamily.joinMemberIDList) else curJoinFamily.joinMemberIDList
+ # 按次数输出
+ if atkCntTotal:
+ remainAtkCnt = atkCntTotal
+ while remainAtkCnt > 0 and atkMemIDList:
+ remainAtkCnt -= 1
+ atkMemID = atkMemIDList.pop(0)
+ atkMemIDList.append(atkMemID)
+ atkMember = zone.GetZoneJoinMember(atkMemID)
+ memHurt = atkMember.fightPower
+ remainHurtTotal += atkMember.fightPower
+ memHurtDict[atkMemID] = memHurtDict.get(atkMemID, 0) + memHurt
+ GameWorld.DebugLog("按总次数攻击: atkCntTotal=%s,remainHurtTotal=%s,atkMem=%s,%s" % (atkCntTotal, remainHurtTotal, len(memHurtDict), memHurtDict))
+
+ # 按总伤害输出
+ elif hurtValueTotal:
+ remainHurtTotal = hurtValueTotal
+ while hurtValueTotal > 0 and atkMemIDList:
+ atkMemID = atkMemIDList.pop(0)
+ atkMemIDList.append(atkMemID)
+ atkMember = zone.GetZoneJoinMember(atkMemID)
+ memHurt = atkMember.fightPower
+ hurtValueTotal -= memHurt
+ memHurtDict[atkMemID] = memHurtDict.get(atkMemID, 0) + memHurt
+ GameWorld.DebugLog("按总伤害攻击: remainHurtTotal=%s,atkMem=%s,%s" % (remainHurtTotal, len(memHurtDict), memHurtDict))
+
+ killCnt = 0
+ curTime = int(time.time())
+ atkedGuardIDList = [] # 被攻击的人员ID列表
+ # GM攻击不限制防守人员击杀上限,直到伤害用完为止
+ GameWorld.DebugLog("计算GM攻击城池: tagCityID=%s,cityHP=%s/%s,remainHurtTotal=%s" % (tagCityID, tagCity.hp, tagCity.hpMax, remainHurtTotal))
+ while not tagCity.IsBroken() and remainHurtTotal > 0:
+ fighterID = tagCity.fighterIDList[0]
+ if tagCity.IsGuardNPC(fighterID):
+ tagGuard = tagCity.guardNPC
+ else:
+ tagGuard = zone.GetZoneJoinMember(fighterID)
+ if not tagGuard or tagGuard.IsDead():
+ tagCity.NextGuard()
+ continue
+ atkedGuardIDList.append(fighterID)
+ tagCity.atkedTime = curTime
+
+ hpBef = tagGuard.hp
+ tagGuard.hp = max(0, hpBef - remainHurtTotal)
+ lostHP = hpBef - tagGuard.hp # 该防守队员实际掉血
+ tagCity.hp = max(0, tagCity.hp - lostHP) # 城池同步扣血
+
+ # 修罗城防爆
+ if tagCityID == XiuluoCityID and tagCity.hp <= 0:
+ tagCity.hp = 1
+ tagGuard.hp = 1
+ lostHP = remainHurtTotal
+ GameWorld.Log(" GM攻击修罗城防爆: zoneID=%s,tagCityID=%s" % (zoneID, tagCityID))
+
+ GameWorld.DebugLog(" tagGuardID=%s,remainHurtTotal=%s,lostHP=%s,hpBef=%s/%s,hpUpd=%s,cityHP=%s"
+ % (fighterID, remainHurtTotal, lostHP, hpBef, tagGuard.hpMax, tagGuard.hp, tagCity.hp))
+
+ remainHurtTotal -= lostHP # 剩余伤害值
+
+ # 战报以实际掉血计算,总量为100%
+ curCity.atkReportDict[tagCityID] = curCity.atkReportDict.get(tagCityID, 0) + lostHP
+ tagCity.defReportDict[curCityID] = tagCity.defReportDict.get(curCityID, 0) + lostHP
+
+ if tagGuard.IsDead():
+ killCnt += 1
+ tagCity.NextGuard()
+
+ GameWorld.DebugLog(" remainHurtTotal=%s,killCnt=%s,atkReportDict=%s,defReportDict=%s"
+ % (remainHurtTotal, killCnt, curCity.atkReportDict, tagCity.defReportDict))
+
+ GameWorld.DebugLog("cityHP=%s/%s,atkedGuardIDList=%s" % (tagCity.hp, tagCity.hpMax, atkedGuardIDList))
+
+ for memID, memHurt in memHurtDict.items():
+ GameWorld.DebugLog("攻击方成员输出: memID=%s,%s" % (memID, memHurt))
+ joinMember = zone.GetZoneJoinMember(memID)
+ if not joinMember:
+ continue
+ joinMember.totalHurtValue += memHurt
+ cmpValue = joinMember.totalHurtValue / ChConfig.Def_PerPointValue
+ cmpValue2 = joinMember.totalHurtValue % ChConfig.Def_PerPointValue
+ CrossBillboard.UpdCrossBillboardPlayer(ShareDefine.Def_CBT_FamilyGCZPlayerHurt, memID, zoneID, cmpValue, cmpValue2, autoSort=False)
+ if curCity.IsBroken():
+ continue
+ curCity.fighterHurtDict[memID] = curCity.fighterHurtDict.get(memID, 0) + memHurt
+ playerRoundHurtTotal = curCity.fighterHurtDict[memID] # 只算生存伤害
+ _, topHurtPlayerValue = batGroup.GetTopHurtPlayerIDValue()
+ if playerRoundHurtTotal > topHurtPlayerValue:
+ batGroup.UpdTopHurtPlayerIDValue(memID, playerRoundHurtTotal)
+
+ if not curCity.IsBroken():
+ UndFamilyRoundHurtBillboard(curJoinFamily)
+
+ if not CheckXiuluoCity(zoneID, curRound, batType, groupNum, gmPlayerID):
+ Sync_FamilyGCZBatSceneInfo(zoneID, batType, groupNum)
+ Sync_FamilyGCZBatCityInfo(zoneID, batType, groupNum, tagCityID)
+ if tagFamilyID:
+ Sync_FamilyGCZCampInfo(zoneID, tagFamilyID, defMemIDList=atkedGuardIDList)
+ return True
+
+def __clientServer_Atk(serverGroupID, msgData):
+ ## 攻击
+ zoneID = msgData["zoneID"]
+ playerID = msgData["playerID"]
+ atkType = msgData["atkType"] # 攻击类型: 1-普通单攻;2-技能单攻;3-技能群攻;
+ tagCityID = msgData["tagCityID"] # 目标城池ID,一般是仙盟ID或者特殊城池ID如修罗城城池,普攻单攻需指定目标,群攻技能发0
+ tagGuardID = msgData["tagGuardID"] # 目标守卫ID,一般是玩家ID或者特殊守卫ID如修罗城守卫,普攻单攻需指定目标,技能攻击发0
+ hurtMulti = msgData["hurtMulti"]
+ #useItemID = msgData["useItemID"]
+ hurtFamilyCnt = msgData["hurtFamilyCnt"]
+
+ GameWorld.DebugLog("仙盟攻城战攻击: zoneID=%s,atkType=%s,tagCityID=%s,tagGuardID=%s,hurtMulti=%s,hurtFamilyCnt=%s"
+ % (zoneID, atkType, tagCityID, tagGuardID, hurtMulti, hurtFamilyCnt), playerID)
+
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ state = actInfo.get(ShareDefine.ActKey_State)
+ if not state:
+ return
+ curRound, roundState = GetRoundState(state)
+ if not curRound or (curRound and roundState != FamilyGCZRoundState_Fight):
+ GameWorld.ErrLog("仙盟攻城战非攻击阶段: state=%s,curRound=%s,roundState=%s" % (state, curRound, roundState), playerID)
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ joinMember = gczMgr.GetJoinMember(playerID)
+ if not joinMember:
+ GameWorld.ErrLog("非仙盟攻城战参赛成员!", playerID)
+ return
+ if zoneID != joinMember.zoneID:
+ GameWorld.ErrLog("非仙盟攻城战参赛成员! zoneID=%s" % joinMember.zoneID, playerID)
+ return
+ zone = gczMgr.GetActZone(zoneID)
+ familyID = joinMember.familyID
+ batType, groupNum = joinMember.batType, joinMember.groupNum
+ curJoinFamily = zone.GetZoneJoinFamily(familyID)
+ if not curJoinFamily:
+ GameWorld.ErrLog("非仙盟攻城战参赛仙盟! familyID=%s" % familyID, playerID)
+ return
+ curCity = curJoinFamily.cityWall
+ curCityID = curCity.cityID
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ GameWorld.ErrLog("仙盟攻城战分组不存在! batType=%s,groupNum=%s" % (batType, groupNum), playerID)
+ return
+
+ canAtkedCityList = [] # 可被攻击的城池列表
+ # 群攻技能
+ if atkType == AtkType_SkillArea:
+ # 群攻时强制目标为0
+ tagCityID, tagGuardID = 0, 0
+ for tagCID in batGroup.cityWallDict.keys(): # 遍历同组城池
+ if tagCID == curCityID:
+ #不打自己
+ continue
+ tagCity = batGroup.GetCityWall(tagCID)
+ if not tagCity or tagCity.IsBroken():
+ # 已被摧毁的
+ continue
+ canAtkedCityList.append(tagCity)
+ if len(canAtkedCityList) > hurtFamilyCnt:
+ random.shuffle(canAtkedCityList)
+ canAtkedCityList = canAtkedCityList[:hurtFamilyCnt]
+
+ # 单攻技能
+ elif atkType == AtkType_SkillSingle:
+ if not tagCityID or tagCityID == curCityID:
+ SendFamilyGCZAtkResult(AtkRet_Other, "TagIDError-tagCityID", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+ tagCity = batGroup.GetCityWall(tagCityID)
+ if not tagCity:
+ SendFamilyGCZAtkResult(AtkRet_Other, "GroupNoTagCity", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+ if tagCity.IsBroken():
+ SendFamilyGCZAtkResult(AtkRet_TagBroken, "TagBroken", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+ tagGuardID = 0 # 单攻技能指定城池,不指定目标
+ canAtkedCityList.append(tagCity)
+
+ # 普通单攻
+ else:
+ if not tagCityID or not tagGuardID or tagCityID == curCityID:
+ SendFamilyGCZAtkResult(AtkRet_Other, "TagIDError-tagCityID-GuardID", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+ tagCity = batGroup.GetCityWall(tagCityID)
+ if not tagCity:
+ SendFamilyGCZAtkResult(AtkRet_Other, "GroupNoTagCity", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+ if tagCity.IsBroken():
+ SendFamilyGCZAtkResult(AtkRet_TagBroken, "TagBroken", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+ if tagCity.GetCurGuardID() != tagGuardID:
+ GameWorld.DebugLog("CurGuardID=%s,fighterIDList=%s" % (tagCity.GetCurGuardID(), tagCity.fighterIDList))
+ SendFamilyGCZAtkResult(AtkRet_TagDead, "TagDead", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+ canAtkedCityList.append(tagCity)
+
+ if not canAtkedCityList:
+ SendFamilyGCZAtkResult(AtkRet_Other, "NoAtkedTag", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+
+ batFightPower = joinMember.fightPower
+ oneHurtTotal = totalHurtValue = batFightPower * hurtMulti # 总伤害
+ if len(canAtkedCityList) > 1 :
+ oneHurtTotal = totalHurtValue / len(canAtkedCityList) # 所有可攻击的目标仙盟平摊伤害
+ GameWorld.DebugLog("batFightPower=%s,totalHurtValue=%s,oneHurtTotal=%s" % (batFightPower, totalHurtValue, oneHurtTotal), playerID)
+
+ curTime = int(time.time())
+ oneCanAtkDefMax = IpyGameDataPY.GetFuncCfg("FamilyGCZCity", 2) # 单盟最大可攻击x个防守人员
+ hurtDict = {} # 最终伤血信息
+ killCntTotal = 0 # 本次攻击击杀数
+
+ for tagCity in canAtkedCityList:
+ if not tagCity or tagCity.IsBroken():
+ continue
+ killCnt = 0
+ tagCityID = tagCity.cityID
+ remainHurtTotal = oneHurtTotal
+ atkedGuardIDList = [] # 被攻击的人员ID列表
+ GameWorld.DebugLog("计算攻击城池: tagCityID=%s,cityHP=%s/%s,oneHurtTotal=%s,oneCanAtkDefMax=%s,fighterIDList=%s"
+ % (tagCityID, tagCity.hp, tagCity.hpMax, oneHurtTotal, oneCanAtkDefMax, tagCity.fighterIDList), playerID)
+ while not tagCity.IsBroken() and len(atkedGuardIDList) < oneCanAtkDefMax and remainHurtTotal > 0:
+ fighterID = tagCity.fighterIDList[0]
+ if tagCity.IsGuardNPC(fighterID):
+ tagGuard = tagCity.guardNPC
+ else:
+ tagGuard = zone.GetZoneJoinMember(fighterID)
+ if not tagGuard or tagGuard.IsDead():
+ tagCity.NextGuard()
+ continue
+ atkedGuardIDList.append(fighterID)
+ tagCity.atkedTime = curTime
+
+ hpBef = tagGuard.hp
+ tagGuard.hp = max(0, hpBef - remainHurtTotal)
+ lostHP = hpBef - tagGuard.hp # 该防守队员实际掉血
+ tagCity.hp = max(0, tagCity.hp - lostHP) # 城池同步扣血
+
+ # 修罗城防爆
+ if tagCityID == XiuluoCityID and tagCity.hp <= 0:
+ tagCity.hp = 1
+ tagGuard.hp = 1
+ lostHP = remainHurtTotal
+ GameWorld.Log(" 修罗城防爆: zoneID=%s,familyID=%s" % (zoneID, familyID), playerID)
+
+ GameWorld.DebugLog(" tagGuardID=%s,remainHurtTotal=%s,lostHP=%s,hpBef=%s/%s,hpUpd=%s,cityHPUpd=%s"
+ % (fighterID, remainHurtTotal, lostHP, hpBef, tagGuard.hpMax, tagGuard.hp, tagCity.hp), playerID)
+
+ remainHurtTotal -= lostHP # 剩余伤害值
+
+ # 战报以实际掉血计算,总量为100%
+ curCity.atkReportDict[tagCityID] = curCity.atkReportDict.get(tagCityID, 0) + lostHP
+ tagCity.defReportDict[curCityID] = tagCity.defReportDict.get(curCityID, 0) + lostHP
+
+ if tagGuard.IsDead():
+ killCnt += 1
+ killCntTotal += 1
+ tagCity.NextGuard()
+
+ GameWorld.DebugLog(" remainHurtTotal=%s,killCnt=%s,atkReportDict=%s,defReportDict=%s"
+ % (remainHurtTotal, killCnt, curCity.atkReportDict, tagCity.defReportDict), playerID)
+
+ if not atkedGuardIDList:
+ continue
+
+ hurtDict[tagCityID] = oneHurtTotal # 飘血按伤害
+ # 通知被攻击盟成员大本营城池信息
+ if tagCity.familyID:
+ Sync_FamilyGCZCampInfo(zoneID, tagCity.familyID, defMemIDList=atkedGuardIDList)
+ Sync_FamilyGCZBatCityInfo(zoneID, batType, groupNum, tagCityID, AtkRet_OK, playerID, oneHurtTotal, killCnt)
+
+ if not hurtDict:
+ SendFamilyGCZAtkResult(AtkRet_Other, "NoHurt", msgData, serverGroupID, zoneID, curRound, batType, groupNum)
+ return
+
+ # 更新个人活动总伤害
+ joinMember.totalHurtValue += totalHurtValue
+ GameWorld.DebugLog(" 更新玩家活动总伤害榜值! memTotalHurt=%s" % (joinMember.totalHurtValue), playerID)
+ cmpValue = joinMember.totalHurtValue / ChConfig.Def_PerPointValue
+ cmpValue2 = joinMember.totalHurtValue % ChConfig.Def_PerPointValue
+ CrossBillboard.UpdCrossBillboardPlayer(ShareDefine.Def_CBT_FamilyGCZPlayerHurt, playerID, zoneID, cmpValue, cmpValue2, autoSort=False)
+
+ # 本盟还未被摧毁,可计算轮次伤害
+ if not curCity.IsBroken():
+ # 本轮成员贡献伤害
+ curCity.fighterHurtDict[playerID] = curCity.fighterHurtDict.get(playerID, 0) + totalHurtValue
+ GameWorld.DebugLog(" 更新本轮仙盟成员贡献伤害! familyID=%s,playerID=%s,addHurtValue=%s,%s"
+ % (familyID, playerID, totalHurtValue, curCity.fighterHurtDict), playerID)
+ UndFamilyRoundHurtBillboard(curJoinFamily)
+
+ playerRoundHurtTotal = curCity.fighterHurtDict[playerID] # 只算生存伤害
+ topHurtPlayerID, topHurtPlayerValue = batGroup.GetTopHurtPlayerIDValue()
+ if playerRoundHurtTotal > topHurtPlayerValue:
+ batGroup.UpdTopHurtPlayerIDValue(playerID, playerRoundHurtTotal)
+ GameWorld.DebugLog(" 更新为本组伤害第一玩家: playerRoundHurtTotal=%s > %s" % (playerRoundHurtTotal, topHurtPlayerValue), playerID)
+ else:
+ GameWorld.DebugLog(" 未超过本组伤害第一玩家: playerRoundHurtTotal=%s <= %s,topPlayerHurtID=%s"
+ % (playerRoundHurtTotal, topHurtPlayerValue, topHurtPlayerID), playerID)
+ else:
+ GameWorld.DebugLog(" 自己仙盟城池已被摧毁,不再累加本轮仙盟伤害榜值! familyID=%s" % familyID, playerID)
+
+ SendFamilyGCZAtkResult(AtkRet_OK, "OK", msgData, serverGroupID, zoneID, curRound, batType, groupNum, hurtDict, killCntTotal)
+ return
+
+def CheckXiuluoCity(zoneID, curRound, batType, groupNum, playerID=0):
+ ## 检查是否刷新修罗城
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ #maxRound = GetMaxRound(zone.joinFamilyCnt)
+ appearRoundList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZXiuluo", 4)
+ if curRound not in appearRoundList:
+ return
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ return
+ xiuluoCity = batGroup.GetCityWall(XiuluoCityID)
+ if xiuluoCity:
+ return
+ aliveFamilyCnt = 0
+ for tagCity in batGroup.cityWallDict.values():
+ if tagCity.IsBroken():
+ continue
+ aliveFamilyCnt += 1
+ if aliveFamilyCnt > 1:
+ return
+ GameWorld.Log("剩下一个仙盟未被摧毁,刷新修罗城! zoneID=%s,curRound=%s,batType=%s,groupNum=%s" % (zoneID, curRound, batType, groupNum), playerID)
+ xiuluoCityLV = IpyGameDataPY.GetFuncCfg("FamilyGCZXiuluo", 3)
+ guardNPCCount = IpyGameDataPY.GetFuncCfg("FamilyGCZXiuluo", 2)
+ batGroup.CreateCityWall(XiuluoCityID, xiuluoCityLV, guardNPCCount=guardNPCCount, isAttrLock=True)
+ Sync_FamilyGCZBatSceneInfo(zoneID, batType, groupNum)
+ return True
+
+def SendFamilyGCZAtkResult(atkRet, errMsg, msgData, serverGroupID, zoneID, curRound, batType, groupNum, hurtDict={}, killCntTotal=0):
+ atkPlayerID = msgData["playerID"]
+ atkType = msgData["atkType"]
+ tagCityID = msgData["tagCityID"]
+
+ if atkPlayerID and atkRet != AtkRet_OK:
+ GameWorld.ErrLog("仙盟攻城战攻击失败: atkRet=%s:%s,atkType=%s,%s" % (atkRet, errMsg, atkType, msgData), atkPlayerID)
+ # 失败时仅通知发起攻击玩家刷新最新信息即可
+ if atkType == AtkType_Normal:
+ Sync_FamilyGCZBatCityInfo(zoneID, batType, groupNum, tagCityID, atkRet, atkPlayerID, toPlayerServerDict={atkPlayerID:serverGroupID})
+ else:
+ Sync_FamilyGCZBatSceneInfo(zoneID, batType, groupNum, atkPlayerID, atkType, toPlayerServerDict={atkPlayerID:serverGroupID})
+
+ # 有玩家攻击成功,需要同步通知在城池场景内及城池内的玩家,因为无论在哪里攻击都会触发城池内城池外双方信息的变化
+ if atkPlayerID and atkRet == AtkRet_OK:
+ #Sync_FamilyGCZBatCityInfo 这个在攻击遍历中已通知,仅通知被攻击的城池
+ Sync_FamilyGCZBatSceneInfo(zoneID, batType, groupNum, atkPlayerID, atkType, hurtDict, killCntTotal)
+
+ msgInfo = {"atkRet":atkRet, "errMsg":errMsg, "reqMsg":msgData, "hurtDict":hurtDict, "killCntTotal":killCntTotal}
+ Send_CrossServerMsg_FamilyGCZ("FamilyGCZAtkResult", msgInfo, [serverGroupID])
+
+ CheckXiuluoCity(zoneID, curRound, batType, groupNum, atkPlayerID)
+ return
+
+def Sync_FamilyGCZBatSceneInfo(zoneID, batType, groupNum, atkPlayerID=0, atkType=0, hurtDict={}, killCntTotal=0, toPlayerServerDict=None):
+ ## 通知城池场景信息
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ return
+
+ onlinePlayerIDDict = {}
+ if toPlayerServerDict != None:
+ onlinePlayerIDDict = toPlayerServerDict
+ else:
+ onlineMgr = ChPlayer.GetOnlinePlayerMgr()
+ notifyPlayerIDList = batGroup.inBatScenePlayerIDList # + [atkPlayerID]
+ for playerID in notifyPlayerIDList:
+ if not playerID or playerID in onlinePlayerIDDict:
+ continue
+ serverGroupID = onlineMgr.GetOLPlayerServerGroupID(playerID)
+ if serverGroupID:
+ onlinePlayerIDDict[playerID] = serverGroupID
+ GameWorld.DebugLog("Sync_FamilyGCZBatSceneInfo zoneID=%s,batType=%s,groupNum=%s,%s,%s"
+ % (zoneID, batType, groupNum, notifyPlayerIDList, onlinePlayerIDDict), atkPlayerID)
+
+ if not onlinePlayerIDDict:
+ return
+
+ sceneShowPlayerIDList = [] # 场景中需要展示的玩家ID列表
+ topFamilyID, topLeaderID = 0, 0
+
+ groupValue2 = GetRoundHurtGroupID(batType, groupNum)
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ roundHurtBillboard = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZRoundHurt, zoneID, groupValue2)
+ idOrderDict = roundHurtBillboard.GetIDOrderDict()
+ if roundHurtBillboard.GetCount():
+ topFamilyBillboard = roundHurtBillboard.At(0)
+ topFamilyID = topFamilyBillboard.ID
+ topFamily = zone.GetZoneJoinFamily(topFamilyID)
+ if topFamily:
+ topLeaderID = topFamily.leaderID
+ if topLeaderID not in sceneShowPlayerIDList:
+ sceneShowPlayerIDList.append(topLeaderID)
+
+ topPlayerID = batGroup.GetTopHurtPlayerIDValue()[0]
+ topPlayerFamilyID = 0
+ if topPlayerID:
+ if topPlayerID not in sceneShowPlayerIDList:
+ sceneShowPlayerIDList.append(topPlayerID)
+ topMember = zone.GetZoneJoinMember(topPlayerID)
+ if topMember:
+ topPlayerFamilyID = topMember.familyID
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZBatSceneInfo()
+ clientPack.BatType = batType
+ clientPack.GroupNum = groupNum
+ clientPack.TopFamilyID = topFamilyID
+ clientPack.TopLeaderID = topLeaderID
+ clientPack.TopPlayerID = topPlayerID
+ clientPack.TopPlayerFamilyID = topPlayerFamilyID
+ # 场景信息只通知技能攻击
+ if atkType != AtkType_Normal and hurtDict:
+ if atkPlayerID not in sceneShowPlayerIDList:
+ sceneShowPlayerIDList.append(atkPlayerID)
+ clientPack.AtkPlayerID = atkPlayerID
+ clientPack.AtkType = atkType
+ clientPack.KillCnt = killCntTotal
+ clientPack.HurtList = []
+ for cityID, hurtTotal in hurtDict.items():
+ hurt = ChPyNetSendPack.tagGCFamilyGCZBatSceneHurt()
+ hurt.CityID = cityID
+ hurt.HurtValue = hurtTotal % ChConfig.Def_PerPointValue
+ hurt.HurtValueEx = hurtTotal / ChConfig.Def_PerPointValue
+ clientPack.HurtList.append(hurt)
+ clientPack.HurtCnt = len(clientPack.HurtList)
+
+ # 场景有变化的城池,暂时都同步,不然可能名次显示有问题
+ #if hurtDict:
+ # syncCityIDList = hurtDict.keys()
+ #else:
+ syncCityIDList = batGroup.GetCityIDList()
+ clientPack.CityList = []
+ for cityID in syncCityIDList:
+ cityWall = batGroup.GetCityWall(cityID)
+ if not cityWall:
+ continue
+ city = ChPyNetSendPack.tagGCFamilyGCZBatSceneCity()
+ city.CityID = cityID
+ city.CityLV = cityWall.cityLV
+ city.FamilyID = cityWall.familyID
+ city.Rank = idOrderDict.get(cityWall.familyID, 0)
+ city.HP = cityWall.hp % ChConfig.Def_PerPointValue
+ city.HPEx = cityWall.hp / ChConfig.Def_PerPointValue
+ city.HPMax = cityWall.hpMax % ChConfig.Def_PerPointValue
+ city.HPMaxEx = cityWall.hpMax / ChConfig.Def_PerPointValue
+ city.LastAtkedTime = cityWall.atkedTime
+ clientPack.CityList.append(city)
+ clientPack.CityCnt = len(clientPack.CityList)
+
+ # 场景需要用到的玩家信息
+ clientPack.PlayerInfoList = []
+ for playerID in sceneShowPlayerIDList:
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if not joinMember:
+ continue
+ scenePlayer = ChPyNetSendPack.tagGCFamilyGCZBatScenePlayer()
+ scenePlayer.PlayerID = playerID
+ scenePlayer.Name = joinMember.playerName
+ scenePlayer.Face = joinMember.face
+ scenePlayer.FacePic = joinMember.facePic
+ clientPack.PlayerInfoList.append(scenePlayer)
+ clientPack.PlayerCnt = len(clientPack.PlayerInfoList)
+
+ NetPackCommon.SendFakePackByCross(onlinePlayerIDDict, clientPack)
+ return
+
+def Sync_FamilyGCZBatCityInfo(zoneID, batType, groupNum, cityID, atkRet=0, atkPlayerID=0, hurtValue=0, killCnt=0, toPlayerServerDict=None):
+ ## 通知城池信息
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ return
+ cityWall = batGroup.GetCityWall(cityID)
+ if not cityWall:
+ return
+
+ onlinePlayerIDDict = {}
+ if toPlayerServerDict != None:
+ onlinePlayerIDDict = toPlayerServerDict
+ else:
+ onlineMgr = ChPlayer.GetOnlinePlayerMgr()
+ notifyPlayerIDList = cityWall.inCityPlayerIDList # + [atkPlayerID]
+ for playerID in notifyPlayerIDList:
+ if not playerID or playerID in onlinePlayerIDDict:
+ continue
+ serverGroupID = onlineMgr.GetOLPlayerServerGroupID(playerID)
+ if serverGroupID:
+ onlinePlayerIDDict[playerID] = serverGroupID
+ GameWorld.DebugLog("Sync_FamilyGCZBatCityInfo zoneID=%s,batType=%s,groupNum=%s,cityID=%s,%s,%s"
+ % (zoneID, batType, groupNum, cityID, notifyPlayerIDList, onlinePlayerIDDict), atkPlayerID)
+
+ if not onlinePlayerIDDict:
+ return
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZBatCityInfo()
+ clientPack.CityID = cityID
+ clientPack.CityLV = cityWall.cityLV
+ clientPack.FamilyID = cityWall.familyID
+ clientPack.GuardID = cityWall.GetCurGuardID()
+ clientPack.HP = cityWall.hp % ChConfig.Def_PerPointValue
+ clientPack.HPEx = cityWall.hp / ChConfig.Def_PerPointValue
+ clientPack.HPMax = cityWall.hpMax % ChConfig.Def_PerPointValue
+ clientPack.HPMaxEx = cityWall.hpMax / ChConfig.Def_PerPointValue
+ clientPack.AtkPlayerID = atkPlayerID
+ clientPack.AtkRet = atkRet
+ clientPack.KillCnt = killCnt
+ clientPack.HurtValue = hurtValue % ChConfig.Def_PerPointValue
+ clientPack.HurtValueEx = hurtValue / ChConfig.Def_PerPointValue
+ NetPackCommon.SendFakePackByCross(onlinePlayerIDDict, clientPack)
+ return
+
+def __clientServer_QueryContributionInfo(playerID, serverGroupID, msgData):
+ ## 查询贡献值信息
+ gczMgr = GetFamilyGCZMgr()
+ joinFamily = gczMgr.GetJoinFamilyByPlayerID(playerID)
+ if not joinFamily:
+ return
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZContributionInfo()
+ clientPack.ContriList = []
+ for memID, value in joinFamily.memAddCampExpInfo.items():
+ contri = ChPyNetSendPack.tagGCFamilyGCZContribution()
+ contri.PlayerID = memID
+ contri.ContributionValue = value
+ clientPack.ContriList.append(contri)
+ clientPack.ContriCnt = len(clientPack.ContriList)
+ NetPackCommon.SendFakePackByCross({playerID:serverGroupID}, clientPack)
+ return
+
+def __clientServer_QueryBatReport(playerID, serverGroupID, repFamilyID):
+ ## 查询战报
+
+ gczMgr = GetFamilyGCZMgr()
+ repFamily = gczMgr.GetJoinFamily(repFamilyID)
+ if not repFamily:
+ return
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZBatReport()
+ clientPack.FamilyID = repFamilyID
+ clientPack.DefRepList = []
+ for tagFamilyID, hurtValue in repFamily.cityWall.defReportDict.items():
+ defRep = ChPyNetSendPack.tagGCFamilyGCZBatRepHurt()
+ defRep.TagFamilyID = tagFamilyID
+ defRep.HurtValue = hurtValue % ChConfig.Def_PerPointValue
+ defRep.HurtValueEx = hurtValue / ChConfig.Def_PerPointValue
+ clientPack.DefRepList.append(defRep)
+ clientPack.DefRepCnt = len(clientPack.DefRepList)
+
+ clientPack.AtkRepList = []
+ for tagFamilyID, hurtValue in repFamily.cityWall.atkReportDict.items():
+ atkRep = ChPyNetSendPack.tagGCFamilyGCZBatRepHurt()
+ atkRep.TagFamilyID = tagFamilyID
+ atkRep.HurtValue = hurtValue % ChConfig.Def_PerPointValue
+ atkRep.HurtValueEx = hurtValue / ChConfig.Def_PerPointValue
+ clientPack.AtkRepList.append(atkRep)
+ clientPack.AtkRepCnt = len(clientPack.AtkRepList)
+
+ NetPackCommon.SendFakePackByCross({playerID:serverGroupID}, clientPack)
+ return
+
+def __clientServer_QueryGroupFamilyMemHurt(playerID, serverGroupID, zoneID, tagFamilyID):
+ ## 查询分组仙盟成员伤害信息
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ joinFamily = zone.GetZoneJoinFamily(tagFamilyID)
+ if not joinFamily:
+ return
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZGroupFamilyMemHurtInfo()
+ clientPack.FamilyID = tagFamilyID
+ clientPack.HurtMemList = []
+ for memID, value in joinFamily.cityWall.fighterHurtDict.items():
+ joinMember = zone.GetZoneJoinMember(memID)
+ memHurt = ChPyNetSendPack.tagGCFamilyGCZGroupFamilyMemHurt()
+ memHurt.PlayerID = memID
+ memHurt.Name = joinMember.playerName if joinMember else ""
+ memHurt.HurtValue = value % ChConfig.Def_PerPointValue
+ memHurt.HurtValueEx = value / ChConfig.Def_PerPointValue
+ clientPack.HurtMemList.append(memHurt)
+ clientPack.HurtMemCnt = len(clientPack.HurtMemList)
+ NetPackCommon.SendFakePackByCross({playerID:serverGroupID}, clientPack)
+ return
+
+def __clientServer_Guess(serverGroupID, msgData):
+ ## 竞猜 - 无参与资格的也可以竞猜
+
+ playerID = msgData["playerID"]
+ selectFamilyIDList = msgData["selectFamilyIDList"]
+
+ zoneID = GetPlayerActJoinInfo(playerID)[0]
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ state = actInfo.get(ShareDefine.ActKey_State)
+ if not state:
+ return
+ canGuessStateList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGuess", 1)
+ if state not in canGuessStateList:
+ GameWorld.ErrLog("仙盟攻城战非竞猜阶段: zoneID=%s,state=%s not in %s" % (zoneID, state, canGuessStateList), playerID)
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ guessCountMax = IpyGameDataPY.GetFuncCfg("FamilyGCZGuess", 3)
+ selectFamilyIDList = selectFamilyIDList[:guessCountMax]
+ for familyID in selectFamilyIDList:
+ if familyID not in zone.familyGuessDict:
+ GameWorld.ErrLog("仙盟攻城战该仙盟ID不可竞猜! zoneID=%s,selectFamilyIDList=%s,familyID=%s not in %s"
+ % (zoneID, selectFamilyIDList, familyID, zone.familyGuessDict.keys()), playerID)
+ return
+
+ for familyID in selectFamilyIDList:
+ zone.familyGuessDict[familyID] = zone.familyGuessDict.get(familyID, 0) + 1
+
+ zone.playerGuessDict[playerID] = selectFamilyIDList
+ GameWorld.DebugLog("仙盟攻城战竞猜: %s,familyGuessDict=%s" % (selectFamilyIDList, zone.familyGuessDict), playerID)
+
+ Sync_FamilyGCZGuessInfo(zoneID, selectPlayerID=playerID)
+ return
+
+def __DoGMGuess(zoneID, state, guessCnt, selectFamilyIDList, playerID, serverGroupID):
+ ## GM山寨竞猜数据
+
+ canGuessStateList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZGuess", 1)
+ if state not in canGuessStateList:
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "非竞猜阶段!state=%s" % (state))
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ guessCountMax = IpyGameDataPY.GetFuncCfg("FamilyGCZGuess", 3)
+ selectFamilyIDList = selectFamilyIDList[:guessCountMax]
+
+ # 没有指定竞猜,则随机
+ if not selectFamilyIDList:
+ familyIDList = zone.familyGuessDict.keys()
+ random.shuffle(familyIDList)
+ selectFamilyIDList = familyIDList[:guessCountMax]
+
+ for familyID in selectFamilyIDList:
+ zone.familyGuessDict[familyID] = zone.familyGuessDict.get(familyID, 0) + guessCnt
+
+ maxFackID = 0
+ for pID in zone.playerGuessDict.keys():
+ if pID < 10000 and pID > maxFackID:
+ maxFackID = pID
+
+ for pID in range(maxFackID + 1, maxFackID + 1 + guessCnt + 1):
+ zone.playerGuessDict[pID] = selectFamilyIDList
+
+ GameWorld.DebugAnswerCross(playerID, serverGroupID, "新增竞猜人数:%s, 总:%s" % (guessCnt, len(zone.playerGuessDict)))
+ Sync_FamilyGCZGuessInfo(zoneID)
+ return
+
+def __clientServer_GetAward(serverGroupID, msgData):
+ ## 领奖
+ playerID = msgData["playerID"]
+ awardType = msgData["awardType"]
+
+ zoneID = GetPlayerActJoinInfo(playerID)[0]
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ actID = actInfo.get(ShareDefine.ActKey_ID)
+ state = actInfo.get(ShareDefine.ActKey_State)
+ if not state or state != FamilyGCZState_Award:
+ GameWorld.ErrLog("仙盟攻城战非领奖阶段: zoneID=%s,state=%s" % (zoneID, state), playerID)
+ return
+
+ ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)
+ if not ipyDataInfo:
+ return
+
+ # 跨服领奖不验证领奖状态,领奖状态只标记已推送,实际领奖由子服地图玩家自行验证
+
+ # 竞猜
+ if awardType == AwwardType_Guess:
+ awardTemplateID = ipyDataInfo.get("GuessTemplateID", 0)
+ __clientServer_GetAward_Guess(zoneID, playerID, serverGroupID, actID, state, awardType, awardTemplateID)
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if not joinMember:
+ GameWorld.ErrLog("非仙盟攻城战参赛成员!", playerID)
+ return
+ zoneID = joinMember.zoneID
+ familyID = joinMember.familyID
+ fmLV = joinMember.fmLV
+
+ billID = playerID
+ billboardType = 0
+ awardTemplateID = 0
+ billValue = None
+
+ # 个人排行
+ if awardType == AwwardType_PlayerHurt:
+ billID = playerID
+ billboardType = ShareDefine.Def_CBT_FamilyGCZPlayerHurt
+ awardTemplateID = ipyDataInfo.get("PersonalTemplateID", 0)
+
+ # 仙盟排行
+ elif awardType == AwwardType_FamilyScore:
+ billID = familyID
+ billboardType = ShareDefine.Def_CBT_FamilyGCZScore
+ awardTemplateID = ipyDataInfo.get("FamilyTemplateID", 0)
+
+ else:
+ return
+
+ if not awardTemplateID:
+ GameWorld.ErrLog("仙盟攻城战领奖时没有排行奖励模版! zoneID=%s,awardType=%s" % (zoneID, awardType), playerID)
+ return
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ billObj = billboardMgr.GetCrossBillboard(billboardType, zoneID)
+ idRankDict = billObj.GetIDOrderDict()
+ billRank = idRankDict.get(billID, 0)
+
+ if not billRank:
+ GameWorld.ErrLog("仙盟攻城战领奖时没有上榜! zoneID=%s,awardType=%s,billboardType=%s,billID=%s"
+ % (zoneID, awardType, billboardType, billID), playerID)
+ return
+
+ playerAwardItemList = GameWorld.GetActBillboardTempAward(playerID, billID, billRank, awardTemplateID, billValue, fmLV)
+ if not playerAwardItemList:
+ return
+
+ GameWorld.Log("仙盟攻城战玩家请求领取奖励! zoneID=%s,awardType=%s,playerAwardItemList=%s"
+ % (zoneID, awardType, playerAwardItemList), playerID)
+
+ joinMember.awardState = joinMember.awardState | pow(2, awardType) # 标记已推送
+ msgInfo = {"zoneID":zoneID, "playerID":playerID, "actID":actID, "awardType":awardType, "awardValue":billRank,
+ "awardItemList":playerAwardItemList, "fmLV":fmLV}
+ Send_CrossServerMsg_FamilyGCZ("FamilyGCZAward", msgInfo, [serverGroupID])
+ return
+
+def __clientServer_GetAward_Guess(zoneID, playerID, serverGroupID, actID, state, awardType, guessTemplateID):
+ ## 竞猜领奖
+ playerAwardID, awardItemList = GetGuessAwardInfo(zoneID, state, guessTemplateID, playerID)
+ if not awardItemList:
+ GameWorld.ErrLog("仙盟攻城战玩家没有竞猜奖励! zoneID=%s" % (zoneID), playerID)
+ return
+ GameWorld.Log("仙盟攻城战玩家请求领取竞猜奖励! zoneID=%s,playerAwardID=%s,awardItemList=%s"
+ % (zoneID, playerAwardID, awardItemList), playerID)
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if joinMember:
+ joinMember.awardState = joinMember.awardState | pow(2, awardType) # 标记已推送
+ msgInfo = {"zoneID":zoneID, "playerID":playerID, "actID":actID, "awardType":awardType, "awardValue":playerAwardID, "awardItemList":awardItemList}
+ Send_CrossServerMsg_FamilyGCZ("FamilyGCZAward", msgInfo, [serverGroupID])
+ return
+
+def GetGuessAwardInfo(zoneID, state, guessTemplateID, playerID):
+ ## 获取竞猜奖励
+ playerAwardID = 0
+ awardItemList = []
+ _, statGuessRetDict = __statGuessFinal(zoneID, state, guessTemplateID)
+ for awardID, rightPlayerIDList in statGuessRetDict.items():
+ if playerID in rightPlayerIDList:
+ playerAwardID = awardID
+ break
+
+ if playerAwardID:
+ ipyData = IpyGameDataPY.GetIpyGameDataByCondition("ActGuess", {"TemplateID":guessTemplateID, "AwardID":playerAwardID}, False)
+ if ipyData:
+ awardItemList = ipyData.GetAwardItemList()
+
+ return playerAwardID, awardItemList
+
+def DoMailReissueAward(zoneID, ipyData):
+ ## 邮件补发奖励 - 仅针对有参与资格的,无参与资格的玩家奖励暂不补发,如竞猜奖励
+
+ if not ipyData:
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ if not zone.joinMemberDict:
+ return
+
+ GameWorld.Log("仙盟攻城战邮件补发未领取奖励: zoneID=%s" % zoneID)
+
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ for playerID in zone.joinMemberDict.keys():
+ if playerID < 10000:
+ continue
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if not joinMember:
+ continue
+ familyID = joinMember.familyID
+ fmLV = joinMember.fmLV
+
+ # 个人伤害名次奖励
+ if not joinMember.awardState&pow(2, AwwardType_PlayerHurt):
+ joinMember.awardState = joinMember.awardState | pow(2, AwwardType_PlayerHurt)
+ billObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZPlayerHurt, zoneID)
+ idRankDict = billObj.GetIDOrderDict()
+ billRank = idRankDict.get(playerID, 0)
+ billValue = None
+ awardTemplateID = ipyData.GetPersonalTemplateID()
+ playerAwardItemList = GameWorld.GetActBillboardTempAward(playerID, playerID, billRank, awardTemplateID, billValue, fmLV)
+ if playerAwardItemList:
+ paramList = [billRank]
+ PlayerCompensation.SendMailByKey("FamilyGCZAwardHurt", [playerID], playerAwardItemList, paramList, crossMail=True)
+
+ # 仙盟积分名次奖励
+ if not joinMember.awardState&pow(2, AwwardType_FamilyScore):
+ joinMember.awardState = joinMember.awardState | pow(2, AwwardType_FamilyScore)
+ billObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
+ idRankDict = billObj.GetIDOrderDict()
+ billRank = idRankDict.get(familyID, 0)
+ billValue = None
+ awardTemplateID = ipyData.GetFamilyTemplateID()
+ playerAwardItemList = GameWorld.GetActBillboardTempAward(playerID, familyID, billRank, awardTemplateID, billValue, fmLV)
+ if playerAwardItemList:
+ paramList = [billRank]
+ PlayerCompensation.SendMailByKey("FamilyGCZAwardScore", [playerID], playerAwardItemList, paramList, crossMail=True)
+
+ # 竞猜奖励
+ if not joinMember.awardState&pow(2, AwwardType_Guess):
+ joinMember.awardState = joinMember.awardState | pow(2, AwwardType_Guess)
+ awardTemplateID = ipyData.GetGuessTemplateID()
+ _, awardItemList = GetGuessAwardInfo(zoneID, None, awardTemplateID, playerID)
+ if awardItemList:
+ paramList = []
+ PlayerCompensation.SendMailByKey("FamilyGCZAwardGuess", [playerID], awardItemList, paramList, crossMail=True)
+
+ return
+
+def Sync_FamilyGCZGuessInfo(zoneID, playerID=0, selectPlayerID=0):
+ ## 同步竞猜信息 - 需同步全服玩家,包含没有参与资格的
+ # @param selectPlayerID: 同步竞猜玩家ID竞猜记录
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ state = actInfo.get(ShareDefine.ActKey_State)
+ if not state:
+ return
+ ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)
+ if not ipyDataInfo:
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ if not zone.familyGuessDict:
+ # 暂无竞猜名单
+ return
+
+ onlinePlayerIDDict = {}
+ onlineMgr = ChPlayer.GetOnlinePlayerMgr()
+ if not playerID:
+ for playerID, serverGroupID in onlineMgr.onlinePlayerDict.items():
+ pActInfo = GetPlayerActJoinInfo(playerID)
+ if zoneID != pActInfo[0]:
+ continue
+ onlinePlayerIDDict[playerID] = serverGroupID
+ else:
+ onlinePlayerIDDict = {playerID:onlineMgr.GetOLPlayerServerGroupID(playerID)}
+
+ if not onlinePlayerIDDict:
+ return
+
+ selectFamilyIDList = []
+ if selectPlayerID:
+ selectFamilyIDList = zone.playerGuessDict.get(selectPlayerID, [])
+
+ guessTemplateID = ipyDataInfo.get("GuessTemplateID", 0)
+ finalFamilyIDList, statGuessRetDict = __statGuessFinal(zoneID, state, guessTemplateID)
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZGuessInfo()
+ clientPack.PlayerID = selectPlayerID
+ clientPack.SelectFamilyIDList = selectFamilyIDList
+ clientPack.SelectCnt = len(clientPack.SelectFamilyIDList)
+
+ clientPack.FinalFamilyIDList = finalFamilyIDList
+ clientPack.FinalCnt = len(clientPack.FinalFamilyIDList)
+
+ clientPack.RightInfoList = []
+ for awardID, rightPlayerIDList in statGuessRetDict.items():
+ right = ChPyNetSendPack.tagGCFamilyGCZGuessRight()
+ right.AwardID = awardID
+ right.RightPlayerCnt = len(rightPlayerIDList)
+ clientPack.RightInfoList.append(right)
+ clientPack.RightCnt = len(clientPack.RightInfoList)
+
+ clientPack.GuessFamilyList = []
+ for familyID, guessValue in zone.familyGuessDict.items():
+ familyGuess = ChPyNetSendPack.tagGCFamilyGCZGuessFamily()
+ familyGuess.FamilyID = familyID
+ familyGuess.GuessValue = guessValue
+ clientPack.GuessFamilyList.append(familyGuess)
+ clientPack.FamilyCnt = len(clientPack.GuessFamilyList)
+
+ NetPackCommon.SendFakePackByCross(onlinePlayerIDDict, clientPack)
+ return
+
+def __statGuessFinal(zoneID, state, guessTemplateID):
+ ## 统计竞猜最终结果
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ if zone.statGuessRetDict != None:
+ statGuessRetDict = zone.statGuessRetDict
+ finalFamilyIDList = zone.guessFinalFamilyIDList
+ return finalFamilyIDList, statGuessRetDict
+
+ finalFamilyIDList = []
+ statGuessRetDict = {}
+ if state != None and state != FamilyGCZState_Award:
+ return finalFamilyIDList, statGuessRetDict
+
+ guessCountMax = IpyGameDataPY.GetFuncCfg("FamilyGCZGuess", 3)
+ billboardMgr = PyDataManager.GetCrossBillboardManager()
+ scoreBillObj = billboardMgr.GetCrossBillboard(ShareDefine.Def_CBT_FamilyGCZScore, zoneID)
+ for index in range(guessCountMax):
+ billData = scoreBillObj.At(index)
+ finalFamilyIDList.append(billData.ID)
+
+ # 统计竞猜结果
+ rightRankAwardIDDict = GameWorld.GetActGuessRightRankAwardIDDict(guessTemplateID)
+ GameWorld.Log("仙盟攻城战统计竞猜结果: zoneID=%s,guessTemplateID=%s,finalFamilyIDList=%s,%s" % (zoneID, guessTemplateID, finalFamilyIDList, rightRankAwardIDDict))
+
+ statGuessRetDict = {}
+ for playerID, guessFamilyIDList in zone.playerGuessDict.items():
+ GameWorld.StatActGuessRet(playerID, guessFamilyIDList, finalFamilyIDList, rightRankAwardIDDict, statGuessRetDict, "FamilyGCZ")
+
+ GameWorld.Log(" zoneID=%s,statGuessRetDict=%s" % (zoneID, statGuessRetDict))
+ zone.statGuessRetDict = statGuessRetDict
+ zone.guessFinalFamilyIDList = finalFamilyIDList
+ return finalFamilyIDList, statGuessRetDict
+
+def Sync_FamilyGCZActInfo(zoneID, playerID=0):
+ ## 同步活动时间信息 - 需同步全服玩家,包含没有参与资格的
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ if not actInfo.get(ShareDefine.ActKey_State):
+ return
+ ipyDataInfo = actInfo.get(ShareDefine.ActKey_IpyDataInfo)
+ if not ipyDataInfo:
+ return
+
+ playerActInfo = {}
+ onlinePlayerIDDict = {}
+ onlineMgr = ChPlayer.GetOnlinePlayerMgr()
+ if not playerID:
+ for playerID, serverGroupID in onlineMgr.onlinePlayerDict.items():
+ pActInfo = GetPlayerActJoinInfo(playerID)
+ if zoneID != pActInfo[0]:
+ continue
+ playerActInfo[playerID] = pActInfo
+ onlinePlayerIDDict[playerID] = serverGroupID
+ else:
+ playerActInfo[playerID] = GetPlayerActJoinInfo(playerID)
+ onlinePlayerIDDict = {playerID:onlineMgr.GetOLPlayerServerGroupID(playerID)}
+
+ if not onlinePlayerIDDict:
+ return
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZActInfo()
+ clientPack.Clear()
+ clientPack.ServerIDRangeInfo = str(actInfo.get(ShareDefine.ActKey_ServerIDRangeList, []))
+ clientPack.ServerInfoLen = len(clientPack.ServerIDRangeInfo)
+ clientPack.ZoneID = zoneID
+ clientPack.ActID = actInfo.get(ShareDefine.ActKey_ID, 0)
+ clientPack.StartDate = ipyDataInfo.get("StartDate", "")
+ clientPack.EndtDate = ipyDataInfo.get("EndDate", "")
+ clientPack.JoinFamilyCnt = ipyDataInfo.get("JoinFamilyCnt", 0)
+ clientPack.ActFlowID = ipyDataInfo.get("ActFlowID", 0)
+ clientPack.GuessTemplateID = ipyDataInfo.get("GuessTemplateID", 0)
+ clientPack.PersonalTemplateID = ipyDataInfo.get("PersonalTemplateID", 0)
+ clientPack.FamilyTemplateID = ipyDataInfo.get("FamilyTemplateID", 0)
+ clientPack.StateError = actInfo.get(ShareDefine.ActKey_StateError, 0)
+
+ clientPack.ActFamilyList = []
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ for familyID in zone.GetZoneLockFamilyIDList():
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ continue
+
+ actFamily = ChPyNetSendPack.tagGCFamilyGCZActFamily()
+ actFamily.FamilyID = familyID
+ actFamily.Name = joinFamily.familyName
+ actFamily.LV = joinFamily.lv
+ actFamily.ServerID = joinFamily.serverID
+ actFamily.EmblemID = joinFamily.emblemID
+ actFamily.FightPower = joinFamily.fightPowerTotal % ChConfig.Def_PerPointValue
+ actFamily.FightPowerEx = joinFamily.fightPowerTotal / ChConfig.Def_PerPointValue
+ actFamily.LeaderID = joinFamily.leaderID
+ actFamily.LeaderName = joinFamily.leaderName
+
+ leaderMem = zone.GetZoneJoinMember(actFamily.LeaderID)
+ if leaderMem:
+ actFamily.LeaderFace = leaderMem.face
+ actFamily.LeaderFacePic = leaderMem.facePic
+
+ clientPack.ActFamilyList.append(actFamily)
+ clientPack.FamilyCount = len(clientPack.ActFamilyList)
+ NetPackCommon.SendFakePackByCross(onlinePlayerIDDict, clientPack)
+
+ #同步场景、同步玩家攻击结果
+ #下发分区活动的时候,顺便下发玩家活动信息
+ msgInfo = {"zoneID":zoneID, "playerActInfo":playerActInfo}
+ Send_CrossServerMsg_FamilyGCZ("FamilyGCZPlayerActInfo", msgInfo, onlinePlayerIDDict.values())
+ return
+
+def Sync_FamilyGCZBatGroupInfo(zoneID, onlinePlayerIDDict=None):
+ ## 同步战场类型分组信息 - 只同步有参与资格的即可
+
+ actInfo = CrossActionControl.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ state = actInfo.get(ShareDefine.ActKey_State)
+ if not state:
+ return
+ curRound, _ = GetRoundState(state)
+ if not curRound:
+ return
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ if onlinePlayerIDDict == None:
+ onlinePlayerIDDict = zone.GetOLServerGroupIDDict()
+
+ if not onlinePlayerIDDict:
+ return
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZBatGroupInfo()
+ clientPack.RoundNum = curRound
+ clientPack.BatList = []
+ for batType, groupNumDict in zone.roundGroupDict.items():
+ batInfo = ChPyNetSendPack.tagGCFamilyGCZBat()
+ batInfo.BatType = batType
+ batInfo.GroupList = []
+ for groupNum in groupNumDict.keys():
+ batGroup = zone.GetBatGroup(batType, groupNum)
+ if not batGroup:
+ continue
+ group = ChPyNetSendPack.tagGCFamilyGCZBatGroup()
+ group.GroupNum = groupNum
+ group.FamilyIDList = batGroup.GetGroupFamilyIDList()
+ group.FamilyIDCnt = len(group.FamilyIDList)
+ batInfo.GroupList.append(group)
+ batInfo.GroupCnt = len(batInfo.GroupList)
+
+ clientPack.BatList.append(batInfo)
+ clientPack.BatTypeCnt = len(clientPack.BatList)
+ NetPackCommon.SendFakePackByCross(onlinePlayerIDDict, clientPack)
+ return
+
+def Sync_FamilyGCZCampInfo(zoneID, familyID, onlinePlayerIDDict=None, defMemIDList=None):
+ ## 同步仙盟大本营信息 - 只同步某个锁定盟的锁定成员即可
+
+ gczMgr = GetFamilyGCZMgr()
+ zone = gczMgr.GetActZone(zoneID)
+ joinFamily = zone.GetZoneJoinFamily(familyID)
+ if not joinFamily:
+ return
+
+ if onlinePlayerIDDict == None:
+ onlinePlayerIDDict = joinFamily.GetOLMemServerGroupIDDict()
+
+ #GameWorld.DebugLog("Sync_FamilyGCZCampInfo zoneID=%s,familyID=%s,%s,defMemIDList=%s" % (zoneID, familyID, onlinePlayerIDDict, defMemIDList))
+ if not onlinePlayerIDDict:
+ return
+
+ clientPack = ChPyNetSendPack.tagGCFamilyGCZCampInfo()
+ clientPack.Clear()
+ clientPack.FamilyID = familyID
+ clientPack.Score = joinFamily.score
+ clientPack.CampLV = joinFamily.campLV
+ clientPack.CampExp = joinFamily.campExp
+ clientPack.CityLV = joinFamily.cityWall.cityLV
+ clientPack.HPBase = joinFamily.cityWall.hpBase % ChConfig.Def_PerPointValue
+ clientPack.HPBaseEx = joinFamily.cityWall.hpBase / ChConfig.Def_PerPointValue
+ clientPack.HPMax = joinFamily.cityWall.hpMax % ChConfig.Def_PerPointValue
+ clientPack.HPMaxEx = joinFamily.cityWall.hpMax / ChConfig.Def_PerPointValue
+ clientPack.HP = joinFamily.cityWall.hp % ChConfig.Def_PerPointValue
+ clientPack.HPEx = joinFamily.cityWall.hp / ChConfig.Def_PerPointValue
+ clientPack.DefMemList = []
+ for playerID in joinFamily.joinMemberIDList:
+ if defMemIDList != None and playerID not in defMemIDList:
+ continue
+ joinMember = zone.GetZoneJoinMember(playerID)
+ if not joinMember:
+ continue
+
+ defMem = ChPyNetSendPack.tagGCFamilyGCZCampMem()
+ defMem.PlayerID = playerID
+ defMem.Name = joinMember.playerName
+ defMem.FamilyLV = joinMember.fmLV
+ defMem.Face = joinMember.face
+ defMem.FacePic = joinMember.facePic
+ defMem.FightPower = joinMember.fightPower % ChConfig.Def_PerPointValue
+ defMem.FightPowerEx = joinMember.fightPower / ChConfig.Def_PerPointValue
+ defMem.HP = joinMember.hp % ChConfig.Def_PerPointValue
+ defMem.HPEx = joinMember.hp / ChConfig.Def_PerPointValue
+ defMem.HPMax = joinMember.hpMax % ChConfig.Def_PerPointValue
+ defMem.HPMaxEx = joinMember.hpMax / ChConfig.Def_PerPointValue
+ defMem.TotalHurt = joinMember.totalHurtValue % ChConfig.Def_PerPointValue
+ defMem.TotalHurtEx = joinMember.totalHurtValue / ChConfig.Def_PerPointValue
+ clientPack.DefMemList.append(defMem)
+
+ clientPack.DefMemCnt = len(clientPack.DefMemList)
+ NetPackCommon.SendFakePackByCross(onlinePlayerIDDict, clientPack)
+ return
+
+## -------------------------------------------------------------------------------------------------
+def OnPlayerLogin(curPlayer):
+ PlayerControl.DoOfflineUnprocessed(curPlayer, "FamilyGCZAtkResult", __DoOfflineFamilyGCZAtkResult)
+ PlayerControl.DoOfflineUnprocessed(curPlayer, "FamilyGCZAward", __DoOfflineFamilyGCZAward)
+ return
+
+def ClientServer_CrossActInfo():
+ ## 子服处理 - 活动状态信息
+ return
+
+def MapServer_FamilyGCZ(curPlayer, msgList):
+ mapID = curPlayer.GetRealMapID()
+ playerID = curPlayer.GetPlayerID()
+ GameWorld.DebugLog("MapServer_FamilyGCZ mapID=%s,msgList=%s" % (mapID, msgList), playerID)
+ if not msgList:
+ return
+
+ #msgType, dataMsg = msgList
+ ret = None
+
+ if ret == None:
+ return
+ return msgList + (ret if isinstance(ret, list) else [ret])
+
+def MapServer_QueryPlayerResult(curPlayer, msgType, dataMsg=[]):
+ ret = 1
+ msgInfo = str([msgType, dataMsg, ret])
+ curPlayer.MapServer_QueryPlayerResult(0, 0, "FamilyGCZ", msgInfo, len(msgInfo))
+ return
+
+#// C0 26 仙盟攻城战查询 #tagCGFamilyGCZQuery
+#
+#struct tagCGFamilyGCZQuery
+#{
+# tagHead Head;
+# BYTE QueryType; //查询类型:1-成员捐献值;2-进入城池场景;3-退出城池场景;4-进入城池;5-退出城池;6-战报;7-分组仙盟成员伤害;
+# BYTE BatType; //指定战场类型,需要发送的查询类型: 2、4
+# BYTE GroupNum; //指定分组编号,需要发送的查询类型: 2、4
+# DWORD FamilyID; //指定仙盟ID或城池ID,查自己盟的可不发,需要发的类型:2、4、6、7
+#};
+def OnFamilyGCZQuery(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ queryType = clientData.QueryType
+ batType = clientData.BatType
+ groupNum = clientData.GroupNum
+ familyID = clientData.FamilyID
+
+ playerID = curPlayer.GetPlayerID()
+ dataMsg = {"ActMsgType":"Query", "playerID":playerID, "queryType":queryType, "batType":batType, "groupNum":groupNum, "familyID":familyID}
+ CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_FamilyGCZ, dataMsg)
+ return
+ return
+
+def CrossServerMsg_FamilyGCZ(dataMsg):
+ ## 收到跨服服务器同步的跨服运营活动状态
+
+ actMsgType = dataMsg["ActMsgType"]
+ if actMsgType == "FamilyGCZPlayerActInfo":
+ __clientServer_FamilyGCZPlayerActInfo(dataMsg)
+
+ elif actMsgType == "FamilyGCZAtkResult":
+ atkRet = dataMsg["atkRet"]
+ playerID = dataMsg["reqMsg"]["playerID"]
+ if not PlayerControl.GetDBPlayerAccIDByID(playerID):
+ return
+ curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+ if not curPlayer:
+ if atkRet != AtkRet_OK:
+ # 不是攻击成功的,玩家不在线可以不处理
+ return
+ PlayerControl.AddOfflineUnprocessed(playerID, "FamilyGCZAtkResult", dataMsg)
+ return
+ MapServer_QueryPlayerResult(curPlayer, "FamilyGCZAtkResult", dataMsg)
+
+ elif actMsgType == "FamilyGCZAward":
+ playerID = dataMsg["playerID"]
+ if not PlayerControl.GetDBPlayerAccIDByID(playerID):
+ return
+ curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
+ if not curPlayer:
+ PlayerControl.AddOfflineUnprocessed(playerID, "FamilyGCZAward", dataMsg)
+ return
+ MapServer_QueryPlayerResult(curPlayer, "FamilyGCZAward", dataMsg)
+
+ return
+
+def __DoOfflineFamilyGCZAtkResult(curPlayer, recData, eventName, eventData):
+ ## 执行离线未处理的战斗结果
+ MapServer_QueryPlayerResult(curPlayer, "FamilyGCZAtkResult", eventData)
+ return
+
+def __DoOfflineFamilyGCZAward(curPlayer, recData, eventName, eventData):
+ ## 执行离线未处理的
+ MapServer_QueryPlayerResult(curPlayer, "FamilyGCZAward", eventData)
+ return
+
+def __clientServer_FamilyGCZPlayerActInfo(dataMsg):
+ playerActInfo = dataMsg["playerActInfo"]
+
+ playerManager = GameWorld.GetPlayerManager()
+ for playerID, pActInfo in playerActInfo.items():
+ if not PlayerControl.GetDBPlayerAccIDByID(playerID):
+ # 非本服玩家
+ return
+ curPlayer = playerManager.FindPlayerByID(playerID)
+ if curPlayer:
+ MapServer_QueryPlayerResult(curPlayer, "FamilyGCZPlayerActInfo", pActInfo)
+
+ return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
index a7f3d39..451dbf4 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
@@ -18,9 +18,11 @@
import GameWorld
import ShareDefine
import PlayerAssist
+import PlayerFamily
import PlayerControl
import PlayerPackData
import PlayerFuncTeam
+import NetPackCommon
import CrossLuckyCloudBuy
import IPY_GameServer
import PlayerViewCache
@@ -35,6 +37,7 @@
import CrossActAllRecharge
import CrossChampionship
import CrossBattlefield
+import CrossFamilyGCZ
import CrossBillboard
import CrossYaomoBoss
import GameWorldBoss
@@ -224,6 +227,12 @@
elif msgType == ShareDefine.ClientServerMsg_LianqiScore:
PlayerActLianqi.ClientServerMsg_LianqiScore(serverGroupID, msgData)
+ elif msgType == ShareDefine.ClientServerMsg_SyncFamilyInfo:
+ PlayerFamily.ClientServerMsg_SyncFamilyInfo(serverGroupID, msgData)
+
+ elif msgType == ShareDefine.ClientServerMsg_FamilyGCZ:
+ CrossFamilyGCZ.ClientServerMsg_FamilyGCZ(serverGroupID, msgData)
+
elif msgType == ShareDefine.ClientServerMsg_CreateFuncTeam:
PlayerFuncTeam.ClientServerMsg_CreateFuncTeam(serverGroupID, msgData)
@@ -405,6 +414,9 @@
elif msgType == ShareDefine.CrossServerMsg_PlayerLoginout:
ChPlayer.CrossServerMsg_PlayerLoginout(msgData)
+ elif msgType == ShareDefine.CrossServerMsg_SendFakePack:
+ NetPackCommon.CrossServerMsg_SendFakePack(msgData)
+
elif msgType == ShareDefine.CrossServerMsg_ChatCrossWorld:
PlayerTalk.CrossServerMsg_ChatCrossWorld(msgData)
@@ -458,6 +470,12 @@
elif msgType == ShareDefine.CrossServerMsg_FuncTeamList:
PlayerFuncTeam.CrossServerMsg_FuncTeamList(msgData)
+
+ elif msgType == ShareDefine.CrossServerMsg_FamilyDelRet:
+ PlayerFamily.CrossServerMsg_FamilyDelRet(msgData)
+
+ elif msgType == ShareDefine.CrossServerMsg_FamilyGCZ:
+ CrossFamilyGCZ.CrossServerMsg_FamilyGCZ(msgData)
elif msgType == ShareDefine.CrossServerMsg_Worship:
GameWorship.CrossServerMsg_Worship(msgData)
@@ -636,5 +654,12 @@
SendMsgToCrossServer(ShareDefine.ClientServerMsg_ServerInitOK, dataMsg)
return
-
-
\ No newline at end of file
+def OnCrossServerStateOpen():
+ '''子服收到跨服服务器通知 - 跨服服务器状态正常开放中,可能是启动、重连、或者维护后重新开放
+ 这里可以处理一些子服与跨服正式建立常规逻辑通讯(注意与socket连接区分,这里指的是逻辑通讯)后的逻辑
+ 注:跨服子服socket连接后,并不能正式开始逻辑消息通讯,需要等待双方都启动成功后才可以
+ 即子服发送 ClientServerMsg_ServerInitOK 告知启动成功
+ 然后跨服回复开启状态后才算正式建立常规逻辑通讯
+ '''
+ PlayerFamily.Sync_ClientFamilyAllToCrossServer()
+ return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py
index 8690970..f1bb836 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameRecData.py
@@ -58,7 +58,7 @@
def SetValue7(self, value7): self.dbRecData.Value7 = value7
def GetValue8(self): return self.dbRecData.Value8
def SetValue8(self, value8): self.dbRecData.Value8 = value8
- def __GetUserDataDict(self):
+ def GetUserDataDict(self):
if self.__userDataDict == None:
try:
self.__userDataDict = eval(self.dbRecData.UserData)
@@ -66,12 +66,12 @@
self.__userDataDict = {}
return self.__userDataDict
def GetUserDataByKey(self, key, defaultValue=None):
- userDataDict = self.__GetUserDataDict()
+ userDataDict = self.GetUserDataDict()
if key in userDataDict:
return userDataDict[key]
return defaultValue
def SetUserDataByKey(self, key, value):
- userDataDict = self.__GetUserDataDict()
+ userDataDict = self.GetUserDataDict()
userDataDict[key] = value
self.__userDataChange = True
return
@@ -112,7 +112,7 @@
return {"RecID":self.GetRecID(), "RecType":self.GetRecType(), "Time":self.GetTime(),
"Value1":self.GetValue1(), "Value2":self.GetValue2(), "Value3":self.GetValue3(), "Value4":self.GetValue4(),
"Value5":self.GetValue5(), "Value6":self.GetValue6(), "Value7":self.GetValue7(), "Value8":self.GetValue8(),
- "UserDataDict":self.__GetUserDataDict()
+ "UserDataDict":self.GetUserDataDict()
}
def SetAttr(self, attrDict, isClear=False):
if isClear:
@@ -324,6 +324,33 @@
matchRecDataList.append(recData)
return matchRecDataList
+ def GetGameRecDataMatchEx(self, recType, valueList, findone=False):
+ '''获取记录类型对应的匹配value值记录
+ @param recType: 记录类型
+ @param valueList: [value1, value2, ...] value为None时不判断该值
+ @param findone: 是否只匹配一条满足的记录
+ @return: recData or [recData, ...] or None
+ '''
+ if recType not in self.recTypeDict:
+ return
+ recDataDict = self.recTypeDict[recType]
+ for recID in recDataDict.keys():
+ matchRet = self.GetGameRecDataMatch(recType, recID, valueList, findone)
+ if matchRet:
+ return matchRet
+ return
+
+ def GetGameRecDataFirst(self, recType, recID, isAddNew):
+ ## 获取记录类型对应的第一条记录,适用于仅需一条的记录类型
+ # @param isAddNew: 没有记录时是否添加一条新记录,一般获取后需要更新数据的可以设置为True,仅判断用的建议设置为False,减少产生多余空数据
+ recData = None
+ recDataList = self.GetGameRecDataList(recType, recID)
+ if recDataList:
+ recData = recDataList[0]
+ elif isAddNew:
+ recData = self.AddGameRecData(recType, recID)
+ return recData
+
def GetGameRecDataList(self, recType, recID):
## 获取记录类型对应记录列表 [recData, ...]
if recType not in self.recTypeDict:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
index 54f790c..4cd71d1 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/GameWorldProcess.py
@@ -97,7 +97,6 @@
import IpyGameDataPY
import PlayerFamilyParty
import PlayerFamilyZhenfa
-import PlayerFamilyEmblem
import GameWorldFamilyWar
import GameWorldArena
import CrossLuckyCloudBuy
@@ -396,12 +395,8 @@
AuctionHouse.OnAuctionItemMinuteProcess(tick)
#福地
GameWorldMineArea.OnProcessOnMinute()
- #每5分钟触发一次仙盟总战力更新
- if curMinute % 5 == 0:
- PlayerFamily.UpdFamilyTotalFightPower()
- PlayerFamilyRedPacket.CheckDelRedpacketData()
- PlayerFamilyEmblem.CheckExpireEmblem()
-
+ #仙盟
+ PlayerFamily.OnMinuteProcess(curMinute)
return
def CheckServerHasPlayerLoginAfterInitOK():
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index d5d148a..b711674 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -646,6 +646,54 @@
("dict", "ScoreAwardEx", 0),
),
+ "ActTimeFlow":(
+ ("DWORD", "FlowID", 1),
+ ("BYTE", "StartDay", 0),
+ ("BYTE", "StartHour", 0),
+ ("BYTE", "StartMinute", 0),
+ ("BYTE", "EndDay", 0),
+ ("BYTE", "EndHour", 0),
+ ("BYTE", "EndMinute", 0),
+ ("WORD", "StateValue", 0),
+ ),
+
+ "ActBillboardAwardTemp":(
+ ("DWORD", "TemplateID", 1),
+ ("BYTE", "Rank", 0),
+ ("DWORD", "NeedValue", 0),
+ ("dict", "ValueAwardEx", 0),
+ ("list", "AwardItemList", 0),
+ ("list", "LeaderAwardItemList", 0),
+ ("list", "EliteAwardItemList", 0),
+ ),
+
+ "ActGuess":(
+ ("DWORD", "TemplateID", 1),
+ ("DWORD", "AwardID", 0),
+ ("list", "RightRankList", 0),
+ ("list", "AwardItemList", 0),
+ ),
+
+ "CrossActFamilyGCZ":(
+ ("DWORD", "CfgID", 1),
+ ("char", "ActGroupName", 0),
+ ("BYTE", "ZoneID", 0),
+ ("list", "ServerIDRangeList", 0),
+ ("char", "StartDate", 0),
+ ("char", "EndDate", 0),
+ ("BYTE", "JoinFamilyCnt", 0),
+ ("WORD", "ActFlowID", 0),
+ ("WORD", "GuessTemplateID", 0),
+ ("WORD", "PersonalTemplateID", 0),
+ ("WORD", "FamilyTemplateID", 0),
+ ),
+
+ "CrossActFamilyGCZCampLV":(
+ ("DWORD", "CampLV", 1),
+ ("DWORD", "LVUPNeedExp", 0),
+ ("DWORD", "AddHPPer", 0),
+ ),
+
"ActXianXiaMJ":(
("DWORD", "CfgID", 1),
("list", "PlatformList", 0),
@@ -2141,6 +2189,79 @@
def GetNeedScore(self): return self.attrTuple[3] # 上榜所需积分 DWORD
def GetScoreAwardEx(self): return self.attrTuple[4] # 达标积分额外奖励 {积分:[[物品ID,个数,是否拍品], ...], ...} dict
+# 活动时间流程表
+class IPY_ActTimeFlow():
+
+ def __init__(self):
+ self.attrTuple = None
+ return
+
+ def GetFlowID(self): return self.attrTuple[0] # DWORD
+ def GetStartDay(self): return self.attrTuple[1] # 开始天 BYTE
+ def GetStartHour(self): return self.attrTuple[2] # 开始时 BYTE
+ def GetStartMinute(self): return self.attrTuple[3] # 开始分 BYTE
+ def GetEndDay(self): return self.attrTuple[4] # 结束天 BYTE
+ def GetEndHour(self): return self.attrTuple[5] # 结束时 BYTE
+ def GetEndMinute(self): return self.attrTuple[6] # 结束分 BYTE
+ def GetStateValue(self): return self.attrTuple[7] # 状态值 WORD
+
+# 活动榜单奖励模版表
+class IPY_ActBillboardAwardTemp():
+
+ def __init__(self):
+ self.attrTuple = None
+ return
+
+ def GetTemplateID(self): return self.attrTuple[0] # 模板编号 DWORD
+ def GetRank(self): return self.attrTuple[1] # 名次 BYTE
+ def GetNeedValue(self): return self.attrTuple[2] # 上榜所需值 DWORD
+ def GetValueAwardEx(self): return self.attrTuple[3] # 达标值额外奖励 {值:[[物品ID,个数,是否拍品], ...], ...} dict
+ def GetAwardItemList(self): return self.attrTuple[4] # 奖励物品列表[[物品ID,个数,是否拍品], ...] list
+ def GetLeaderAwardItemList(self): return self.attrTuple[5] # 仙盟榜盟主奖励物品信息列表[[物品ID,个数,是否拍品], ...] list
+ def GetEliteAwardItemList(self): return self.attrTuple[6] # 仙盟榜精英奖励物品信息列表[[物品ID,个数,是否拍品], ...] list
+
+# 活动竞猜表
+class IPY_ActGuess():
+
+ def __init__(self):
+ self.attrTuple = None
+ return
+
+ def GetTemplateID(self): return self.attrTuple[0] # 模板编号 DWORD
+ def GetAwardID(self): return self.attrTuple[1] # 奖励ID DWORD
+ def GetRightRankList(self): return self.attrTuple[2] # 猜对名次列表 list
+ def GetAwardItemList(self): return self.attrTuple[3] # 对应奖励列表 [[物品ID,个数,是否拍品], ...] list
+
+# 仙盟攻城战活动表
+class IPY_CrossActFamilyGCZ():
+
+ def __init__(self):
+ self.attrTuple = None
+ return
+
+ def GetCfgID(self): return self.attrTuple[0] # 配置ID DWORD
+ def GetActGroupName(self): return self.attrTuple[1] # 活动组名(同组活动的名字需相同) char
+ def GetZoneID(self): return self.attrTuple[2] # 组内分组编号 BYTE
+ def GetServerIDRangeList(self): return self.attrTuple[3] # 活动的服务器ID范围列表 [[serverIDA, serverIDB], ...] list
+ def GetStartDate(self): return self.attrTuple[4] # 开启日期 char
+ def GetEndDate(self): return self.attrTuple[5] # 结束日期 char
+ def GetJoinFamilyCnt(self): return self.attrTuple[6] # 参与仙盟数 BYTE
+ def GetActFlowID(self): return self.attrTuple[7] # 活动流程ID,对应H.活动时间流程表 WORD
+ def GetGuessTemplateID(self): return self.attrTuple[8] # 竞猜奖励模版,对应H.活动竞猜表 WORD
+ def GetPersonalTemplateID(self): return self.attrTuple[9] # 个人伤害排行奖励模版,对应H.活动榜单奖励模版表 WORD
+ def GetFamilyTemplateID(self): return self.attrTuple[10] # 仙盟积分排行奖励模版,对应H.活动榜单奖励模版表 WORD
+
+# 仙盟攻城战大本营等级表
+class IPY_CrossActFamilyGCZCampLV():
+
+ def __init__(self):
+ self.attrTuple = None
+ return
+
+ def GetCampLV(self): return self.attrTuple[0] # 大本营等级 DWORD
+ def GetLVUPNeedExp(self): return self.attrTuple[1] # 升下一级所需经验 DWORD
+ def GetAddHPPer(self): return self.attrTuple[2] # 生命累计总加成百分比 DWORD
+
# 仙匣秘境活动时间表
class IPY_ActXianXiaMJ():
@@ -3111,6 +3232,11 @@
self.__LoadFileData("ActGubaoBillTemp", onlyCheck)
self.__LoadFileData("CrossActLianqi", onlyCheck)
self.__LoadFileData("ActLianqiBillTemp", onlyCheck)
+ self.__LoadFileData("ActTimeFlow", onlyCheck)
+ self.__LoadFileData("ActBillboardAwardTemp", onlyCheck)
+ self.__LoadFileData("ActGuess", onlyCheck)
+ self.__LoadFileData("CrossActFamilyGCZ", onlyCheck)
+ self.__LoadFileData("CrossActFamilyGCZCampLV", onlyCheck)
self.__LoadFileData("ActXianXiaMJ", onlyCheck)
self.__LoadFileData("CrossActXianXiaMJ", onlyCheck)
self.__LoadFileData("ActXianXiaMJBillTemp", onlyCheck)
@@ -3795,6 +3921,41 @@
self.CheckLoadData("ActLianqiBillTemp")
return self.ipyActLianqiBillTempCache[index]
+ def GetActTimeFlowCount(self):
+ self.CheckLoadData("ActTimeFlow")
+ return self.ipyActTimeFlowLen
+ def GetActTimeFlowByIndex(self, index):
+ self.CheckLoadData("ActTimeFlow")
+ return self.ipyActTimeFlowCache[index]
+
+ def GetActBillboardAwardTempCount(self):
+ self.CheckLoadData("ActBillboardAwardTemp")
+ return self.ipyActBillboardAwardTempLen
+ def GetActBillboardAwardTempByIndex(self, index):
+ self.CheckLoadData("ActBillboardAwardTemp")
+ return self.ipyActBillboardAwardTempCache[index]
+
+ def GetActGuessCount(self):
+ self.CheckLoadData("ActGuess")
+ return self.ipyActGuessLen
+ def GetActGuessByIndex(self, index):
+ self.CheckLoadData("ActGuess")
+ return self.ipyActGuessCache[index]
+
+ def GetCrossActFamilyGCZCount(self):
+ self.CheckLoadData("CrossActFamilyGCZ")
+ return self.ipyCrossActFamilyGCZLen
+ def GetCrossActFamilyGCZByIndex(self, index):
+ self.CheckLoadData("CrossActFamilyGCZ")
+ return self.ipyCrossActFamilyGCZCache[index]
+
+ def GetCrossActFamilyGCZCampLVCount(self):
+ self.CheckLoadData("CrossActFamilyGCZCampLV")
+ return self.ipyCrossActFamilyGCZCampLVLen
+ def GetCrossActFamilyGCZCampLVByIndex(self, index):
+ self.CheckLoadData("CrossActFamilyGCZCampLV")
+ return self.ipyCrossActFamilyGCZCampLVCache[index]
+
def GetActXianXiaMJCount(self):
self.CheckLoadData("ActXianXiaMJ")
return self.ipyActXianXiaMJLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/NetPackCommon.py b/ServerPython/CoreServerGroup/GameServer/Script/NetPackCommon.py
index 6ca8e2a..e354686 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/NetPackCommon.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/NetPackCommon.py
@@ -31,6 +31,8 @@
import ChMapToGamePyPack
import CrossRealmMsg
import PlayerControl
+import ChPlayer
+import ShareDefine
#-------------------------------------------------------------------------------
#---全局变量---
@@ -241,6 +243,34 @@
SendFakePack(curPlayer, clientPack)
return
+def SendFakePackByCross(onlinePlayerIDDict, clientPack):
+ '''由跨服服务器直接给子服在线玩家发送封包,适用于接受的玩家封包数据一致的
+ @param onlinePlayerIDDict: 在线玩家GroupID字典 {playerID:groupID, ...}
+ 功能自行通过 onlineMgr = ChPlayer.GetOnlinePlayerMgr() 过滤
+ onlineMgr.GetOLPlayerServerGroupID(playerID) 获取ServerGroupID
+ '''
+ if not onlinePlayerIDDict:
+ return
+ innerPackData = clientPack.GetBuffer()
+ dataMsg = {"playerIDList":onlinePlayerIDDict.keys(), "innerPackData":innerPackData}
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_SendFakePack, dataMsg, onlinePlayerIDDict.values())
+ return
+
+def CrossServerMsg_SendFakePack(msgData):
+ ## 子服收到由跨服直接发送给玩家的封包
+ playerIDList = msgData["playerIDList"]
+ innerPackData = msgData["innerPackData"]
+
+ playerManager = GameWorld.GetPlayerManager()
+ for playerID in playerIDList:
+ curPlayer = playerManager.FindPlayerByID(playerID)
+ if curPlayer == None:
+ continue
+ if PlayerControl.GetIsTJG(curPlayer):
+ continue
+ curPlayer.Sync_GeneralPack(len(innerPackData), innerPackData)
+
+ return
#-------------------------------------------------------------------------------
#---Py封包注册信息
PyPackTable = ReadPyPackTable("PyNetPack")
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
index 5232ad5..a260ded 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -81,6 +81,7 @@
import PlayerRecData
import GameWorship
import GameXiangong
+import CrossFamilyGCZ
#---------------------------------------------------------------------
#---------------------------------------------------------------------
@@ -95,6 +96,8 @@
return
def IsOnline(self, playerID): return playerID in self.onlinePlayerDict
+
+ def GetOLPlayerServerGroupID(self, playerID): return self.onlinePlayerDict.get(playerID, 0)
def __SetOnline(self, playerID, serverGroupID):
self.onlinePlayerDict[playerID] = serverGroupID
@@ -287,6 +290,8 @@
CrossBattlefield.OnPlayerLogin(curPlayer)
#跨服排位
CrossChampionship.OnPlayerLogin(curPlayer, tick)
+ #仙盟攻城战
+ CrossFamilyGCZ.OnPlayerLogin(curPlayer)
#跨服全民充值
CrossActAllRecharge.OnPlayerLogin(curPlayer)
#跨服妖魔boss
@@ -708,6 +713,8 @@
CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_PlayerPackDataState, syncStateInfo, [serverGroupID])
GameXiangong.OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID)
+ #仙盟攻城战
+ CrossFamilyGCZ.OnPlayerLogin_CrossLogic(serverGroupID, serverID, playerID)
# 下线
else:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py
index 7dbf112..d070849 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py
@@ -167,7 +167,9 @@
if curPlayer == None:
continue
PlayerControl.SetCrossMapID(curPlayer, 0)
-
+ else:
+ CrossRealmMsg.OnCrossServerStateOpen()
+
GameWorld.GetGameWorld().SendCrossServerStateToLoginServer(isOpen)
# 通知地图
GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_CrossServerOpen, isOpen)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
index 674d42a..e103424 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerDBGSEvent.py
@@ -195,6 +195,8 @@
Def_ActHorsePetTrainAwardC = "ActHorsePetTrainAwardC_%s"
#跨服炼器结算状态,参数(zoneID)
Def_ActLianqiAwardC = "ActLianqiAwardC_%s"
+#活动流程状态是否已经异常 - 按流程走的活动只能按状态顺序执行,不能跳状态,否则视为活动异常,参数(actName, zoneID),存储的值为异常的活动ID
+Def_ActFlowStateError = "SE%s%s"
def SetInitOpenServerTime(initTime):
openDatetime = GameWorld.ChangeTimeNumToDatetime(initTime)
@@ -268,7 +270,7 @@
# @param value 设置value
# @return 返回trig
# @remarks 函数详细说明.
-def SetDBGSTrig_ByKey( key , value ):
+def SetDBGSTrig_ByKey( key , value):
gsEventTrigManager = GameWorld.GetGameWorld().GetDBGameServerEventTrigManager()
trig = gsEventTrigManager.Find( key )
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
index d9af3a4..ff60117 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
@@ -44,6 +44,8 @@
import PlayerFamilySWRH
import PlayerViewCache
import GameWorldBoss
+import CrossRealmMsg
+import CrossFamilyGCZ
import AuctionHouse
import PlayerAssist
import PlayerTalk
@@ -61,6 +63,62 @@
ImpeachLastTime # 弹劾需要持续的时间
) = range(3)
+class FamilyMgr():
+
+ def __init__(self):
+ self.sortFamilyIDList = [] #本服仙盟排序顺序 [familyID, ...]
+ self.fightPowerChangeFamilyIDList = [] # 仙盟成员战力有变更的仙盟ID [familyID, ...]
+
+ #这里仅针对增改信息,删除的另外处理,因为删除的需要确保成功删除,所以需要入库未成功删除的记录
+ #而变更同步的会定时同步,每次重连服务器也会强制同步,所以不需要有成功回复
+ self.syncCrossFamilyDict = {} # 需要同步跨服的仙盟 {familyID:[需要同步的成员ID, ...], ...}
+ return
+
+ def OnDeleteFamilyID(self, familyID):
+ if familyID in self.sortFamilyIDList:
+ self.sortFamilyIDList.remove(familyID) # 直接从排序列表中移除, 不需要重新排序
+ self.SetSyncCrossFamilyDel(familyID) # 解散仙盟
+ return
+
+ def GetFamilyIDRank(self, familyID):
+ if familyID not in self.sortFamilyIDList:
+ return len(self.sortFamilyIDList) + 1
+ return self.sortFamilyIDList.index(familyID) + 1
+
+ def AddFamilyIDToFightPowerChangeList(self, familyID, playerID=0):
+ if familyID not in self.fightPowerChangeFamilyIDList:
+ self.fightPowerChangeFamilyIDList.append(familyID)
+ GameWorld.DebugLog("仙盟战力变更待处理列表: fightPowerChangeFamilyIDList=%s" % self.fightPowerChangeFamilyIDList)
+ self.SetSyncCrossFamilyUpd(familyID, playerID) # 仙盟战力变更、成员战力变更
+ return
+
+ def SetSyncCrossFamilyUpd(self, familyID, playerID=0, syncNow=False):
+ if familyID not in self.syncCrossFamilyDict:
+ self.syncCrossFamilyDict[familyID] = []
+ if playerID:
+ needSyncMemIDList = self.syncCrossFamilyDict[familyID]
+ if playerID not in needSyncMemIDList:
+ needSyncMemIDList.append(playerID)
+ # 变更数据是否立即同步跨服,否则等待定时同步即可
+ if syncNow:
+ Sync_ClientFamilyUpdToCrossServer()
+ return
+
+ def SetSyncCrossFamilyDel(self, familyID, playerID=0):
+ ## 设置同步跨服服务器仙盟删除
+ # @param playerID: 如果有值代表仅成员删除
+ valueSetList = [playerID]
+ gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+ gameRecMgr.AddGameRecData(ShareDefine.Def_GameRecType_FamilyDelSyncCross, familyID, valueSetList)
+ Sync_ClientFamilyDelToCrossServer() # 删除的立马同步
+ return
+
+def GetFamilyMgr():
+ mgr = PyGameData.g_familyMgr
+ if not mgr:
+ mgr = FamilyMgr()
+ PyGameData.g_familyMgr = mgr
+ return mgr
## ------------------ 仙盟 ----------------------
## 仙盟联赛排名
@@ -71,6 +129,7 @@
def SetFamilyTotalFightPower(curFamily, totalFightPower):
curFamily.SetExtra4(totalFightPower / ChConfig.Def_PerPointValue)
curFamily.SetExtra5(totalFightPower % ChConfig.Def_PerPointValue)
+ GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID()) # 仙盟战力变更
return
def GetFamilyTotalFightPowerByID(familyID):
family = GameWorld.GetFamilyManager().FindFamily(familyID)
@@ -79,7 +138,10 @@
return GetFamilyTotalFightPower(family)
# 徽章ID
def GetFamilyEmblemID(curFamily): return curFamily.GetExtra6()
-def SetFamilyEmblemID(curFamily, emblemID): return curFamily.SetExtra6(emblemID)
+def SetFamilyEmblemID(curFamily, emblemID):
+ curFamily.SetExtra6(emblemID)
+ GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID()) # 徽章变更
+ return
# 公告修改次数
def GetFamilyBroadcastCnt(curFamily): return curFamily.GetExtra3()
@@ -108,11 +170,17 @@
def OnGameServerInitOK():
## 服务器启动成功处理
- DoFamilySort()
+ if GameWorld.IsCrossServer():
+ pass
+ else:
+ DoFamilySort()
return
def OnMixServerInit():
## 合服后首次启动成功处理
+
+ if GameWorld.IsCrossServer():
+ return
# 仙盟联赛重置
GameWorldFamilyWar.DoFamilyWarReset()
@@ -440,7 +508,7 @@
#加入家族
familyMember = curFamily.AddMember(jionPlayer)
#刷新基本信息
- RefreshFamilyMemberBaseMsg(familyMember, jionPlayer)
+ RefreshFamilyMemberBaseMsg(curFamily, familyMember, jionPlayer)
#族长设置
if jionFamilySetLv == IPY_GameServer.fmlLeader:
@@ -486,7 +554,7 @@
#仙盟拍品
AuctionHouse.Sync_FamilyAuctionItemInfo(jionPlayer, curFamily.GetID())
SetMemberFightPower(familyMember, PlayerControl.GetFightPower(jionPlayer))
- AddFamilyIDToFightPowerChangeList(curFamily.GetID())
+ GetFamilyMgr().AddFamilyIDToFightPowerChangeList(curFamily.GetID(), jionPlayer.GetPlayerID())
#通知仙盟盛宴题目
PlayerFamilyParty.NotifyFamilyPartyQuestion(jionPlayer)
@@ -678,7 +746,7 @@
# @remarks 通知客户端服务器家族信息
def Sync_AllFamilyInfo(curPlayer, viewPage, pageCnt=ChConfig.Def_ViewAllFamilyPageCount, sortRule=IPY_GameServer.fsrHornor):
#familyCount = GameWorld.GetFamilyManager().GetCount()
- familyCount = len(PyGameData.g_sortFamilyIDList)
+ familyCount = len(GetFamilyMgr().sortFamilyIDList)
allPageCnt = GameWorld.GetIntUpper(familyCount, pageCnt)
if allPageCnt != 0 and (viewPage < 0 or viewPage >= allPageCnt):
@@ -716,7 +784,8 @@
return
def Sync_PyAllFamilyInfo(curPlayer, allPageCnt, viewPage, startIndex, endIndex):
- familyCount = len(PyGameData.g_sortFamilyIDList)
+ sortFamilyIDList = GetFamilyMgr().sortFamilyIDList
+ familyCount = len(sortFamilyIDList)
if startIndex < 0 or endIndex >= familyCount:
return
@@ -727,7 +796,7 @@
familyViewPack.CurPage = viewPage
familyViewPack.Family = []
for i in xrange(startIndex, endIndex + 1):
- familyID = PyGameData.g_sortFamilyIDList[i]
+ familyID = sortFamilyIDList[i]
family = familyMgr.FindFamily(familyID)
if not family:
continue
@@ -785,7 +854,7 @@
familyViewPack.TotalCount = 1
#familyViewPack.CurPage = viewPage
familyViewPack.Family = []
- for i, familyID in enumerate(PyGameData.g_sortFamilyIDList):
+ for i, familyID in enumerate(GetFamilyMgr().sortFamilyIDList):
family = familyMgr.FindFamily(familyID)
if not family:
continue
@@ -822,7 +891,7 @@
familyViewPack.TotalCount = 1
#familyViewPack.CurPage = viewPage
familyViewPack.Family = []
- for i, familyID in enumerate(PyGameData.g_sortFamilyIDList):
+ for i, familyID in enumerate(GetFamilyMgr().sortFamilyIDList):
family = familyMgr.FindFamily(familyID)
if not family:
continue
@@ -908,6 +977,7 @@
continue
curPlayer.ChatMi(notifyPlayer, 1, pack.GetMsg(), 0, PlayerTalk.GetTalkExtraValue(curPlayer))
PyDataManager.GetContactsManager().AddContactsBoth(curPlayer.GetID(), notifyPlayer.GetID())
+ GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID()) # 公告变更
return
## 检测目标玩家是否可以加入家族
@@ -1696,11 +1766,12 @@
PlayerFamilyAction.DelFamilyOfficerModelEquip(curFamily.GetID(), leavePlayerID)
# 玩家战盟名变更处理
__OnFamilyNameChange(leavePlayerID, '')
- AddFamilyIDToFightPowerChangeList(curFamily.GetID())
+ GetFamilyMgr().AddFamilyIDToFightPowerChangeList(curFamily.GetID(), leavePlayerID)
PlayerViewCache.OnPlayerFamilyChange(leavePlayerID, 0, "")
PlayerAssist.OnPlayerLeaveFamily(curFamily.GetID(), leavePlayerID, tagPlayer)
if leavePlayerID in PyGameData.g_autoViceleaderDict.get(curFamily.GetID(),[]):
PyGameData.g_autoViceleaderDict[curFamily.GetID()].remove(leavePlayerID)
+ GetFamilyMgr().SetSyncCrossFamilyDel(curFamily.GetID(), leavePlayerID) # 成员离开、踢出
return
#//////////////////////////////////////////////////////////////
@@ -1845,7 +1916,7 @@
SetMemberFightPower(curMember, fightPower)
GameWorld.DebugLog("仙盟成员战力变更 familyID=%s,fightPower=%s" % (familyID, fightPower), playerID)
- AddFamilyIDToFightPowerChangeList(familyID)
+ GetFamilyMgr().AddFamilyIDToFightPowerChangeList(familyID, playerID)
return
## A4 07 升级家族#tagCGFamilyLVUp
@@ -1954,6 +2025,7 @@
#世界服务器家族重新排序
#GameWorld.GetFamilyManager().SortByLV()
DoFamilySort() # 升级直接强排一次
+ GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID(), syncNow=True) # 仙盟等级变更
return True
#---------------------------------------------------------------------
@@ -2002,6 +2074,8 @@
# @remarks 函数详细说明.
def OnPlayerChangeMap(curPlayer, tick):
#同步给玩家, 最新的家族信息(家族等级刷新)
+ if GameWorld.IsCrossServer():
+ return
curPlayer.MapServer_FamilyRefresh()
return
@@ -2151,7 +2225,7 @@
# @param curPlayer 真实玩家
# @return None
# @remarks 刷新家族成员基本信息
-def RefreshFamilyMemberBaseMsg(curMember, curPlayer):
+def RefreshFamilyMemberBaseMsg(curFamily, curMember, curPlayer):
curMember.SetName(curPlayer.GetName())
curMember.SetLV(curPlayer.GetLV())
curMember.SetReincarnationLv(curPlayer.GetReincarnationLv())
@@ -2160,6 +2234,7 @@
curMember.SetOfficialRank(curPlayer.GetOfficialRank())
curMember.SetFace(curPlayer.GetFace())
curMember.SetFacePic(curPlayer.GetFacePic())
+ GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID(), curPlayer.GetPlayerID()) # 成员基础信息刷新,含加入仙盟刷新
return
#---------------------------------------------------------------------
## 玩家刷新
@@ -2174,9 +2249,9 @@
if curMember == None:
return
- RefreshFamilyMemberBaseMsg(curMember, curPlayer)
- #家族长境界
family = curPlayer.GetFamily()
+ RefreshFamilyMemberBaseMsg(family, curMember, curPlayer)
+ #家族长境界
if family.GetLeaderID() == curPlayer.GetID():
family.SetLeaderOfficialRank(curPlayer.GetOfficialRank())
return
@@ -2292,8 +2367,7 @@
#重新排序家族
#GameWorld.GetFamilyManager().SortByLV()
- if familyID in PyGameData.g_sortFamilyIDList:
- PyGameData.g_sortFamilyIDList.remove(familyID) # 直接从排序列表中移除, 不需要重新排序
+ GetFamilyMgr().OnDeleteFamilyID(familyID)
#家族科技删除, 改为地图直接处理, 暂屏蔽
#PlayerFamilyTech.DelFamilyTechData(familyID)
@@ -2322,6 +2396,7 @@
#设置族长权限
ChangeFamilyMemberLv(familyMember, IPY_GameServer.fmlLeader)
GameWorldFamilyWar.OnChangeFamilyLeader(curFamily.GetID(), familyMember.GetPlayerID())
+ GetFamilyMgr().SetSyncCrossFamilyUpd(curFamily.GetID(), syncNow=True) # 盟主变更
return
#---------------------------------------------------------------------
##更改家族成员等级.
@@ -2353,6 +2428,8 @@
# 变为普通成员,删除模型装备信息
elif changeFamilyLV == IPY_GameServer.fmlMember:
PlayerFamilyAction.DelFamilyOfficerModelEquip(familyMember.GetFamilyID(), familyMember.GetPlayerID())
+
+ GetFamilyMgr().SetSyncCrossFamilyUpd(familyMember.GetFamilyID(), familyMember.GetPlayerID(), syncNow=True) # 成员职位变更
return
#---------------------------------------------------------------------
@@ -2531,6 +2608,7 @@
#通知家族刷新
curFamily.Broadcast_FamilyChange()
+ GetFamilyMgr().SetSyncCrossFamilyUpd(curFamilyID, syncNow=True) # 仙盟改名
playerManager = GameWorld.GetPlayerManager()
#仙盟联赛
@@ -2711,6 +2789,8 @@
# @return 返回值无意义
# @remarks 家族过天
def FamilyOnDay(tick):
+ if GameWorld.IsCrossServer():
+ return
#---设置所有玩家可以再次加入家族---
GameWorld.GetPlayerManager().ClearForbiddenEnterFamily()
#---扣除地图上所有家族的维护费---
@@ -2769,6 +2849,8 @@
return
def FamilyOnDayEx(tick):
+ if GameWorld.IsCrossServer():
+ return
familyManager = GameWorld.GetFamilyManager()
for i in range(0, familyManager.GetCount()):
family = familyManager.GetAt(i)
@@ -2784,7 +2866,8 @@
# @return 返回值无意义
# @remarks 家族过周
def FamilyOnWeek(tick):
-
+ if GameWorld.IsCrossServer():
+ return
#---计算上周家族活跃度---
familyManager = GameWorld.GetFamilyManager()
for i in range(0, familyManager.GetCount()):
@@ -2816,6 +2899,8 @@
return
def FamilyOnHour():
+ if GameWorld.IsCrossServer():
+ return
familyManager = GameWorld.GetFamilyManager()
for i in xrange(familyManager.GetCount()):
family = familyManager.GetAt(i)
@@ -2885,12 +2970,31 @@
return cmp(GetMemberJoinTime(member1), GetMemberJoinTime(member2))
return ret
+def SortCrossFamily(serverIDList, top=0):
+ ''' 跨服仙盟排序, 排序规则: 总战力 > 等级 > ID
+ @param serverIDList: 仙盟所属区服ID范围列表
+ @param top: 返回排序靠前x个仙盟,0则全部返回
+ '''
+ familyList = []
+ familyManager = GameWorld.GetFamilyManager()
+ for i in xrange(familyManager.GetCount()):
+ family = familyManager.GetAt(i)
+ serverID = family.GetServerID()
+ if not GameWorld.CheckServerIDInList(serverID, serverIDList):
+ continue
+ familyList.append(family)
+ familyList.sort(key=lambda f: (GetFamilyTotalFightPower(f), f.GetLV(), f.GetID()), reverse=True)
+ totalCnt = len(familyList)
+ return familyList[:top] if top else familyList, totalCnt
+
#---------------------------------------------------------------------
##通知地图服务器, 玩家家族属性刷新
# @param curFamily 家族实例
# @return 返回值无意义
# @remarks IPY_MFamilyRefresh
def SendPack_MapServer_PlayerFamilyRefresh(curFamily):
+ if GameWorld.IsCrossServer():
+ return
#===============================================================================
# 当家族以下权限变更时要通知地图服务器 IPY_MFamilyRefresh
# GetFamilyLV
@@ -3534,21 +3638,30 @@
break
return leaderLV
-def AddFamilyIDToFightPowerChangeList(familyID):
- if familyID not in PyGameData.g_fightPowerChangeFamilyIDList:
- PyGameData.g_fightPowerChangeFamilyIDList.append(familyID)
- GameWorld.DebugLog("仙盟战力变更待处理列表: fightPowerChangeFamilyIDList=%s" % PyGameData.g_fightPowerChangeFamilyIDList)
+def OnMinuteProcess(curMinute):
+ if GameWorld.IsCrossServer():
+ return
+
+ #每5分钟触发一次仙盟更新
+ if curMinute % 5 != 0:
+ return
+
+ UpdFamilyTotalFightPower()
+ PlayerFamilyRedPacket.CheckDelRedpacketData()
+ PlayerFamilyEmblem.CheckExpireEmblem()
+ Sync_ClientFamilyUpdToCrossServer()
return
def UpdFamilyTotalFightPower():
## 更新仙盟总战力
- if not PyGameData.g_fightPowerChangeFamilyIDList:
+ mgr = GetFamilyMgr()
+ if not mgr.fightPowerChangeFamilyIDList:
#GameWorld.DebugLog("不需要更新仙盟总战力!")
return
- GameWorld.DebugLog("更新仙盟总战力 fightPowerChangeFamilyIDList=%s" % PyGameData.g_fightPowerChangeFamilyIDList)
+ GameWorld.DebugLog("更新仙盟总战力 fightPowerChangeFamilyIDList=%s" % mgr.fightPowerChangeFamilyIDList)
familyManager = GameWorld.GetFamilyManager()
- for familyID in PyGameData.g_fightPowerChangeFamilyIDList:
+ for familyID in mgr.fightPowerChangeFamilyIDList:
family = familyManager.FindFamily(familyID)
if not family:
continue
@@ -3560,19 +3673,17 @@
SetFamilyTotalFightPower(family, totalFightPower)
GameWorld.DebugLog(" familyID=%s,totalFightPower=%s" % (familyID, totalFightPower))
- PyGameData.g_fightPowerChangeFamilyIDList = []
+ mgr.fightPowerChangeFamilyIDList = []
DoFamilySort(False) # 此处必须为False
return True
-def GetSortFamilyIDList(): return PyGameData.g_sortFamilyIDList
+def GetSortFamilyIDList(): return GetFamilyMgr().sortFamilyIDList
def GetFamilyIDRank(familyID):
'''获取仙盟的排名, 注意与联赛排名区分
每个仙盟一定有排名,但是不一定有联赛排名,联赛排名只是决定仙盟最终排名的一个比较因素
'''
- if familyID not in PyGameData.g_sortFamilyIDList:
- return len(PyGameData.g_sortFamilyIDList) + 1
- return PyGameData.g_sortFamilyIDList.index(familyID) + 1
+ return GetFamilyMgr().GetFamilyIDRank(familyID)
def DoFamilySort(isUpdTotalFightPower=True):
''' 仙盟排序, 排序规则: 联赛评级 > 总战力 > 等级 > 创建时间
@@ -3590,12 +3701,13 @@
familyList.append(family)
familyList.sort(cmp=CmpFamilySort)
- PyGameData.g_sortFamilyIDList = []
+ mgr = GetFamilyMgr()
+ mgr.sortFamilyIDList = []
for i, family in enumerate(familyList, 1):
GameWorld.DebugLog(" i=%s,warRank=%s,fightPower=%s,LV=%s,CreateTime=%s,familyID=%s"
% (i, GetFamilyWarRank(family), GetFamilyTotalFightPower(family), family.GetLV(), family.GetCreateTime(), family.GetID()))
- PyGameData.g_sortFamilyIDList.append(family.GetID())
- GameWorld.DebugLog(" sortFamilyIDList=%s" % PyGameData.g_sortFamilyIDList)
+ mgr.sortFamilyIDList.append(family.GetID())
+ GameWorld.DebugLog(" sortFamilyIDList=%s" % mgr.sortFamilyIDList)
return
def CmpFamilySort(family1, family2):
@@ -3836,6 +3948,17 @@
##--------------------------------------------------------------------------------------------------
+def CrossServerMsg_FamilyDelRet(msgData):
+ ## 跨服仙盟删除结果,有收到结果即代表成功
+ familyID = msgData["familyID"]
+ playerID = msgData.get("playerID", 0)
+ gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+ if playerID:
+ gameRecMgr.DelGameRecDataByTypeValue(ShareDefine.Def_GameRecType_FamilyDelSyncCross, [playerID], familyID)
+ else:
+ gameRecMgr.DelGameRecDataByTypeID(ShareDefine.Def_GameRecType_FamilyDelSyncCross, familyID)
+ return
+
def GetFamilyBillboardInfo(curFamily):
## 获取仙盟榜单信息 区服ID、徽章、仙盟名、盟主名、仙盟总战力、仙盟等级
familyID = curFamily.GetID()
@@ -3851,3 +3974,222 @@
return {"id":familyID, "name":name, "id2":id2, "name2":name2, "value1":value1, "value2":value2,
"value3":value3, "value4":value4, "value5":value5}
+def Sync_ClientFamilyUpdToCrossServer():
+ ## 定时同步仙盟变更数据到跨服服务器
+
+ Sync_ClientFamilyDelToCrossServer() # 防止未删除成功,这里补通知
+
+ mgr = GetFamilyMgr()
+ if not mgr.syncCrossFamilyDict:
+ return
+
+ familyManager = GameWorld.GetFamilyManager()
+ for familyID, updMemIDList in mgr.syncCrossFamilyDict.items():
+ family = familyManager.FindFamily(familyID)
+ if not family:
+ continue
+ Send_ClientServerMsg_SyncFamilyInfo("FamilyUpd", GetSyncCrossServerFamilyInfo(family, updMemIDList))
+
+ mgr.syncCrossFamilyDict = {}
+ return
+
+def Sync_ClientFamilyAllToCrossServer():
+ ## 同步子服所有仙盟信息到跨服
+
+ if GameWorld.GetGameWorld().GetDictByKey(ChConfig.Def_WorldKey_SyncFamilyAllToCross):
+ return
+ GameWorld.GetGameWorld().SetDict(ChConfig.Def_WorldKey_SyncFamilyAllToCross, 1)
+ GameWorld.Log("开始同步本服所有仙盟到跨服服务器!")
+
+ Sync_ClientFamilyDelToCrossServer() # 防止未删除成功,这里补通知
+
+ familyManager = GameWorld.GetFamilyManager()
+ for i in xrange(familyManager.GetCount()):
+ family = familyManager.GetAt(i)
+ if not family:
+ continue
+ Send_ClientServerMsg_SyncFamilyInfo("FamilyUpd", GetSyncCrossServerFamilyInfo(family))
+ return
+
+def Sync_ClientFamilyDelToCrossServer():
+ ## 同步仙盟删除数据到跨服服务器
+ gameRecMgr = PyDataManager.GetDBGameRecDataManager()
+ recDataDict = gameRecMgr.GetGameRecDataDict(ShareDefine.Def_GameRecType_FamilyDelSyncCross)
+ for familyID, recDataList in recDataDict.items():
+ for recData in recDataList:
+ playerID = recData.GetValue1()
+ Send_ClientServerMsg_SyncFamilyInfo("FamilyDel", {"familyID":familyID, "playerID":playerID})
+ return
+
+def GetCrossFamilyBaseInfo(family):
+ return {"ID": family.GetID(), "Name": family.GetName(), "LV":family.GetLV(), "FightPower":GetFamilyTotalFightPower(family),
+ "LeaderID": family.GetLeaderID(), "LeaderName": family.GetLeaderName(), "EmblemID":GetFamilyEmblemID(family),
+ "ServerID":family.GetServerID(), "Broadcast":family.GetBroadcast()}
+
+def GetCrossFamilyMemInfo(member):
+ return {"Name":member.GetName(), "LV":member.GetLV(), "Job":member.GetJob(), "OfficialRank":member.GetOfficialRank(),
+ "Face":member.GetFace(), "FacePic":member.GetFacePic(), "FamilyLV":member.GetFamilyLV(), "FightPower":GetMemberFightPower(member)}
+
+def GetSyncCrossServerFamilyInfo(family, memIDList=None):
+ ## 获取仙盟跨服所需信息
+ # @param memIDList: 需要获取成员信息ID列表,不传则取所有成员
+
+ crossFamilyInfo = GetCrossFamilyBaseInfo(family)
+
+ memAll = True if memIDList == None else False
+ memInfo = {}
+ for m in xrange(family.GetCount()):
+ member = family.GetAt(m)
+ memID = member.GetPlayerID()
+ if not memID:
+ continue
+ if memIDList and memID not in memIDList:
+ continue
+ memInfo[memID] = GetCrossFamilyMemInfo(member)
+
+ crossFamilyInfo.update({"memInfo":memInfo, "memAll":memAll})
+ return crossFamilyInfo
+
+def Send_ClientServerMsg_SyncFamilyInfo(syncType, syncInfo):
+ dataMsg = {"syncType":syncType, "syncInfo":syncInfo}
+ CrossRealmMsg.SendMsgToCrossServer(ShareDefine.ClientServerMsg_SyncFamilyInfo, dataMsg)
+ return
+
+def ClientServerMsg_SyncFamilyInfo(serverGroupID, msgData):
+ ## 收到子服 - 仙盟信息
+
+ syncType = msgData["syncType"]
+ syncInfo = msgData["syncInfo"]
+
+ if syncType == "FamilyUpd":
+ __CrossServer_FamilyUpd(syncInfo)
+
+ elif syncType == "FamilyDel":
+ __CrossServer_FamilyDel(serverGroupID, syncInfo)
+
+ return
+
+def __CrossServer_FamilyDel(serverGroupID, syncInfo):
+ ## 跨服服务器删除子服仙盟、成员
+ familyID = syncInfo["familyID"]
+ playerID = syncInfo.get("playerID", 0)
+ if playerID:
+ curFamily = GameWorld.GetFamilyManager().FindFamily(familyID)
+ if curFamily:
+ curFamily.DeleteMember(playerID)
+ else:
+ #删除家族
+ GameWorld.GetFamilyManager().DelFamily(familyID)
+ #删除家族行为数据
+ PlayerFamilyAction.ClearFamilyAction(familyID)
+
+ # 直接回复就是删除成功
+ CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_FamilyDelRet, syncInfo, [serverGroupID])
+ return
+
+def __CrossServer_FamilyUpd(familyInfo):
+ ## 跨服服务器更新子服仙盟 - 这里只覆盖更新,不考虑删除的情况
+
+ familyID = familyInfo["ID"]
+ familyName = familyInfo["Name"]
+ curFamily = FindAndFixCrossFamilyByIDName(familyID, familyName)
+ if not curFamily:
+ GameWorld.ErrLog("跨服更新仙盟失败! 仙盟不存在或者创建失败! familyID=%s" % familyID)
+ return
+
+ #curFamily.SetName(familyInfo["Name"]) # 这里不再更新名称
+ curFamily.SetLV(familyInfo["LV"])
+ SetFamilyTotalFightPower(curFamily, familyInfo["FightPower"])
+ curFamily.SetLeaderID(familyInfo["LeaderID"])
+ curFamily.SetLeaderName(familyInfo["LeaderName"])
+ SetFamilyEmblemID(curFamily, familyInfo["EmblemID"])
+ curFamily.SetServerID(familyInfo["ServerID"])
+ curFamily.SetBroadcast(familyInfo["Broadcast"])
+
+ updMemIDList = []
+ memAll = familyInfo.get("memAll", False)
+ memInfoDict = familyInfo.get("memInfo", {})
+ if memInfoDict:
+ for m in range(curFamily.GetCount())[::-1]:
+ member = curFamily.GetAt(m)
+ memID = member.GetPlayerID()
+ if not memID:
+ continue
+ if memID not in memInfoDict:
+ if memAll:
+ curFamily.DeleteMember(memID)
+ continue
+ memInfo = memInfoDict.pop(memID)
+ __updCrossFamilyMemberInfo(curFamily, member, memInfo)
+ updMemIDList.append(memID)
+
+ # 剩下的就是新增的成员
+ for memID, memInfo in memInfoDict.items():
+ member = curFamily.AddMemberEx(memID)
+ if not member:
+ continue
+ __updCrossFamilyMemberInfo(curFamily, member, memInfo)
+ updMemIDList.append(memID)
+
+ # 相关活动数据更新
+ CrossFamilyGCZ.OnCrossJoinFamilyMemberUpd(curFamily, updMemIDList)
+ return
+
+def FindAndFixCrossFamilyByIDName(familyID, familyName):
+ ## 按仙盟名及ID查找跨服仙盟,重名时系统会自动修改仙盟名
+
+ familyManager = GameWorld.GetFamilyManager()
+ curFamily = familyManager.FindFamily(familyID)
+ if not curFamily:
+ for i in range(100):
+ crossFamilyName = familyName if i == 0 else ("%s_%s" % (familyName, i))
+ curFamily = familyManager.AddFamilyEx(crossFamilyName, familyID)
+ if curFamily:
+ GameWorld.DebugLog("跨服添加新仙盟! familyID=%s, i=%s" % (familyID, i))
+ break
+ return curFamily
+
+ # 验证当前名字是否还是唯一的,因为延迟同步的原因,仙盟可能改名时在本服唯一,但是在跨服不唯一
+ nameFamily = familyManager.FindFamilyByName(familyName)
+ if not nameFamily:
+ GameWorld.DebugLog("新同步的名字已经不存在仙盟了,可直接替换新仙盟名! familyID=%s" % familyID)
+ curFamily.SetName(familyName)
+ return curFamily
+
+ if nameFamily.GetID() == familyID:
+ #GameWorld.DebugLog("还是自己原来的仙盟名,直接返回! familyID=%s" % familyID)
+ return curFamily
+
+ # 尝试修改仙盟名,如果没有唯一名,则不修改保留最后一次同步的仙盟名,至少最后一次的名字还是唯一的
+ for i in range(1, 100):
+ fixFamilyName = "%s_%s" % (familyName, i)
+ family = familyManager.FindFamilyByName(fixFamilyName)
+ if family:
+ if family.GetID() == familyID:
+ #GameWorld.DebugLog("保留原系统修改的仙盟名! familyID=%s" % familyID)
+ break
+ # 已存在该仙盟名,且不是自己的仙盟
+ continue
+ curFamily.SetName(fixFamilyName)
+ GameWorld.Log("跨服强制修改仙盟名: familyID=%s,%s,%s" % (familyID, i, fixFamilyName))
+ break
+
+ return curFamily
+
+def __updCrossFamilyMemberInfo(curFamily, member, memInfo):
+ member.SetName(memInfo.get("Name", ""))
+ member.SetLV(memInfo.get("LV", 1))
+ member.SetJob(memInfo.get("Job", 1))
+ member.SetOfficialRank(memInfo.get("OfficialRank", 1))
+ member.SetFace(memInfo.get("Face", 0))
+ member.SetFacePic(memInfo.get("FacePic", 0))
+ SetMemberFightPower(member, memInfo.get("FightPower", 0))
+ memFamilyLV = memInfo.get("FamilyLV", 0)
+ member.SetFamilyLV(memFamilyLV)
+ if memFamilyLV == IPY_GameServer.fmlLeader:
+ curFamily.SetLeaderID(member.GetPlayerID())
+ curFamily.SetLeaderName(member.GetName())
+ curFamily.SetLeaderOfficialRank(member.GetOfficialRank())
+
+ return
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
index a4c6352..c892648 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -77,6 +77,7 @@
import CrossChampionship
import CrossBattlefield
import CrossActAllRecharge
+import CrossFamilyGCZ
import PlayerActGubao
import PlayerActHorsePetTrain
import PlayerActLianqi
@@ -1052,6 +1053,16 @@
return
resultName = '%s' % ret
+ # 仙盟攻城战
+ if callName == "FamilyGCZ":
+ curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
+ if not curPlayer:
+ return
+ ret = CrossFamilyGCZ.MapServer_FamilyGCZ(curPlayer, eval(resultName))
+ if ret == None:
+ return
+ resultName = '%s' % ret
+
# 仙盟珍宝阁
if callName =="FamilyZhenbaoge":
curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
index dcadebf..e087772 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerViewCache.py
@@ -132,10 +132,14 @@
PlayerPackData.DelOutofTimePackData()
+ onlineMgr = ChPlayer.GetOnlinePlayerMgr()
pyViewCacheMgr = PyDataManager.GetPlayerViewCachePyManager()
playerViewCachePyDict = pyViewCacheMgr.playerViewCachePyDict
for playerID, viewCache in playerViewCachePyDict.items():
if IsSaveDBViewCache(viewCache):
+ continue
+ if onlineMgr.IsOnline(playerID):
+ #在线的先不删除
continue
playerViewCachePyDict.pop(playerID)
@@ -234,24 +238,28 @@
def GetSyncCrossCacheBase(curPlayer):
## 获取同步跨服基础查看缓存,主要用于个别功能需要提前先同步玩家基础缓存到跨服,因为跨服不一定有玩家缓存,需要提前同步
- playerID = curPlayer.GetPlayerID()
+ if isinstance(curPlayer, int):
+ playerID = curPlayer
+ curPlayer = None
+ else:
+ playerID = curPlayer.GetPlayerID()
cacheDict = GetCachePropDataDict(FindViewCache(playerID))
cacheBase = {
- "AccID":curPlayer.GetAccID(),
- "LV":curPlayer.GetLV(),
- "RealmLV":curPlayer.GetOfficialRank(),
- "Job":curPlayer.GetJob(),
- "VIPLV":curPlayer.GetVIPLv(),
- "Name":CrossRealmPlayer.GetCrossPlayerName(curPlayer),
- "Face":curPlayer.GetFace(),
- "FacePic":curPlayer.GetFacePic(),
- "FamilyID":curPlayer.GetFamilyID(),
+ "AccID":curPlayer.GetAccID() if curPlayer else cacheDict.get("AccID", ""),
+ "LV":curPlayer.GetLV() if curPlayer else cacheDict.get("LV", 1),
+ "RealmLV":curPlayer.GetOfficialRank() if curPlayer else cacheDict.get("RealmLV", 1),
+ "Job":curPlayer.GetJob() if curPlayer else cacheDict.get("Job", 1),
+ "VIPLV":curPlayer.GetVIPLv() if curPlayer else cacheDict.get("VIPLV", 0),
+ "Name":curPlayer.GetName() if curPlayer else cacheDict.get("Name", ""), # 此处不用跨服名称,如前端需要展示跨服名称,可通过ServerID或AccID取得ServerID展示
+ "Face":curPlayer.GetFace() if curPlayer else cacheDict.get("Face", 0),
+ "FacePic":curPlayer.GetFacePic() if curPlayer else cacheDict.get("FacePic", 0),
+ "FamilyID":curPlayer.GetFamilyID() if curPlayer else cacheDict.get("FacmilyID", 0),
"FamilyName":cacheDict.get("FamilyName", ""),
"TitleID":cacheDict.get("TitleID", 0),
- "FightPower":PlayerControl.GetFightPower(curPlayer),
+ "FightPower":PlayerControl.GetFightPower(curPlayer) if curPlayer else cacheDict.get("FightPower", 0),
"EquipShowSwitch":cacheDict.get("EquipShowSwitch", 0),
"EquipShowID":cacheDict.get("EquipShowID", []),
- "ServerGroupID":PlayerControl.GetPlayerServerGroupID(curPlayer),
+ "ServerGroupID":PlayerControl.GetPlayerServerGroupID(curPlayer) if curPlayer else cacheDict.get("ServerGroupID", GameWorld.GetServerGroupID()),
}
return cacheBase
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
index 32db39d..c2e882c 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -15,6 +15,7 @@
import GameWorld
import PlayerSocial
import CrossBillboard
+import CrossFamilyGCZ
import PlayerFamilyStore
import PlayerCompensation
import PlayerBourse
@@ -39,6 +40,10 @@
import time
def GetSavePyData():
+
+ #存储数据前,一些功能业务数据先转化为存档数据
+ CrossFamilyGCZ.OnSavePyData()
+
pyGameDataMgr = GetPyGameDataManager()
result = pyGameDataMgr.GetSaveData()
GameWorld.Log("GetSavePyData!! id = %s-%s"%(id(pyGameDataMgr), len(result)))
@@ -52,7 +57,12 @@
def LoadPyGameData(gameBuffer, pos):
pyGameDataMgr = GetPyGameDataManager()
GameWorld.Log("LoadPyGameData!!id = %s %s"%(id(pyGameDataMgr), len(gameBuffer)))
- return pyGameDataMgr.LoadGameData(gameBuffer, pos)
+ pos = pyGameDataMgr.LoadGameData(gameBuffer, pos)
+
+ #加载数据后,一些功能转化为功能业务数据
+ CrossFamilyGCZ.OnLoadPyData()
+
+ return pos
#协助感谢表
class PlayerAssistThanksPyManager(object):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py b/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
index 5c20298..0aef8b5 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyGameData.py
@@ -58,12 +58,13 @@
#请求列表 玩家的AddRequest废弃
g_playerRequests = {}
-g_fightPowerChangeFamilyIDList = [] #仙盟成员战力有变更的仙盟ID [familyID, ...]
-g_sortFamilyIDList = [] #仙盟排序顺序 [familyID, ...]
+g_familyMgr = None # 仙盟管理
g_familyWarFightingIDList = [] # 仙盟联赛中正在战斗中的仙盟ID列表 [familyID, ...]
g_familyWarFamilyIDList = [] # 仙盟联赛参赛仙盟ID列表 [familyID, ...]
g_familyWarMemDict = {} # 仙盟联赛参赛人员名单 {playerID:memRecData, ...}
+g_familyGCZMgr = None
+
#boss刷新排序列表
g_sortBOSSRefreshList = []
g_swrhJoinRecord = [] #守护人皇家族今日参加记录(已正常结算)[familyID]
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
index 809da18..d28397e 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyGameDataStruct.py
@@ -813,8 +813,8 @@
class tagDBCrossBillboard(Structure):
_pack_ = 1
_fields_ = [
- ('GroupValue1', ctypes.c_ubyte),
- ('GroupValue2', ctypes.c_ubyte),
+ ('GroupValue1', ctypes.c_ulong),
+ ('GroupValue2', ctypes.c_ulong),
('BillboardType', ctypes.c_ubyte),
('ID', ctypes.c_ulong),
('ID2', ctypes.c_ulong),
@@ -870,8 +870,8 @@
if len(buf) < pos + self.getLength():
return -1
self.clear()
- self.GroupValue1, pos = CommFunc.ReadBYTE(buf, pos)
- self.GroupValue2, pos = CommFunc.ReadBYTE(buf, pos)
+ self.GroupValue1, pos = CommFunc.ReadDWORD(buf, pos)
+ self.GroupValue2, pos = CommFunc.ReadDWORD(buf, pos)
self.BillboardType, pos = CommFunc.ReadBYTE(buf, pos)
self.ID, pos = CommFunc.ReadDWORD(buf, pos)
self.ID2, pos = CommFunc.ReadDWORD(buf, pos)
@@ -896,8 +896,8 @@
def getBuffer(self):
buf = ''
- buf = CommFunc.WriteBYTE(buf, self.GroupValue1)
- buf = CommFunc.WriteBYTE(buf, self.GroupValue2)
+ buf = CommFunc.WriteDWORD(buf, self.GroupValue1)
+ buf = CommFunc.WriteDWORD(buf, self.GroupValue2)
buf = CommFunc.WriteBYTE(buf, self.BillboardType)
buf = CommFunc.WriteDWORD(buf, self.ID)
buf = CommFunc.WriteDWORD(buf, self.ID2)
@@ -921,8 +921,8 @@
def getLength(self):
length = 0
- length += sizeof(ctypes.c_ubyte)
- length += sizeof(ctypes.c_ubyte)
+ length += sizeof(ctypes.c_ulong)
+ length += sizeof(ctypes.c_ulong)
length += sizeof(ctypes.c_ubyte)
length += sizeof(ctypes.c_ulong)
length += sizeof(ctypes.c_ulong)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index 25a3322..39d2b8e 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -364,10 +364,11 @@
CrossActName_Gubao = "CrossActGubao" # 古宝养成 - 跨服
CrossActName_HorsePetTrain = "CrossActHorsePetTrain" # 骑宠养成 - 跨服
CrossActName_Lianqi = "CrossActLianqi" # 炼器 - 跨服
+CrossActName_FamilyGCZ = "CrossActFamilyGCZ" # 仙盟攻城战
#跨服运营活动列表
CrossActNameList = [CrossActName_CTGBillboard, CrossActName_AllRecharge, CrossActName_LuckyCloudBuy, CrossActName_BossTrial,
- CrossActName_XianXiaMJ, CrossActName_Gubao, CrossActName_HorsePetTrain, CrossActName_Lianqi]
+ CrossActName_XianXiaMJ, CrossActName_Gubao, CrossActName_HorsePetTrain, CrossActName_Lianqi, CrossActName_FamilyGCZ]
#需要锁定活动分区分配直到活动结束的跨服运营活动,即使热更分区配置,也不会改变正在活动中的分区设定,直到活动结束
CrossActLockServerGroupIDList = [CrossActName_CTGBillboard, CrossActName_AllRecharge]
@@ -375,6 +376,7 @@
ActKey_ID = "ID" # 活动ID,唯一标识的ID,一般是活动开启的time值
ActKey_State = "State" # 活动状态 0-未开启, >0开启中,也代表当日的第几个时间段
ActKey_StateJoin = "StateJoin" # 活动某些功能可参与状态 0-还不可参与, >0可参与,一般可参与时该状态等于state
+ActKey_StateError = "StateError" # 按流程走的活动状态是否已异常
ActKey_CfgID = "CfgID" # 活动表配置ID
ActKey_ActNum = "ActNum" # 活动分组编号
ActKey_DayIndex = "DayIndex" # 当前活动天索引,0开始,代表第1天
@@ -917,7 +919,10 @@
Def_CBT_HorsePetTrainScore, # 骑宠养成积分 - 个人榜 164
Def_CBT_CrossRealmPK, # 跨服PK竞技场 165
Def_CBT_LianqiScore, # 炼器积分 - 个人榜 166
-) = range(150, 166 + 1)
+Def_CBT_FamilyGCZScore, # 仙盟攻城战 - 仙盟积分总榜 167 (zoneID, 0)
+Def_CBT_FamilyGCZPlayerHurt, # 仙盟攻城战 - 玩家伤害总榜 168 (zoneID, 0)
+Def_CBT_FamilyGCZRoundHurt, # 仙盟攻城战 - 本轮分组仙盟伤害榜 169 (zoneID, batType*100+groupNum)
+) = range(150, 169 + 1)
#职业对应战力排行榜类型
JobFightPowerBillboardDict = {
@@ -1435,7 +1440,12 @@
#通用信息记录类型 - 新 从 300 开始,原通用记录类型最大到255
Def_GameRecTypeList = (
Def_GameRecType_Xiangong, # 仙宫记录 300
- ) = range(300, 1 + 300)
+ Def_GameRecType_FamilyDelSyncCross, # 仙盟删除同步跨服状态本服记录, familyID 301
+ Def_GameRecType_FamilyGCZMgr, # 仙盟攻城战公共管理信息记录, zoneID 302
+ Def_GameRecType_FamilyGCZJoinFamily, # 仙盟攻城战参与仙盟信息, zoneID 303
+ Def_GameRecType_FamilyGCZJoinMember, # 仙盟攻城战参与成员信息, zoneID 304
+ Def_GameRecType_FamilyGCZCityWall, # 仙盟攻城战城池信息, zoneID 305
+ ) = range(300, 1 + 305)
#通用信息记录新 - 字典key配置,如果有配置,则可额外按对应记录Value值存储字典,方便快速取值,可配置Value编号 1~8,配空默认 Value1
Def_GameRecValueKeyDict = {
Def_GameRecType_Xiangong:[1],
@@ -1640,6 +1650,7 @@
CrossServerMsg_CrossServerState = "CrossServerState" # 跨服服务器状态变更
CrossServerMsg_PlayerLoginout = "PlayerLoginout" # 玩家上下线状态同步
CrossServerMsg_ExitCrossServer = "ExitCrossServer" # 退出跨服服务器
+CrossServerMsg_SendFakePack = "SendFakePack" # 给子服玩家发送封包
CrossServerMsg_Notify = "Notify" # 提示信息
CrossServerMsg_ChatCrossWorld = "ChatCrossWorld" # 跨服世界聊天
CrossServerMsg_ViewPlayerCacheRet = "ViewPlayerCacheRet"# 查看跨服玩家信息结果
@@ -1693,6 +1704,8 @@
CrossServerMsg_FuncTeamInfo = "FuncTeamInfo" # 功能队伍信息同步
CrossServerMsg_FuncTeamDel = "FuncTeamDel" # 功能队伍删除同步
CrossServerMsg_FuncTeamList = "FuncTeamList" # 功能队伍列表同步
+CrossServerMsg_FamilyDelRet = "FamilyDelRet" # 仙盟删除结果
+CrossServerMsg_FamilyGCZ = "FamilyGCZ" # 仙盟攻城战
# 子服发送跨服信息定义
ClientServerMsg_ServerInitOK = "ServerInitOK" # 子服启动成功
@@ -1742,6 +1755,8 @@
ClientServerMsg_HorsePetTrainScore = "HorsePetTrainScore" # 骑宠养成积分
ClientServerMsg_QueryXiangong = "QueryXiangong" # 查看仙宫仙名录
ClientServerMsg_LianqiScore = "LianqiScore" # 炼器积分
+ClientServerMsg_SyncFamilyInfo = "SyncFamilyInfo" # 仙盟信息同步
+ClientServerMsg_FamilyGCZ = "FamilyGCZ" # 仙盟攻城战
#跨服广播类型定义
CrossNotify_CrossAct = "CrossAct"
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index 4296654..99d11ac 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -2012,3 +2012,23 @@
PacketCMD_4=0xB0
PacketSubCMD_4=0x35
PacketCallFunc_4=OnMineHouseKeeperFreeUse
+
+;仙盟攻城战
+[PlayerActFamilyGCZ]
+ScriptName = Player\PlayerActFamilyGCZ.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 3
+
+PacketCMD_1=0xC1
+PacketSubCMD_1=0x24
+PacketCallFunc_1=OnFamilyGCZContribution
+
+PacketCMD_2=0xC1
+PacketSubCMD_2=0x25
+PacketCallFunc_2=OnFamilyGCZAtk
+
+PacketCMD_3=0xC1
+PacketSubCMD_3=0x26
+PacketCallFunc_3=OnFamilyGCZGuess
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 4d0d5d4..5687fe6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -2327,6 +2327,7 @@
1000 * 20, # 仙盟充值互助
1000 * 20, # 仙盟珍宝阁
300, # 砍树
+ 1000 * 20, # 仙盟攻城战
]
TYPE_Player_Tick_Count = len(TYPE_Player_Tick_Time)
@@ -2411,6 +2412,7 @@
TYPE_Player_Tick_FamilyCTGAssist, #仙盟充值互助
TYPE_Player_Tick_FamilyZhenbaoge, #仙盟珍宝阁
TYPE_Player_Tick_CutTree, #砍树
+TYPE_Player_Tick_FamilyGCZ, #仙盟攻城战
) = range(0, TYPE_Player_Tick_Count)
#---------------------------------------------------------------------
@@ -4245,6 +4247,16 @@
#购买次数礼包活动
Def_PDict_BuyCountGiftID = "BuyCountGiftID_%s" # 玩家身上的活动ID,唯一标识,取活动开始日期time,参数(活动编号)
Def_PDict_BuyCountGiftAward = "BuyCountGiftAward_%s" # 礼包奖励记录,按位记录是否已领取,参数(活动编号)
+
+#仙盟攻城战
+Def_PDict_FamilyGCZID = "FamilyGCZID" # 玩家身上的活动ID,唯一标识,取活动开始日期time值
+Def_PDict_FamilyGCZZoneID = "FamilyGCZZoneID" # 参与的分区ID
+Def_PDict_FamilyGCZFamilyID = "FamilyGCZFamilyID" # 参与的仙盟ID
+Def_PDict_FamilyGCZRoundNum = "FamilyGCZRoundNum" # 记录的轮次
+Def_PDict_FamilyGCZContributionCnt = "FamilyGCZContributionCnt" # 轮次低级捐献次数
+Def_PDict_FamilyGCZEnergy = "FamilyGCZEnergy" # 进攻剩余体力
+Def_PDict_FamilyGCZEnergyTime = "FamilyGCZEnergyTime" # 上次恢复体力时间戳,为0时不再恢复
+Def_PDict_FamilyGCZAwardState = "FamilyGCZAwardState" # 活动奖励领取状态,按二进制位判断是否已领取,0-竞猜奖励;1-个人排行奖励;2-仙盟排名奖励;
#-------------------------------------------------------------------------------
#开服活动,Def_PDictType_OpenServerCampaign
@@ -6178,7 +6190,9 @@
Def_RewardType_OpenServerDailyAward, # 开服每日奖励 76
Def_RewardType_TreasureCntAward, # 寻宝累计次数奖励 77
Def_RewardType_LunhuidianAward, # 轮回殿奖励 78
-)= range(79)
+Def_RewardType_RechargeDayAward, # 累充每日奖励 79
+Def_RewardType_FamilyGCZ, # 仙盟攻城战 80
+)= range(81)
#boss复活相关活动定义
BossRebornActIDList = (
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 2163321..dec4787 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -5089,6 +5089,70 @@
#------------------------------------------------------
+# C0 26 仙盟攻城战查询 #tagCGFamilyGCZQuery
+
+class tagCGFamilyGCZQuery(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("QueryType", c_ubyte), #查询类型:1-成员捐献值;2-进入城池场景;3-退出城池场景;4-进入城池;5-退出城池;6-战报;7-分组仙盟成员伤害;
+ ("BatType", c_ubyte), #指定战场类型,需要发送的查询类型: 2、4
+ ("GroupNum", c_ubyte), #指定分组编号,需要发送的查询类型: 2、4
+ ("FamilyID", c_int), #指定仙盟ID或城池ID,查自己盟的可不发,需要发的类型:2、4、6、7
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC0
+ self.SubCmd = 0x26
+ 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 = 0xC0
+ self.SubCmd = 0x26
+ self.QueryType = 0
+ self.BatType = 0
+ self.GroupNum = 0
+ self.FamilyID = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCGFamilyGCZQuery)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 26 仙盟攻城战查询 //tagCGFamilyGCZQuery:
+ Cmd:%s,
+ SubCmd:%s,
+ QueryType:%d,
+ BatType:%d,
+ GroupNum:%d,
+ FamilyID:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.QueryType,
+ self.BatType,
+ self.GroupNum,
+ self.FamilyID
+ )
+ return DumpString
+
+
+m_NAtagCGFamilyGCZQuery=tagCGFamilyGCZQuery()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCGFamilyGCZQuery.Cmd,m_NAtagCGFamilyGCZQuery.SubCmd))] = m_NAtagCGFamilyGCZQuery
+
+
+#------------------------------------------------------
# C0 03 强制退出跨服状态 #tagCGForceQuitCrossState
class tagCGForceQuitCrossState(Structure):
@@ -5245,8 +5309,8 @@
("Cmd", c_ubyte),
("SubCmd", c_ubyte),
("Type", c_ubyte), #榜单类型
- ("GroupValue1", c_ubyte), # 分组值1
- ("GroupValue2", c_ubyte), # 分组值2,与分组值1组合归为同组榜单数据
+ ("GroupValue1", c_int), # 分组值1
+ ("GroupValue2", c_int), # 分组值2,与分组值1组合归为同组榜单数据
("StartIndex", c_int), #查看的起始名次索引, 默认0
("WatchCnt", c_ubyte), #查看条数,默认20,最大不超过100
("WatchID", c_int), #查看指定ID名次前后,如玩家ID、家族ID等
@@ -23599,6 +23663,189 @@
#------------------------------------------------------
+# C1 25 仙盟攻城战攻击 #tagCMFamilyGCZAtk
+
+class tagCMFamilyGCZAtk(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("AtkType", c_ubyte), #攻击类型: 1-普通单攻;2-技能单攻;3-技能群攻;
+ ("TagCityID", c_int), #目标城池ID,一般是仙盟ID或者特殊城池ID如修罗城城池,普攻单攻需指定目标,群攻技能发0
+ ("TagGuardID", c_int), #目标守卫ID,一般是玩家ID或者特殊守卫ID如修罗城守卫,普攻单攻需指定目标,技能攻击发0
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC1
+ 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 = 0xC1
+ self.SubCmd = 0x25
+ self.AtkType = 0
+ self.TagCityID = 0
+ self.TagGuardID = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCMFamilyGCZAtk)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C1 25 仙盟攻城战攻击 //tagCMFamilyGCZAtk:
+ Cmd:%s,
+ SubCmd:%s,
+ AtkType:%d,
+ TagCityID:%d,
+ TagGuardID:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.AtkType,
+ self.TagCityID,
+ self.TagGuardID
+ )
+ return DumpString
+
+
+m_NAtagCMFamilyGCZAtk=tagCMFamilyGCZAtk()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFamilyGCZAtk.Cmd,m_NAtagCMFamilyGCZAtk.SubCmd))] = m_NAtagCMFamilyGCZAtk
+
+
+#------------------------------------------------------
+# C1 24 仙盟攻城战捐献 #tagCMFamilyGCZContribution
+
+class tagCMFamilyGCZContribution(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("ContributionType", c_ubyte), #捐献类型: 0-低级;1-高级
+ ("UseCount", c_int), #物品捐献时使用个数
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC1
+ self.SubCmd = 0x24
+ 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 = 0xC1
+ self.SubCmd = 0x24
+ self.ContributionType = 0
+ self.UseCount = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagCMFamilyGCZContribution)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C1 24 仙盟攻城战捐献 //tagCMFamilyGCZContribution:
+ Cmd:%s,
+ SubCmd:%s,
+ ContributionType:%d,
+ UseCount:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.ContributionType,
+ self.UseCount
+ )
+ return DumpString
+
+
+m_NAtagCMFamilyGCZContribution=tagCMFamilyGCZContribution()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFamilyGCZContribution.Cmd,m_NAtagCMFamilyGCZContribution.SubCmd))] = m_NAtagCMFamilyGCZContribution
+
+
+#------------------------------------------------------
+# C1 26 仙盟攻城战竞猜 #tagCMFamilyGCZGuess
+
+class tagCMFamilyGCZGuess(Structure):
+ Head = tagHead()
+ SelectCnt = 0 #(BYTE SelectCnt)
+ SelectFamilyIDList = list() #(vector<DWORD> SelectFamilyIDList)// 竞猜选择的仙盟ID排名顺序
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC1
+ self.Head.SubCmd = 0x26
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.SelectCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.SelectCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.SelectFamilyIDList.append(value)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC1
+ self.Head.SubCmd = 0x26
+ self.SelectCnt = 0
+ self.SelectFamilyIDList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 4 * self.SelectCnt
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.SelectCnt)
+ for i in range(self.SelectCnt):
+ data = CommFunc.WriteDWORD(data, self.SelectFamilyIDList[i])
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ SelectCnt:%d,
+ SelectFamilyIDList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.SelectCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagCMFamilyGCZGuess=tagCMFamilyGCZGuess()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMFamilyGCZGuess.Head.Cmd,m_NAtagCMFamilyGCZGuess.Head.SubCmd))] = m_NAtagCMFamilyGCZGuess
+
+
+#------------------------------------------------------
# C1 10 幸运云购购买 #tagCMLuckyCloudBuy
class tagCMLuckyCloudBuy(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 9e7d65d..58ed11c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -17027,8 +17027,8 @@
class tagGCCrossBillboardInfo(Structure):
Head = tagHead()
Type = 0 #(BYTE Type)//榜单类型
- GroupValue1 = 0 #(BYTE GroupValue1)// 分组值1
- GroupValue2 = 0 #(BYTE GroupValue2)// 分组值2,与分组值1组合归为同组榜单数据
+ GroupValue1 = 0 #(DWORD GroupValue1)// 分组值1
+ GroupValue2 = 0 #(DWORD GroupValue2)// 分组值2,与分组值1组合归为同组榜单数据
WatchID = 0 #(DWORD WatchID)//查看指定ID名次前后,如玩家ID、家族ID等
BillboardCount = 0 #(BYTE BillboardCount)
CrossBillboardDataList = list() #(vector<tagGCCrossBillboardData> CrossBillboardDataList)
@@ -17044,8 +17044,8 @@
self.Clear()
_pos = self.Head.ReadData(_lpData, _pos)
self.Type,_pos = CommFunc.ReadBYTE(_lpData, _pos)
- self.GroupValue1,_pos = CommFunc.ReadBYTE(_lpData, _pos)
- self.GroupValue2,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupValue1,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.GroupValue2,_pos = CommFunc.ReadDWORD(_lpData, _pos)
self.WatchID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
self.BillboardCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
for i in range(self.BillboardCount):
@@ -17071,8 +17071,8 @@
length = 0
length += self.Head.GetLength()
length += 1
- length += 1
- length += 1
+ length += 4
+ length += 4
length += 4
length += 1
for i in range(self.BillboardCount):
@@ -17084,8 +17084,8 @@
data = ''
data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
data = CommFunc.WriteBYTE(data, self.Type)
- data = CommFunc.WriteBYTE(data, self.GroupValue1)
- data = CommFunc.WriteBYTE(data, self.GroupValue2)
+ data = CommFunc.WriteDWORD(data, self.GroupValue1)
+ data = CommFunc.WriteDWORD(data, self.GroupValue2)
data = CommFunc.WriteDWORD(data, self.WatchID)
data = CommFunc.WriteBYTE(data, self.BillboardCount)
for i in range(self.BillboardCount):
@@ -18518,6 +18518,1750 @@
m_NAtagGCCrossZoneInfo=tagGCCrossZoneInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCCrossZoneInfo.Cmd,m_NAtagGCCrossZoneInfo.SubCmd))] = m_NAtagGCCrossZoneInfo
+
+
+#------------------------------------------------------
+# C0 24 仙盟攻城战活动信息 #tagGCFamilyGCZActInfo
+
+class tagGCFamilyGCZActFamily(Structure):
+ FamilyID = 0 #(DWORD FamilyID)
+ Name = "" #(char Name[33])//参与仙盟名字
+ LV = 0 #(BYTE LV)//仙盟等级
+ ServerID = 0 #(DWORD ServerID)//仙盟所属区服ID
+ EmblemID = 0 #(DWORD EmblemID)//徽章ID
+ FightPower = 0 #(DWORD FightPower)//仙盟总战力,求余亿部分
+ FightPowerEx = 0 #(DWORD FightPowerEx)//仙盟总战力,整除亿部分
+ LeaderID = 0 #(DWORD LeaderID)//盟主ID
+ LeaderName = "" #(char LeaderName[33])//盟主名
+ LeaderFace = 0 #(DWORD LeaderFace)
+ LeaderFacePic = 0 #(DWORD LeaderFacePic)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.LV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ServerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.EmblemID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.LeaderID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.LeaderName,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.LeaderFace,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.LeaderFacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.FamilyID = 0
+ self.Name = ""
+ self.LV = 0
+ self.ServerID = 0
+ self.EmblemID = 0
+ self.FightPower = 0
+ self.FightPowerEx = 0
+ self.LeaderID = 0
+ self.LeaderName = ""
+ self.LeaderFace = 0
+ self.LeaderFacePic = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 33
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteBYTE(data, self.LV)
+ data = CommFunc.WriteDWORD(data, self.ServerID)
+ data = CommFunc.WriteDWORD(data, self.EmblemID)
+ data = CommFunc.WriteDWORD(data, self.FightPower)
+ data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+ data = CommFunc.WriteDWORD(data, self.LeaderID)
+ data = CommFunc.WriteString(data, 33, self.LeaderName)
+ data = CommFunc.WriteDWORD(data, self.LeaderFace)
+ data = CommFunc.WriteDWORD(data, self.LeaderFacePic)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ FamilyID:%d,
+ Name:%s,
+ LV:%d,
+ ServerID:%d,
+ EmblemID:%d,
+ FightPower:%d,
+ FightPowerEx:%d,
+ LeaderID:%d,
+ LeaderName:%s,
+ LeaderFace:%d,
+ LeaderFacePic:%d
+ '''\
+ %(
+ self.FamilyID,
+ self.Name,
+ self.LV,
+ self.ServerID,
+ self.EmblemID,
+ self.FightPower,
+ self.FightPowerEx,
+ self.LeaderID,
+ self.LeaderName,
+ self.LeaderFace,
+ self.LeaderFacePic
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZActInfo(Structure):
+ Head = tagHead()
+ ServerInfoLen = 0 #(BYTE ServerInfoLen)
+ ServerIDRangeInfo = "" #(String ServerIDRangeInfo)//开放该活动的服务器ID范围列表,json格式 [[IDA, IDB], ...], [] 为全服
+ ZoneID = 0 #(BYTE ZoneID)// 活动分区ID,公示期为0
+ ActID = 0 #(DWORD ActID)// 活动ID,代表某一次活动的唯一ID,前端如果有活动相关的本地记录可以通过验证此ID变更进行重置
+ StartDate = "" #(char StartDate[10])// 开始日期 y-m-d
+ EndtDate = "" #(char EndtDate[10])// 结束日期 y-m-d
+ JoinFamilyCnt = 0 #(BYTE JoinFamilyCnt)// 参与仙盟数
+ ActFlowID = 0 #(WORD ActFlowID)// 活动流程ID,对应H.活动时间流程表中的编号,前端根据跨服时间自行计算当前所处流程状态
+ GuessTemplateID = 0 #(WORD GuessTemplateID)// 竞猜奖励模版,对应H.活动竞猜表,前端自行读表展示
+ PersonalTemplateID = 0 #(WORD PersonalTemplateID)// 个人伤害排行奖励模版,对应H.活动榜单奖励模版表,前端自行读表展示
+ FamilyTemplateID = 0 #(WORD FamilyTemplateID)// 仙盟积分排行奖励模版,对应H.活动榜单奖励模版表,前端自行读表展示
+ StateError = 0 #(BYTE StateError)// 活动流程状态是否异常,如果不为0代表活动已异常,前端自行决定是不显示活动还是活动页面做提示
+ FamilyCount = 0 #(BYTE FamilyCount)
+ ActFamilyList = list() #(vector<tagGCFamilyGCZActFamily> ActFamilyList)//本分区参与的仙盟名单
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x24
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ServerInfoLen,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ServerIDRangeInfo,_pos = CommFunc.ReadString(_lpData, _pos,self.ServerInfoLen)
+ self.ZoneID,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ActID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.StartDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.EndtDate,_pos = CommFunc.ReadString(_lpData, _pos,10)
+ self.JoinFamilyCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.ActFlowID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.GuessTemplateID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.PersonalTemplateID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.FamilyTemplateID,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.StateError,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.FamilyCount,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FamilyCount):
+ temActFamilyList = tagGCFamilyGCZActFamily()
+ _pos = temActFamilyList.ReadData(_lpData, _pos)
+ self.ActFamilyList.append(temActFamilyList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x24
+ self.ServerInfoLen = 0
+ self.ServerIDRangeInfo = ""
+ self.ZoneID = 0
+ self.ActID = 0
+ self.StartDate = ""
+ self.EndtDate = ""
+ self.JoinFamilyCnt = 0
+ self.ActFlowID = 0
+ self.GuessTemplateID = 0
+ self.PersonalTemplateID = 0
+ self.FamilyTemplateID = 0
+ self.StateError = 0
+ self.FamilyCount = 0
+ self.ActFamilyList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += len(self.ServerIDRangeInfo)
+ length += 1
+ length += 4
+ length += 10
+ length += 10
+ length += 1
+ length += 2
+ length += 2
+ length += 2
+ length += 2
+ length += 1
+ length += 1
+ for i in range(self.FamilyCount):
+ length += self.ActFamilyList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ServerInfoLen)
+ data = CommFunc.WriteString(data, self.ServerInfoLen, self.ServerIDRangeInfo)
+ data = CommFunc.WriteBYTE(data, self.ZoneID)
+ data = CommFunc.WriteDWORD(data, self.ActID)
+ data = CommFunc.WriteString(data, 10, self.StartDate)
+ data = CommFunc.WriteString(data, 10, self.EndtDate)
+ data = CommFunc.WriteBYTE(data, self.JoinFamilyCnt)
+ data = CommFunc.WriteWORD(data, self.ActFlowID)
+ data = CommFunc.WriteWORD(data, self.GuessTemplateID)
+ data = CommFunc.WriteWORD(data, self.PersonalTemplateID)
+ data = CommFunc.WriteWORD(data, self.FamilyTemplateID)
+ data = CommFunc.WriteBYTE(data, self.StateError)
+ data = CommFunc.WriteBYTE(data, self.FamilyCount)
+ for i in range(self.FamilyCount):
+ data = CommFunc.WriteString(data, self.ActFamilyList[i].GetLength(), self.ActFamilyList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ServerInfoLen:%d,
+ ServerIDRangeInfo:%s,
+ ZoneID:%d,
+ ActID:%d,
+ StartDate:%s,
+ EndtDate:%s,
+ JoinFamilyCnt:%d,
+ ActFlowID:%d,
+ GuessTemplateID:%d,
+ PersonalTemplateID:%d,
+ FamilyTemplateID:%d,
+ StateError:%d,
+ FamilyCount:%d,
+ ActFamilyList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ServerInfoLen,
+ self.ServerIDRangeInfo,
+ self.ZoneID,
+ self.ActID,
+ self.StartDate,
+ self.EndtDate,
+ self.JoinFamilyCnt,
+ self.ActFlowID,
+ self.GuessTemplateID,
+ self.PersonalTemplateID,
+ self.FamilyTemplateID,
+ self.StateError,
+ self.FamilyCount,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZActInfo=tagGCFamilyGCZActInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZActInfo.Head.Cmd,m_NAtagGCFamilyGCZActInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZActInfo
+
+
+#------------------------------------------------------
+# C0 29 仙盟攻城战城池战斗信息 #tagGCFamilyGCZBatCityInfo
+
+class tagGCFamilyGCZBatCityInfo(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("CityID", c_int), #城池ID
+ ("CityLV", c_ubyte), #城池等级
+ ("FamilyID", c_int), #所属仙盟ID,可能为0
+ ("GuardID", c_int), #当前防守成员ID,为0时表示没有防守成员了,城池已被击毁
+ ("HP", c_int), #防守成员剩余生命,求余亿部分,剩余生命为0时代表该防守成员被击败
+ ("HPEx", c_int), #防守成员剩余生命,整除亿部分
+ ("HPMax", c_int), #防守成员最大生命,求余亿部分
+ ("HPMaxEx", c_int), #防守成员最大生命,整除亿部分
+ ("AtkPlayerID", c_int), #发起攻击的玩家ID,可能为0,判断是否自己的ID进行相应的攻击表现
+ ("AtkRet", c_ubyte), #攻击结果,仅在攻击玩家ID不为0时有效,0--成功;1-目标已被击杀;2-城池已被摧毁;3-其他
+ ("KillCnt", c_ubyte), #本次攻击击杀防守人员数
+ ("HurtValue", c_int), #伤害飘血,求余亿部分
+ ("HurtValueEx", c_int), #伤害飘血,整除亿部分
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC0
+ self.SubCmd = 0x29
+ 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 = 0xC0
+ self.SubCmd = 0x29
+ self.CityID = 0
+ self.CityLV = 0
+ self.FamilyID = 0
+ self.GuardID = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.AtkPlayerID = 0
+ self.AtkRet = 0
+ self.KillCnt = 0
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatCityInfo)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 29 仙盟攻城战城池战斗信息 //tagGCFamilyGCZBatCityInfo:
+ Cmd:%s,
+ SubCmd:%s,
+ CityID:%d,
+ CityLV:%d,
+ FamilyID:%d,
+ GuardID:%d,
+ HP:%d,
+ HPEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ AtkPlayerID:%d,
+ AtkRet:%d,
+ KillCnt:%d,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.CityID,
+ self.CityLV,
+ self.FamilyID,
+ self.GuardID,
+ self.HP,
+ self.HPEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.AtkPlayerID,
+ self.AtkRet,
+ self.KillCnt,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatCityInfo=tagGCFamilyGCZBatCityInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatCityInfo.Cmd,m_NAtagGCFamilyGCZBatCityInfo.SubCmd))] = m_NAtagGCFamilyGCZBatCityInfo
+
+
+#------------------------------------------------------
+# C0 25 仙盟攻城战轮次分组信息 #tagGCFamilyGCZBatGroupInfo
+
+class tagGCFamilyGCZBatGroup(Structure):
+ GroupNum = 0 #(BYTE GroupNum)// 分组编号,从1开始,对应A
+ FamilyIDCnt = 0 #(BYTE FamilyIDCnt)
+ FamilyIDList = list() #(vector<DWORD> FamilyIDList)// 仙盟ID列表,前端可以通过判断参与的仙盟ID是否在某个分组里面验证有没有战场参赛资格
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.GroupNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.FamilyIDCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FamilyIDCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.FamilyIDList.append(value)
+ return _pos
+
+ def Clear(self):
+ self.GroupNum = 0
+ self.FamilyIDCnt = 0
+ self.FamilyIDList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ length += 4 * self.FamilyIDCnt
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.GroupNum)
+ data = CommFunc.WriteBYTE(data, self.FamilyIDCnt)
+ for i in range(self.FamilyIDCnt):
+ data = CommFunc.WriteDWORD(data, self.FamilyIDList[i])
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ GroupNum:%d,
+ FamilyIDCnt:%d,
+ FamilyIDList:%s
+ '''\
+ %(
+ self.GroupNum,
+ self.FamilyIDCnt,
+ "..."
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBat(Structure):
+ BatType = 0 #(BYTE BatType)// 战场类型 1-初级;2-中级;3-高级;
+ GroupCnt = 0 #(BYTE GroupCnt)// 分组数
+ GroupList = list() #(vector<tagGCFamilyGCZBatGroup> GroupList)// 分组列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.BatType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.GroupCnt):
+ temGroupList = tagGCFamilyGCZBatGroup()
+ _pos = temGroupList.ReadData(_lpData, _pos)
+ self.GroupList.append(temGroupList)
+ return _pos
+
+ def Clear(self):
+ self.BatType = 0
+ self.GroupCnt = 0
+ self.GroupList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 1
+ length += 1
+ for i in range(self.GroupCnt):
+ length += self.GroupList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteBYTE(data, self.BatType)
+ data = CommFunc.WriteBYTE(data, self.GroupCnt)
+ for i in range(self.GroupCnt):
+ data = CommFunc.WriteString(data, self.GroupList[i].GetLength(), self.GroupList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ BatType:%d,
+ GroupCnt:%d,
+ GroupList:%s
+ '''\
+ %(
+ self.BatType,
+ self.GroupCnt,
+ "..."
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatGroupInfo(Structure):
+ Head = tagHead()
+ RoundNum = 0 #(BYTE RoundNum)// 第x轮的分组,从1开始,没有在对应轮次战场分组里的视为没有该轮次的参赛资格
+ BatTypeCnt = 0 #(BYTE BatTypeCnt)// 战场类型数
+ BatList = list() #(vector<tagGCFamilyGCZBat> BatList)//战场列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x25
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.RoundNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.BatTypeCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.BatTypeCnt):
+ temBatList = tagGCFamilyGCZBat()
+ _pos = temBatList.ReadData(_lpData, _pos)
+ self.BatList.append(temBatList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x25
+ self.RoundNum = 0
+ self.BatTypeCnt = 0
+ self.BatList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 1
+ for i in range(self.BatTypeCnt):
+ length += self.BatList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.RoundNum)
+ data = CommFunc.WriteBYTE(data, self.BatTypeCnt)
+ for i in range(self.BatTypeCnt):
+ data = CommFunc.WriteString(data, self.BatList[i].GetLength(), self.BatList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ RoundNum:%d,
+ BatTypeCnt:%d,
+ BatList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.RoundNum,
+ self.BatTypeCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatGroupInfo=tagGCFamilyGCZBatGroupInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatGroupInfo.Head.Cmd,m_NAtagGCFamilyGCZBatGroupInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZBatGroupInfo
+
+
+#------------------------------------------------------
+# C0 30 仙盟攻城战战斗战报 #tagGCFamilyGCZBatReport
+
+class tagGCFamilyGCZBatRepHurt(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("TagFamilyID", c_int), #目标仙盟ID
+ ("HurtValue", c_int), #输出伤害,求余亿部分
+ ("HurtValueEx", c_int), #输出伤害,整除亿部分
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.TagFamilyID = 0
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatRepHurt)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 30 仙盟攻城战战斗战报 //tagGCFamilyGCZBatReport:
+ TagFamilyID:%d,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.TagFamilyID,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatReport(Structure):
+ Head = tagHead()
+ FamilyID = 0 #(DWORD FamilyID)// 战报仙盟ID
+ DefRepCnt = 0 #(BYTE DefRepCnt)
+ DefRepList = list() #(vector<tagGCFamilyGCZBatRepHurt> DefRepList)// 防守战报
+ AtkRepCnt = 0 #(BYTE AtkRepCnt)
+ AtkRepList = list() #(vector<tagGCFamilyGCZBatRepHurt> AtkRepList)// 进攻战报
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x30
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.DefRepCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.DefRepCnt):
+ temDefRepList = tagGCFamilyGCZBatRepHurt()
+ _pos = temDefRepList.ReadData(_lpData, _pos)
+ self.DefRepList.append(temDefRepList)
+ self.AtkRepCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.AtkRepCnt):
+ temAtkRepList = tagGCFamilyGCZBatRepHurt()
+ _pos = temAtkRepList.ReadData(_lpData, _pos)
+ self.AtkRepList.append(temAtkRepList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x30
+ self.FamilyID = 0
+ self.DefRepCnt = 0
+ self.DefRepList = list()
+ self.AtkRepCnt = 0
+ self.AtkRepList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 1
+ for i in range(self.DefRepCnt):
+ length += self.DefRepList[i].GetLength()
+ length += 1
+ for i in range(self.AtkRepCnt):
+ length += self.AtkRepList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteBYTE(data, self.DefRepCnt)
+ for i in range(self.DefRepCnt):
+ data = CommFunc.WriteString(data, self.DefRepList[i].GetLength(), self.DefRepList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.AtkRepCnt)
+ for i in range(self.AtkRepCnt):
+ data = CommFunc.WriteString(data, self.AtkRepList[i].GetLength(), self.AtkRepList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ FamilyID:%d,
+ DefRepCnt:%d,
+ DefRepList:%s,
+ AtkRepCnt:%d,
+ AtkRepList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.FamilyID,
+ self.DefRepCnt,
+ "...",
+ self.AtkRepCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatReport=tagGCFamilyGCZBatReport()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatReport.Head.Cmd,m_NAtagGCFamilyGCZBatReport.Head.SubCmd))] = m_NAtagGCFamilyGCZBatReport
+
+
+#------------------------------------------------------
+# C0 28 仙盟攻城战城池场景信息 #tagGCFamilyGCZBatSceneInfo
+
+class tagGCFamilyGCZBatScenePlayer(Structure):
+ PlayerID = 0 #(DWORD PlayerID)
+ Name = "" #(char Name[33])
+ Face = 0 #(DWORD Face)
+ FacePic = 0 #(DWORD FacePic)
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.PlayerID = 0
+ self.Name = ""
+ self.Face = 0
+ self.FacePic = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteDWORD(data, self.Face)
+ data = CommFunc.WriteDWORD(data, self.FacePic)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ PlayerID:%d,
+ Name:%s,
+ Face:%d,
+ FacePic:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.Name,
+ self.Face,
+ self.FacePic
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatSceneHurt(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("CityID", c_int), #被攻击的城池ID
+ ("HurtValue", c_int), #伤害飘血,求余亿部分
+ ("HurtValueEx", c_int), #伤害飘血,整除亿部分
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.CityID = 0
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatSceneHurt)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 28 仙盟攻城战城池场景信息 //tagGCFamilyGCZBatSceneInfo:
+ CityID:%d,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.CityID,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatSceneCity(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("CityID", c_int), #城池ID
+ ("CityLV", c_ubyte), #城池等级
+ ("FamilyID", c_int), #所属仙盟ID,可能为0
+ ("Rank", c_ubyte), #当前名次,从1开始
+ ("HP", c_int), #剩余生命,求余亿部分,剩余生命为0时代表被摧毁
+ ("HPEx", c_int), #剩余生命,整除亿部分
+ ("HPMax", c_int), #最大生命,求余亿部分
+ ("HPMaxEx", c_int), #最大生命,整除亿部分
+ ("LastAtkedTime", c_int), #最后一次被攻击时间戳,可能为0
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.CityID = 0
+ self.CityLV = 0
+ self.FamilyID = 0
+ self.Rank = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.LastAtkedTime = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZBatSceneCity)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 28 仙盟攻城战城池场景信息 //tagGCFamilyGCZBatSceneInfo:
+ CityID:%d,
+ CityLV:%d,
+ FamilyID:%d,
+ Rank:%d,
+ HP:%d,
+ HPEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ LastAtkedTime:%d
+ '''\
+ %(
+ self.CityID,
+ self.CityLV,
+ self.FamilyID,
+ self.Rank,
+ self.HP,
+ self.HPEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.LastAtkedTime
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZBatSceneInfo(Structure):
+ Head = tagHead()
+ BatType = 0 #(BYTE BatType)// 战场类型 1-初级;2-中级;3-高级;
+ GroupNum = 0 #(BYTE GroupNum)// 分组编号,从1开始,对应A
+ TopFamilyID = 0 #(DWORD TopFamilyID)// 伤害第一仙盟ID
+ TopLeaderID = 0 #(DWORD TopLeaderID)// 伤害第一盟主ID
+ TopPlayerID = 0 #(DWORD TopPlayerID)// 伤害第一玩家ID
+ TopPlayerFamilyID = 0 #(DWORD TopPlayerFamilyID)// 伤害第一玩家仙盟ID
+ AtkPlayerID = 0 #(DWORD AtkPlayerID)// 发起攻击的玩家,可能为0,仅技能攻击时通知,普攻时仅通知血量等信息
+ AtkType = 0 #(BYTE AtkType)// 攻击类型,有发起攻击的玩家时有效
+ KillCnt = 0 #(BYTE KillCnt)// 本次攻击累计击杀数,有发起攻击的玩家时有效
+ HurtCnt = 0 #(BYTE HurtCnt)
+ HurtList = list() #(vector<tagGCFamilyGCZBatSceneHurt> HurtList)//本次攻击伤血信息,有发起攻击的玩家时有效
+ CityCnt = 0 #(BYTE CityCnt)
+ CityList = list() #(vector<tagGCFamilyGCZBatSceneCity> CityList)// 城池信息,仅通知变化的城池
+ PlayerCnt = 0 #(BYTE PlayerCnt)
+ PlayerInfoList = list() #(vector<tagGCFamilyGCZBatScenePlayer> PlayerInfoList)// 场景展示所需要用到的玩家信息,如第一玩家、使用技能玩家
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x28
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.BatType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.GroupNum,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.TopFamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TopLeaderID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TopPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TopPlayerFamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AtkPlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.AtkType,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.KillCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.HurtCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.HurtCnt):
+ temHurtList = tagGCFamilyGCZBatSceneHurt()
+ _pos = temHurtList.ReadData(_lpData, _pos)
+ self.HurtList.append(temHurtList)
+ self.CityCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.CityCnt):
+ temCityList = tagGCFamilyGCZBatSceneCity()
+ _pos = temCityList.ReadData(_lpData, _pos)
+ self.CityList.append(temCityList)
+ self.PlayerCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.PlayerCnt):
+ temPlayerInfoList = tagGCFamilyGCZBatScenePlayer()
+ _pos = temPlayerInfoList.ReadData(_lpData, _pos)
+ self.PlayerInfoList.append(temPlayerInfoList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x28
+ self.BatType = 0
+ self.GroupNum = 0
+ self.TopFamilyID = 0
+ self.TopLeaderID = 0
+ self.TopPlayerID = 0
+ self.TopPlayerFamilyID = 0
+ self.AtkPlayerID = 0
+ self.AtkType = 0
+ self.KillCnt = 0
+ self.HurtCnt = 0
+ self.HurtList = list()
+ self.CityCnt = 0
+ self.CityList = list()
+ self.PlayerCnt = 0
+ self.PlayerInfoList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 1
+ length += 1
+ length += 1
+ for i in range(self.HurtCnt):
+ length += self.HurtList[i].GetLength()
+ length += 1
+ for i in range(self.CityCnt):
+ length += self.CityList[i].GetLength()
+ length += 1
+ for i in range(self.PlayerCnt):
+ length += self.PlayerInfoList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.BatType)
+ data = CommFunc.WriteBYTE(data, self.GroupNum)
+ data = CommFunc.WriteDWORD(data, self.TopFamilyID)
+ data = CommFunc.WriteDWORD(data, self.TopLeaderID)
+ data = CommFunc.WriteDWORD(data, self.TopPlayerID)
+ data = CommFunc.WriteDWORD(data, self.TopPlayerFamilyID)
+ data = CommFunc.WriteDWORD(data, self.AtkPlayerID)
+ data = CommFunc.WriteBYTE(data, self.AtkType)
+ data = CommFunc.WriteBYTE(data, self.KillCnt)
+ data = CommFunc.WriteBYTE(data, self.HurtCnt)
+ for i in range(self.HurtCnt):
+ data = CommFunc.WriteString(data, self.HurtList[i].GetLength(), self.HurtList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.CityCnt)
+ for i in range(self.CityCnt):
+ data = CommFunc.WriteString(data, self.CityList[i].GetLength(), self.CityList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.PlayerCnt)
+ for i in range(self.PlayerCnt):
+ data = CommFunc.WriteString(data, self.PlayerInfoList[i].GetLength(), self.PlayerInfoList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ BatType:%d,
+ GroupNum:%d,
+ TopFamilyID:%d,
+ TopLeaderID:%d,
+ TopPlayerID:%d,
+ TopPlayerFamilyID:%d,
+ AtkPlayerID:%d,
+ AtkType:%d,
+ KillCnt:%d,
+ HurtCnt:%d,
+ HurtList:%s,
+ CityCnt:%d,
+ CityList:%s,
+ PlayerCnt:%d,
+ PlayerInfoList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.BatType,
+ self.GroupNum,
+ self.TopFamilyID,
+ self.TopLeaderID,
+ self.TopPlayerID,
+ self.TopPlayerFamilyID,
+ self.AtkPlayerID,
+ self.AtkType,
+ self.KillCnt,
+ self.HurtCnt,
+ "...",
+ self.CityCnt,
+ "...",
+ self.PlayerCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZBatSceneInfo=tagGCFamilyGCZBatSceneInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZBatSceneInfo.Head.Cmd,m_NAtagGCFamilyGCZBatSceneInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZBatSceneInfo
+
+
+#------------------------------------------------------
+# C0 26 仙盟攻城战大本营信息 #tagGCFamilyGCZCampInfo
+
+class tagGCFamilyGCZCampMem(Structure):
+ PlayerID = 0 #(DWORD PlayerID)
+ Name = "" #(char Name[33])//参与玩家名字
+ FamilyLV = 0 #(BYTE FamilyLV)//参与时的家族职位
+ Face = 0 #(DWORD Face)//基本脸型
+ FacePic = 0 #(DWORD FacePic)//头像框
+ FightPower = 0 #(DWORD FightPower)//战力,求余亿部分
+ FightPowerEx = 0 #(DWORD FightPowerEx)//战力,整除亿部分
+ HP = 0 #(DWORD HP)//剩余生命,求余亿部分
+ HPEx = 0 #(DWORD HPEx)//剩余生命,整除亿部分
+ HPMax = 0 #(DWORD HPMax)//最大生命,求余亿部分
+ HPMaxEx = 0 #(DWORD HPMaxEx)//最大生命,整除亿部分
+ TotalHurt = 0 #(DWORD TotalHurt)//活动总伤害,求余亿部分,如果不在榜上则读该值
+ TotalHurtEx = 0 #(DWORD TotalHurtEx)//活动总伤害,整除亿部分
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.FamilyLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ self.Face,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FacePic,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPower,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.FightPowerEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMax,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMaxEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TotalHurt,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.TotalHurtEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.PlayerID = 0
+ self.Name = ""
+ self.FamilyLV = 0
+ self.Face = 0
+ self.FacePic = 0
+ self.FightPower = 0
+ self.FightPowerEx = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.TotalHurt = 0
+ self.TotalHurtEx = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 1
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteBYTE(data, self.FamilyLV)
+ data = CommFunc.WriteDWORD(data, self.Face)
+ data = CommFunc.WriteDWORD(data, self.FacePic)
+ data = CommFunc.WriteDWORD(data, self.FightPower)
+ data = CommFunc.WriteDWORD(data, self.FightPowerEx)
+ data = CommFunc.WriteDWORD(data, self.HP)
+ data = CommFunc.WriteDWORD(data, self.HPEx)
+ data = CommFunc.WriteDWORD(data, self.HPMax)
+ data = CommFunc.WriteDWORD(data, self.HPMaxEx)
+ data = CommFunc.WriteDWORD(data, self.TotalHurt)
+ data = CommFunc.WriteDWORD(data, self.TotalHurtEx)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ PlayerID:%d,
+ Name:%s,
+ FamilyLV:%d,
+ Face:%d,
+ FacePic:%d,
+ FightPower:%d,
+ FightPowerEx:%d,
+ HP:%d,
+ HPEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ TotalHurt:%d,
+ TotalHurtEx:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.Name,
+ self.FamilyLV,
+ self.Face,
+ self.FacePic,
+ self.FightPower,
+ self.FightPowerEx,
+ self.HP,
+ self.HPEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.TotalHurt,
+ self.TotalHurtEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZCampInfo(Structure):
+ Head = tagHead()
+ FamilyID = 0 #(DWORD FamilyID)//所在活动仙盟ID,可能不是玩家当前的仙盟ID,活动以该ID为准
+ Score = 0 #(WORD Score)//活动总积分,如果不在榜上则读该值
+ CampLV = 0 #(WORD CampLV)//大本营当前等级
+ CampExp = 0 #(DWORD CampExp)//大本营当前经验
+ CityLV = 0 #(WORD CityLV)//城池属性等级,开战后可能与当前大本营等级不一样
+ HPBase = 0 #(DWORD HPBase)//基础生命,求余亿部分
+ HPBaseEx = 0 #(DWORD HPBaseEx)//基础生命,整除亿部分
+ HPMax = 0 #(DWORD HPMax)//总生命,求余亿部分
+ HPMaxEx = 0 #(DWORD HPMaxEx)//总大生命,整除亿部分
+ HP = 0 #(DWORD HP)//剩余生命,求余亿部分
+ HPEx = 0 #(DWORD HPEx)//剩余生命,整除亿部分
+ DefMemCnt = 0 #(BYTE DefMemCnt)
+ DefMemList = list() #(vector<tagGCFamilyGCZCampMem> DefMemList)//防守成员列表,有同步则差异更新,没有在防守成员里的视为没有参与资格
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x26
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Score,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.CampLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.CampExp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.CityLV,_pos = CommFunc.ReadWORD(_lpData, _pos)
+ self.HPBase,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPBaseEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMax,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPMaxEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HP,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HPEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.DefMemCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.DefMemCnt):
+ temDefMemList = tagGCFamilyGCZCampMem()
+ _pos = temDefMemList.ReadData(_lpData, _pos)
+ self.DefMemList.append(temDefMemList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x26
+ self.FamilyID = 0
+ self.Score = 0
+ self.CampLV = 0
+ self.CampExp = 0
+ self.CityLV = 0
+ self.HPBase = 0
+ self.HPBaseEx = 0
+ self.HPMax = 0
+ self.HPMaxEx = 0
+ self.HP = 0
+ self.HPEx = 0
+ self.DefMemCnt = 0
+ self.DefMemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 2
+ length += 2
+ length += 4
+ length += 2
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 4
+ length += 1
+ for i in range(self.DefMemCnt):
+ length += self.DefMemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteWORD(data, self.Score)
+ data = CommFunc.WriteWORD(data, self.CampLV)
+ data = CommFunc.WriteDWORD(data, self.CampExp)
+ data = CommFunc.WriteWORD(data, self.CityLV)
+ data = CommFunc.WriteDWORD(data, self.HPBase)
+ data = CommFunc.WriteDWORD(data, self.HPBaseEx)
+ data = CommFunc.WriteDWORD(data, self.HPMax)
+ data = CommFunc.WriteDWORD(data, self.HPMaxEx)
+ data = CommFunc.WriteDWORD(data, self.HP)
+ data = CommFunc.WriteDWORD(data, self.HPEx)
+ data = CommFunc.WriteBYTE(data, self.DefMemCnt)
+ for i in range(self.DefMemCnt):
+ data = CommFunc.WriteString(data, self.DefMemList[i].GetLength(), self.DefMemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ FamilyID:%d,
+ Score:%d,
+ CampLV:%d,
+ CampExp:%d,
+ CityLV:%d,
+ HPBase:%d,
+ HPBaseEx:%d,
+ HPMax:%d,
+ HPMaxEx:%d,
+ HP:%d,
+ HPEx:%d,
+ DefMemCnt:%d,
+ DefMemList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.FamilyID,
+ self.Score,
+ self.CampLV,
+ self.CampExp,
+ self.CityLV,
+ self.HPBase,
+ self.HPBaseEx,
+ self.HPMax,
+ self.HPMaxEx,
+ self.HP,
+ self.HPEx,
+ self.DefMemCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZCampInfo=tagGCFamilyGCZCampInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZCampInfo.Head.Cmd,m_NAtagGCFamilyGCZCampInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZCampInfo
+
+
+#------------------------------------------------------
+# C0 27 仙盟攻城战成员贡献值信息 #tagGCFamilyGCZContributionInfo
+
+class tagGCFamilyGCZContribution(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("PlayerID", c_int),
+ ("ContributionValue", c_int), #贡献值
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.PlayerID = 0
+ self.ContributionValue = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZContribution)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 27 仙盟攻城战成员贡献值信息 //tagGCFamilyGCZContributionInfo:
+ PlayerID:%d,
+ ContributionValue:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.ContributionValue
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZContributionInfo(Structure):
+ Head = tagHead()
+ ContriCnt = 0 #(BYTE ContriCnt)
+ ContriList = list() #(vector<tagGCFamilyGCZContribution> ContriList)//成员贡献值列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x27
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.ContriCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.ContriCnt):
+ temContriList = tagGCFamilyGCZContribution()
+ _pos = temContriList.ReadData(_lpData, _pos)
+ self.ContriList.append(temContriList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x27
+ self.ContriCnt = 0
+ self.ContriList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 1
+ for i in range(self.ContriCnt):
+ length += self.ContriList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.ContriCnt)
+ for i in range(self.ContriCnt):
+ data = CommFunc.WriteString(data, self.ContriList[i].GetLength(), self.ContriList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ ContriCnt:%d,
+ ContriList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.ContriCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZContributionInfo=tagGCFamilyGCZContributionInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZContributionInfo.Head.Cmd,m_NAtagGCFamilyGCZContributionInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZContributionInfo
+
+
+#------------------------------------------------------
+# C0 31 仙盟攻城战分组仙盟成员伤害明细 #tagGCFamilyGCZGroupFamilyMemHurtInfo
+
+class tagGCFamilyGCZGroupFamilyMemHurt(Structure):
+ PlayerID = 0 #(DWORD PlayerID)
+ Name = "" #(char Name[33])//参与玩家名字
+ HurtValue = 0 #(DWORD HurtValue)//伤害,求余亿部分
+ HurtValueEx = 0 #(DWORD HurtValueEx)//伤害,整除亿部分
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.Name,_pos = CommFunc.ReadString(_lpData, _pos,33)
+ self.HurtValue,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HurtValueEx,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ return _pos
+
+ def Clear(self):
+ self.PlayerID = 0
+ self.Name = ""
+ self.HurtValue = 0
+ self.HurtValueEx = 0
+ return
+
+ def GetLength(self):
+ length = 0
+ length += 4
+ length += 33
+ length += 4
+ length += 4
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteString(data, 33, self.Name)
+ data = CommFunc.WriteDWORD(data, self.HurtValue)
+ data = CommFunc.WriteDWORD(data, self.HurtValueEx)
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ PlayerID:%d,
+ Name:%s,
+ HurtValue:%d,
+ HurtValueEx:%d
+ '''\
+ %(
+ self.PlayerID,
+ self.Name,
+ self.HurtValue,
+ self.HurtValueEx
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZGroupFamilyMemHurtInfo(Structure):
+ Head = tagHead()
+ FamilyID = 0 #(DWORD FamilyID)//查看的目标仙盟ID
+ HurtMemCnt = 0 #(BYTE HurtMemCnt)
+ HurtMemList = list() #(vector<tagGCFamilyGCZGroupFamilyMemHurt> HurtMemList)//成员伤害明细列表,只算城池被摧毁前的伤害,未排序,前端自己排序
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x31
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.FamilyID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.HurtMemCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.HurtMemCnt):
+ temHurtMemList = tagGCFamilyGCZGroupFamilyMemHurt()
+ _pos = temHurtMemList.ReadData(_lpData, _pos)
+ self.HurtMemList.append(temHurtMemList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x31
+ self.FamilyID = 0
+ self.HurtMemCnt = 0
+ self.HurtMemList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 1
+ for i in range(self.HurtMemCnt):
+ length += self.HurtMemList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.FamilyID)
+ data = CommFunc.WriteBYTE(data, self.HurtMemCnt)
+ for i in range(self.HurtMemCnt):
+ data = CommFunc.WriteString(data, self.HurtMemList[i].GetLength(), self.HurtMemList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ FamilyID:%d,
+ HurtMemCnt:%d,
+ HurtMemList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.FamilyID,
+ self.HurtMemCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo=tagGCFamilyGCZGroupFamilyMemHurtInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo.Head.Cmd,m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZGroupFamilyMemHurtInfo
+
+
+#------------------------------------------------------
+# C0 32 仙盟攻城战竞猜名单信息 #tagGCFamilyGCZGuessInfo
+
+class tagGCFamilyGCZGuessFamily(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("FamilyID", c_int), #备选仙盟ID
+ ("GuessValue", c_ushort), #竞猜热度值,玩家每次选择则加1,重复选择也算
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.FamilyID = 0
+ self.GuessValue = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZGuessFamily)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 32 仙盟攻城战竞猜名单信息 //tagGCFamilyGCZGuessInfo:
+ FamilyID:%d,
+ GuessValue:%d
+ '''\
+ %(
+ self.FamilyID,
+ self.GuessValue
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZGuessRight(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("AwardID", c_ubyte), #奖励ID
+ ("RightPlayerCnt", c_ushort), #猜中玩家个数
+ ]
+
+ def __init__(self):
+ self.Clear()
+ 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.AwardID = 0
+ self.RightPlayerCnt = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagGCFamilyGCZGuessRight)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C0 32 仙盟攻城战竞猜名单信息 //tagGCFamilyGCZGuessInfo:
+ AwardID:%d,
+ RightPlayerCnt:%d
+ '''\
+ %(
+ self.AwardID,
+ self.RightPlayerCnt
+ )
+ return DumpString
+
+
+class tagGCFamilyGCZGuessInfo(Structure):
+ Head = tagHead()
+ PlayerID = 0 #(DWORD PlayerID)//竞猜玩家ID,有玩家修改竞猜时会附带该信息,如果是自己ID,则更新自己的竞猜选项,否则无视
+ SelectCnt = 0 #(BYTE SelectCnt)
+ SelectFamilyIDList = list() #(vector<DWORD> SelectFamilyIDList)//竞猜玩家选择的仙盟ID顺序
+ FinalCnt = 0 #(BYTE FinalCnt)
+ FinalFamilyIDList = list() #(vector<DWORD> FinalFamilyIDList)//最终排名顺序,仅活动排名出来后才有值
+ RightCnt = 0 #(BYTE RightCnt)
+ RightInfoList = list() #(vector<tagGCFamilyGCZGuessRight> RightInfoList)//猜中个数明细列表
+ FamilyCnt = 0 #(BYTE FamilyCnt)
+ GuessFamilyList = list() #(vector<tagGCFamilyGCZGuessFamily> GuessFamilyList)//备选仙盟名单列表
+ data = None
+
+ def __init__(self):
+ self.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x32
+ return
+
+ def ReadData(self, _lpData, _pos=0, _Len=0):
+ self.Clear()
+ _pos = self.Head.ReadData(_lpData, _pos)
+ self.PlayerID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+ self.SelectCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.SelectCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.SelectFamilyIDList.append(value)
+ self.FinalCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FinalCnt):
+ value,_pos=CommFunc.ReadDWORD(_lpData,_pos)
+ self.FinalFamilyIDList.append(value)
+ self.RightCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.RightCnt):
+ temRightInfoList = tagGCFamilyGCZGuessRight()
+ _pos = temRightInfoList.ReadData(_lpData, _pos)
+ self.RightInfoList.append(temRightInfoList)
+ self.FamilyCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+ for i in range(self.FamilyCnt):
+ temGuessFamilyList = tagGCFamilyGCZGuessFamily()
+ _pos = temGuessFamilyList.ReadData(_lpData, _pos)
+ self.GuessFamilyList.append(temGuessFamilyList)
+ return _pos
+
+ def Clear(self):
+ self.Head = tagHead()
+ self.Head.Clear()
+ self.Head.Cmd = 0xC0
+ self.Head.SubCmd = 0x32
+ self.PlayerID = 0
+ self.SelectCnt = 0
+ self.SelectFamilyIDList = list()
+ self.FinalCnt = 0
+ self.FinalFamilyIDList = list()
+ self.RightCnt = 0
+ self.RightInfoList = list()
+ self.FamilyCnt = 0
+ self.GuessFamilyList = list()
+ return
+
+ def GetLength(self):
+ length = 0
+ length += self.Head.GetLength()
+ length += 4
+ length += 1
+ length += 4 * self.SelectCnt
+ length += 1
+ length += 4 * self.FinalCnt
+ length += 1
+ for i in range(self.RightCnt):
+ length += self.RightInfoList[i].GetLength()
+ length += 1
+ for i in range(self.FamilyCnt):
+ length += self.GuessFamilyList[i].GetLength()
+
+ return length
+
+ def GetBuffer(self):
+ data = ''
+ data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+ data = CommFunc.WriteDWORD(data, self.PlayerID)
+ data = CommFunc.WriteBYTE(data, self.SelectCnt)
+ for i in range(self.SelectCnt):
+ data = CommFunc.WriteDWORD(data, self.SelectFamilyIDList[i])
+ data = CommFunc.WriteBYTE(data, self.FinalCnt)
+ for i in range(self.FinalCnt):
+ data = CommFunc.WriteDWORD(data, self.FinalFamilyIDList[i])
+ data = CommFunc.WriteBYTE(data, self.RightCnt)
+ for i in range(self.RightCnt):
+ data = CommFunc.WriteString(data, self.RightInfoList[i].GetLength(), self.RightInfoList[i].GetBuffer())
+ data = CommFunc.WriteBYTE(data, self.FamilyCnt)
+ for i in range(self.FamilyCnt):
+ data = CommFunc.WriteString(data, self.GuessFamilyList[i].GetLength(), self.GuessFamilyList[i].GetBuffer())
+ return data
+
+ def OutputString(self):
+ DumpString = '''
+ Head:%s,
+ PlayerID:%d,
+ SelectCnt:%d,
+ SelectFamilyIDList:%s,
+ FinalCnt:%d,
+ FinalFamilyIDList:%s,
+ RightCnt:%d,
+ RightInfoList:%s,
+ FamilyCnt:%d,
+ GuessFamilyList:%s
+ '''\
+ %(
+ self.Head.OutputString(),
+ self.PlayerID,
+ self.SelectCnt,
+ "...",
+ self.FinalCnt,
+ "...",
+ self.RightCnt,
+ "...",
+ self.FamilyCnt,
+ "..."
+ )
+ return DumpString
+
+
+m_NAtagGCFamilyGCZGuessInfo=tagGCFamilyGCZGuessInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagGCFamilyGCZGuessInfo.Head.Cmd,m_NAtagGCFamilyGCZGuessInfo.Head.SubCmd))] = m_NAtagGCFamilyGCZGuessInfo
#------------------------------------------------------
@@ -57675,6 +59419,70 @@
#------------------------------------------------------
+# C1 10 仙盟攻城战玩家信息 #tagMCFamilyGCZPlayerInfo
+
+class tagMCFamilyGCZPlayerInfo(Structure):
+ _pack_ = 1
+ _fields_ = [
+ ("Cmd", c_ubyte),
+ ("SubCmd", c_ubyte),
+ ("ContributionCnt", c_ubyte), # 轮次低级捐献已捐献次数,轮次变更时会重置
+ ("Energy", c_ubyte), # 当前可用免费体力
+ ("EnergyTime", c_int), # 上次恢复免费体力时间戳,为0时不再恢复
+ ("AwardState", c_int), # 活动奖励领取状态,按二进制位判断是否已领取,0-竞猜奖励;1-个人排行奖励;2-仙盟排名奖励;
+ ]
+
+ def __init__(self):
+ self.Clear()
+ self.Cmd = 0xC1
+ 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 = 0xC1
+ self.SubCmd = 0x10
+ self.ContributionCnt = 0
+ self.Energy = 0
+ self.EnergyTime = 0
+ self.AwardState = 0
+ return
+
+ def GetLength(self):
+ return sizeof(tagMCFamilyGCZPlayerInfo)
+
+ def GetBuffer(self):
+ return string_at(addressof(self), self.GetLength())
+
+ def OutputString(self):
+ DumpString = '''// C1 10 仙盟攻城战玩家信息 //tagMCFamilyGCZPlayerInfo:
+ Cmd:%s,
+ SubCmd:%s,
+ ContributionCnt:%d,
+ Energy:%d,
+ EnergyTime:%d,
+ AwardState:%d
+ '''\
+ %(
+ self.Cmd,
+ self.SubCmd,
+ self.ContributionCnt,
+ self.Energy,
+ self.EnergyTime,
+ self.AwardState
+ )
+ return DumpString
+
+
+m_NAtagMCFamilyGCZPlayerInfo=tagMCFamilyGCZPlayerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyGCZPlayerInfo.Cmd,m_NAtagMCFamilyGCZPlayerInfo.SubCmd))] = m_NAtagMCFamilyGCZPlayerInfo
+
+
+#------------------------------------------------------
# C1 08 幸运云购玩家信息 #tagMCLuckyCloudBuyPlayerInfo
class tagMCLuckyCloudBuyPlayerInfo(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/FamilyGCZ.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/FamilyGCZ.py
new file mode 100644
index 0000000..fd4d6a0
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/FamilyGCZ.py
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.FamilyGCZ
+#
+# @todo:仙盟攻城战
+# @author hxp
+# @date 2025-04-09
+# @version 1.0
+#
+# 详细描述: 仙盟攻城战
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-04-09 16:00"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import GameWorld
+import PlayerControl
+import PlayerActFamilyGCZ
+import ShareDefine
+
+#---------------------------------------------------------------------
+#逻辑实现
+
+## GM命令执行入口
+# @param curPlayer 当前玩家
+# @param msgList 参数列表
+# @return None
+# @remarks 函数详细说明.
+def OnExec(curPlayer, msgList):
+
+ if not msgList:
+ GameWorld.DebugAnswer(curPlayer, "捐献次数: FamilyGCZ j 低级捐献次数")
+ GameWorld.DebugAnswer(curPlayer, "设置体力: FamilyGCZ e 体力")
+ GameWorld.DebugAnswer(curPlayer, "成员捐献: FamilyGCZ x 经验 [成员数]")
+ GameWorld.DebugAnswer(curPlayer, "设大本营: FamilyGCZ c 等级 [经验]")
+ GameWorld.DebugAnswer(curPlayer, "攻击城池: FamilyGCZ a 城池ID [攻击次数 仙盟ID]")
+ GameWorld.DebugAnswer(curPlayer, "攻击城池: FamilyGCZ h 城池ID 剩余血量 [攻击方人数 仙盟ID]")
+ GameWorld.DebugAnswer(curPlayer, "击毁城池: FamilyGCZ k [城池ID 攻击方仙盟ID]")
+ GameWorld.DebugAnswer(curPlayer, "输出城池: FamilyGCZ p [战场类型 分组编号]")
+ GameWorld.DebugAnswer(curPlayer, "山寨竞猜: FamilyGCZ g 人数 [竞猜ID1 ID2 ID3]")
+ GameWorld.DebugAnswer(curPlayer, "城池ID一般等同于仙盟ID,修罗城ID=20亿")
+ GameWorld.DebugAnswer(curPlayer, "攻击次数默认1自己攻击,大于1仙盟成员轮流攻击")
+ GameWorld.DebugAnswer(curPlayer, "剩余血量 :由指定的攻击方人数平摊输出,1个时默认自己")
+ GameWorld.DebugAnswer(curPlayer, "击毁城池没有指定ID时则随机击毁一个")
+ GameWorld.DebugAnswer(curPlayer, "攻击方仙盟ID有值可指定A盟攻击B盟")
+ GameWorld.DebugAnswer(curPlayer, "攻击方仙盟ID没填则A盟默认自己盟")
+ return
+
+ playerID = curPlayer.GetPlayerID()
+ value = msgList[0]
+
+ # 捐献次数
+ if value == "j":
+ contriCnt = msgList[1] if len(msgList) > 1 else 0
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZContributionCnt, contriCnt)
+ GameWorld.DebugAnswer(curPlayer, "设置低级捐献次数: %s" % contriCnt)
+ PlayerActFamilyGCZ.Sync_FamilyGCZPlayerInfo(curPlayer)
+ return
+
+ # 设置体力
+ if value == "e":
+ setEnergy = msgList[1] if len(msgList) > 1 else 0
+ updEnergy = PlayerActFamilyGCZ.SetEnergy(curPlayer, setEnergy)
+ GameWorld.DebugAnswer(curPlayer, "设置体力: %s" % updEnergy)
+ return
+
+ if value in ["x", "c", "a", "h", "k", "p", "g"]:
+ dataMsg = {"ActMsgType":"GMCMD", "playerID":playerID, "msgList":msgList}
+ GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_FamilyGCZ, dataMsg)
+ return
+
+ return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
index 1dfdf39..fd0fd8c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ItemControler.py
@@ -224,6 +224,47 @@
def IsEventItem(item):
return (item.GetType() == ChConfig.Def_ItemType_MissionItem)
+def DelPlayerItemByPacks(curPlayer, itemID, delCount, eventName="", saveDataDict={},
+ packTypeList=[IPY_GameWorld.rptItem, IPY_GameWorld.rptWarehouse]):
+ '''扣除玩家物品,从多个背包检查,一般是用于不是立马扣除的逻辑,防止玩家快速把背包物品放入仓库导致扣除失败
+ 如跨服功能,有些逻辑需要跨服验证或处理后才进行扣除
+ '''
+ remainDelCnt = delCount # 剩余需要扣除数量
+ for packType in packTypeList:
+ curPack = curPlayer.GetItemManager().GetPack(packType)
+ for i in range(0, curPack.GetCount()):
+ curItem = curPack.GetAt(i)
+ if curItem.IsEmpty():
+ continue
+ if curItem.GetItemTypeID() != itemID:
+ continue
+ if curItem.GetIsLocked():
+ continue
+
+ itemCount = GetItemCount(curItem)
+
+ #身上物品比要删除的物品多
+ if itemCount > remainDelCnt:
+ updItemCount = itemCount - remainDelCnt
+ SetItemCount(curItem, updItemCount)
+ if ItemNeedRecord(curItem):
+ itemNoteDict = ItemCommon.GetItemNoteDict(curItem, remainDelCnt, itemCount, updItemCount)
+ ItemCommon.DR_DelItem(curPlayer, packType, eventName, itemNoteDict, saveDataDict)
+ remainDelCnt = 0
+ else:
+ if ItemNeedRecord(curItem):
+ itemNoteDict = ItemCommon.GetItemNoteDict(curItem, itemCount, itemCount, 0)
+ ItemCommon.DR_DelItem(curPlayer, packType, eventName, itemNoteDict, saveDataDict)
+ curItem.Clear()
+ remainDelCnt -= itemCount
+
+ if remainDelCnt <= 0:
+ return True
+
+ GameWorld.ErrLog("扣除物品失败,物品不足! itemID=%s,delCount=%s,remainDelCnt=%s,eventName=%s"
+ % (itemID, delCount, remainDelCnt, eventName), curPlayer.GetPlayerID())
+ return False
+
## 删除物品
# @param curPlayer 当前玩家
# @param packindex 背包索引
@@ -2534,7 +2575,7 @@
return True
-def GivePlayerItemOrMail(curPlayer, itemList, mailKey=None, event=["", False, {}], isNotifyAward=True):
+def GivePlayerItemOrMail(curPlayer, itemList, mailKey=None, event=["", False, {}], isNotifyAward=True, notifyDataEx=None):
##给物品,背包满则发邮件
if not itemList:
return
@@ -2570,7 +2611,7 @@
if isNotifyAward:
eventName = event[0] if event else ""
- NotifyGiveAwardInfo(curPlayer, giveItemList, eventName)
+ NotifyGiveAwardInfo(curPlayer, giveItemList, eventName, dataEx=notifyDataEx)
return
def NotifyGiveAwardInfo(curPlayer, giveItemInfo, eventName="", exp=0, moneyInfo=None, dataEx=None):
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 6df29d6..4ed2bea 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -170,6 +170,7 @@
import PlayerActLoginNew
import PlayerActBuyCountGift
import PlayerActLunhuidian
+import PlayerActFamilyGCZ
import PlayerActYunshi
import PlayerActTask
@@ -1006,6 +1007,7 @@
PlayerCutTree.OnPlayerLogin(curPlayer)
PlayerMineArea.OnPlayerLogin(curPlayer)
PlayerGuaji.OnPlayerLogin(curPlayer)
+ PlayerActFamilyGCZ.OnPlayerLogin(curPlayer)
# 上线查询一次充值订单
curPlayer.SendDBQueryRecharge()
@@ -5706,6 +5708,9 @@
# 仙盟充值互助活动奖励
elif rewardType == ChConfig.Def_RewardType_FamilyCTGAssist:
PlayerActFamilyCTGAssist.GetFamilyCTGAssistAward(curPlayer, dataEx, dataExStr)
+ # 仙盟攻城战活动奖励
+ elif rewardType == ChConfig.Def_RewardType_FamilyGCZ:
+ PlayerActFamilyGCZ.GetFamilyGCZAward(curPlayer, dataEx, tick)
# 天道树奖励
elif rewardType == ChConfig.Def_RewardType_TiandaoTree:
PlayerXiangong.GetTiandaoTreeAward(curPlayer, dataEx)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
index 0245418..3e623b8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/CrossRealmPlayer.py
@@ -206,6 +206,19 @@
return actInfo
return {}
+def GetCrossActInfoByZoneID(actName, zoneID):
+ ## 根据分区获取跨服对应的跨服活动信息
+ actInfoDict = PyGameData.g_crossActInfoDict.get(actName, {})
+ if not actInfoDict:
+ return {}
+ for actInfo in actInfoDict.values():
+ if not actInfo.get(ShareDefine.ActKey_State, 0):
+ continue
+ ipyDataDict = actInfo.get(ShareDefine.ActKey_IpyDataInfo, {})
+ if zoneID == ipyDataDict.get("ZoneID", 0):
+ return actInfo
+ return {}
+
def NotifyCrossActEnd(curPlayer, actName):
'''通知跨服运营活动结束
防止跨服服务器与子服时间不一致导致可能出现活动实际已关闭
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActFamilyGCZ.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActFamilyGCZ.py
new file mode 100644
index 0000000..4c3d753
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerActFamilyGCZ.py
@@ -0,0 +1,525 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerActFamilyGCZ
+#
+# @todo:仙盟攻城战
+# @author hxp
+# @date 2025-04-09
+# @version 1.0
+#
+# 详细描述: 仙盟攻城战
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-04-09 16:00"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import GameWorld
+import ShareDefine
+import IpyGameDataPY
+import NetPackCommon
+import CrossRealmPlayer
+import ChPyNetSendPack
+import IPY_GameWorld
+import PlayerControl
+import ItemControler
+import ItemCommon
+
+import time
+
+## 1-公示期;99-领奖期;轮次状态=轮次*10+轮次阶段;轮次阶段:1-分组战备;2-战斗;3-休战
+FamilyGCZState_Publicity = 1 # 公示期
+FamilyGCZState_Award = 99 # 结束领奖期
+
+# 轮次状态信息
+FamilyGCZRoundState_Group = 1 # 分组+战备
+FamilyGCZRoundState_Fight = 2 # 战斗
+FamilyGCZRoundState_Over = 3 # 休战结算
+
+# 攻击类型
+(
+AtkType_Normal, # 普通单攻 1
+AtkType_SkillSingle, # 技能单攻 2
+AtkType_SkillArea, # 技能群攻 3
+) = range(1, 1 + 3)
+
+def GetRoundState(state):
+ ## 获取轮次、状态信息
+ if state < 10 or state == FamilyGCZState_Award:
+ return 0, state
+ return state / 10, state % 10
+
+def SendToGameServer_FamilyGCZ(curPlayer, msgType, dataMsg=""):
+ playerID = curPlayer.GetPlayerID()
+ msgList = str([msgType, dataMsg])
+ GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "FamilyGCZ", msgList, len(msgList))
+ GameWorld.DebugLog("仙盟攻城战发送GameServer: %s, %s" % (msgType, dataMsg), playerID)
+ return
+
+def GameServer_FamilyGCZ(curPlayer, msgData, tick):
+ ## 收到GameServer攻城战信息
+ curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_FamilyGCZ, 0)
+
+ msgType, dataMsg, ret = msgData
+
+ if not ret:
+ return
+
+ if msgType == "FamilyGCZPlayerActInfo":
+ __CheckPlayerFamilyGCZByCrossGameServer(curPlayer, dataMsg)
+
+ elif msgType == "FamilyGCZAtkResult":
+ __OnFamilyGCZAtkResult(curPlayer, dataMsg)
+
+ elif msgType == "FamilyGCZAward":
+ __OnFamilyGCZAward(curPlayer, dataMsg)
+
+ return
+
+def OnPlayerLogin(curPlayer):
+ __CheckPlayerFamilyGCZByMapServer(curPlayer)
+ return
+
+def RefreshActFamilyGCZInfo():
+ ## 收到GameServer同步的活动信息,刷新活动信息
+ playerManager = GameWorld.GetPlayerManager()
+ for index in xrange(playerManager.GetPlayerCount()):
+ curPlayer = playerManager.GetPlayerByIndex(index)
+ if not GameWorld.IsNormalPlayer(curPlayer):
+ continue
+
+ __CheckPlayerFamilyGCZByMapServer(curPlayer)
+
+ return
+
+def __CheckPlayerFamilyGCZByMapServer(curPlayer):
+ ## 本服地图仅检查结束重置即可
+
+ playerID = curPlayer.GetPlayerID()
+ playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZID)
+ playerZoneID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZZoneID)
+ playerRoundNum = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZRoundNum)
+
+ actInfo = CrossRealmPlayer.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, playerZoneID)
+ actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+ state = actInfo.get(ShareDefine.ActKey_State, 0)
+ if not playerActID and not playerZoneID:
+ GameWorld.DebugLog("仙盟攻城战活动玩家没有活动数据不需要重置! playerZoneID=%s,playerActID=%s" % (playerZoneID, playerActID), playerID)
+ if state:
+ roundNum, _ = GetRoundState(state)
+ if roundNum and roundNum != playerRoundNum:
+ __doPlayerRoundChange(curPlayer, playerRoundNum, roundNum)
+ return
+
+ ipyDataDict = actInfo.get(ShareDefine.ActKey_IpyDataInfo, {})
+ zoneID = ipyDataDict.get("ZoneID", 0)
+
+ if state and playerActID == actID and playerZoneID == zoneID:
+ GameWorld.DebugLog("仙盟攻城战活动玩家正常活动中不需要重置! playerZoneID=%s,playerActID=%s,state=%s" % (playerZoneID, playerActID, state), playerID)
+ return
+ GameWorld.DebugLog("仙盟攻城战活动玩家重置End! zoneID=%s,actID=%s,playerZoneID=%s,playerActID=%s,state=%s"
+ % (zoneID, actID, playerZoneID, playerActID, state), playerID)
+
+ __doPlayerFamilyGCZReset(curPlayer)
+ return
+
+def __CheckPlayerFamilyGCZByCrossGameServer(curPlayer, joinInfo):
+ '''检查玩家参与的活动信息,以锁定盟为准的活动统一根据跨服GameServer同步的参与信息处理
+ 锁定名单信息都在跨服GameServer,所以跨服GameServer统一管理
+ 注:结束重置的在本服地图直接处理即可
+ '''
+
+ playerID = curPlayer.GetPlayerID()
+ zoneID, familyID = joinInfo
+
+ actInfo = CrossRealmPlayer.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ actID = actInfo.get(ShareDefine.ActKey_ID, 0)
+ state = actInfo.get(ShareDefine.ActKey_State, 0)
+
+ playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZID)
+ playerZoneID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZZoneID)
+ if playerActID == actID and playerZoneID == zoneID:
+ GameWorld.DebugLog("仙盟攻城战活动ID不变,不处理! zoneID=%s,actID=%s,state=%s,familyID=%s" % (zoneID, actID, state, familyID), playerID)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZFamilyID, familyID)
+ if state:
+ Sync_FamilyGCZPlayerInfo(curPlayer)
+ return
+
+ GameWorld.DebugLog("仙盟攻城战活动玩家重置! zoneID=%s,actID=%s,playerZoneID=%s,playerActID=%s"
+ % (zoneID, actID, playerZoneID, playerActID), playerID)
+ __doPlayerFamilyGCZReset(curPlayer, state, actID, zoneID, familyID)
+ return
+
+def __doPlayerRoundChange(curPlayer, playerRoundNum, roundNum):
+ ## 轮次变更
+ playerID = curPlayer.GetPlayerID()
+ GameWorld.DebugLog(" 仙盟攻城战活动玩家轮次变更! playerRoundNum=%s,roundNum=%s" % (playerRoundNum, roundNum), playerID)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZRoundNum, roundNum)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZContributionCnt, 0)
+ addEnergy = IpyGameDataPY.GetFuncCfg("FamilyGCZEnergy", 3)
+ if addEnergy > 0:
+ SetEnergy(curPlayer, curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergy) + addEnergy, False)
+ Sync_FamilyGCZPlayerInfo(curPlayer)
+ return
+
+def __doPlayerFamilyGCZReset(curPlayer, state=0, actID=0, zoneID=0, familyID=0):
+ ## 活动变更重置
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZID, actID)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZZoneID, zoneID)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZFamilyID, familyID)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZRoundNum, 0)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZContributionCnt, 0)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergy, 0)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergyTime, 0)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZAwardState, 0)
+
+# # 回收道具
+# for itemID in IpyGameDataPY.GetFuncEvalCfg("LianqiUseItem", 5):
+# ItemControler.RecycleItem(curPlayer, itemID, "ActLianqiRecycleItem")
+
+ if state:
+ maxEnergy = IpyGameDataPY.GetFuncCfg("FamilyGCZEnergy", 1)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergy, maxEnergy)
+ Sync_FamilyGCZPlayerInfo(curPlayer)
+
+ return True
+
+def OnProcess(curPlayer):
+ if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZID):
+ return
+ curEnergy = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergy)
+ maxEnergy = IpyGameDataPY.GetFuncCfg("FamilyGCZEnergy", 1)
+ if curEnergy >= maxEnergy:
+ #GameWorld.DebugLog("仙盟攻城战体力已满,无需恢复! curEnergy=%s >= %s" % (curEnergy, maxEnergy), curPlayer.GetPlayerID())
+ return
+ needSeconds = IpyGameDataPY.GetFuncCfg("FamilyGCZEnergy", 2) * 60
+ if not needSeconds:
+ return
+ curTime = int(time.time())
+ lastTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergyTime)
+ if not lastTime:
+ lastTime = curTime
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergyTime, lastTime)
+ return
+ passTime = curTime - lastTime
+ addEnergy = passTime / needSeconds
+ if addEnergy <= 0:
+ return
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergyTime, curTime)
+ updEnergy = SetEnergy(curPlayer, min(curEnergy + addEnergy, maxEnergy))
+ GameWorld.DebugLog("时间恢复仙盟攻城战体力: passTime=%s(%s-%s),addEnergy=%s,updEnergy=%s"
+ % (passTime, curTime, lastTime, addEnergy, updEnergy), curPlayer.GetPlayerID())
+ return
+
+def SetEnergy(curPlayer, setEnergy, isNotify=True):
+ ## 设置体力
+ maxEnergy = IpyGameDataPY.GetFuncCfg("FamilyGCZEnergy", 1)
+ curEnergy = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergy)
+ updEnergy = min(maxEnergy, max(setEnergy, 0))
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergy, updEnergy)
+
+ if updEnergy >= maxEnergy:
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergyTime, 0)
+ elif curEnergy >= maxEnergy and updEnergy < maxEnergy:
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZEnergyTime, int(time.time()))
+
+ if isNotify:
+ Sync_FamilyGCZPlayerInfo(curPlayer)
+ return updEnergy
+
+#// C1 24 仙盟攻城战捐献 #tagCMFamilyGCZContribution
+#
+#struct tagCMFamilyGCZContribution
+#{
+# tagHead Head;
+# BYTE ContributionType; //捐献类型: 0-低级;1-高级
+# DWORD UseCount; //物品捐献时使用个数
+#};
+def OnFamilyGCZContribution(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ contributionType = clientData.ContributionType
+ useCount = clientData.UseCount
+
+ # 大本营被摧毁无法再捐献,前端自己判断,后端不限制
+
+ if contributionType == 1:
+ __doContiributionHigh(curPlayer, useCount)
+ else:
+ __doContiributionLow(curPlayer)
+ return
+
+def __doContiributionLow(curPlayer):
+ ## 低级捐献 - 货币
+ playerID = curPlayer.GetPlayerID()
+ moneyType = IpyGameDataPY.GetFuncCfg("FamilyGCZContributionLow", 1)
+ costMoneyList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZContributionLow", 2)
+ if not moneyType or not costMoneyList:
+ return
+ maxCnt = len(costMoneyList)
+ contriCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZContributionCnt)
+ if contriCnt >= maxCnt:
+ GameWorld.DebugLog("仙盟攻城战已达本轮最大低级捐献次数! contriCnt=%s >= %s" % (contriCnt, maxCnt), playerID)
+ return
+ costMoney = costMoneyList[contriCnt]
+ if not costMoney or not PlayerControl.PayMoney(curPlayer, moneyType, costMoney, "FamilyGCZ"):
+ return
+ contriCnt += 1
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZContributionCnt, contriCnt)
+ Sync_FamilyGCZPlayerInfo(curPlayer)
+
+ addCampExp = IpyGameDataPY.GetFuncCfg("FamilyGCZContributionLow", 3)
+ randItemWeightList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZContributionLow", 4)
+ randItemInfo = GameWorld.GetResultByWeightList(randItemWeightList)
+ if randItemInfo and len(randItemInfo) >= 2:
+ ItemControler.GivePlayerItemOrMail(curPlayer, [randItemInfo], event=["FamilyGCZContiribution", False, {}])
+
+ GameWorld.DebugLog("仙盟攻城战低级捐献! contriCnt=%s,moneyType=%s,costMoney=%s,addCampExp=%s,randItemInfo=%s"
+ % (contriCnt, moneyType, costMoney, addCampExp, randItemInfo), playerID)
+ dataMsg = {"ActMsgType":"AddCampExp", "playerID":playerID, "addCampExp":addCampExp}
+ GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_FamilyGCZ, dataMsg)
+ return
+
+def __doContiributionHigh(curPlayer, useCount):
+ ## 高级捐献 - 物品
+ playerID = curPlayer.GetPlayerID()
+ costItemID = IpyGameDataPY.GetFuncCfg("FamilyGCZContributionHigh", 1)
+
+ costItemIndexList, bindCnt, unBindCnt = ItemCommon.GetPackItemBindStateIndexInfo(curPlayer, costItemID, useCount)
+ lackCnt = useCount - bindCnt - unBindCnt
+ if lackCnt > 0:
+ GameWorld.DebugLog("仙盟攻城战高级捐献消耗道具不足! costItemID=%s,useCount=%s,bindCnt=%s,unBindCnt=%s,lackCnt=%s"
+ % (costItemID, useCount, bindCnt, unBindCnt, lackCnt))
+ return
+ # 扣除消耗
+ ItemCommon.DelCostItemByBind(curPlayer, costItemIndexList, bindCnt, unBindCnt, useCount, "FamilyGCZContiribution")
+
+ addCampExp = IpyGameDataPY.GetFuncCfg("FamilyGCZContributionHigh", 2) * useCount
+ randItemWeightList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZContributionHigh", 3)
+ awardItemList = []
+ for _ in range(useCount):
+ randItemInfo = GameWorld.GetResultByWeightList(randItemWeightList)
+ if randItemInfo and len(randItemInfo) >= 2:
+ awardItemList.append(randItemInfo)
+ if awardItemList:
+ ItemControler.GivePlayerItemOrMail(curPlayer, GameWorld.MergeItemList(awardItemList), event=["FamilyGCZContiribution", False, {}])
+
+ GameWorld.DebugLog("仙盟攻城战高级捐献! costItemID=%s,useCount=%s,addCampExp=%s,awardItemList=%s"
+ % (costItemID, useCount, addCampExp, awardItemList), playerID)
+ dataMsg = {"ActMsgType":"AddCampExp", "playerID":playerID, "addCampExp":addCampExp}
+ GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_FamilyGCZ, dataMsg)
+ return
+
+#// C1 25 仙盟攻城战攻击 #tagCMFamilyGCZAtk
+#
+#struct tagCMFamilyGCZAtk
+#{
+# tagHead Head;
+# BYTE AtkType; //攻击类型: 1-普通单攻;2-技能单攻;3-技能群攻;
+# DWORD TagCityID; //目标城池ID,一般是仙盟ID或者特殊城池ID如修罗城城池,普攻单攻需指定目标,群攻技能发0
+# DWORD TagGuardID; //目标守卫ID,一般是玩家ID或者特殊守卫ID如修罗城守卫,普攻单攻需指定目标,技能攻击发0
+#};
+def OnFamilyGCZAtk(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ atkType = clientData.AtkType
+ tagCityID = clientData.TagCityID
+ tagGuardID = clientData.TagGuardID
+
+ playerID = curPlayer.GetPlayerID()
+
+ zoneID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZZoneID)
+ actInfo = CrossRealmPlayer.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ state = actInfo.get(ShareDefine.ActKey_State, 0)
+ roundNum, roundState = GetRoundState(state)
+ if not roundNum or roundState != FamilyGCZRoundState_Fight:
+ GameWorld.ErrLog("仙盟攻城战非攻击阶段: state=%s,roundNum=%s,roundState=%s" % (state, roundNum, roundState), playerID)
+ return
+
+ hurtFamilyCnt = 1
+ useItemID = 0
+ # 普攻
+ if atkType == AtkType_Normal:
+ curEnergy = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergy)
+ if not curEnergy:
+ useItemID = IpyGameDataPY.GetFuncCfg("FamilyGCZAtk", 2)
+ if not useItemID:
+ return
+ if not ItemCommon.FindItemInPackByItemID(curPlayer, useItemID, IPY_GameWorld.rptItem):
+ GameWorld.DebugLog("仙盟攻城战普攻道具不足! useItemID=%s" % useItemID, playerID)
+ return
+ hurtMulti = IpyGameDataPY.GetFuncCfg("FamilyGCZAtk", 1)
+
+ # 技能
+ else:
+ useItemID = IpyGameDataPY.GetFuncCfg("FamilyGCZAtk", 4)
+ if not useItemID:
+ return
+ if not ItemCommon.FindItemInPackByItemID(curPlayer, useItemID, IPY_GameWorld.rptItem):
+ GameWorld.DebugLog("仙盟攻城战技能道具不足! useItemID=%s" % useItemID, playerID)
+ return
+ hurtMulti = IpyGameDataPY.GetFuncCfg("FamilyGCZAtk", 3)
+
+ # 群攻
+ if atkType == AtkType_SkillArea:
+ hurtFamilyCnt = IpyGameDataPY.GetFuncCfg("FamilyGCZAtk", 5)
+
+ tick = GameWorld.GetGameWorld().GetTick()
+ if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_FamilyGCZ, tick):
+ GameWorld.DebugLog("攻城战请求CD中...", playerID)
+ PlayerControl.NotifyCode(curPlayer, "RequestLater")
+ return
+
+ dataMsg = {"ActMsgType":"GCZAtk", "zoneID":zoneID, "playerID":playerID, "atkType":atkType,
+ "tagCityID":tagCityID, "tagGuardID":tagGuardID, "hurtMulti":hurtMulti,
+ "useItemID":useItemID, "hurtFamilyCnt":hurtFamilyCnt}
+ GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_FamilyGCZ, dataMsg)
+ return
+
+def __OnFamilyGCZAtkResult(curPlayer, retInfo):
+ ## 跨服同步回来的攻击结果
+ #"atkRet":atkRet, "errMsg":errMsg, "reqMsg":msgData, "hurtDict":hurtDict, "killCntTotal":killCntTotal
+
+ playerID = curPlayer.GetPlayerID()
+ atkRet = retInfo["atkRet"]
+ errMsg = retInfo["errMsg"]
+ hurtDict = retInfo["hurtDict"]
+ killCntTotal = retInfo["killCntTotal"]
+ reqMsg = retInfo["reqMsg"]
+
+ atkType = reqMsg["atkType"]
+ useItemID = reqMsg["useItemID"]
+
+ GameWorld.DebugLog("仙盟攻城战攻击结果! atkType=%s,takRet=%s:%s" % (atkType, atkRet, errMsg), playerID)
+ if atkRet != 0 or errMsg != "OK":
+ # 攻击失败可暂时不处理
+ return
+
+ # 攻击成功处理
+
+ # 扣除物品
+ if useItemID:
+ delCount = 1
+ if not ItemControler.DelPlayerItemByPacks(curPlayer, useItemID, delCount, "FamilyGCZAtk"):
+ return
+ GameWorld.DebugLog(" 扣除道具: useItemID=%s" % (useItemID), playerID)
+
+ fixAwardItemList = [] # 固定奖励
+ # 普通攻击
+ if atkType == AtkType_Normal:
+ if useItemID:
+ fixAwardItemList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZAtkAward", 2)
+ else:
+ fixAwardItemList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZAtkAward", 1)
+ # 非道具普攻,扣体力
+ curEnergy = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergy)
+ updEnergy = SetEnergy(curPlayer, curEnergy - 1)
+ GameWorld.DebugLog(" 扣除体力: curEnergy=%s,updEnergy=%s" % (curEnergy, updEnergy), playerID)
+
+ # 技能攻击
+ elif atkType in [AtkType_SkillSingle, AtkType_SkillArea]:
+ fixAwardItemList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZAtkAward", 3)
+
+ killAwardItemList = []
+ killAwardRandCnt = IpyGameDataPY.GetFuncCfg("FamilyGCZAtkAward", 5) * killCntTotal
+ killAwardWeightList = IpyGameDataPY.GetFuncEvalCfg("FamilyGCZAtkAward", 4)
+ for _ in range(killAwardRandCnt):
+ randItem = GameWorld.GetResultByWeightList(killAwardWeightList)
+ if randItem and isinstance(randItem, list) and len(randItem) == 3:
+ killAwardItemList.append(randItem)
+
+ hurtCnt = len(hurtDict)
+ hurtValueTotal = sum(hurtDict.values())
+ GameWorld.DebugLog(" hurtCnt=%s,hurtValueTotal=%s,killCntTotal=%s" % (hurtCnt, hurtValueTotal, killCntTotal), playerID)
+
+ notifyDataEx = {"atkType":atkType, "killCntTotal":killCntTotal, "hurtCnt":hurtCnt, "hurtValueTotal":hurtValueTotal}
+ giveAwardItemList = GameWorld.MergeItemList(fixAwardItemList + killAwardItemList)
+ GameWorld.DebugLog(" giveAwardItemList=%s,fixAwardItemList=%s,killAwardItemList=%s" % (giveAwardItemList, fixAwardItemList, killAwardItemList), playerID)
+ ItemControler.GivePlayerItemOrMail(curPlayer, giveAwardItemList, event=["FamilyGCZAtk", False, {}], notifyDataEx=notifyDataEx)
+ return
+
+#// C1 26 仙盟攻城战竞猜 #tagCMFamilyGCZGuess
+#
+#struct tagCMFamilyGCZGuess
+#{
+# tagHead Head;
+# BYTE SelectCnt;
+# DWORD SelectFamilyIDList[SelectCnt]; // 竞猜选择的仙盟ID排名顺序
+#};
+def OnFamilyGCZGuess(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ selectFamilyIDList = clientData.SelectFamilyIDList
+ playerID = curPlayer.GetPlayerID()
+ zoneID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZZoneID)
+ dataMsg = {"ActMsgType":"Guess", "zoneID":zoneID, "playerID":playerID, "selectFamilyIDList":selectFamilyIDList}
+ GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_FamilyGCZ, dataMsg)
+ return
+
+def GetFamilyGCZAward(curPlayer, awardType, tick):
+ ## 领奖 0-竞猜奖励;1-个人排行奖励;2-仙盟排名奖励;
+ playerID = curPlayer.GetPlayerID()
+ awardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZAwardState)
+ if awardState&pow(2, awardType):
+ GameWorld.DebugLog("仙盟攻城战已领取该奖励! awardType=%s,awardState=%s" % (awardType, awardState), playerID)
+ return
+
+ zoneID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZZoneID)
+ actInfo = CrossRealmPlayer.GetCrossActInfoByZoneID(ShareDefine.CrossActName_FamilyGCZ, zoneID)
+ if not actInfo:
+ return
+ state = actInfo.get(ShareDefine.ActKey_State, 0)
+ if state != FamilyGCZState_Award:
+ GameWorld.ErrLog("仙盟攻城战非领奖阶段: state=%s" % state, playerID)
+ return
+
+ if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_FamilyGCZ, tick):
+ GameWorld.DebugLog("攻城战请求CD中...", playerID)
+ PlayerControl.NotifyCode(curPlayer, "RequestLater")
+ return
+
+ dataMsg = {"ActMsgType":"GetAward", "zoneID":zoneID, "playerID":playerID, "awardType":awardType}
+ GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_FamilyGCZ, dataMsg)
+ return
+
+def __OnFamilyGCZAward(curPlayer, dataMsg):
+ ## 跨服同步回来的领奖结果
+ #"zoneID":zoneID, "playerID":playerID, "actID":actID, "awardType":awardType, "awardItemList":awardItemList
+ zoneID = dataMsg["zoneID"]
+ playerID = dataMsg["playerID"]
+ actID = dataMsg["actID"]
+ awardType = dataMsg["awardType"]
+ awardItemList = dataMsg["awardItemList"]
+ awardValue = dataMsg.get("awardValue", 0)
+ fmLV = dataMsg.get("fmLV", 0)
+ playerActID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZID)
+ awardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZAwardState)
+ if awardState&pow(2, awardType):
+ GameWorld.Log("仙盟攻城战发放奖励时已领取该奖励! awardType=%s,awardState=%s,zoneID=%s,actID=%s"
+ % (awardType, awardState, zoneID, actID), playerID)
+ return
+
+ GameWorld.DebugLog("仙盟攻城战发放奖励! awardType=%s,awardValue=%s,fmLV=%s,awardItemList=%s,awardState=%s"
+ % (awardType, awardValue, fmLV, awardItemList, awardState), playerID)
+
+ # 同一个活动,更新领奖记录
+ if playerActID == actID:
+ updAwardState = awardState|pow(2, awardType)
+ PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyGCZAwardState, updAwardState)
+ GameWorld.DebugLog(" 更新领奖记录! awardType=%s,awardState=%s,updAwardState=%s" % (awardType, awardState, updAwardState), playerID)
+ Sync_FamilyGCZPlayerInfo(curPlayer)
+
+ drDict = {"zoneID":zoneID, "actID":actID, "awardType":awardType, "awardValue":awardValue, "fmLV":fmLV}
+ ItemControler.GivePlayerItemOrMail(curPlayer, awardItemList, event=["FamilyGCZAward", True, drDict])
+ return
+
+def Sync_FamilyGCZPlayerInfo(curPlayer):
+ clientPack = ChPyNetSendPack.tagMCFamilyGCZPlayerInfo()
+ clientPack.ContributionCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZContributionCnt)
+ clientPack.Energy = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergy)
+ clientPack.EnergyTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZEnergyTime)
+ clientPack.AwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyGCZAwardState)
+ NetPackCommon.SendFakePack(curPlayer, clientPack)
+ return
+
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 0b8de83..0218108 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -86,6 +86,7 @@
import PlayerActHorsePetTrain
import PlayerActLianqi
import PlayerActGodGift
+import PlayerActFamilyGCZ
import PlayerActFamilyCTGAssist
import PlayerActRechargeRebateGold
import PlayerActManyDayRecharge
@@ -1576,6 +1577,9 @@
elif actionName == ShareDefine.CrossActName_Lianqi:
PlayerActLianqi.RefreshCrossActLianqiInfo()
+ elif actionName == ShareDefine.CrossActName_FamilyGCZ:
+ PlayerActFamilyGCZ.RefreshActFamilyGCZInfo()
+
return
if key == ShareDefine.Def_Notify_WorldKey_CrossZoneName:
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 13e0de7..f4b95b2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerState.py
@@ -55,6 +55,7 @@
import FormulaControl
import PlayerGoldGift
import PlayerActLianqi
+import PlayerActFamilyGCZ
import PlayerFlashSale
import PlayerChatBox
import PlayerFace
@@ -1300,6 +1301,8 @@
FBLogic.OnCustomSceneProcess(curPlayer, tick)
#炼器
PlayerActLianqi.OnProcess(curPlayer)
+ #仙盟攻城战
+ PlayerActFamilyGCZ.OnProcess(curPlayer)
#跨服数据同步,放最后
CrossPlayerData.ProcessCrossPlayer(curPlayer, tick)
return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyGCZ.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyGCZ.py
new file mode 100644
index 0000000..645f194
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyGCZ.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.RemoteQuery.GY_Query_FamilyGCZ
+#
+# @todo:仙盟攻城战
+# @author hxp
+# @date 2025-04-09
+# @version 1.0
+#
+# 详细描述: 仙盟攻城战
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-04-09 16:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PlayerActFamilyGCZ
+
+#---------------------------------------------------------------------
+#逻辑实现
+## 请求逻辑
+# @param query_Type 请求类型
+# @param query_ID 请求的玩家ID
+# @param packCMDList 发包命令 [ ]
+# @param tick 当前时间
+# @return "True" or "False" or ""
+# @remarks 函数详细说明.
+def DoLogic(query_Type, query_ID, packCMDList, tick):
+ return ""
+
+#---------------------------------------------------------------------
+#执行结果
+## 执行结果
+# @param curPlayer 发出请求的玩家
+# @param callFunName 功能名称
+# @param funResult 查询的结果
+# @param tick 当前时间
+# @return None
+# @remarks 函数详细说明.
+def DoResult(curPlayer, callFunName, funResult, tick):
+ GameWorld.DebugLog("GY_Query_FamilyGCZ DoResult %s" % str(funResult), curPlayer.GetPlayerID())
+ if funResult != "":
+ PlayerActFamilyGCZ.GameServer_FamilyGCZ(curPlayer, eval(funResult), tick)
+ return
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 25a3322..39d2b8e 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -364,10 +364,11 @@
CrossActName_Gubao = "CrossActGubao" # 古宝养成 - 跨服
CrossActName_HorsePetTrain = "CrossActHorsePetTrain" # 骑宠养成 - 跨服
CrossActName_Lianqi = "CrossActLianqi" # 炼器 - 跨服
+CrossActName_FamilyGCZ = "CrossActFamilyGCZ" # 仙盟攻城战
#跨服运营活动列表
CrossActNameList = [CrossActName_CTGBillboard, CrossActName_AllRecharge, CrossActName_LuckyCloudBuy, CrossActName_BossTrial,
- CrossActName_XianXiaMJ, CrossActName_Gubao, CrossActName_HorsePetTrain, CrossActName_Lianqi]
+ CrossActName_XianXiaMJ, CrossActName_Gubao, CrossActName_HorsePetTrain, CrossActName_Lianqi, CrossActName_FamilyGCZ]
#需要锁定活动分区分配直到活动结束的跨服运营活动,即使热更分区配置,也不会改变正在活动中的分区设定,直到活动结束
CrossActLockServerGroupIDList = [CrossActName_CTGBillboard, CrossActName_AllRecharge]
@@ -375,6 +376,7 @@
ActKey_ID = "ID" # 活动ID,唯一标识的ID,一般是活动开启的time值
ActKey_State = "State" # 活动状态 0-未开启, >0开启中,也代表当日的第几个时间段
ActKey_StateJoin = "StateJoin" # 活动某些功能可参与状态 0-还不可参与, >0可参与,一般可参与时该状态等于state
+ActKey_StateError = "StateError" # 按流程走的活动状态是否已异常
ActKey_CfgID = "CfgID" # 活动表配置ID
ActKey_ActNum = "ActNum" # 活动分组编号
ActKey_DayIndex = "DayIndex" # 当前活动天索引,0开始,代表第1天
@@ -917,7 +919,10 @@
Def_CBT_HorsePetTrainScore, # 骑宠养成积分 - 个人榜 164
Def_CBT_CrossRealmPK, # 跨服PK竞技场 165
Def_CBT_LianqiScore, # 炼器积分 - 个人榜 166
-) = range(150, 166 + 1)
+Def_CBT_FamilyGCZScore, # 仙盟攻城战 - 仙盟积分总榜 167 (zoneID, 0)
+Def_CBT_FamilyGCZPlayerHurt, # 仙盟攻城战 - 玩家伤害总榜 168 (zoneID, 0)
+Def_CBT_FamilyGCZRoundHurt, # 仙盟攻城战 - 本轮分组仙盟伤害榜 169 (zoneID, batType*100+groupNum)
+) = range(150, 169 + 1)
#职业对应战力排行榜类型
JobFightPowerBillboardDict = {
@@ -1435,7 +1440,12 @@
#通用信息记录类型 - 新 从 300 开始,原通用记录类型最大到255
Def_GameRecTypeList = (
Def_GameRecType_Xiangong, # 仙宫记录 300
- ) = range(300, 1 + 300)
+ Def_GameRecType_FamilyDelSyncCross, # 仙盟删除同步跨服状态本服记录, familyID 301
+ Def_GameRecType_FamilyGCZMgr, # 仙盟攻城战公共管理信息记录, zoneID 302
+ Def_GameRecType_FamilyGCZJoinFamily, # 仙盟攻城战参与仙盟信息, zoneID 303
+ Def_GameRecType_FamilyGCZJoinMember, # 仙盟攻城战参与成员信息, zoneID 304
+ Def_GameRecType_FamilyGCZCityWall, # 仙盟攻城战城池信息, zoneID 305
+ ) = range(300, 1 + 305)
#通用信息记录新 - 字典key配置,如果有配置,则可额外按对应记录Value值存储字典,方便快速取值,可配置Value编号 1~8,配空默认 Value1
Def_GameRecValueKeyDict = {
Def_GameRecType_Xiangong:[1],
@@ -1640,6 +1650,7 @@
CrossServerMsg_CrossServerState = "CrossServerState" # 跨服服务器状态变更
CrossServerMsg_PlayerLoginout = "PlayerLoginout" # 玩家上下线状态同步
CrossServerMsg_ExitCrossServer = "ExitCrossServer" # 退出跨服服务器
+CrossServerMsg_SendFakePack = "SendFakePack" # 给子服玩家发送封包
CrossServerMsg_Notify = "Notify" # 提示信息
CrossServerMsg_ChatCrossWorld = "ChatCrossWorld" # 跨服世界聊天
CrossServerMsg_ViewPlayerCacheRet = "ViewPlayerCacheRet"# 查看跨服玩家信息结果
@@ -1693,6 +1704,8 @@
CrossServerMsg_FuncTeamInfo = "FuncTeamInfo" # 功能队伍信息同步
CrossServerMsg_FuncTeamDel = "FuncTeamDel" # 功能队伍删除同步
CrossServerMsg_FuncTeamList = "FuncTeamList" # 功能队伍列表同步
+CrossServerMsg_FamilyDelRet = "FamilyDelRet" # 仙盟删除结果
+CrossServerMsg_FamilyGCZ = "FamilyGCZ" # 仙盟攻城战
# 子服发送跨服信息定义
ClientServerMsg_ServerInitOK = "ServerInitOK" # 子服启动成功
@@ -1742,6 +1755,8 @@
ClientServerMsg_HorsePetTrainScore = "HorsePetTrainScore" # 骑宠养成积分
ClientServerMsg_QueryXiangong = "QueryXiangong" # 查看仙宫仙名录
ClientServerMsg_LianqiScore = "LianqiScore" # 炼器积分
+ClientServerMsg_SyncFamilyInfo = "SyncFamilyInfo" # 仙盟信息同步
+ClientServerMsg_FamilyGCZ = "FamilyGCZ" # 仙盟攻城战
#跨服广播类型定义
CrossNotify_CrossAct = "CrossAct"
--
Gitblit v1.8.0