From 328648da94a07437fc46024f3e9b7e48c2e2ae38 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 29 十月 2024 17:15:29 +0800
Subject: [PATCH] 10275 【越南】【英语】【砍树】【tqxbqy】仙盟珍宝阁-后端

---
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py                                             |    3 
 ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py                                                    |   56 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py                         |  109 ++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py |   45 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                 |    3 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py                                               |   11 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                                 |   52 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                             |   56 +++
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py                                                      |   52 +++
 ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Zhenbaoge.py                                            |   82 ++++
 ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py                                                  |    6 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                                  |   56 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py                       |   67 +++
 ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py                                                        |   22 +
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py                                              |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                                         |    6 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyZhenbaoge.py                                     |  241 ++++++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py                                                         |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py                                   |   23 +
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                                      |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                        |    8 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyAction.py                                        |   41 +-
 PySysDB/PySysDBG.h                                                                                                 |   20 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                    |    4 
 24 files changed, 950 insertions(+), 23 deletions(-)

diff --git a/PySysDB/PySysDBG.h b/PySysDB/PySysDBG.h
index a88d5b5..3efb7fa 100644
--- a/PySysDB/PySysDBG.h
+++ b/PySysDB/PySysDBG.h
@@ -53,6 +53,7 @@
 	DWORD		NeedMoney;	//升级需要资金
 	DWORD		WeekMissionMoneyMax;	//每周任务最大可获得仙盟资金
 	BYTE		BossFBCnt;	//BOSS副本次数
+	DWORD		ZhenbaogeWeights;	//珍宝阁总权重
 };
 
 //仙盟徽章表
@@ -65,6 +66,25 @@
 	DWORD		CustomFamilyID;	//定制仙盟ID
 };
 
+//仙盟珍宝阁砍价
+
+struct tagFamilyZhenbaogeCut
+{
+	BYTE		_CutNum;	//砍价人次
+	DWORD		CutWeight;	//砍价权重
+	float		MinRatio;	//保底比值
+	float		RandRatio;	//随机比值
+};
+
+//仙盟珍宝阁物品
+
+struct tagFamilyZhenbaogeItem
+{
+	BYTE		_ItemGroupNum;	//物品组编号
+	DWORD		ItemWeight;	//随机权重
+	list		ItemList;	//物品列表[[物品ID,个数,是否拍品], ...]
+};
+
 //仙盟试炼伤血奖励表
 
 struct tagFamilyBossHurtAward
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
index a8bc41e..7d15d0e 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -212,8 +212,9 @@
 Def_FamilySetting_LvUpCost,           #家族升级需要消耗升级所需资金
 Def_FamilySetting_WeekMissionMoneyMax,#每周任务最大可获得仙盟资金
 Def_FamilySetting_BossFBCnt,          #BOSS副本次数
+Def_FamilySetting_ZhenbaogeWeights,   #珍宝阁总权重
 Def_FamilySetting_Max,                #表长度异常(必须放最后)
-) = range(0, 6 + 1)
+) = range(0, 7 + 1)
 FamilySettingDict = {
                      Def_FamilySetting_MaxMemberCnt:'MemberCnt',
                      Def_FamilySetting_MaxHuFaCnt:'DeputyLeaderCnt',
@@ -221,6 +222,7 @@
                      Def_FamilySetting_LvUpCost:'NeedMoney',
                      Def_FamilySetting_WeekMissionMoneyMax:'WeekMissionMoneyMax',
                      Def_FamilySetting_BossFBCnt:'BossFBCnt',
+                     Def_FamilySetting_ZhenbaogeWeights:'ZhenbaogeWeights',
                      }
 
 #家族成员接口对应家族配置表索引
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index 4351f9c..80b6ad4 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -15639,6 +15639,58 @@
 
 
 #------------------------------------------------------
+# A6 16 珍宝阁操作 #tagCMZhenbaogeOP
+
+class  tagCMZhenbaogeOP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("OpType", c_ubyte),    # 操作:0-砍价;1-购买
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x16
+        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 = 0xA6
+        self.SubCmd = 0x16
+        self.OpType = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMZhenbaogeOP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 16 珍宝阁操作 //tagCMZhenbaogeOP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                OpType:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.OpType
+                                )
+        return DumpString
+
+
+m_NAtagCMZhenbaogeOP=tagCMZhenbaogeOP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMZhenbaogeOP.Cmd,m_NAtagCMZhenbaogeOP.SubCmd))] = m_NAtagCMZhenbaogeOP
+
+
+#------------------------------------------------------
 # A7 02 宠物激活 #tagCMActivatePet
 
 class  tagCMActivatePet(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index e928a98..b4a37a1 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -29931,6 +29931,62 @@
 
 
 #------------------------------------------------------
+# A5 12 珍宝阁信息 #tagMCFamilyZhenbaogeInfo
+
+class  tagMCFamilyZhenbaogeInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("CutState", c_ubyte),    # 今日是否已砍价,此状态为全局状态,与盟Action砍价状态不同
+                  ("BuyState", c_ubyte),    # 今日是否已购买,此状态为全局状态,与盟Action购买状态不同
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA5
+        self.SubCmd = 0x12
+        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 = 0xA5
+        self.SubCmd = 0x12
+        self.CutState = 0
+        self.BuyState = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCFamilyZhenbaogeInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A5 12 珍宝阁信息 //tagMCFamilyZhenbaogeInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                CutState:%d,
+                                BuyState:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.CutState,
+                                self.BuyState
+                                )
+        return DumpString
+
+
+m_NAtagMCFamilyZhenbaogeInfo=tagMCFamilyZhenbaogeInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyZhenbaogeInfo.Cmd,m_NAtagMCFamilyZhenbaogeInfo.SubCmd))] = m_NAtagMCFamilyZhenbaogeInfo
+
+
+#------------------------------------------------------
 # A5 09 仙盟阵法信息 #tagMCFamilyZhenfaInfo
 
 class  tagMCFamilyZhenfa(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Zhenbaoge.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Zhenbaoge.py
new file mode 100644
index 0000000..47b121e
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Zhenbaoge.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Zhenbaoge
+#
+# @todo:珍宝阁
+# @author hxp
+# @date 2024-10-29
+# @version 1.0
+#
+# 详细描述: 珍宝阁
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-10-29 17:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PlayerFamilyZhenbaoge
+import PlayerFamilyAction
+import ShareDefine
+import random
+
+## 执行逻辑
+#  @param curPlayer 当前玩家
+#  @param gmList []
+#  @return None
+def OnExec(curPlayer, gmList):
+    
+    if not gmList:
+        #GameWorld.DebugAnswer(curPlayer, "重置珍宝阁: Zhenbaoge 0")
+        #GameWorld.DebugAnswer(curPlayer, "新增假砍价: Zhenbaoge 次数 [随机A值 至B值]")
+        #GameWorld.DebugAnswer(curPlayer, "AB值没有填则按常规砍价价格计算")
+        return
+    
+    curFamily = curPlayer.GetFamily()
+    if not curFamily:
+        return
+    
+    value1 = gmList[0]
+    if value1 == 0:
+        PlayerFamilyZhenbaoge.OnZhenbaogeReset(curFamily)
+        GameWorld.DebugAnswer(curPlayer, "重置仙盟珍宝阁OK")
+        return
+    
+    familyID = curFamily.GetID()
+    gActionData = PlayerFamilyZhenbaoge.GetZhenbaogeActionData(familyID, PlayerFamilyZhenbaoge.ActionGlobalID)
+    if not gActionData:
+        GameWorld.DebugAnswer(curPlayer, "请先重置珍宝阁")
+        return
+    
+    familyAction = GameWorld.GetFamilyActionManager().GetFamilyAction(familyID, PlayerFamilyZhenbaoge.ActionType)
+    actionCount = familyAction.Count()
+    
+    fackCount = value1
+    randValue1 = gmList[1] if len(gmList) > 1 else 0
+    randValue2 = gmList[2] if len(gmList) > 2 else 0
+    syncActionDataList = [gActionData]
+    startFackID = 1000 + actionCount
+    for fackID in range(startFackID, startFackID + fackCount):
+        FakeName = "假名字".decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
+        playerID = fackID
+        playerName = "%s%s" % (FakeName, fackID)
+        
+        if randValue1 and randValue2 and randValue1 <= randValue2:     
+            cutPrice = random.randint(randValue1, randValue2)
+        else:
+            cutPrice = PlayerFamilyZhenbaoge.CalcCutPrice(curFamily, gActionData, playerID)
+            
+        if not cutPrice:
+            continue
+        
+        actionData = PlayerFamilyZhenbaoge.AddCutPrice(familyID, playerID, playerName, cutPrice, gActionData, False)
+        syncActionDataList.append(actionData)
+        nowPrice = PlayerFamilyZhenbaoge.GetFAPriceFinal(gActionData)
+        GameWorld.DebugAnswer(curPlayer, "砍价人次:%s,砍价:%s,现价:%s" % (fackID % 1000, cutPrice, nowPrice))
+        
+    PlayerFamilyAction.SendFamilyAction(syncActionDataList)
+    nowPrice = PlayerFamilyZhenbaoge.GetFAPriceFinal(gActionData)
+    GameWorld.DebugAnswer(curPlayer, "添加假砍价数:%s,总砍价数:%s,当前价格:%s" % (fackCount, familyAction.Count() - 1, nowPrice))
+    return
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
index 1283b15..c287f47 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorld.py
@@ -1040,6 +1040,28 @@
     
     return fullName
 
+def MergeItemList(itemList):
+    ## 合并物品列表,将相同物品数量合并
+    itemDict = {}
+    for itemInfo in itemList:
+        if len(itemInfo) == 3:
+            itemID, itemCount, isAuctionItem = itemInfo
+        elif len(itemInfo) == 2:
+            itemID, itemCount = itemInfo
+            isAuctionItem = None
+        else:
+            continue
+        key = (itemID, isAuctionItem)
+        itemDict[key] = itemDict.get(key, 0) + itemCount
+        
+    mItemList = []
+    for key, itemCount in itemDict.items():
+        itemID, isAuctionItem = key
+        if isAuctionItem == None:
+            mItemList.append([itemID, itemCount])
+        else:
+            mItemList.append([itemID, itemCount, isAuctionItem])
+    return mItemList
 
 ## 从列表中产生物品,[[几率,object], ....],万分率
 #  @param itemList 待选列表
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
index 1844e1f..ff942d5 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -70,6 +70,7 @@
                         ("DWORD", "NeedMoney", 0),
                         ("DWORD", "WeekMissionMoneyMax", 0),
                         ("BYTE", "BossFBCnt", 0),
+                        ("DWORD", "ZhenbaogeWeights", 0),
                         ),
 
                 "FamilyEmblem":(
@@ -77,6 +78,19 @@
                         ("BYTE", "UnlockFamilyLV", 0),
                         ("DWORD", "ExpireMinutes", 0),
                         ("DWORD", "CustomFamilyID", 0),
+                        ),
+
+                "FamilyZhenbaogeCut":(
+                        ("BYTE", "CutNum", 1),
+                        ("DWORD", "CutWeight", 0),
+                        ("float", "MinRatio", 0),
+                        ("float", "RandRatio", 0),
+                        ),
+
+                "FamilyZhenbaogeItem":(
+                        ("BYTE", "ItemGroupNum", 1),
+                        ("DWORD", "ItemWeight", 0),
+                        ("list", "ItemList", 0),
                         ),
 
                 "FamilyBossHurtAward":(
@@ -1248,7 +1262,8 @@
     def GetEliteCnt(self): return self.attrTuple[3] # 精英数量 BYTE
     def GetNeedMoney(self): return self.attrTuple[4] # 升级需要资金 DWORD
     def GetWeekMissionMoneyMax(self): return self.attrTuple[5] # 每周任务最大可获得仙盟资金 DWORD
-    def GetBossFBCnt(self): return self.attrTuple[6] # BOSS副本次数 BYTE
+    def GetBossFBCnt(self): return self.attrTuple[6] # BOSS副本次数 BYTE
+    def GetZhenbaogeWeights(self): return self.attrTuple[7] # 珍宝阁总权重 DWORD
 
 # 仙盟徽章表
 class IPY_FamilyEmblem():
@@ -1261,6 +1276,29 @@
     def GetUnlockFamilyLV(self): return self.attrTuple[1] # 解锁仙盟等级,为0时代表其他方式解锁 BYTE
     def GetExpireMinutes(self): return self.attrTuple[2] # 有效时长,分钟 DWORD
     def GetCustomFamilyID(self): return self.attrTuple[3] # 定制仙盟ID DWORD
+
+# 仙盟珍宝阁砍价
+class IPY_FamilyZhenbaogeCut():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetCutNum(self): return self.attrTuple[0] # 砍价人次 BYTE
+    def GetCutWeight(self): return self.attrTuple[1] # 砍价权重 DWORD
+    def GetMinRatio(self): return self.attrTuple[2] # 保底比值 float
+    def GetRandRatio(self): return self.attrTuple[3] # 随机比值 float
+
+# 仙盟珍宝阁物品
+class IPY_FamilyZhenbaogeItem():
+    
+    def __init__(self):
+        self.attrTuple = None
+        return
+        
+    def GetItemGroupNum(self): return self.attrTuple[0] # 物品组编号 BYTE
+    def GetItemWeight(self): return self.attrTuple[1] # 随机权重 DWORD
+    def GetItemList(self): return self.attrTuple[2] # 物品列表[[物品ID,个数,是否拍品], ...] list
 
 # 仙盟试炼伤血奖励表
 class IPY_FamilyBossHurtAward():
@@ -2934,6 +2972,8 @@
         self.__LoadFileData("WorldLV", onlyCheck)
         self.__LoadFileData("Family", onlyCheck)
         self.__LoadFileData("FamilyEmblem", onlyCheck)
+        self.__LoadFileData("FamilyZhenbaogeCut", onlyCheck)
+        self.__LoadFileData("FamilyZhenbaogeItem", onlyCheck)
         self.__LoadFileData("FamilyBossHurtAward", onlyCheck)
         self.__LoadFileData("FamilyZhenfa", onlyCheck)
         self.__LoadFileData("MarketQuery", onlyCheck)
@@ -3290,6 +3330,20 @@
         self.CheckLoadData("FamilyEmblem")
         return self.ipyFamilyEmblemCache[index]
 
+    def GetFamilyZhenbaogeCutCount(self):
+        self.CheckLoadData("FamilyZhenbaogeCut")
+        return self.ipyFamilyZhenbaogeCutLen
+    def GetFamilyZhenbaogeCutByIndex(self, index):
+        self.CheckLoadData("FamilyZhenbaogeCut")
+        return self.ipyFamilyZhenbaogeCutCache[index]
+
+    def GetFamilyZhenbaogeItemCount(self):
+        self.CheckLoadData("FamilyZhenbaogeItem")
+        return self.ipyFamilyZhenbaogeItemLen
+    def GetFamilyZhenbaogeItemByIndex(self, index):
+        self.CheckLoadData("FamilyZhenbaogeItem")
+        return self.ipyFamilyZhenbaogeItemCache[index]
+
     def GetFamilyBossHurtAwardCount(self):
         self.CheckLoadData("FamilyBossHurtAward")
         return self.ipyFamilyBossHurtAwardLen
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
index bd0de0c..8e93f0b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -849,7 +849,11 @@
     if packType == ShareDefine.CDBPlayerRefresh_ExAttr17:
         PlayerControl.SetPlayerAccState(curPlayer, packValue)
         return
-
+    
+    if packType == ShareDefine.CDBPlayerRefresh_ExAttr19:
+        PlayerControl.SetLeaveFamilyTimeEx(curPlayer, packValue)
+        return
+    
     if packType == IPY_GameServer.CDBPlayerRefresh_State:
         # 脱机在线
         PlayerControl.SetIsTJG(curPlayer, packValue)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
index 3f874ac..c572d25 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
@@ -280,6 +280,9 @@
         curPlayer.MapServer_QueryPlayerResult(0, 0, "SetLeaveFamilyTime", sysMsg, len(sysMsg))
     return 
 def GetLeaveFamilyTime(curPlayer):return curPlayer.GetExAttr12()
+##玩家离开仙盟时间(主动或被踢都算)
+def GetLeaveFamilyTimeEx(curPlayer):return curPlayer.GetExAttr19()
+def SetLeaveFamilyTimeEx(curPlayer, value):return curPlayer.SetExAttr19(value)
 
 ## 玩家所属服务器组ID
 def GetPlayerServerGroupID(curPlayer): return curPlayer.GetExAttr13()
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
index f3eaaaa..aca9647 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
@@ -29,6 +29,7 @@
 import DataRecordPack
 import PlayerFamilyBoss
 import IpyGameDataPY
+import PlayerFamilyZhenbaoge
 import PlayerFamilyRedPacket
 import GameWorldFamilyWar
 import ChPyNetSendPack
@@ -2771,6 +2772,8 @@
         family = familyManager.GetAt(i)
         #仙盟boss
         PlayerFamilyBoss.FamilyBossFBOnDayEx(family)
+        #珍宝阁
+        PlayerFamilyZhenbaoge.OnDayEx(family)
     return
 
 #---------------------------------------------------------------------
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyAction.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyAction.py
index 0528290..463e12b 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyAction.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyAction.py
@@ -557,8 +557,14 @@
         
     return
 
-def SendFamilyAction(familyActionData, curPlayer=None):
-    
+def SendFamilyAction(actionDataList, curPlayer=None):
+    ## 同步指定action
+    # @param actionDataList: 支持列表或指定actionData
+    if not isinstance(actionDataList, list):
+        actionDataList = [actionDataList]
+    if not actionDataList:
+        return
+    familyActionData = actionDataList[0]
     familyID = familyActionData.GetFamilyId()
     
     actionInfoPack = ChPyNetSendPack.tagGCFamilyActionInfo()
@@ -567,21 +573,22 @@
     actionInfoPack.ActionType = familyActionData.GetActionType()
     actionInfoPack.FamilyActionList = []    
     
-    actionData = ChPyNetSendPack.tagGCFamilyAction()
-    actionData.Clear()
-    actionData.Time = familyActionData.GetTime()
-    actionData.Name = familyActionData.GetName()
-    actionData.NameLen = len(actionData.Name)
-    actionData.Value1 = familyActionData.GetValue1()
-    actionData.Value2 = familyActionData.GetValue2()
-    actionData.Value3 = familyActionData.GetValue3()
-    actionData.Value4 = familyActionData.GetValue4()
-    actionData.Value5 = familyActionData.GetValue5()
-    actionData.Value6 = familyActionData.GetValue6()
-    actionData.UseData = familyActionData.GetUseData()
-    actionData.UseDataLen = len(actionData.UseData)
-    actionInfoPack.FamilyActionList.append(actionData)
-    
+    for familyActionData in actionDataList:
+        actionData = ChPyNetSendPack.tagGCFamilyAction()
+        actionData.Clear()
+        actionData.Time = familyActionData.GetTime()
+        actionData.Name = familyActionData.GetName()
+        actionData.NameLen = len(actionData.Name)
+        actionData.Value1 = familyActionData.GetValue1()
+        actionData.Value2 = familyActionData.GetValue2()
+        actionData.Value3 = familyActionData.GetValue3()
+        actionData.Value4 = familyActionData.GetValue4()
+        actionData.Value5 = familyActionData.GetValue5()
+        actionData.Value6 = familyActionData.GetValue6()
+        actionData.UseData = familyActionData.GetUseData()
+        actionData.UseDataLen = len(actionData.UseData)
+        actionInfoPack.FamilyActionList.append(actionData)
+        
     actionInfoPack.Count = len(actionInfoPack.FamilyActionList)
     
     if curPlayer:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyZhenbaoge.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyZhenbaoge.py
new file mode 100644
index 0000000..b2b0df7
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamilyZhenbaoge.py
@@ -0,0 +1,241 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package PlayerFamilyZhenbaoge
+#
+# @todo:珍宝阁
+# @author hxp
+# @date 2024-10-29
+# @version 1.0
+#
+# 详细描述: 珍宝阁
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-10-29 17:30"""
+#-------------------------------------------------------------------------------
+
+import ChConfig
+import ShareDefine
+import PlayerFamilyAction
+import IpyGameDataPY
+import PlayerFamily
+import GameWorld
+
+import random
+import time
+
+ActionType = ShareDefine.Def_ActionType_Zhenbaoge
+ActionGlobalID = 1 # 全局记录ID
+
+# 全局记录
+#Time    本轮开始时间戳
+#Value1    ActionGlobalID
+def GetFAPrice(gActionData): return gActionData.GetValue2()
+def SetFAPrice(gActionData, price): return gActionData.SetValue2(price)
+def GetFAIsNegative(gActionData): return gActionData.GetValue3() # 是否负值
+def SetFAIsNegative(gActionData, isNegative): return gActionData.SetValue3(isNegative)
+def GetFAPriceFinal(gActionData):
+    ## 获取最终价格
+    price = GetFAPrice(gActionData)
+    isNegative = GetFAIsNegative(gActionData)
+    return price if not isNegative else -price
+def SetFAPriceFinal(gActionData, totalPrice):
+    SetFAPrice(gActionData, abs(totalPrice))
+    SetFAIsNegative(gActionData, 1 if totalPrice < 0 else 0)
+    return
+def GetFAItemList(gActionData): return eval(gActionData.GetUseData()) # 物品列表
+def SetFAItemList(gActionData, itemList):
+    dataStr = str(itemList)
+    gActionData.SetUseData(dataStr, len(dataStr))
+    return
+
+# 成员砍价记录
+#Time    砍价时间戳
+#Name    玩家名
+def GetFAPlayerID(actionData): return actionData.GetValue1()
+def SetFAPlayerID(actionData, playerID): return actionData.SetValue1(playerID)
+def GetFACutPrice(actionData): return actionData.GetValue2() # 玩家砍了多少
+def SetFACutPrice(actionData, cutPrice): return actionData.SetValue2(cutPrice)
+def GetFABuyState(actionData): return actionData.GetValue3() # 玩家是否已购买
+def SetFABuyState(actionData, buyState): return actionData.SetValue3(buyState)
+
+def OnDayEx(family):
+    OnZhenbaogeReset(family)        
+    return
+
+def OnZhenbaogeReset(family):
+    ## 珍宝阁重置
+    
+    familyID = family.GetID()
+    curTime = int(time.time())
+    
+    GameWorld.GetFamilyActionManager().DelFamilyAction(familyID, ActionType)
+    
+    familyAction = GameWorld.GetFamilyActionManager().GetFamilyAction(familyID, ActionType)
+    gActionData = familyAction.AddAction()
+    gActionData.SetTime(curTime)
+    gActionData.SetFamilyId(familyID)
+    gActionData.SetActionType(ActionType)
+    SetFAPlayerID(gActionData, ActionGlobalID)
+    
+    initPrice = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 2)
+    
+    randItemList = []
+    ipyDataMgr = IpyGameDataPY.IPY_Data()
+    for index in range(ipyDataMgr.GetFamilyZhenbaogeItemCount()):
+        ipyData = ipyDataMgr.GetFamilyZhenbaogeItemByIndex(index)
+        randItemList.append([ipyData.GetItemWeight(), ipyData.GetItemList()])
+        
+    itemList = GameWorld.GetResultByWeightList(randItemList, [])
+    
+    SetFAPriceFinal(gActionData, initPrice)
+    SetFAItemList(gActionData, itemList)
+    
+    PlayerFamilyAction.SendFamilyAction(gActionData)
+    GameWorld.DebugLog("珍宝阁重置! familyID=%s,itemList=%s" % (familyID, itemList), familyID)    
+    return
+
+def GetZhenbaogeActionData(familyID, playerID):
+    ## 获取Action
+    findActionData = None
+    familyAction = GameWorld.GetFamilyActionManager().GetFamilyAction(familyID, ActionType)
+    for index in range(0, familyAction.Count()):
+        actionData = familyAction.At(index)
+        if GetFAPlayerID(actionData) == playerID:
+            findActionData = actionData
+            break
+    return findActionData
+
+def MapServer_ZhenbaogeOP(curPlayer, msgList):
+    mapID = curPlayer.GetRealMapID()
+    playerID = curPlayer.GetPlayerID()
+    GameWorld.DebugLog("MapServer_ZhenbaogeOP mapID=%s,msgList=%s" % (mapID, msgList), playerID)
+    if not msgList:
+        return
+    
+    curFamily = curPlayer.GetFamily()
+    if not curFamily:
+        return
+    
+    familyID = curFamily.GetID()
+    gActionData = GetZhenbaogeActionData(familyID, ActionGlobalID)
+    if not gActionData:
+        GameWorld.DebugLog("珍宝阁还没有刷新! familyID=%s" % familyID, playerID)
+        return
+    
+    msgType, dataMsg = msgList
+    ret = None
+    
+    if msgType == "Cut":
+        cutPrice = CalcCutPrice(curFamily, gActionData, playerID)
+        if cutPrice:
+            AddCutPrice(familyID, playerID, curPlayer.GetName(), cutPrice, gActionData)
+        ret = [cutPrice]
+        
+    elif msgType == "Buy":
+        buyRet = __DoZhenbaogeBuy(familyID, playerID, gActionData, dataMsg)
+        if buyRet:
+            ret = [True] + list(buyRet)
+        else:
+            ret = [False]
+            
+    if ret == None:
+        return
+    return msgList + (ret if isinstance(ret, list) else [ret])
+
+def CalcCutPrice(curFamily, gActionData, playerID):
+    ## 计算砍价价格
+    # @return: None-砍价限制等;>0-砍价值
+    
+    familyID = curFamily.GetID()
+    
+    familyAction = GameWorld.GetFamilyActionManager().GetFamilyAction(familyID, ActionType)
+    actionCount = familyAction.Count() # 其中1条是公共数据
+    hadCutCount = actionCount - 1
+    maxMemberCnt = PlayerFamily.GetFamilySetting(curFamily, ChConfig.Def_FamilySetting_MaxMemberCnt)
+    if hadCutCount >= maxMemberCnt:
+        GameWorld.ErrLog("已达到仙盟砍价人次上限! hadCutCount=%s >= %s,familyID=%s,familyLV=%s" 
+                         % (hadCutCount, maxMemberCnt, familyID, curFamily.GetLV()), playerID)
+        return
+    
+    actionData = GetZhenbaogeActionData(familyID, playerID)
+    if actionData and GetFACutPrice(actionData):
+        GameWorld.DebugLog("已经在该盟珍宝阁砍价过了! familyID=%s" % familyID, playerID)
+        return
+    
+    cutNum = hadCutCount + 1
+    cutIpyData = IpyGameDataPY.GetIpyGameData("FamilyZhenbaogeCut", cutNum)
+    if not cutIpyData:
+        return
+    cutWeight = cutIpyData.GetCutWeight()
+    minRatio = cutIpyData.GetMinRatio()
+    randRatio = cutIpyData.GetRandRatio()
+    totalWeight = PlayerFamily.GetFamilySetting(curFamily, ChConfig.Def_FamilySetting_ZhenbaogeWeights)
+    rand = random.random()  #随机值 0~1
+    
+    initPrice = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 2)
+    
+    cutPrice = max(1, eval(IpyGameDataPY.GetFuncCompileCfg("ZhenbaogeCut", 2)))
+    
+    nowPrice = GetFAPriceFinal(gActionData)
+    updPrice = nowPrice - cutPrice
+    
+    lowestPrice = IpyGameDataPY.GetFuncCfg("ZhenbaogeCut", 1) # 最低价格保护
+    if updPrice < lowestPrice:
+        if nowPrice > lowestPrice:
+            updPrice = int(lowestPrice - random.randint(0, 2)) # 之前还未到达最低价,固定最低价+随机0~2
+            cutPrice = nowPrice - updPrice
+        else:
+            cutPrice = random.randint(1, 2) # 低于最低价格后砍价只能随机1或2
+            updPrice = nowPrice - cutPrice
+        GameWorld.DebugLog("珍宝阁砍价计算地板价保护: cutPrice=%s,nowPrice=%s,updPrice=%s" % (cutPrice, nowPrice, updPrice), playerID)
+    else:
+        GameWorld.DebugLog("珍宝阁砍价计算: cutPrice=%s,nowPrice=%s,updPrice=%s,cutWeight=%s/%s,minRatio=%s,randRatio=%s,rand=%s,initPrice=%s" 
+                   % (cutPrice, nowPrice, updPrice, cutWeight, totalWeight, minRatio, randRatio, rand, initPrice), playerID)
+        
+    return max(1, cutPrice)
+
+def AddCutPrice(familyID, playerID, playerName, cutPrice, gActionData, isNotify=True):
+    ## 添加砍价记录
+    familyAction = GameWorld.GetFamilyActionManager().GetFamilyAction(familyID, ActionType)
+    actionData = familyAction.AddAction()
+    actionData.SetFamilyId(familyID)
+    actionData.SetActionType(ActionType)
+    actionData.SetTime(int(time.time()))
+    actionData.SetName(playerName)
+    SetFAPlayerID(actionData, playerID)
+    SetFACutPrice(actionData, cutPrice)
+    
+    # 更新最终价格
+    nowPrice = GetFAPriceFinal(gActionData)
+    updPrice = nowPrice - cutPrice    
+    SetFAPriceFinal(gActionData, updPrice)
+    GameWorld.DebugLog("珍宝阁砍价更新: playerID=%s,cutPrice=%s,nowPrice=%s,updPrice=%s,familyID=%s" 
+                       % (playerID, cutPrice, nowPrice, updPrice, familyID), playerID)
+    if isNotify:
+        PlayerFamilyAction.SendFamilyAction([gActionData, actionData])
+    return actionData
+
+def __DoZhenbaogeBuy(familyID, playerID, gActionData, dataMsg):
+    playerMoneyValue = dataMsg[0]
+    actionData = GetZhenbaogeActionData(familyID, playerID)
+    if not actionData:
+        GameWorld.DebugLog("珍宝阁未砍价,无法购买! familyID=%s" % familyID, playerID)
+        return
+    if GetFABuyState(actionData):
+        GameWorld.DebugLog("珍宝阁已经购买过了! familyID=%s" % familyID, playerID)
+        return
+    nowPrice = GetFAPriceFinal(gActionData)
+    if nowPrice > 0 and playerMoneyValue < nowPrice:
+        GameWorld.DebugLog("玩家当前货币不足,无法购买珍宝阁物品! playerMoneyValue=%s < %s" % (playerMoneyValue, nowPrice), playerID)
+        return
+    
+    giveItemList = GetFAItemList(gActionData)
+    GameWorld.DebugLog("珍宝阁购买! familyID=%s,nowPrice=%s,giveItemList=%s" % (familyID, nowPrice, giveItemList), playerID)
+    
+    # 设置已买
+    SetFABuyState(actionData, 1)
+    PlayerFamilyAction.SendFamilyAction(actionData)
+    return nowPrice, giveItemList
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
index de96e43..a48d8cc 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -54,6 +54,7 @@
 #import PlayerFamilyTech
 import PlayerFamilyZhenfa
 import PlayerFamilyRedPacket
+import PlayerFamilyZhenbaoge
 import PlayerFBHelpBattle
 import PlayerHorsePetBoss
 #import PlayerFamilyStore
@@ -1071,6 +1072,16 @@
             return
         resultName = '%s' % ret
         
+    # 仙盟珍宝阁
+    if callName =="FamilyZhenbaoge":
+        curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
+        if not curPlayer:
+            return
+        ret = PlayerFamilyZhenbaoge.MapServer_ZhenbaogeOP(curPlayer, eval(resultName))
+        if ret == None:
+            return
+        resultName = '%s' % ret
+        
     # 仙盟boss
     if callName == "FamilyBoss":
         ret = PlayerFamilyBoss.MapServer_FamilyBoss(eval(resultName), tick)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index e6b956c..0b8f31d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -1498,7 +1498,8 @@
                       Def_ActionType_BossTrialSubmit,    #boss凭证提交 13
                       Def_ActionType_FamilyCTGAssist,    #仙盟充值协助活动 14
                       Def_ActionType_FamilyEmblem,    #仙盟时效徽章信息 15
-                      ) = range(0, 16)
+                      Def_ActionType_Zhenbaoge,    #珍宝阁 16
+                      ) = range(0, 17)
 
 # 家族行为事件类型定义; Def_ActionType_FamilyEvent; 存与事件记录Value1
 # 通用:time-时间;name-玩家;value1-事件类型
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index e0ada7e..dee19f4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -189,7 +189,7 @@
 Writer = alee
 Releaser = alee
 RegType = 0
-RegisterPackCount = 8
+RegisterPackCount = 9
 
 PacketCMD_1=0xA6
 PacketSubCMD_1=0x01
@@ -223,6 +223,10 @@
 PacketSubCMD_8=0x15
 PacketCallFunc_8=OnChuangongOP
 
+PacketCMD_9=0xA6
+PacketSubCMD_9=0x16
+PacketCallFunc_9=OnZhenbaogeOP
+
 ;家族仓库
 [PlayerFamilyStore]
 ScriptName = Player\PlayerFamilyStore.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 9876879..26483bd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -2349,6 +2349,7 @@
                          1000 * 10,                        # 跨服妖魔boss
                          1000 * 10,                        # 仙盟阵法
                          1000 * 20,                        # 仙盟充值互助
+                         1000 * 20,                        # 仙盟珍宝阁
                          ]
 TYPE_Player_Tick_Count = len(TYPE_Player_Tick_Time) 
 
@@ -2431,6 +2432,7 @@
 TYPE_Player_Tick_CrossYaomoBoss,        #跨服妖魔boss
 TYPE_Player_Tick_FamilyZhenfa,        #仙盟阵法
 TYPE_Player_Tick_FamilyCTGAssist,        #仙盟充值互助
+TYPE_Player_Tick_FamilyZhenbaoge,        #仙盟珍宝阁
 ) = range(0, TYPE_Player_Tick_Count)
 
 #---------------------------------------------------------------------
@@ -3654,6 +3656,8 @@
 Def_Player_Dict_FamilyDayAward = "FamilyDayAward"  # 仙盟每日奖励领奖记录
 Def_Player_Dict_FamilyMoneyDonateCount = "FamilyMoneyDonateCount"  # 仙盟今日货币捐献次数
 Def_Player_Dict_FamilyEmblemID = "FamilyEmblemID"  # 仙盟徽章ID
+Def_Player_Dict_FamilyZhenbaogeCut = "FamilyZhenbaogeCut" #珍宝阁今日是否已砍过价
+Def_Player_Dict_FamilyZhenbaogeBuy = "FamilyZhenbaogeBuy" #珍宝阁今日是否已购买过
 
 # 仙盟事务
 Def_Player_Dict_FamilyAffairRefreshFree = "FamilyAffairRefreshFree"  # 今日已免费刷新事务次数
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 4351f9c..80b6ad4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -15639,6 +15639,58 @@
 
 
 #------------------------------------------------------
+# A6 16 珍宝阁操作 #tagCMZhenbaogeOP
+
+class  tagCMZhenbaogeOP(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("OpType", c_ubyte),    # 操作:0-砍价;1-购买
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA6
+        self.SubCmd = 0x16
+        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 = 0xA6
+        self.SubCmd = 0x16
+        self.OpType = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMZhenbaogeOP)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A6 16 珍宝阁操作 //tagCMZhenbaogeOP:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                OpType:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.OpType
+                                )
+        return DumpString
+
+
+m_NAtagCMZhenbaogeOP=tagCMZhenbaogeOP()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMZhenbaogeOP.Cmd,m_NAtagCMZhenbaogeOP.SubCmd))] = m_NAtagCMZhenbaogeOP
+
+
+#------------------------------------------------------
 # A7 02 宠物激活 #tagCMActivatePet
 
 class  tagCMActivatePet(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index e928a98..b4a37a1 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -29931,6 +29931,62 @@
 
 
 #------------------------------------------------------
+# A5 12 珍宝阁信息 #tagMCFamilyZhenbaogeInfo
+
+class  tagMCFamilyZhenbaogeInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("CutState", c_ubyte),    # 今日是否已砍价,此状态为全局状态,与盟Action砍价状态不同
+                  ("BuyState", c_ubyte),    # 今日是否已购买,此状态为全局状态,与盟Action购买状态不同
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA5
+        self.SubCmd = 0x12
+        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 = 0xA5
+        self.SubCmd = 0x12
+        self.CutState = 0
+        self.BuyState = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCFamilyZhenbaogeInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A5 12 珍宝阁信息 //tagMCFamilyZhenbaogeInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                CutState:%d,
+                                BuyState:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.CutState,
+                                self.BuyState
+                                )
+        return DumpString
+
+
+m_NAtagMCFamilyZhenbaogeInfo=tagMCFamilyZhenbaogeInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCFamilyZhenbaogeInfo.Cmd,m_NAtagMCFamilyZhenbaogeInfo.SubCmd))] = m_NAtagMCFamilyZhenbaogeInfo
+
+
+#------------------------------------------------------
 # A5 09 仙盟阵法信息 #tagMCFamilyZhenfaInfo
 
 class  tagMCFamilyZhenfa(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
new file mode 100644
index 0000000..2933ce4
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Zhenbaoge.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Zhenbaoge
+#
+# @todo:珍宝阁
+# @author hxp
+# @date 2024-10-29
+# @version 1.0
+#
+# 详细描述: 珍宝阁
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-10-29 17:30"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PlayerControl
+import PlayerFamily
+import ChConfig
+import time
+
+## GM命令执行入口
+#  @param curPlayer 当前玩家
+#  @param msgList 参数列表 [addSkillID]
+#  @return None
+#  @remarks 函数详细说明.
+def OnExec(curPlayer, msgList):
+    
+    if not msgList:
+        GameWorld.DebugAnswer(curPlayer, "重置仙盟珍宝阁: Zhenbaoge 0")
+        GameWorld.DebugAnswer(curPlayer, "重置今日状态值: Zhenbaoge d")
+        GameWorld.DebugAnswer(curPlayer, "设置退仙盟时间: Zhenbaoge ft x分钟前")
+        GameWorld.DebugAnswer(curPlayer, "新增假砍价数据: Zhenbaoge 次数 [随机A值 至B值]")
+        GameWorld.DebugAnswer(curPlayer, "AB值没有填则按常规砍价价格计算")
+        return
+    
+    if not curPlayer.GetFamilyID():
+        GameWorld.DebugAnswer(curPlayer, "没有仙盟")
+        return
+    
+    isSendGameServer = False
+    
+    value1 = msgList[0]
+    if value1 == 0:
+        isSendGameServer = True
+        
+    elif value1 == "d":
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 0)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 0)
+        PlayerFamily.Sync_ZhenbaogeInfo(curPlayer)
+        GameWorld.DebugAnswer(curPlayer, "重置珍宝阁玩家今日状态OK")
+        return
+    
+    elif value1 == "ft":
+        minutes = msgList[1] if len(msgList) > 1 else 0
+        leaveFamilyTimeEx = int(time.time()) - minutes * 60
+        PlayerControl.SetLeaveFamilyTimeEx(curPlayer, leaveFamilyTimeEx)
+        GameWorld.DebugAnswer(curPlayer, "设置退仙盟时间:%s" % GameWorld.ChangeTimeNumToStr(leaveFamilyTimeEx))
+        return
+    
+    else:
+        isSendGameServer = True
+        
+    return isSendGameServer
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
index db0b2f9..fe37d50 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorld.py
@@ -1456,6 +1456,29 @@
     curPlayer.SetTickByType(funcKey, tick)
     return True
 #---------------------------------------------------------------------
+def MergeItemList(itemList):
+    ## 合并物品列表,将相同物品数量合并
+    itemDict = {}
+    for itemInfo in itemList:
+        if len(itemInfo) == 3:
+            itemID, itemCount, isAuctionItem = itemInfo
+        elif len(itemInfo) == 2:
+            itemID, itemCount = itemInfo
+            isAuctionItem = None
+        else:
+            continue
+        key = (itemID, isAuctionItem)
+        itemDict[key] = itemDict.get(key, 0) + itemCount
+        
+    mItemList = []
+    for key, itemCount in itemDict.items():
+        itemID, isAuctionItem = key
+        if isAuctionItem == None:
+            mItemList.append([itemID, itemCount])
+        else:
+            mItemList.append([itemID, itemCount, isAuctionItem])
+    return mItemList
+
 ## 从列表中产生物品列表<不重复>
 #  @param riseList 随机列表
 #  @param randomNum 随机次数
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 931d175..c9b4cb6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -6593,6 +6593,14 @@
         return 0
     return realmDifficulty
 
+##玩家离开仙盟时间(主动或被踢都算)
+def GetLeaveFamilyTimeEx(curPlayer):return curPlayer.GetExAttr19()
+def SetLeaveFamilyTimeEx(curPlayer, value):
+    curPlayer.SetExAttr19(value)
+    SendGameServerRefreshState(curPlayer, ShareDefine.CDBPlayerRefresh_ExAttr19, value)
+    SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ExAttr19, value)
+    return
+
 ##获得玩家威望值
 def GetPrestige(curPlayer): return 0
 def SetPrestige(curPlayer, value): return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
index 1d7f145..d42e119 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
@@ -183,6 +183,7 @@
     curPlayer.SetFamilyActiveValue(0)
     curPlayer.SetLastWeekFamilyActiveValue(0)
     curPlayer.SetFamilyLV(0)
+    PlayerControl.SetLeaveFamilyTimeEx(curPlayer, int(time.time()))
     
     #触发玩家离开家族的任务
     EventShell.EventResponse_OnLeaveFamily(curPlayer)
@@ -637,6 +638,10 @@
     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyMoneyDonateCount, 0)
     Sync_FamilyDayRewardState(curPlayer)
     __FamilyAffair_Refresh(curPlayer, True)
+    
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 0)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 0)
+    Sync_ZhenbaogeInfo(curPlayer)
     return
 
 
@@ -652,6 +657,7 @@
     Sync_FamilyDayRewardState(curPlayer)
     __FamilyAffair_CheckReset(curPlayer)
     PlayerFamilyZhenfa.OnPlayerLogin(curPlayer)
+    Sync_ZhenbaogeInfo(curPlayer)
     return
 
 def FamilyPlayerOnLoginCross(curPlayer):
@@ -1301,3 +1307,106 @@
     return
 
 ##--------------------------------------------------------------------------------------------------
+##----------------------------------------- 珍宝阁 --------------------------------------------------
+#// A6 16 珍宝阁操作 #tagCMZhenbaogeOP
+#
+#struct    tagCMZhenbaogeOP
+#{
+#    tagHead     Head;
+#    BYTE    OpType;    // 操作:0-砍价;1-购买
+#};
+def OnZhenbaogeOP(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    opType = clientData.OpType
+    playerID = curPlayer.GetPlayerID()
+    if not curPlayer.GetFamilyID():
+        GameWorld.DebugLog("没有仙盟无法操作珍宝阁!", playerID)
+        return
+    
+    # 砍价
+    if opType == 0:
+        leaveTimeEx = PlayerControl.GetLeaveFamilyTimeEx(curPlayer)
+        cutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
+        if cutState and leaveTimeEx:
+            cutCDTimes = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 3) * 60
+            passTimes = int(time.time()) - leaveTimeEx
+            if passTimes < cutCDTimes:
+                GameWorld.DebugLog("今日已砍价变更仙盟砍价CD中! passTimes=%s < %s" % (passTimes, cutCDTimes), playerID)
+                return
+        SendGameServer_FamilyZhenbaoge(curPlayer, "Cut", [])
+        
+    # 购买
+    elif opType == 1:
+        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+        if buyState:
+            GameWorld.DebugLog("珍宝阁今日已购买!", playerID)
+            return
+        moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
+        playerMoneyValue = PlayerControl.GetMoney(curPlayer, moneyType)
+        SendGameServer_FamilyZhenbaoge(curPlayer, "Buy", [playerMoneyValue])
+        
+    return
+
+def SendGameServer_FamilyZhenbaoge(curPlayer, msgType, msgData):
+    playerID = curPlayer.GetPlayerID()
+    tick = GameWorld.GetGameWorld().GetTick()
+    if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_FamilyZhenbaoge, tick):
+        GameWorld.DebugLog("请求CD中...", playerID)
+        return
+    GameWorld.DebugLog("珍宝阁同步GameServer: msgType=%s,%s" % (msgType, msgData), playerID)
+    msgInfo = str([msgType, msgData])
+    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "FamilyZhenbaoge", msgInfo, len(msgInfo))
+    return
+
+def GameServer_FamilyZhenbaogeRet(curPlayer, resultList):
+    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_FamilyZhenbaoge, 0)
+    playerID = curPlayer.GetPlayerID()
+    msgType, _ = resultList[:2]
+    retData = resultList[2:]
+    GameWorld.Log("仙盟珍宝阁GameServer返回: %s" % str(resultList), playerID)
+    if msgType == "Cut":
+        cutPrice = retData[0]
+        if not cutPrice:
+            # 砍价失败不处理后续
+            return
+        PlayerControl.NotifyCode(curPlayer, "ZhenbaogeCut", [cutPrice])
+        if not curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut):
+            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeCut, 1)
+            Sync_ZhenbaogeInfo(curPlayer)
+        
+    elif msgType == "Buy":
+        isOK = retData[0]
+        if not isOK:
+            return
+        buyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+        if buyState:
+            #一天只能买一次,防止变更仙盟刷
+            return
+        nowPrice, giveItemList = retData[1:]
+        
+        moneyType = IpyGameDataPY.GetFuncCfg("Zhenbaoge", 1)
+        if nowPrice > 0:
+            if not PlayerControl.PayMoney(curPlayer, moneyType, nowPrice, "Zhenbaoge"):
+                GameWorld.ErrLog("珍宝阁购买货币不足! nowPrice=%s" % nowPrice, playerID)
+                return
+        elif nowPrice < 0:
+            PlayerControl.GiveMoney(curPlayer, moneyType, -nowPrice, "Zhenbaoge")
+        else: # 0不处理
+            pass
+        
+        if giveItemList:
+            ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList, event=["Zhenbaoge", False, {}])
+            
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy, 1)
+        Sync_ZhenbaogeInfo(curPlayer)
+            
+    return
+
+def Sync_ZhenbaogeInfo(curPlayer):
+    clientPack = ChPyNetSendPack.tagMCFamilyZhenbaogeInfo()
+    clientPack.CutState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeCut)
+    clientPack.BuyState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyZhenbaogeBuy)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+##--------------------------------------------------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py
new file mode 100644
index 0000000..325d665
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_FamilyZhenbaoge.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.RemoteQuery.GY_Query_FamilyZhenbaoge
+#
+# @todo:珍宝阁
+# @author hxp
+# @date 2024-10-29
+# @version 1.0
+#
+# 详细描述: 珍宝阁
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2024-10-29 17:30"""
+#-------------------------------------------------------------------------------
+
+import PlayerFamily
+
+#---------------------------------------------------------------------
+#逻辑实现
+## 请求逻辑
+#  @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):
+    PlayerFamily.GameServer_FamilyZhenbaogeRet(curPlayer, eval(funResult))
+    return
+
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index e6b956c..0b8f31d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -1498,7 +1498,8 @@
                       Def_ActionType_BossTrialSubmit,    #boss凭证提交 13
                       Def_ActionType_FamilyCTGAssist,    #仙盟充值协助活动 14
                       Def_ActionType_FamilyEmblem,    #仙盟时效徽章信息 15
-                      ) = range(0, 16)
+                      Def_ActionType_Zhenbaoge,    #珍宝阁 16
+                      ) = range(0, 17)
 
 # 家族行为事件类型定义; Def_ActionType_FamilyEvent; 存与事件记录Value1
 # 通用:time-时间;name-玩家;value1-事件类型

--
Gitblit v1.8.0