From 4087d18ce7cbd1578a6e287962bd902386984048 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 14 七月 2025 10:55:57 +0800
Subject: [PATCH] Merge branch 'master' of http://192.168.1.20:10010/r/Project_SG_ServerCode

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py | 2349 ++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 1,306 insertions(+), 1,043 deletions(-)

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 e7a0ee6..a59e6a5 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
@@ -13,170 +13,434 @@
 #---------------------------------------------------------------------
 #"""Version = 2017-07-12 21:00""" 
 #---------------------------------------------------------------------
-import IPY_GameWorld
-import GameWorld
-import EventShell
+
 import FBLogic
 import ChConfig
-import PlayerControl
+import GameWorld
 import ShareDefine
-import ReadChConfig
-import PlayerTruck
+import PlayerControl
 import NetPackCommon
+import PlayerViewCache
 import ChPyNetSendPack
-import DataRecordPack
-import GameLogic_FamilyWar
-import GameLogic_FamilyBoss
-import ChMapToGamePyPack
 import PlayerFamilyTech
-import PlayerFamilyRedPacket
+import PlayerFamilyEmblem
 import PlayerFamilyZhenfa
-import PlayerTongTianLing
-import PlayerWeekParty
-import PlayerActivity
-import ItemControler
-import SkillCommon
-import BuffSkill
-import ItemCommon
-import PlayerSuccess
-import GameFuncComm
-import PlayerTJG
+import PlayerFamilyZhenbaoge
+import IPY_PlayerDefine
 import IpyGameDataPY
-import cPickle
+import IPY_GameWorld
+import GameFuncComm
+import ItemCommon
+import DBDataMgr
+import DirtyList
 
-import time
 import random
-#---------------------------------------------------------------------
-#家族刷新
-#class   IPY_MFamilyRefresh
-#{
-#public:
-#
-#    int      GetFamilyID();
-#
-#    char *      GetFamilyName();
-#};
-## 家族刷新
-#  @param index 玩家索引
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def GameServer_FamilyRefresh(index, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    refreshPack = IPY_GameWorld.IPY_MFamilyRefresh()
-    
-    if curPlayer.GetID() != refreshPack.GetPlayerID():
-        #不是自己
+import time
+
+#申请、审核、退出、踢人、捐献、升级
+
+Def_CreatFamily_MaxStr = 33
+
+#仙盟变更类型
+FamilyChangeTypes = (
+FamilyChangeType_None,
+FamilyChangeType_MemJoin, # 成员加入 1
+FamilyChangeType_MemLeave, # 成员退出 2
+FamilyChangeType_JoinSet, # 收人设置修改 3
+FamilyChangeType_Broadcast, # 公告修改 4
+FamilyChangeType_EChange, # 徽章修改 5
+FamilyChangeType_LeaderChange, # 盟主变更 6
+FamilyChangeType_MemFmlvChange, # 成员职位变更 7
+FamilyChangeType_MemLogin, # 成员上线 8
+FamilyChangeType_MemLogout, # 成员离线9
+) = range(10)
+
+#仙盟权限
+(
+FamilyPowerID_Call,         #招人 1
+FamilyPowerID_ChangeFmlv,   #变更职位 2
+FamilyPowerID_Broadcast,    #发布公告 3
+FamilyPowerID_Kick,         #踢人 4
+) = range(1, 1 + 4)
+
+#仙盟职位对应人数设置属性名
+Def_FmlSetAttrName = {
+                      IPY_PlayerDefine.fmlMember:"MemberMax",
+                      IPY_PlayerDefine.fmlCounsellor:"EliteMax",
+                      IPY_PlayerDefine.fmlViceLeader:"DeputyLeaderMax",
+                      }
+
+def FamilyOnDay():
+    if GameWorld.IsCrossServer():
         return
     
-    lastFamilyID = curPlayer.GetFamilyID()
-    
-#************族长变更删除发布任务*************************************************
-    if (curPlayer.GetFamilyMemberLV() == IPY_GameWorld.fmlLeader 
-        and refreshPack.GetFamilyMemberLV()!= IPY_GameWorld.fmlLeader):
-        EventShell.EventResponse_OnMemberChange(curPlayer)
-#*******************************************************************
+    familyManager = DBDataMgr.GetFamilyMgr()
+    for i in range(0, familyManager.GetCount()):
+        family = familyManager.GetAt(i)
+        #珍宝阁
+        PlayerFamilyZhenbaoge.OnDay(family)
+        
+    return
 
-    #---根据封包修改玩家家族属性---
-    if lastFamilyID != refreshPack.GetFamilyID():
-        curPlayer.SetFamilyID(refreshPack.GetFamilyID())
-        familyIDChangeTime = int(time.time())
-        #PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyIDChangeTime, familyIDChangeTime)
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_LastFamilyID, lastFamilyID)
-        GameWorld.Log("记录家族变更时间...familyIDChangeTime=%s,lastFamilyID=%s,nextFamilyID=%s" 
-                           % (familyIDChangeTime, lastFamilyID, refreshPack.GetFamilyID()), curPlayer.GetPlayerID())
-        
-        #触发玩家加入家族事件
-        EventShell.EventResponse_OnFamilyAdd(curPlayer)
-        
-    if curPlayer.GetFamilyName() != refreshPack.GetFamilyName():
-        curPlayer.SetFamilyName(refreshPack.GetFamilyName())
-        #通知周围玩家家族名称刷新
-        curPlayer.Notify_FamilyNameRefresh()
+def PlayerOnDay(curPlayer):
+    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+        return
+    #每日福利奖励
+    Sync_FamilyDayRewardState(curPlayer)
+    __FamilyAffair_Refresh(curPlayer, True)
     
-    refreshFamilyLV = refreshPack.GetFamilyLV()
-    lastFamilyLV = curPlayer.GetFamilyLV()
-    if lastFamilyLV != refreshFamilyLV:
-        #任务需求,记录先前的家族等级
-        curPlayer.SetDict(ChConfig.Def_PlayerKey_FamilyLVLeave, lastFamilyLV)
+    PlayerFamilyZhenbaoge.PlayerOnDay(curPlayer)
+    return
+
+def OnPlayerLogin(curPlayer, tick):
+    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+        return
+    PlayerLoginRefreshFamily(curPlayer, tick)
+    Sync_RequestAddFamilyInfo(curPlayer, False)
+    Sync_FamilyDayRewardState(curPlayer)
+    PlayerFamilyTech.Sync_PlayerFamilyTechLV(curPlayer)
+    __FamilyAffair_CheckReset(curPlayer)
+    PlayerFamilyZhenfa.OnPlayerLogin(curPlayer)
+    PlayerFamilyZhenbaoge.OnPlayerLogin(curPlayer)
+    return
+
+def OnPlayerLogout(curPlayer):
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if not familyID:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    curMember.SetOffTime(int(time.time()))
+    #XW_JZ_LeaguerLeaveline  <n color="0,190,255">{%S1%}</n><n color="255,255,0">下线了!</n>    25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaguerLeaveline", [curPlayer.GetPlayerName()])
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLogout, excludeIDList=[playerID])
+    return
+
+def OnWeekEx(curPlayer):
+    #重置
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
+    for actionid in ShareDefine.FamilyActiveIDList:
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
+    return
+
+def PlayerLoginRefreshFamily(curPlayer, tick):
+    ## 玩家登录时刷新家族
+    
+    playerID = curPlayer.GetPlayerID()
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    refreshFamilyID = familyMgr.GetPlayerFamilyID(playerID)
+    MapServer_FamilyRefresh(curPlayer, refreshFamilyID)
+    
+    familyID = curPlayer.GetFamilyID()
+    if not familyID:
+        return
+    
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    curMember.SetOffTime(0) # 在线0,脱机1,>1离线时间
+    curMember.RefreshMember(curPlayer)
+    Sync_FamilyInfo(curPlayer)
+    
+    #通知招人
+    if GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
+        NetPackCommon.SendFakePack(curPlayer, GetPack_FamilyReqJoinInfo(familyID))
+            
+    #XW_JZ_LeaguerOnline <n color="0,190,255">{%S1%}</n><n color="255,255,0">上线了!</n>    25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaguerOnline", [curPlayer.GetName()], [playerID])
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLogin, excludeIDList=[playerID])
+    
+    # 盟主上线处理
+    if curMember.GetFmLV() == IPY_PlayerDefine.fmlLeader:
+        OnFamilyLeaderLogin(curPlayer)
+    return
+
+def OnFamilyLeaderLogin(curPlayer):
+    ## 盟主登录额外处理
+    
+    return
+
+#// A6 04 创建家族 #tagCMCreateFamily
+#
+#struct    tagCMCreateFamily
+#{
+#    tagHead        Head;
+#    char        Name[33];
+#    WORD        EmblemID; //选择徽章ID,解锁仙盟等级为1级的均为可选ID
+#};
+def OnCreateFamily(index, clientPack, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    inputName = clientPack.Name
+    emblemID = clientPack.EmblemID
+    
+    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
+        return
         
+    playerID = curPlayer.GetPlayerID()
+    playerFamilyID = curPlayer.GetFamilyID()
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    if playerFamilyID:
+        curFamily = familyMgr.FindFamily(playerFamilyID)
+        if curFamily:
+            if curFamily.FindMember(playerID):
+                #玩家已经有家族, 创建失败
+                PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_85890")
+                return
+            
+    fullFamilyName = CheckInputFamilyName(curPlayer, inputName)
+    if not fullFamilyName:
+        return
+    
+    needMoney = IpyGameDataPY.GetFuncCfg("CreateFamily", 1)
+    moneyType = IpyGameDataPY.GetFuncCfg("CreateFamily", 2)
+    if moneyType and needMoney:
+        if not PlayerControl.PayMoney(curPlayer, moneyType, needMoney, "CreateFamily"):
+            return
+        
+    serverID = GameWorld.GetPlayerServerID(curPlayer)
+    curFamily = familyMgr.AddFamily(fullFamilyName, serverID)
+    if curFamily == None:
+        GameWorld.ErrLog("创建家族失败", playerID)
+        return
+    newFamilyID = curFamily.GetID()
+    curFamily.SetLV(1)
+    emblemIDList = PlayerFamilyEmblem.GetDefaultFamilyEmblemIDList()
+    if not emblemID or emblemID not in emblemIDList:
+        emblemID = random.choice(emblemIDList) # 从默认徽章中随机选择一个
+    GameWorld.Log("创建仙盟: familyID=%s,playerID=%s,emblemID=%s" % (newFamilyID, playerID, emblemID))
+    curFamily.SetEmblemID(emblemID)
+    
+    #-设置家族成员属性
+    DoPlayerJionFamily(curFamily, playerID, curPlayer, IPY_PlayerDefine.fmlLeader)
+    familyMgr.Sort()
+    
+    #XW_JZ_EstablishSud <n color="255,255,0">恭喜您,家族建立成功!</n>    25  -   -
+    PlayerControl.NotifyCode(curPlayer, "XW_JZ_EstablishSud")
+    PlayerControl.WorldNotify(0, "jiazu_liubo_671654", [curPlayer.GetName(), fullFamilyName, newFamilyID])
+    PlayerFamilyZhenbaoge.OnZhenbaogeReset(curFamily)
+    return
+
+def CheckInputFamilyName(curPlayer, inputName):
+    '''检查玩家输入的仙盟名是否合法,建盟、改名通用
+    @return: None-不合法;非空-合法的仙盟全名
+    '''
+    #C++过滤空格
+    familyName = GameWorld.GetGameWorld().GetCharTrim(inputName)
+    fullFamilyName = GetFamilyFullName(curPlayer, familyName)
+    if not fullFamilyName:
+        GameWorld.ErrLog("家族全名异常!", curPlayer.GetPlayerID())
+        return
+    
+    if DirtyList.IsWordForbidden(familyName):
+        #XW_JZ_Family_NameNoLegality 对不起,家族名称中含有非法字符
+        PlayerControl.NotifyCode(curPlayer, "XW_JZ_Family_NameNoLegality")
+        return
+    
+    if len(familyName) <= 0 or len(familyName) > Def_CreatFamily_MaxStr:
+        PlayerControl.NotifyCode(curPlayer, "GeRen_liubo_980181", [Def_CreatFamily_MaxStr / 2, Def_CreatFamily_MaxStr])
+        return
+    
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    if familyMgr.FindFamilyByName(fullFamilyName):
+        #XW_JZ_EstablishErr_Name    <n color="255,255,0">对不起,您输入的家族名已存在,建立家族失败!</n> 25  -   -
+        PlayerControl.NotifyCode(curPlayer, "XW_JZ_EstablishErr_Name")
+        return
+    
+    return fullFamilyName
+
+
+## 获取家族全名
+def GetFamilyFullName(curPlayer, familyName):
+    serverID = GameWorld.GetPlayerServerID(curPlayer)
+    
+    maxServerID = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 3)
+    if serverID > maxServerID or serverID <= 0:
+        GameWorld.ErrLog("仙盟全名 serverID=%s error! maxServerID=%s, check FamilyNameFormat.txt" % (serverID, maxServerID))
+        return ""
+    
+    specServerDict = IpyGameDataPY.GetFuncEvalCfg("FamilyNameFormat", 4, {})
+    nameFormatInfo = GameWorld.GetDictValueByRangeKey(specServerDict, serverID)
+    if not nameFormatInfo:
+        nameFormatInfo = IpyGameDataPY.GetFuncEvalCfg("FamilyNameFormat", 1)
+    if not nameFormatInfo:
+        return ""
+    nameFormat = nameFormatInfo[0]
+    paramList = [eval(pName) for pName in nameFormatInfo[1:]]
+    fullName = nameFormat % tuple(paramList)
+    
+    maxLen = IpyGameDataPY.GetFuncCfg("FamilyNameFormat", 2)
+    if len(fullName) > maxLen:
+        GameWorld.ErrLog("仙盟全名 familyName=%s,全名=%s len=%s > %s, check FamilyNameFormat.txt" % (familyName, fullName, len(fullName), maxLen))
+        PlayerControl.NotifyCode(curPlayer, "GeRen_liubo_980181", [maxLen / 2, maxLen])
+        return ""
+    
+    return fullName
+
+def DoPlayerJionFamily(family, playerID, jionPlayer, jionFamilySetLv=IPY_PlayerDefine.fmlMember, broadcastFamilyChange=True):
+    '''加入家族,支持离线玩家加入
+    @param jionPlayer: 如果是离线玩家则为None
+    '''
+    if isinstance(family, int):
+        familyID = family
+        familyMgr = DBDataMgr.GetFamilyMgr()
+        curFamily = familyMgr.FindFamily(familyID)
+    else:
+        curFamily = family
+        
+    if not curFamily:
+        return
+    
+    familyID = curFamily.GetID()
+    member = curFamily.AddMember(playerID)
+    member.SetFmLV(jionFamilySetLv)
+    if jionPlayer:
+        member.RefreshMember(jionPlayer)
+    else:
+        member.RefreshMemberByID(playerID)
+    curFamily.SetFightPowerTotal(curFamily.GetFightPowerTotal() + member.GetFightPowerTotal())
+    
+    if jionFamilySetLv == IPY_PlayerDefine.fmlLeader:
+        curFamily.SetLeaderID(playerID)
+        
+    #设置玩家身上保存的家族信息
+    if jionPlayer:
+        MapServer_FamilyRefresh(jionPlayer, familyID)
+        Sync_FamilyInfo(jionPlayer)
+        
+    if jionFamilySetLv != IPY_PlayerDefine.fmlLeader:
+        if broadcastFamilyChange:
+            Broadcast_FamilyChange(familyID, FamilyChangeType_MemJoin, excludeIDList=[playerID])
+        #通知所有家族成员, 这个人加入了家族
+        NotifyAllFamilyMemberMsg(familyID, "XW_JZ_EnterFamily", [member.GetPlayerName()], excludeIDList=[playerID])
+        if jionPlayer:
+            PlayerControl.NotifyCode(jionPlayer, 'XW_JZ_EnterFamilyInfo', [family.GetName()])
+            
+    #记录加入事件
+    tick = GameWorld.GetGameWorld().GetTick()
+    AddFamilyActionNote(member.GetPlayerName(), familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_Join, jionFamilySetLv, 0], tick)
+    
+    #玩家缓存
+    #PlayerViewCache.OnPlayerFamilyChange(jionPlayer.GetPlayerID(), curFamily.GetID(), curFamily.GetName())
+    #PlayerTeam.OnTeamMemFamilyRefresh(jionPlayer, curFamily.GetID())
+    #SetMemberFightPower(familyMember, PlayerControl.GetFightPower(jionPlayer))
+    #GetFamilyMgr().AddFamilyIDToFightPowerChangeList(curFamily.GetID(), jionPlayer.GetPlayerID())
+    return
+
+def AddFamilyActionNote(curName, familyID, actionType, actionDataList, tick, isClearNone=True, useData=""):
+    '''统一添加家族Action数据
+    '''
+    if actionType not in ShareDefine.Def_ActionTypeList:
+        #记录行为类型错误
+        GameWorld.ErrLog("记录家族行为类型:%s 错误")
+        return False
+    
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+    actionData = familyAction.AddAction()
+    if not actionData:
+        return False
+    
+    #---设置行为对象数据---
+    actionData.SetName(curName)  # 设置名字
+    actionData.SetUserData(useData) # 设置自定义数据
+    for num, value in enumerate(actionDataList, 1):
+        setFunc = getattr(actionData, "SetValue%s" % num)
+        if setFunc:
+            setFunc(value)
+    return True
+
+def MapServer_FamilyRefresh(curPlayer, refreshFamilyID):
+    ''' 相当于GameServer调用 curPlayer.MapServer_FamilyRefresh()
+    @param familyID: 玩家更新的familyID
+    '''
+    
+    tick = GameWorld.GetGameWorld().GetTick()
+    playerID = curPlayer.GetPlayerID()
+    refreshFmLV = 0
+    refreshFamilyLV = 0
+    refreshEmblemID = 0
+    refreshFamilyName = ""
+    if refreshFamilyID:
+        familyMgr = DBDataMgr.GetFamilyMgr()
+        curFamily = familyMgr.FindFamily(refreshFamilyID)
+        if curFamily:
+            refreshFamilyLV = curFamily.GetLV()
+            refreshFamilyName = curFamily.GetName()
+            refreshEmblemID = curFamily.GetEmblemID()
+            member = curFamily.FindMember(playerID)
+            if member:
+                refreshFmLV = member.GetFmLV()
+        else:
+            refreshFamilyID = 0
+            
+    lastFamilyID = curPlayer.GetFamilyID()
+    lastFamilyLV = curPlayer.GetFamilyLV() # 仙盟等级,非职位等级
+    lastFmLV = PlayerControl.GetFamilyMemberLV(curPlayer)
+    
+    if lastFamilyID != refreshFamilyID:
+        curPlayer.SetFamilyID(refreshFamilyID)
+        
+    if curPlayer.GetFamilyName() != refreshFamilyName:
+        curPlayer.SetFamilyName(refreshFamilyName)
+        curPlayer.Notify_FamilyNameRefresh() #//04 36    周围玩家家族名刷新#tagPlayerFamilyNameRefresh
+        
+    if PlayerControl.GetFamilyEmblemID(curPlayer) != refreshEmblemID:
+        PlayerControl.SetFamilyEmblemID(curPlayer, refreshEmblemID)
+            
+    if lastFmLV != refreshFmLV:
+        PlayerControl.SetFamilyMemberLV(curPlayer, refreshFmLV)
+        
+    if lastFamilyLV != refreshFamilyLV:
         isLVUP = False
         if lastFamilyLV and refreshFamilyLV > 0:
             #触发家族升级事件
             isLVUP = True
-        
         curPlayer.SetFamilyLV(refreshFamilyLV)
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyLV, refreshFamilyLV)
-        
-        __OnFamilyLVBuffChange(curPlayer, tick)
         #触发家族升级事件, 在SetFamilyLV之后,任务可以取等级判定
         if isLVUP:
-            EventShell.EventResponse_OnFamilyLVUp(curPlayer)
+            pass
         
-    if curPlayer.GetFamilyMemberLV() != refreshPack.GetFamilyMemberLV():
-        # 因为仙盟职位没有存DBPlayer,而跨服后又没有Family信息,所以这里做个存储,用于跨服用
-        curPlayer.SetReceivedSalary(refreshPack.GetFamilyMemberLV())
-        curPlayer.SetFamilyMemberLV(refreshPack.GetFamilyMemberLV())
-        #通知周围玩家家族职位刷新
-        #curPlayer.Notify_FamilyMemberLVRefresh()
-        GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
-    
-    if curPlayer.GetFamilyMoney() != refreshPack.GetFamilyMoney():
-        curPlayer.SetFamilyMoney(refreshPack.GetFamilyMoney())
-    
-    if curPlayer.GetFamilyLastWeekActiveValue() != refreshPack.GetLastWeekFamilyActiveValue():
-        curPlayer.SetFamilyLastWeekActiveValue(refreshPack.GetLastWeekFamilyActiveValue())
-        
-    if PlayerControl.GetFamilyEmblemID(curPlayer) != refreshPack.GetExtra6():
-        PlayerControl.SetFamilyEmblemID(curPlayer, refreshPack.GetExtra6())
-        
-    #---处理特殊逻辑, 进入退出家族---
-
     if lastFamilyID != 0 and curPlayer.GetFamilyID() == 0:
         #玩家离开家族
         __OnLeaveFamily(curPlayer, tick)
         
-        #改变镖车身上记录的主人信息
-        PlayerTruck.ChangeTruckNoteInfo(curPlayer)
-
     elif lastFamilyID == 0 and curPlayer.GetFamilyID() != 0:
         #刚进家族并为族长,触发建家族事件
         if curPlayer.GetFamilyMemberLV() == IPY_GameWorld.fmlLeader:
-            EventShell.EventResponse_OnCreateFamily(curPlayer)
-        
+            pass
+            
         #进入家族触发事件
         __OnEnterFamily(curPlayer, tick)
         
-        #改变镖车身上记录的主人信息
-        PlayerTruck.ChangeTruckNoteInfo(curPlayer)
-        
     #---通知客户端刷新属性---
-    curPlayer.View_FamilyInfoRefresh()
+    curPlayer.View_FamilyInfoRefresh() #//04 30 玩家家族名字职位等信息刷新#tagPlayerInFamilyInfoRefresh
     return
 
-## 进入家族触发事件
-#  @param curPlayer 当前玩家
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
 def __OnEnterFamily(curPlayer, tick):
-    EventShell.EventResponse_OnFamily(curPlayer)
-    __OnFamilyLVBuffChange(curPlayer, tick)
+    ## 进入家族触发事件
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    familyMgr.DelPlayerReqJoinFamilyIDAll(curPlayer.GetPlayerID())
+    Sync_RequestAddFamilyInfo(curPlayer)
     __FamilyAffair_CheckReset(curPlayer)
     PlayerFamilyTech.Sync_PlayerFamilyTechLV(curPlayer)
-    DelAddFamilyRecord(curPlayer)
-    GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
-    GameLogic_FamilyBoss.OnEnterFamily(curPlayer)
-    PlayerFamilyRedPacket.CreatCacheRedPacktet(curPlayer)
-    PlayerFamilyZhenfa.OnEnterFamily(curPlayer)
+    #GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
+    #GameLogic_FamilyBoss.OnEnterFamily(curPlayer)
+    #PlayerFamilyRedPacket.CreatCacheRedPacktet(curPlayer)
+    #PlayerFamilyZhenfa.OnEnterFamily(curPlayer)
     return
 
-## 退出家族触发事件
-#  @param curPlayer 当前玩家
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
 def __OnLeaveFamily(curPlayer, tick):
+    ## 退出家族触发事件
     #---清空家族相关信息---
     curPlayer.SetPerExp(0)
     curPlayer.SetFamilyHornor(0)
@@ -185,616 +449,760 @@
     curPlayer.SetFamilyLV(0)
     PlayerControl.SetLeaveFamilyTimeEx(curPlayer, int(time.time()))
     
-    #触发玩家离开家族的任务
-    EventShell.EventResponse_OnLeaveFamily(curPlayer)
-    
-    #设置领奖限制
-    __SetForbidFamilyAward(curPlayer)
     FBLogic.OnLeaveFamily(curPlayer, tick)
-    
-    __OnFamilyLVBuffChange(curPlayer, tick)
-    #清空仓库积分
-    PlayerControl.SetPlayerCurrency(curPlayer, ShareDefine.TYPE_Price_FamilyStoreScore, 0)
-    GameLogic_FamilyWar.DoCheckChampionFamilyTitle(curPlayer)
-    PlayerFamilyZhenfa.OnLeaveFamily(curPlayer)
     return
 
-## 家族等级加持buff变更处理(进、退家族时 及 家族等级变更时)
-def __OnFamilyLVBuffChange(curPlayer, tick):
+def GetFamilyMemberHasPow(member, powerID):
+    ## 仙盟成员是否有该权限
+    powerDict = IpyGameDataPY.GetFuncEvalCfg("FamilyPower", 1, {})
+    if str(powerID) not in powerDict:
+        return False
+    needMemberLV = powerDict[str(powerID)]
+    return member.GetFmLV() >= needMemberLV
+
+def Sync_FamilyInfo(curPlayer, infoPack=None):
+    ## // A5 20 玩家家族信息 #tagMCRoleFamilyInfo
+    familyID = curPlayer.GetFamilyID()
+    if not familyID:
+        return
+    if not infoPack:
+        infoPack = GetPack_FamilyInfo(familyID)
+    NetPackCommon.SendFakePack(curPlayer, infoPack)
     return
-    # 跨服服务器不处理,防止登录跨服服务器后无战盟导致战力下降
-    if GameWorld.IsCrossServer():
+
+def GetPack_FamilyInfo(familyID):
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
         return
     
-    familyLVBuffSkillTypeID = ReadChConfig.GetEvalChConfig("FamilyLVBuff")
-    if not familyLVBuffSkillTypeID:
-        return
-    
-    # 先删后加
-    playerSkillManager = curPlayer.GetSkillManager()
-    BuffSkill.DelBuffBySkillID(curPlayer, familyLVBuffSkillTypeID, tick)
-    playerSkillManager.DeleteSkillBySkillTypeID(familyLVBuffSkillTypeID)
-    familyLV = curPlayer.GetFamilyLV()
-    GameWorld.DebugLog("__OnFamilyLVBuffChange familyLV=%s,familyLVBuffSkillTypeID=%s" % (familyLV, familyLVBuffSkillTypeID))
-    if familyLV > 0:
-        curSkill = GameWorld.GetGameData().FindSkillByType(familyLVBuffSkillTypeID , familyLV)
-        if not curSkill:
-            return
-        skillID = curSkill.GetSkillID()
-        playerSkillManager.LVUPSkillByID(skillID)
-        SkillCommon.AddBuffBySkillType(curPlayer, familyLVBuffSkillTypeID, tick, familyLV)
-    
-    curControl = PlayerControl.PlayerControl(curPlayer)
-    #curControl.CalcPassiveBuffAttr()
-    curControl.RefreshPlayerAttrByBuff()
+    clientPack = ChPyNetSendPack.tagMCRoleFamilyInfo()
+    clientPack.FamilyID = familyID
+    clientPack.FamilyName = curFamily.GetName()
+    clientPack.FamilyLV = curFamily.GetLV()
+    clientPack.FamilyLVExp = curFamily.GetExp()
+    clientPack.JoinReview = curFamily.GetJoinReview()
+    clientPack.JoinLVMin = curFamily.GetJoinLVMin()
+    clientPack.ServerID = curFamily.GetServerID()
+    clientPack.EmblemID = curFamily.GetEmblemID()
+    clientPack.FightPower = curFamily.GetFightPower()
+    clientPack.FightPowerEx = curFamily.GetFightPowerEx()
+    clientPack.Broadcast = curFamily.GetBroadcast()
+    clientPack.BroadcastLen = len(clientPack.Broadcast)
+    clientPack.LeaderID = curFamily.GetLeaderID()
+    clientPack.MemberList = []
+    for index in xrange(curFamily.GetCount()):
+        member = curFamily.GetAt(index)
+        memInfo = ChPyNetSendPack.tagMCRoleFamilyMember()
+        memInfo.PlayerID = member.GetPlayerID()
+        memInfo.JoinTime = member.GetJoinTime()
+        memInfo.Name = member.GetPlayerName()
+        memInfo.NameLen = len(memInfo.Name)
+        memInfo.LV = member.GetLV()
+        memInfo.Job = member.GetJob()
+        memInfo.RealmLV = member.GetRealmLV()
+        memInfo.Face = member.GetFace()
+        memInfo.FacePic = member.GetFacePic()
+        memInfo.FightPower = member.GetFightPower()
+        memInfo.FightPowerEx = member.GetFightPowerEx()
+        memInfo.FmLV = member.GetFmLV()
+        memInfo.ServerID = member.GetServerID()
+        memInfo.ContribTotal = member.GetContribTotal()
+        memInfo.ContribWeek = member.GetContribWeek()
+        memInfo.OffTime = member.GetOffTime()
+        clientPack.MemberList.append(memInfo)
+    clientPack.MemberCount = len(clientPack.MemberList)
+    return clientPack
+
+def Broadcast_FamilyChange(familyID, changeType=FamilyChangeType_None, powerID=None, excludeIDList=None):
+    ## // A5 21 家族变更 #tagMCFamilyChange
+    # @param excludeIDList: 不广播的成员ID列表
+    clientPack = ChPyNetSendPack.tagMCFamilyChange()
+    clientPack.Type = changeType
+    Broadcast_FamilyPack(familyID, clientPack, powerID, excludeIDList)
     return
 
-def GetPlayerChangeFamilyPastHour(curPlayer):
-    ## 获取玩家家族变更已经经过了多长时间
-    curTime = int(time.time())
-    changeTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyIDChangeTime)
-    return (curTime - changeTime) / 3600
+def Broadcast_FamilyPack(familyID, clientPack, powerID=None, excludeIDList=None):
+    ## 广播家族成员封包
+    # @param powerID: 可指定只发给有该权限的成员
+    # @param excludeIDList: 不广播的成员ID列表
+    if not clientPack:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(curFamily.GetCount()):
+        member = curFamily.GetAt(index)
+        playerID = member.GetPlayerID()
+        if excludeIDList and playerID in excludeIDList:
+            continue
+        
+        curPlayer = playerManager.FindPlayerByID(playerID)
+        if not curPlayer:
+            continue
+        
+        if powerID != None and not GetFamilyMemberHasPow(member, powerID):
+            continue
+        
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
 
+def NotifyAllFamilyMemberMsg(familyID, code, paramList=[], excludeIDList=None):
+    ## 通知所有家族成员信息
+    # @param excludeIDList: 不通知的成员ID列表
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    playerManager = GameWorld.GetPlayerManager()
+    for i in xrange(curFamily.GetCount()):
+        member = curFamily.GetAt(i)
+        playerID = member.GetPlayerID()
+        if excludeIDList and playerID in excludeIDList:
+            continue
+        curPlayer = playerManager.FindPlayerByID(playerID)
+        if not curPlayer:
+            continue
+        PlayerControl.NotifyCode(curPlayer, code, paramList)
+    return
+    
+#// A6 01 向玩家申请加入家族 #tagCMRequestJoinFamilyByPlayer
 #
-#//////////////////////////////////////////////////////////////
-#//08 04 申请家族战#tagMRequestFamilyWar
-#tagMRequestFamilyWar       *   GettagMRequestFamilyWar();
-#
-#class   IPY_MRequestFamilyWar
+#struct    tagCMRequestJoinFamilyByPlayer
 #{
-#public:
-#
-#    int      GetFamilyID();
-#
-#    char *      GetFamilyName();
-#
-#    int      GetVSFamilyID();
-#
-#    char *      GetVSFamilyName();
+#    tagHead        Head;
+#    DWORD        TagPlayerID;    //目标家族玩家ID
 #};
-## 08 04 申请家族战#
-#  @param index 玩家索引
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def GameServer_RequestFamilyWar(index, tick):
-#===============================================================================
-#    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-#    pack = IPY_GameWorld.IPY_MRequestFamilyWar()
-#    familyID = pack.GetFamilyID()
-#    familyName = pack.GetFamilyName()
-#    vsFamilyID = pack.GetVSFamilyID()
-#    vsFamilyName = pack.GetVSFamilyName()
-#    FBLogic.OnRequestFamilyWar(curPlayer, familyID, familyName, vsFamilyID, vsFamilyName, tick)
-#===============================================================================
-    GameWorld.ErrLog('GameServer_RequestFamilyWar, 此接口废弃')
-    return
-#---------------------------------------------------------------------
-##玩家金钱转换为家族金钱
-# @param playerMoney 玩家金钱
-# @return 家族金钱
-# @remarks 玩家金钱转换为家族金钱
-def GetPlayerMoney_Change_FamilyMoney(playerMoney):
-    return int(playerMoney * ShareDefine.Def_PlayerMoney_Change_FamilyMoney_Rate)
-#---------------------------------------------------------------------
-##玩家活跃度转换为家族活跃度
-# @param activeValue 玩家活跃度
-# @return 家族活跃度
-# @remarks 玩家活跃度转换为家族活跃度
-def GetPlayerActiveValue_Change_ActiveValue(activeValue):
-    return activeValue
-
-#---------------------------------------------------------------------
-##累加玩家的家族活跃度
-# @param curPlayer 玩家实例
-# @param addValue 添加的数值
-# @param sendPackGameServer 是否通知GameServer累加家族活跃度
-# @param reason 来源, 原因
-# @return None
-# @remarks 累加玩家的家族活跃度
-def AddPlayerFamilyActiveValue(curPlayer, addValue, sendPackGameServer = False, reason = 0, isSysMsg=False):
-    if addValue <= 0:
-        #GameWorld.ErrLog("AddPlayerFamilyActiveValue Err = %s"%(addValue))
+def OnRequestJoinFamilyByPlayer(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    tagPlayerID = clientData.TagPlayerID
+    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
+    if not tagPlayer:
+        GameWorld.DebugLog("对方不在线! tagPlayerID=%s" % tagPlayerID)
         return
-    
-    curActiveValue = curPlayer.GetFamilyActiveValue()
-    totalActiveValue = curPlayer.GetLastWeekFamilyActiveValue()
-
-    #---累加玩家家族活跃度---
-    if curActiveValue < ChConfig.Def_UpperLimit_DWord:
-        #累计活跃度
-        curPlayer.SetFamilyActiveValue(min(curActiveValue + addValue, ChConfig.Def_UpperLimit_DWord))
-        curPlayer.SetLastWeekFamilyActiveValue(min(totalActiveValue + addValue, ChConfig.Def_UpperLimit_DWord))
-        
-    #增加贡献度
-    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_Family_Contribution, addValue, isSysHint=isSysMsg)
-    
-    #流向记录:
-    DataRecordPack.DR_AddPlayerFamilyActiveValue(curPlayer, addValue, curPlayer.GetFamilyActiveValue(), reason)
-
-    #---通知世界服务器累加家族活跃度---
-    #@warning: 刀剑笑项目, 玩家家族活跃度累加同时累加家族活跃度
-    #          如果这边没有加上去在外面要处理一次累加家族活跃度
-    if not sendPackGameServer:
-        return True
-      
-    #刀剑笑要求, 玩家活跃度累加的同时累加家族活跃度 1活跃=1资金
-    SendPack_GameServer_AddFamilyDetailEx(curPlayer, addValue, addValue, resion=reason)
-    return True
-
-#---------------------------------------------------------------------
-##通知世界服务器累加家族属性
-# @param curPlayer 玩家实例
-# @param addFamilyHornor 添加家族兽粮
-# @param addFamilyMoney 添加家族资金
-# @param addFamilyActiveValue 增加家族活跃度
-# @return 返回值无意义
-# @remarks 通知世界服务器累加家族属性
-def SendPack_GameServer_AddFamilyDetail(curPlayer, addFamilyHornor = 0, addFamilyMoney = 0, addFamilyActiveValue = 0, resion=0):
-#    //增加家族荣誉
-#    int      GetAddFamilyHornor();
-#    //增加家族资金
-#    int      GetAddFamilyMoney();
-#    //增加家族活跃度
-#    int      GetFamilyActiveValue();
-#    GameWorld.Log('addFamilyHornor = %s, addFamilyMoney = %s, addFamilyActiveValue = %s'%
-#                        (addFamilyHornor, addFamilyMoney, addFamilyActiveValue))
-
-    #curPlayer.GameServer_AddFamilyDetail(addFamilyHornor, addFamilyMoney, addFamilyActiveValue)
-    #改为PY包
-    if not curPlayer.GetFamilyID():
+    tagFamilyID = tagPlayer.GetFamilyID()
+    if tagFamilyID <= 0:
+        GameWorld.DebugLog("对方没有家族! tagPlayerID=%s" % tagPlayerID)
         return
-    sendPack = ChMapToGamePyPack.tagMGAddFamilyDetail()
-    sendPack.PlayerID = curPlayer.GetPlayerID()
-    sendPack.AddFamilyHornor = addFamilyHornor
-    sendPack.AddFamilyMoney = addFamilyMoney
-    sendPack.FamilyActiveValue = addFamilyActiveValue
-    sendPack.AddResion = resion
-    NetPackCommon.SendPyPackToGameServer(sendPack)
-    GameWorld.DebugLog("AddFamilyDetail addFamilyHornor=%s,addFamilyMoney=%s,addFamilyActiveValue=%s, resion=%s" 
-                       % (addFamilyHornor, addFamilyMoney, addFamilyActiveValue, resion), curPlayer.GetPlayerID())
-    return
-#---------------------------------------------------------------------
-##通知世界服务器累加家族属性
-# @param curPlayer 玩家实例
-# @param addFamilyActiveValue 增加玩家家族活跃度
-# @param addFamilyHornor 添加家族荣誉
-# @param addFamilyMoney 添加家族资金
-# @return 返回值无意义
-# @remarks 通知世界服务器累加家族属性
-def SendPack_GameServer_AddFamilyDetailEx(curPlayer, addPlayerActiveValue, addFamilyMoney = 0, addFamilyHornor = 0, resion=0):
-    
-    #刀剑笑增加玩家活跃度默认新增家族活跃度
-    addFamilyActiveValue = GetPlayerActiveValue_Change_ActiveValue(addPlayerActiveValue)
-        
-    SendPack_GameServer_AddFamilyDetail(curPlayer, addFamilyHornor, addFamilyMoney, addFamilyActiveValue, resion)
-    
-    return
-#---------------------------------------------------------------------
-##通知GameServer, 客户端开始创建家族
-# @param curPlayer 玩家实例
-# @return 返回值无意义
-# @remarks 通知GameServer, 客户端开始创建家族
-def SendPack_GameServer_InputFamilyName(curPlayer):
-    #通知GameServer设置查看状态, 防外挂
-    curPlayer.GameServer_SetPlayerViewFamilyState(ShareDefine.TViewFamilyType_CreateFamily)
-    #通知客户端打开输入家族名界面
-    curPlayer.Frm_InputFamilyName()
+    RequestJoinTagFamily(curPlayer, tagFamilyID)
     return
 
-##通知GameServer, 客户端开始浏览家族信息
-# @param curPlayer 玩家实例
-# @return 返回值无意义
-# @remarks 通知GameServer, 客户端开始浏览家族信息
-def SendPack_GameServer_ViewAllFamily(curPlayer):
-    #通知GameServer设置查看状态, 防外挂
-    curPlayer.GameServer_SetPlayerViewFamilyState(ShareDefine.TViewFamilyType_FamilyWar)
-    #通知GameServer给客户端家族信息
-    curPlayer.GameServer_ViewAllFamily()
-    return
-
-##通知GameServer, 清除客户端浏览家族状态
-# @param curPlayer 玩家实例
-# @return 返回值无意义
-# @remarks 通知GameServer, 通知GameServer, 清除客户端浏览家族状态
-def SendPack_GameServer_ClearViewFamilyState(curPlayer):
-    #MapServer告诉GameServer自己是否在创建家族状态
-    #因为家族封包是在GameServer处理的, 防止被骗
-    if curPlayer.GetViewFamilyState() in [ShareDefine.TViewFamilyType_None, 
-                                          ShareDefine.TViewFamilyType_CreateFamily]:
-        #TViewFamilyType_CreateFamily状态在GameServer DoCreateFamily结束后解除
-        return
-    
-    curPlayer.GameServer_SetPlayerViewFamilyState(ShareDefine.TViewFamilyType_None)
-    return
-
-def __SetForbidFamilyAward(curPlayer):
-    ''' 设置家族相关活动领奖限制 
-     如果退出时今日已开始过对应活动,则设置领奖限制
-    '''
-    
-    playerID = curPlayer.GetPlayerID()
-    openState = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_FamilyActivityDayState)
-    forbidState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ForbidFamilyAward)
-    GameWorld.DebugLog("退出家族处理家族活动奖励领取限制! openState=%s,forbidState=%s" % (openState, forbidState), playerID)
-    
-    updForbidState = forbidState
-    for activityType in ShareDefine.Def_FamActivityList:
-        
-        if not openState&pow(2, activityType):
-            GameWorld.DebugLog("    该家族活动今日未开启过! 不设置限制领奖! activityType=%s" % activityType, playerID)
-            continue
-        updForbidState = updForbidState|pow(2, activityType)
-        GameWorld.DebugLog("    家族活动领奖限制 activityType=%s,updForbidState=%s" % (activityType, updForbidState), playerID)
-       
-    if updForbidState != forbidState:
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ForbidFamilyAward, updForbidState)
-        GameWorld.DebugLog("    更新家族活动领奖限制: forbidState=%s,updForbidState=%s" % (forbidState, updForbidState), playerID)
-        
-    return
-
-## 设置玩家是否可以参加家族活动
-#  @param curPlayer 玩家实例
-#  @param isForbid 是否限制
-#  @return 返回值无意义
-def SetForbidFamilyAction(curPlayer, isForbid):
-    #===============================================================================================
-    # if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ForbidFamilyAction) != isForbid:
-    #    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ForbidFamilyAction, isForbid)
-    # 
-    #    # 通知玩家是否可以参加家族活动
-    #    SendClientForbidFamilyAction(curPlayer)
-    #===============================================================================================
-    return
-
-
-## 通知玩家是否可以参加家族活动
-#  @param curPlayer 玩家实例
-#  @return 返回值无意义
-def SendClientForbidFamilyAction(curPlayer):
-#    isForbid = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ForbidFamilyAction)
-#    
-#    outCardsCDTime = ChPyNetSendPack.tagPyFamilyActionForbid()
-#    outCardsCDTime.Clear()
-#    
-#    outCardsCDTime.IsForbid = isForbid
-#    NetPackCommon.SendFakePack(curPlayer, outCardsCDTime)
-    return
-
-    
-#===============================================================================
-# //A6 01  向玩家申请加入家族 #tagCGRequestJoinFamilyByPlayer
-# 
-# struct    tagCGRequestJoinFamilyByPlayer
-# 
-# {
+#// A6 02 申请加入家族#tagCMRequesJoinFamily
+#
+#struct    tagCMRequesJoinFamily
+#{
 #    tagHead        Head;
-#    DWORD        AddPlayerID;    //申请加入的玩家ID
-# };
-#===============================================================================
-## 通过申请加入家族
-#  @param index: 玩家索引
-#  @param clientData: 封包结构体
-#  @param tick: 时间戳
-#  @return: None
-def RequestAddFamilyByID(index, clientData, tick):
+#    BYTE        Type;        //申请类型,0-申请;1-撤销
+#    DWORD        TagFamilyID;    //目标家族ID,申请时为0代表一键申请家族任意家族
+#};
+def OnRequesJoinFamily(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
     
-    addPlayerID = clientData.AddPlayerID    #申请进入的家族ID
-    
-    addPlayer = GameWorld.GetPlayerManager().FindPlayerByID(addPlayerID)
-    #对方下线
-    if not addPlayer:
-        return
-    
-    addFamilyID = addPlayer.GetFamilyID()
-    #对方没有家族
-    if addFamilyID <= 0:
-        return
-    
-    #申请加入
-    AddFamily(curPlayer, addFamilyID)
-    
-    #通知当前申请加入的哪些家族
-    #Sync_RequestAddFamilyInfo(curPlayer) 
-    return
-    
-    
-#===============================================================================
-# //A6 02  申请加入家族#tagCGRequesJoinFamily
-# 
-# struct    tagCGRequesJoinFamily
-# 
-# {
-#    tagHead        Head;
-#    BYTE        Type;        //申请类型
-#    DWORD        AddFamilyID;    //申请加入的家族
-# };
-#===============================================================================
-## 申请加入家族
-#  @param index: 玩家索引
-#  @param clientData: 封包结构体
-#  @param tick: 时间戳
-#  @return: None
-def RequestAddFamily(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    
-    addFamilyID = clientData.AddFamilyID  # 申请进入的家族ID
+    tagFamilyID = clientData.TagFamilyID  # 申请进入的家族ID
     requestType = clientData.Type   # 申请类型(申请/撤销)
-
-    if requestType == 0:
-        #申请加入
-        AddFamily(curPlayer, addFamilyID)
-        
-    elif requestType == 1:
-        DelAddFamilyRecord()
-        
     
-    #通知当前申请加入的哪些家族
-    Sync_RequestAddFamilyInfo(curPlayer) 
+    # 申请加入
+    if requestType == 0:
+        if not tagFamilyID:
+            AutoJoinFamily(curPlayer)
+        else:
+            RequestJoinTagFamily(curPlayer, tagFamilyID)
+            
+    # 撤销申请
+    elif requestType == 1:
+        CancelJoinTagFamily(curPlayer, tagFamilyID)
+        
     return
 
-def DelAddFamilyRecord(curPlayer):
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-            
-        #申请加入的家族ID
-        requestAddFamilyID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index) 
-        if not requestAddFamilyID:
-            continue
-        #本版本因为客户端没有单个取消申请的操作,此处发一次包一次性全部取消
-#            if addFamilyID != requestAddFamilyID:
-#                continue
-        
-        #申请数量-1
-        requestAddFamilyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyCnt)
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyCnt, requestAddFamilyCnt - 1)
-        
-        #清除撤销申请的家族ID记录
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyID%index, 0)
-        
-        #向GameServer发送请求删除该玩家的申请家族信息情况
-        sendMsg = str(requestAddFamilyID)
-        curPlayer.GameServer_QueryPlayerByID(ChConfig.queryType_DelFamilyAction, 
-                                     ShareDefine.Def_ActionType_FamilyAdd, '', sendMsg, len(sendMsg))
+def AutoJoinFamily(curPlayer):
+    if curPlayer.GetFamilyID():
+        return
+    playerID = curPlayer.GetPlayerID()
+    playerLV = curPlayer.GetLV()
+    GameWorld.DebugLog("玩家一键自动加入家族! playerLV=%s" % playerLV, playerID)
     
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    indexList = range(familyMgr.GetCount())
+    random.shuffle(indexList) #打乱顺序
+    for index in indexList:
+        family = familyMgr.GetAt(index)
+        if not family:
+            continue
+        familyID = family.GetID()
+        lvMin = family.GetJoinLVMin()
+        if lvMin and playerLV < lvMin:
+            GameWorld.DebugLog("    等级不足的不处理! familyID=%s,lvMin=%s" % (familyID, lvMin), playerID)
+            continue
+        if family.GetJoinReview():
+            GameWorld.DebugLog("    需要审核的不处理! familyID=%s" % familyID, playerID)
+            continue
+        MemberMax = GetFamilySetting(family.GetLV(), "MemberMax")
+        if family.GetCount() >= MemberMax:
+            GameWorld.DebugLog("    成员已满的不处理! familyID=%s" % familyID, playerID)
+            continue
+        
+        #直接加入
+        DoPlayerJionFamily(family, playerID, curPlayer)
+        return
+    
+    # 可再扩展自动请求,暂时不处理
+    GameWorld.DebugLog("没有可自动进入的仙盟!")
+    return
+
+def GetFamilySetting(familyLV, fieldName):
+    ## 获取仙盟等级表对应字段值
+    if not fieldName:
+        return 0
+    ipyData = IpyGameDataPY.GetIpyGameData("Family", familyLV)
+    if not ipyData:
+        return 0
+    attrName = "Get%s" % fieldName
+    if not hasattr(ipyData, attrName):
+        return 0
+    return getattr(ipyData, attrName)()
+
+def RequestJoinTagFamily(curPlayer, familyID):
+    ## 申请加入
+    playerID = curPlayer.GetPlayerID()
+    if curPlayer.GetFamilyID():
+        GameWorld.DebugLog('已经有仙盟不能再申请加入! familyID=%s' % curPlayer.GetFamilyID(), playerID)
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    reqFamilyIDList = familyMgr.GetPlayerReqJoinFamilyIDList(playerID)
+    if playerID in reqFamilyIDList:
+        GameWorld.DebugLog('已经在申请加入仙盟列表中! familyID=%s' % familyID, playerID)
+        return
+    
+    maxReqFamilyCnt = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 2)
+    if len(reqFamilyIDList) >= maxReqFamilyCnt:
+        GameWorld.DebugLog('已经达到最大申请加入仙盟数! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
+        return
+    
+    tagFamily = familyMgr.FindFamily(familyID)
+    if not tagFamily:
+        return
+    
+    lvMin = tagFamily.GetJoinLVMin()
+    if curPlayer.GetLV() < lvMin:
+        GameWorld.DebugLog('等级未达到该仙盟加入最低等级限制! lv=%s < %s' % (curPlayer.GetLV(), lvMin), playerID)
+        return
+    
+    # 需要审核,满员后端不限制申请,由前端自行决定是否可申请
+    if tagFamily.GetJoinReview():
+        reqPlayerIDDict = tagFamily.GetReqJoinPlayerInfo()
+        if playerID not in reqPlayerIDDict:
+            maxReqPlayerCnt = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 1)
+            if len(reqPlayerIDDict) >= maxReqPlayerCnt:
+                GameWorld.DebugLog('目标仙盟申请加入数已满! %s, %s' % (len(reqFamilyIDList), reqFamilyIDList), playerID)
+                PlayerControl.NotifyCode(curPlayer, "jiazu_pan_141056")
+                return
+            
+        tagFamily.AddReqJoinPlayerID(playerID)
+        # 广播给有招人权限的
+        Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
+        
+        #jiazu_pan_500807:申请入帮成功!请等待帮会管理人员审批! 
+        PlayerControl.NotifyCode(curPlayer, "jiazu_pan_500807")
+        Sync_RequestAddFamilyInfo(curPlayer)
+        return
+    
+    # 不需要审核,自动加入
+    memberMax = GetFamilySetting(tagFamily.GetLV(), "MemberMax")
+    if tagFamily.GetCount() >= memberMax:
+        GameWorld.DebugLog('目标仙盟成员已满! familyLV=%s,memberMax=%s' % (tagFamily.GetLV(), memberMax), playerID)
+        return
+    
+    DoPlayerJionFamily(tagFamily, playerID, curPlayer)
+    return
+
+def CancelJoinTagFamily(curPlayer, familyID):
+    # 撤销申请
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    playerID = curPlayer.GetPlayerID()
+    tagFamily = familyMgr.FindFamily(familyID)
+    if tagFamily:
+        tagFamily.DelReqJoinPlayerID(playerID)
+    familyMgr.DelPlayerReqJoinFamilyID(playerID, familyID)
+    Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
     Sync_RequestAddFamilyInfo(curPlayer)
     return
 
-## 通知当前申请加入的哪些家族
-#  @param curPlayer:玩家实例
-#  @return:  None
-def Sync_RequestAddFamilyInfo(curPlayer):
-    requestAddFamilyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyCnt)
+def Sync_RequestAddFamilyInfo(curPlayer, isForce=True):
+    ## 通知当前申请加入的哪些家族
+    playerID = curPlayer.GetPlayerID()
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    reqFamilyIDList = familyMgr.GetPlayerReqJoinFamilyIDList(playerID)
+    # 非强制通知时没有申请记录的可不通知,如登录
+    if not isForce and not reqFamilyIDList:
+        return
+    clientPack = ChPyNetSendPack.tagMCNotifyRequestJoinFamilyInfo()
+    clientPack.Clear()
+    clientPack.RequestJoinFamilyIDList = reqFamilyIDList
+    clientPack.RequestCount = len(clientPack.RequestJoinFamilyIDList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def GetPack_FamilyReqJoinInfo(familyID):
+    ## 获取 // A5 22 家族申请加入的玩家信息 #tagMCFamilyReqJoinInfo
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    curFamily = familyMgr.FindFamily(familyID)
+    if not curFamily:
+        return
+    reqPlayerIDDict = curFamily.GetReqJoinPlayerInfo()
     
-    packList = []
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-        familyID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index)
-        if familyID == 0:
+    playerManager = GameWorld.GetPlayerManager()
+    clientPack = ChPyNetSendPack.tagMCFamilyReqJoinInfo()
+    clientPack.ReqJoinList = []
+    for playerID, reqTime in reqPlayerIDDict.items():
+        curPlayer = playerManager.FindPlayerByID(playerID)
+        reqInfo = ChPyNetSendPack.tagMCFamilyReqJoinPlayer()
+        reqInfo.PlayerID = playerID
+        reqInfo.ReqTime = reqTime
+        if curPlayer:
+            reqInfo.IsOnLine = True
+        viewCache = PlayerViewCache.FindViewCache(playerID)
+        if viewCache:
+            reqInfo.Name = viewCache.GetPlayerName()
+            reqInfo.NameLen = len(reqInfo.Name)
+            reqInfo.LV = viewCache.GetLV()
+            reqInfo.Job = viewCache.GetJob()
+            reqInfo.RealmLV = viewCache.GetRealmLV()
+            reqInfo.Face = viewCache.GetFace()
+            reqInfo.FacePic = viewCache.GetFacePic()
+            reqInfo.FightPower = viewCache.GetFightPower()
+            reqInfo.FightPowerEx = viewCache.GetFightPowerEx()
+            reqInfo.ServerID = viewCache.GetServerID()
+        clientPack.ReqJoinList.append(reqInfo)
+        if len(clientPack.ReqJoinList) >= 100:
+            break
+    clientPack.ReqCnt = len(clientPack.ReqJoinList)
+    return clientPack
+
+#// A6 21 审核请求加入家族 #tagCMJoinFamilyReply
+#
+#struct tagCMJoinFamilyReply
+#{
+#    tagHead    Head;
+#    DWORD    TagPlayerID;    //被审核玩家ID 0则代表全部
+#    BYTE    IsOK;        //是否同意其加入
+#};
+def OnJoinFamilyReply(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    tagPlayerID = clientData.TagPlayerID
+    isOK = clientData.IsOK
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
+        #GameWorld.DebugLog("没有招人权限,无法审核人员入盟!", playerID)
+        PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Popedom")
+        return
+    
+    GameWorld.DebugLog("审核入盟申请: tagPlayerID=%s,familyID=%s,isOK=%s" % (tagPlayerID, familyID, isOK), playerID)
+    reqPlayerIDDict = family.GetReqJoinPlayerInfo()
+    tagPlayerIDList = reqPlayerIDDict.keys()
+    if tagPlayerID:
+        if tagPlayerID not in reqPlayerIDDict:
+            GameWorld.DebugLog("不存在该申请人员! tagPlayerID=%s" % tagPlayerID)
+            return
+        tagPlayerIDList = [tagPlayerID]
+        
+    if not tagPlayerIDList:
+        GameWorld.DebugLog("没有申请人员!")
+        return
+    
+    playerManager = GameWorld.GetPlayerManager()
+    # 拒绝
+    if not isOK:
+        for tagPlayerID in tagPlayerIDList:
+            family.DelReqJoinPlayerID(tagPlayerID)
+            tagPlayer = playerManager.FindPlayerByID(tagPlayerID)
+            if not tagPlayer:
+                continue
+            Sync_RequestAddFamilyInfo(tagPlayer)
+            #jiazu_pan_592934:{%S}拒绝了您的入帮申请
+            PlayerControl.NotifyCode(tagPlayer, "jiazu_pan_592934", [family.GetName()])
+        Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
+        return
+    
+    # 处理同意
+    offlinePlayerCanJoin = IpyGameDataPY.GetFuncCfg("FamilyReqJoin", 3)
+    MemberMax = GetFamilySetting(family.GetLV(), "MemberMax")
+    joinOKPlayerIDList = []
+    for tagPlayerID in tagPlayerIDList:
+        if family.GetCount() >= MemberMax:
+            PlayerControl.NotifyCode(curPlayer, "jiazu_lhs_202580")
+            break
+        tagPlayer = playerManager.FindPlayerByID(tagPlayerID)
+        #申请目标不在线
+        if not tagPlayer:
+            if not offlinePlayerCanJoin:
+                GameWorld.DebugLog("离线玩家无法加入仙盟! tagPlayerID=%s" % tagPlayerID, playerID)
+                PlayerControl.NotifyCode(curPlayer, "jiazu_hwj35_367906")
+                continue
+            
+        if family.FindMember(tagPlayerID):
+            GameWorld.DebugLog("已经是本盟成员! tagPlayerID=%s" % tagPlayerID, playerID)
+            PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Repeat")
             continue
         
-        requestAddFamilyInfo = ChPyNetSendPack.tagRequestJoinFamily()
-        requestAddFamilyInfo.RequestFamilyID = familyID
-        packList.append(requestAddFamilyInfo)
-    
-    requestAddFamily = ChPyNetSendPack.tagMCNotifyRequestJoinFamilyInfo()
-    requestAddFamily.Clear()
-    requestAddFamily.RequestCount = len(packList)
-    requestAddFamily.RequestAddFamilyInfo = packList
-    
-    NetPackCommon.SendFakePack(curPlayer, requestAddFamily)
+        tagFamilyID = familyMgr.GetPlayerFamilyID(tagPlayerID)
+        if tagFamilyID:
+            GameWorld.DebugLog("已经加入其他仙盟! tagPlayerID=%s,tagFamilyID=%s" % (tagPlayerID, tagFamilyID), playerID)
+            PlayerControl.NotifyCode(curPlayer, "XW_JZ_InviteErr_Repeat")
+            continue
+        
+        DoPlayerJionFamily(family, tagPlayerID, tagPlayer, broadcastFamilyChange=False)
+        joinOKPlayerIDList.append(tagPlayerID)
+        
+    if not joinOKPlayerIDList:
+        return
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemJoin, excludeIDList=joinOKPlayerIDList)
+    Broadcast_FamilyPack(familyID, GetPack_FamilyReqJoinInfo(familyID), FamilyPowerID_Call)
     return
 
-
-## 申请加入帮会
-#@param curPlayer 家族实例
-#@param familyID 家族ID
-#@return 返回值无意义
-def AddFamily(curPlayer, familyID):
+#// A6 22 修改收人方式 #tagCMChangeFamilyJoin
+#
+#struct    tagCMChangeFamilyJoin
+#{
+#    tagHead         Head;
+#    BYTE        JoinReview;    //成员加入是否需要审核,默认0自动加入
+#    WORD        JoinLVMin;    //限制最低可加入的玩家等级
+#};
+def OnChangeFamilyJoin(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    joinReview = clientData.JoinReview
+    joinLVMin = clientData.JoinLVMin
     
-    requestAddFamilyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyCnt)
-    if requestAddFamilyCnt >= ChConfig.Def_Player_RequestAddFamilyMaxCnt:
-        # jiazu_pan_21675 改为 jiazu_lhs_31379 最多同时向%s个帮会发出申请
-        PlayerControl.NotifyCode(curPlayer, "jiazu_lhs_31379", [ChConfig.Def_Player_RequestAddFamilyMaxCnt])
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
         return
-        
-    #是否已经申请了
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-        if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index) == familyID:
-            GameWorld.DebugLog('已经在申请列表中')
-            #已经在申请列表中
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Call):
+        GameWorld.DebugLog("没有招人权限", playerID)
+        return
+    GameWorld.DebugLog("修改招人设置: familyID=%s,joinReview=%s,joinLVMin=%s" % (familyID, joinReview, joinLVMin), playerID)
+    family.SetJoinReview(joinReview)
+    family.SetJoinLVMin(joinLVMin)
+    Sync_FamilyInfo(curPlayer)
+    Broadcast_FamilyChange(familyID, FamilyChangeType_JoinSet, FamilyPowerID_Call, excludeIDList=[playerID])
+    return
+
+#// A6 23 修改家族公告 #tagCMChangeFamilyBroadcast
+#
+#struct    tagCMChangeFamilyBroadcast
+#{
+#    tagHead        Head;
+#    char        Msg[200];
+#};
+def OnChangeFamilyBroadcast(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    broadcast = clientData.Msg
+    
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Broadcast):
+        GameWorld.DebugLog("没有修改公告权限", playerID)
+        return
+    family.SetBroadcast(broadcast)
+    GameWorld.DebugLog('更改仙盟公告: Family=%s,公告=%s' % (GameWorld.CodeToGbk(family.GetName()), GameWorld.CodeToGbk(broadcast)), playerID)
+    Sync_FamilyInfo(curPlayer)
+    Broadcast_FamilyChange(familyID, FamilyChangeType_Broadcast, excludeIDList=[playerID])
+    return
+
+#// A6 24 修改家族徽章 #tagCMChangeFamilyEmblem
+#
+#struct    tagCMChangeFamilyEmblem
+#{
+#    tagHead        Head;
+#    BYTE        EmblemID;    // 更换的徽章ID
+#};
+def OnChangeFamilyEmblem(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    changeEmblemID = clientData.EmblemID
+    PlayerFamilyEmblem.OnChangeFamilyEmblem(curPlayer, changeEmblemID)
+    return
+
+#// A6 25 修改家族成员职位 #tagCMChangeFamilyMemLV
+#
+#struct    tagCMChangeFamilyMemLV
+#{
+#    tagHead        Head;
+#    DWORD        PlayerID; // 目标成员ID
+#    BYTE        FmLV;  // 变更为xx职位
+#};
+def OnChangeFamilyMemLV(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    OnChangeFamilyMemberLV(curPlayer, clientData.PlayerID, clientData.FmLV)
+    return
+
+def OnChangeFamilyMemberLV(curPlayer, tagID, changeFmlv, isGMOP=False):
+    '''变更成员职位
+    @param curPlayer: 操作的玩家
+    @param tagID: 目标成员ID
+    @param changeFmlv: 修改为xx职位
+    @param isGMOP: 是否是GM后台发起的,如果是GM发起的,一般curPlayer传入的为目标成员ID实例
+    '''
+    if not curPlayer:
+        return
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    if changeFmlv < 0 or changeFmlv > IPY_PlayerDefine.fmlLeader:
+        GameWorld.DebugLog("不存在该职位等级! changeFmlv=%s" % changeFmlv)
+        return
+    # 非GM操作的需检查权限
+    if not isGMOP:
+        if not GetFamilyMemberHasPow(curMember, FamilyPowerID_ChangeFmlv):
             return
-
-    #请求记录申请进入家族信息
-    sendMsg = cPickle.dumps([familyID, PlayerControl.GetFightPower(curPlayer)], 2)
-    curPlayer.GameServer_QueryPlayerByID(ChConfig.queryType_AddFamilyAction, 
-                                        ShareDefine.Def_ActionType_FamilyAdd, '', sendMsg, len(sendMsg))
-    
-    #等GameServer反馈结果再处理
-    return
-    
-    #记录个人申请加入的家族ID
-    for index in range(0, ChConfig.Def_Player_RequestAddFamilyMaxCnt):
-        if curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RequestAddFamilyID%index) == 0:
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyID%index, familyID)
-            break
+        if playerID == tagID:
+            GameWorld.DebugLog("不能任免自己的家族职位", playerID)
+            return
         
-    #记录个人申请加入家族的个数
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RequestAddFamilyCnt, requestAddFamilyCnt + 1)
+    tagMember = family.FindMember(tagID)
+    if tagMember == None:
+        GameWorld.DebugLog("更改家族成员职位时目标成员不存在! tagID=%s" % tagID, playerID)
+        return 
     
-    return
-
-
-
-
-    
-## 战盟玩家OnDay
-#  @param curPlayer
-#  @return None
-def FamilyPlayerOnDay(curPlayer):
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
-        return
-    #每日福利奖励
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyDayAward, 0)
-    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
-
-
-## 战盟玩家OnLogin
-#  @param curPlayer
-#  @return None
-def FamilyPlayerOnLogin(curPlayer, tick):
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_Family):
-        return
-
-    PlayerFamilyTech.Sync_PlayerFamilyTechLV(curPlayer)
-    SyncFamilyActivityInfo(curPlayer)
-    Sync_FamilyDayRewardState(curPlayer)
-    __FamilyAffair_CheckReset(curPlayer)
-    PlayerFamilyZhenfa.OnPlayerLogin(curPlayer)
-    Sync_ZhenbaogeInfo(curPlayer)
-    return
-
-def FamilyPlayerOnLoginCross(curPlayer):
-    ## 登录跨服服务器
-    crossFamilyMemberLV = curPlayer.GetReceivedSalary()
-    if crossFamilyMemberLV:
-        curPlayer.SetFamilyMemberLV(crossFamilyMemberLV)
-        GameWorld.DebugLog("跨服登录设置仙盟职位等级: %s" % crossFamilyMemberLV, curPlayer.GetPlayerID())
+    if not isGMOP:
+        if curMember.GetFmLV() != IPY_PlayerDefine.fmlLeader:
+            if changeFmlv >= curMember.GetFmLV():
+                GameWorld.DebugLog("修改的职位不能比自己高或平级! changeFmlv=%s" % changeFmlv, playerID)
+                return
+            if tagMember.GetFmLV() >= curMember.GetFmLV():
+                GameWorld.DebugLog("修改的目标成员职位不能比自己高或平级! tagFmlv=%s" % tagMember.GetFmLV(), playerID)
+                return
+            
+    if changeFmlv == IPY_PlayerDefine.fmlLeader:
+        changeType = FamilyChangeType_LeaderChange
+        ChangeFamilyLeader(family, tagMember)
         
-    return
+    else:
+        fmLVMemCnt = 0
+        for index in range(family.GetCount()):
+            familyMember = family.GetAt(index)
+            if familyMember.GetFmLV() != changeFmlv:
+                continue
+            fmLVMemCnt += 1
+            
+        maxCnt = GetFamilySetting(family.GetLV(), Def_FmlSetAttrName.get(changeFmlv, ""))
+        if fmLVMemCnt >= maxCnt:
+            # jiazu_hwj35_272921 改为 jiazu_chenxin_31379
+            PlayerControl.NotifyCode(curPlayer, "jiazu_chenxin_31379")
+            GameWorld.DebugLog("目前该职位的人数已经达到上限! changeFmlv=%s,fmLVMemCnt=%s >= %s" % (changeFmlv, fmLVMemCnt, maxCnt))
+            return
+        changeType = FamilyChangeType_MemFmlvChange
+        ChangeFamilyMemberLv(tagMember, changeFmlv)
+        
+    if isGMOP:
+        family.SetBroadcast("")
+    Sync_FamilyInfo(curPlayer)
+    Broadcast_FamilyChange(familyID, changeType, excludeIDList=[playerID, tagID])
+    return True
 
-
-
-
-## 通知GameServer增加家族相关信息值
-# @param curPlayer 玩家实例
-# @param infoDict 信息字典
-# @return 
-def Send_GameServer_PyAddFamilyInfoValue(curPlayer, infoDict={}):
-    if not isinstance(infoDict, dict) or not infoDict:
-        GameWorld.DebugLog("Send_GameServer_PyAddFamilyInfoValue infoDict=%s err!" % str(infoDict))
+def ChangeFamilyLeader(family, newLeaderMem):
+    ## 变更家族族长
+    
+    familyID = family.GetID()
+    befLeaderID = family.GetLeaderID()
+    newLeaderID = newLeaderMem.GetPlayerID()
+    if befLeaderID == newLeaderID:
         return
     
-    sendMsg = '%s'%(infoDict)
-    #GameWorld.DebugLog("Send_GameServer_PyAddFamilyInfoValue sendMsg=%s" % sendMsg)
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, 'PyAddFamilyInfoValue', sendMsg, len(sendMsg))
+    befLeaderMem = family.FindMember(befLeaderID)
+    if befLeaderMem:
+        #把原族长降为普通成员
+        ChangeFamilyMemberLv(befLeaderMem, IPY_PlayerDefine.fmlMember)
+        
+    family.SetLeaderID(newLeaderID)
+    ChangeFamilyMemberLv(newLeaderMem, IPY_PlayerDefine.fmlLeader)
+    GameWorld.Log("家族设置新族长! familyID=%s,newLeaderID=%s,befLeaderID=%s" % (familyID, newLeaderID, befLeaderID))
     return
 
-#---------------------------------------------------------------------
-
-
-
-## 添加家族事件记录
-def AddFamilyEventNote(curPlayer, eventType, valueList):
-    ##同步记录到GameServer, eventType默认为value1
-    sendMsg = cPickle.dumps([eventType] + valueList, 2)
-    curPlayer.GameServer_QueryPlayerByID(ChConfig.queryType_AddFamilyAction, ShareDefine.Def_ActionType_FamilyEvent, '', sendMsg, len(sendMsg))
-    GameWorld.DebugLog("AddFamilyEventNote sendMsg=%s" % sendMsg)
-    return
-
-
-## --------------------------------- 仙盟活跃 -----------------------------------
-def OnWeekEx(curPlayer):
-    #重置
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
-    for actionid in ShareDefine.FamilyActiveIDList:
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
+def ChangeFamilyMemberLv(tagMember, changeFamilyLV):
+    ## 修改成员职位,只做修改逻辑,不做验证,验证由各调用入口自行验证
+    familyID = tagMember.GetFamilyID()
+    tagID = tagMember.GetPlayerID()
+    memName = tagMember.GetPlayerName()
+    befFamilyLV = tagMember.GetFmLV()
     
-    SyncFamilyActivityInfo(curPlayer)
+    tagMember.SetFmLV(changeFamilyLV)
+    
+    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagID)
+    if tagPlayer:
+        MapServer_FamilyRefresh(tagPlayer, familyID)
+        Sync_FamilyInfo(tagPlayer)
+        if GetFamilyMemberHasPow(tagMember, FamilyPowerID_Call):
+            NetPackCommon.SendFakePack(tagPlayer, GetPack_FamilyReqJoinInfo(familyID))
+        
+    # 记录家族事件记录信息
+    tick = GameWorld.GetGameWorld().GetTick()
+    AddFamilyActionNote(memName, familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_FMLV, changeFamilyLV, befFamilyLV], tick)
+    
+    #xx被任命为xx
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_AppointFamily", [memName, changeFamilyLV])
+    #GetFamilyMgr().SetSyncCrossFamilyUpd(familyMember.GetFamilyID(), familyMember.GetPlayerID(), syncNow=True) # 成员职位变更
     return
 
-## 领取仙盟活跃度奖励
-#  @param curPlayer
-#  @param awardIndex
-#  @return None
-def GetFamilyActivityAward(curPlayer, awardIndex):
+#// A6 26 请求家族成员列表 #tagCMGetFamilyInfo
+#
+#struct    tagCMGetFamilyInfo
+#{
+#    tagHead        Head;
+#};
+def OnGetFamilyInfo(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    Sync_FamilyInfo(curPlayer)
     return
-    familyActiveList = IpyGameDataPY.GetFuncEvalCfg('FamilyActive')
-    familyActiveAwardList = IpyGameDataPY.GetFuncEvalCfg('FamilyActive', 2)
-    if awardIndex < 0 or awardIndex >= len(familyActiveList):
-        GameWorld.ErrLog("活跃度奖励索引不合法,index=%s,Len=%s" % (awardIndex, len(familyActiveList)))
+
+#// A6 03 离开家族 #tagCMLeaveFamily
+#
+#struct    tagCMLeaveFamily
+#{
+#    tagHead        Head;
+#};
+def OnLeaveFamily(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
         return
     
-    # 判断是否已领取
-    getAwardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
-    if getAwardRecord & pow(2, awardIndex):
-        GameWorld.Log("已经领取过该活跃度奖励,index=%s" % (awardIndex))
+    familyLV = curMember.GetFmLV()  # 职位
+    if family.GetCount() > 1 and familyLV == IPY_PlayerDefine.fmlLeader:
+        GameWorld.DebugLog("族长在成员人数大于1时不能直接退出家族", playerID)
         return
     
+    # 功能限制退出仙盟
+    # ...
     
-    needActivity = familyActiveList[awardIndex]
-    totalActivity = __GetTotalFamilyActivity(curPlayer)#总活跃度
+    # 进出时间限制暂不做,等正式功能再补
+    #PlayerControl.SetLeaveFamilyTime(curPlayer, updTime)
     
-    # 判断活跃度
-    if totalActivity < needActivity:
-        GameWorld.Log("领奖活跃度不足,index=%s,needActivity=%s,totalActivity=%s" 
-                      % (awardIndex, needActivity, totalActivity))
+    # 执行退出
+    GameWorld.DebugLog("离开家族! familyID=%s" % familyID, playerID)
+    
+    family.DeleteMember(playerID)
+    AddFamilyActionNote(curPlayer.GetName(), familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_Leave], tick)
+    
+    #XW_JZ_LeaveFamily   <n color="0,190,255">{%S1%}</n><n color="255,255,0">退出了家族!</n>  25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [curPlayer.GetName()])
+    
+    MapServer_FamilyRefresh(curPlayer, 0)
+    
+    if family.GetCount() == 0:
+        #玩家离开后, 家族没有人了 , 删除这个家族
+        familyMgr.DelFamily(familyID)
         return
-   
-    activityValue = familyActiveAwardList[awardIndex]
-    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_FamilyActivity, activityValue)
-    
-    # 更新已领取成功标记
-    updAwardRecord = getAwardRecord | (1 << awardIndex)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityAwardRecord, updAwardRecord)
-    
-    SyncFamilyActivityInfo(curPlayer)
-    GameWorld.DebugLog("领取仙盟活跃度奖励OK! index=%s,needActivity=%s,totalActivity=%s,awardRecord=%s" 
-                       % (awardIndex, needActivity, totalActivity, updAwardRecord))
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLeave)
     return
 
-def AddFamilyActivity(curPlayer, actionid, addCnt=1):
-    return
-    ipyData = IpyGameDataPY.GetIpyGameData('FamilyActivity', actionid)
-    if not ipyData:
+#// A6 05 删除家族成员 #tagCMDeleteFamilyMember
+#
+#struct    tagCMDeleteFamilyMember
+#{
+#    tagHead        Head;
+#    DWORD        MemberID;
+#};
+def OnDeleteFamilyMember(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    tagMemberID = clientData.MemberID
+    
+    playerID = curPlayer.GetPlayerID()
+    if playerID == tagMemberID:
         return
-    if not GameFuncComm.GetFuncCanUse(curPlayer, ipyData.GetUnLockFuncID()):
+    
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
         return
-    finishCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
-    maxCnt = ipyData.GetTotalActivityTime()
-    if finishCnt >= maxCnt:
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
         return
-    newCnt = min(maxCnt, finishCnt+addCnt)
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, newCnt)
-    SyncFamilyActivityInfo(curPlayer, actionid)
-    GameWorld.DebugLog('    仙盟活跃完成次数 actionid=%s,newCnt=%s'%(actionid, newCnt))
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    
+    if not GetFamilyMemberHasPow(curMember, FamilyPowerID_Kick):
+        GameWorld.DebugLog("没有踢人权限!")
+        return
+    
+    tagMember = family.FindMember(tagMemberID)
+    if not tagMember:
+        return
+    
+    curFmlv = curMember.GetFmLV()
+    tagFmlv = tagMember.GetFmLV()
+    if tagFmlv >= curFmlv:
+        GameWorld.DebugLog("只能踢比自己职位低的成员! tagMemberID=%s,tagFmlv(%s) >= curFmlv(%s)" % (tagMemberID, tagFmlv, curFmlv), playerID)
+        return
+    
+    # 功能限制踢人
+    # ...
+    
+    tagPlayerName = tagMember.GetPlayerName()  # 被踢玩家名
+    tagPlayerID = tagMember.GetPlayerID()  # 被踢玩家ID
+    
+    family.DeleteMember(tagPlayerID)
+    
+    AddFamilyActionNote(tagPlayerName, familyID, ShareDefine.Def_ActionType_FamilyEvent, 
+                        [ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_KickOut], tick)
+    
+    #XW_JZ_LeaveFamily   <n color="0,190,255">{%S1%}</n><n color="255,255,0">退出了家族!</n>  25  -   -
+    NotifyAllFamilyMemberMsg(familyID, "XW_JZ_LeaveFamily", [tagPlayerName])
+    
+    #删除玩家
+    tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagMemberID)
+    if tagPlayer:
+        MapServer_FamilyRefresh(tagPlayer, 0)
+        
+    Broadcast_FamilyChange(familyID, FamilyChangeType_MemLeave)
     return
 
-def __GetTotalFamilyActivity(curPlayer):
-    ##获取总仙盟活跃度
-    totalPoint = 0
-    ipyDataMgr = IpyGameDataPY.IPY_Data()
-    for i in xrange(ipyDataMgr.GetFamilyActivityCount()):
-        ipyData = ipyDataMgr.GetFamilyActivityByIndex(i)
-        actionid = ipyData.GetID()
-        curTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
-        totalPoint += curTimes/ipyData.GetSingleTimes()*ipyData.GetSingleActiveValue()
-    return totalPoint
-
-def SyncFamilyActivityInfo(curPlayer, syncActionid=-1):
-    return
-    #通知活跃领取情况
-    syncActionIDList = ShareDefine.FamilyActiveIDList if syncActionid==-1 else [syncActionid]
-    sendPack = ChPyNetSendPack.tagMCFamilyActivityInfo()
-    sendPack.Clear()
-    sendPack.AwardRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityAwardRecord, 0)
-    sendPack.InfoList = []
-    for actionid in syncActionIDList:
-        activityInfo = ChPyNetSendPack.tagMCFamilyActionCnt()
-        activityInfo.ActionID = actionid
-        activityInfo.FinishCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyActivityFinishCnt%actionid, 0)
-        sendPack.InfoList.append(activityInfo)
-    sendPack.Count = len(sendPack.InfoList)
-    NetPackCommon.SendFakePack(curPlayer, sendPack)
-    return
-
-#=================仙盟改名======================
 #// A6 11 家族改名 #tagCMRenameFamily
 #
 #struct tagCMRenameFamily
@@ -805,189 +1213,263 @@
 #    BYTE        ItemIndex;  //改名物品在背包中的位置
 #};
 def UpdateFamilyName(index, clientData, tick):
-    
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    if GameWorld.IsCrossServer():
-        #itemuse_lzxkoy_0:不可在跨服环境下使用改名功能。
-        PlayerControl.NotifyCode(curPlayer, "itemuse_lzxkoy_0")
-        return
-    
-    if not curPlayer.GetFamilyID():
-        return
-    
-    if curPlayer.GetDictByKey(ChConfig.Def_Player_Dict_UpdateFamilyName):
-        #正在改名中
-        GameWorld.Log("仙盟已经在改名中...", curPlayer.GetID())
-        return
-    
-    #新名字
     newName = clientData.NewName
     itemIndex = clientData.ItemIndex
-     
+    
+    playerID = curPlayer.GetPlayerID()
+    familyID = curPlayer.GetFamilyID()
+    if familyID <= 0:
+        return
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    family = familyMgr.FindFamily(familyID)
+    if not family:
+        return
+    curMember = family.FindMember(playerID)
+    if not curMember:
+        return
+    
+    if curMember.GetFmLV() != IPY_PlayerDefine.fmlLeader:
+        GameWorld.DebugLog("非盟主不可改名!", playerID)
+        return
+    
+    familyName = CheckInputFamilyName(curPlayer, newName)
+    if not familyName:
+        return
+    
     itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
     curItem = itemPack.GetAt(itemIndex)
-    if not ItemCommon.CheckItemCanUse(curItem):
+    if not ItemCommon.CheckItemCanUse(curItem) or curItem.GetType() != ChConfig.Def_ItemType_ChangeFamilyName:
+        GameWorld.DebugLog("没有仙盟改名道具! itemIndex=%s" % itemIndex, playerID)
         return
-    if curItem.GetType() != ChConfig.Def_ItemType_ChangeFamilyName:
-        return
-
-    #改名物品在背包的位置
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_UpdateFamilyNameItemIndex, itemIndex)
+    ItemCommon.DelItem(curPlayer, curItem, 1, True, 'UpdateFamilyName')
     
-    #设置正在改名中...
-    curPlayer.SetDict(ChConfig.Def_Player_Dict_UpdateFamilyName, 1)
+    #oldName = curFamily.GetName()
+    family.SetName(familyName)
     
-    #通知GameServer正式改名
-    newNameMsg = str(newName)
-    GameWorld.Log("UpdateFamilyName 通知GameServer正式改名为:%s"%newNameMsg, curPlayer.GetID())
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(curPlayer.GetID(), 0, 0, 'UpdateFamilyName', newNameMsg, len(newNameMsg))
+    infoPack = GetPack_FamilyInfo(familyID)
+    playerManager = GameWorld.GetPlayerManager()
+    for index in xrange(family.GetCount()):
+        member = family.GetAt(index)
+        memID = member.GetPlayerID()
+        player = playerManager.FindPlayerByID(memID)
+        if not player:
+            continue
+        Sync_FamilyInfo(player, infoPack)
+        player.SetFamilyName(familyName)
+        player.Notify_FamilyNameRefresh() #//04 36    周围玩家家族名刷新#tagPlayerFamilyNameRefresh
+        
+    #PlayerCompensation.SendMailByKey('FamilyNameChange', memberIDList, [], [oldName, familyName])    
+    #PlayerControl.WorldNotify(0, 'Family_ChangeName', [oldName, familyName])
     return
 
-
-## 扣除改名消耗
-#  @param curPlayer: 玩家实例
-#  @return: None
-def PayUpdateFamilyNameCost(curPlayer): 
-    itemIndex = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_UpdateFamilyNameItemIndex)
-    #扣除物品
-    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
-    curItem = itemPack.GetAt(itemIndex)
-    if curItem:
-        ItemCommon.DelItem(curPlayer, curItem, 1, True, 'UpdateFamilyName')
+#// A6 20 搜索家族列表 #tagCMViewFamilyPage
+#
+#struct    tagCMViewFamilyPage
+#{
+#    tagHead        Head;
+#    BYTE        MsgLen;        //模糊搜索家族,如果输入为空,则为不限制该条件
+#    char        Msg[MsgLen];    //size = MsgLen
+#    BYTE        PageIndex;    //查询第X页索引,0~n
+#    BYTE        ShowCount;    //每页数量,前端可自行指定,最大50
+#};
+def OnViewFamilyPage(index, clientData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    msg = clientData.Msg
+    pageIndex = clientData.PageIndex
+    showCount = min(clientData.ShowCount, 50)
     
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_UpdateFamilyNameItemIndex, 0)
-    return
-
-def GetFamilyDayAward(curPlayer):
-    ##领取仙盟每日奖励 2小时脱机挂时间
-    if not curPlayer.GetFamilyID():
-        return
-    hasGot = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyDayAward)
-    if hasGot:
-        GameWorld.DebugLog('领取仙盟每日奖励 当日已领取!')
-        return
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyDayAward, 1)
-    #addTime = IpyGameDataPY.GetFuncCfg('FamilyDayAward')
-    #PlayerTJG.AddTJGTime(curPlayer, addTime)
-    #通知
-    Sync_FamilyDayRewardState(curPlayer)
-    #PlayerControl.NotifyCode(curPlayer, 'OfflinePlugSuccess', [addTime/60/60])
+    familyMgr = DBDataMgr.GetFamilyMgr()
+    familyCount = familyMgr.GetCount()
+    totalPage = 0
     
-    return
-
-def Sync_FamilyDayRewardState(curPlayer):
-    clientPack = ChPyNetSendPack.tagMCFamilyDayAward()
-    clientPack.GetState = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyDayAward)
-    clientPack.MoneyDonateCount = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyMoneyDonateCount)
+    if not msg:
+        startIndex = pageIndex * showCount
+        endIndex = startIndex + showCount - 1
+        if familyCount > 0:
+            totalPage = GameWorld.GetIntUpper(familyCount, showCount)
+            
+    # 有指定搜索内容的后端固定返回单页   
+    else:
+        pageIndex = 0
+        showCount = 20
+        totalPage = 1
+        startIndex = 0
+        endIndex = familyCount - 1
+        
+    clientPack = ChPyNetSendPack.tagMCFamilyViewList()
+    clientPack.Msg = msg
+    clientPack.MsgLen = len(clientPack.Msg)
+    clientPack.PageIndex = pageIndex
+    clientPack.ShowCount = showCount
+    clientPack.TotalPage = totalPage
+    clientPack.FamilyList = []
+    for index in range(startIndex, endIndex + 1):
+        if index >= familyCount:
+            break
+        family = familyMgr.GetAt(index)
+        if not family:
+            continue
+        if msg and msg not in family.GetName():
+            continue
+        familyView = ChPyNetSendPack.tagMCFamilyView()
+        familyView.FamilyID = family.GetID()
+        familyView.FamilyName = family.GetName()
+        familyView.FamilyNameLen = len(familyView.FamilyName)
+        familyView.LeaderID = family.GetLeaderID()
+        leaderMember = family.FindMember(familyView.LeaderID)
+        familyView.LeaderName = leaderMember.GetPlayerName() if leaderMember else ""
+        familyView.LeaderNameLen = len(familyView.LeaderName)
+        familyView.FamilyLV = family.GetLV()
+        familyView.JoinReview = family.GetJoinReview()
+        familyView.JoinLVMin = family.GetJoinLVMin()
+        familyView.ServerID = family.GetServerID()
+        familyView.EmblemID = family.GetEmblemID()
+        familyView.FightPower = family.GetFightPower()
+        familyView.FightPowerEx = family.GetFightPowerEx()
+        familyView.MemberCount = family.GetCount()
+        clientPack.FamilyList.append(familyView)
+        clientPack.FamilyCount = len(clientPack.FamilyList)
+        if clientPack.FamilyCount >= showCount:
+            break
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return
 
-
-#// A6 06 家族兑换活跃令 #tagCMFamilyActivityExchange
-#
-#struct    tagCMFamilyActivityExchange
-#{
-#    tagHead        Head;
-#    BYTE        Count;        //材料所在背包索引的数量
-#    WORD        IndexList[Count];    //材料所在背包索引列表
-#    DWORD        ItemIDList[Count];    //材料所在背包物品ID列表
-#};
-## 家族兑换活跃令 
-#  @param playerIndex 玩家索引  
-#  @param clientData 客户端封包  
-#  @param tick 时间
-#  @return None
-def OnFamilyActivityExchange(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    if not clientData.Count:
-        return
-    playerID = curPlayer.GetID()
-    eatIndexList = clientData.IndexList
-    eatItemIDList = clientData.ItemIDList
-    givePoint = 0 #分解得到活跃令
-    familyDonateDict = IpyGameDataPY.GetFuncEvalCfg('FamilyDonate', 1, {})
-    familyDonateSpecialDict = IpyGameDataPY.GetFuncEvalCfg('FamilyDonate', 2, {})
-    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
-    for i, index in enumerate(eatIndexList):
-        eatItem = itemPack.GetAt(index)
-        if not ItemCommon.CheckItemCanUse(eatItem):
-            GameWorld.DebugLog("物品不可用,无法兑换!itemIndex=%s" % index)
-            continue
-        eatItemID = eatItem.GetItemTypeID()
-        if eatItemID != eatItemIDList[i]:
-            GameWorld.Log('家族兑换活跃令 发的物品ID不对应index=%s eatItemID=%s,ItemIDList[i]=%s' % (index, eatItemID, eatItemIDList[i]), playerID)
-            continue
-        #if eatItem.GetIsBind():
-        #    GameWorld.DebugLog("装备已绑定,无法兑换!itemIndex=%s" % index)
-        #    continue
-        if eatItem.GetEndureReduceType():
-            GameWorld.DebugLog("有时效耐久物品,无法兑换!itemIndex=%s" % index)
-            continue
-        if eatItemID in familyDonateSpecialDict:
-            addPoint = familyDonateSpecialDict[eatItemID]
-        else:
-            if not ItemCommon.CheckItemIsEquip(eatItem):
-                GameWorld.DebugLog("非装备,无法兑换!itemIndex=%s" % index)
-                continue
-            itemColor = eatItem.GetItemColor()
-            if str(itemColor) not in familyDonateDict:
-                continue
-            isSuite = eatItem.GetSuiteID()
-            addPoint = familyDonateDict[str(itemColor)][1 if isSuite else 0]
-        itemCnt = eatItem.GetCount()
-        givePoint += addPoint * itemCnt
-        ItemCommon.DelItem(curPlayer, eatItem, itemCnt, True, ChConfig.ItemDel_FamilyStore, {'addPoint':addPoint}, True)
-    
-    if not givePoint:
-        GameWorld.DebugLog("家族兑换活跃令,没有装备可兑换!")
-        return
-    PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_FamilyActivity, givePoint)
-    
-    #通知结果
-    packData = ChPyNetSendPack.tagMCFamilyActivityExchangeResult()
-    packData.Clear()
-    packData.Point = givePoint
-    NetPackCommon.SendFakePack(curPlayer, packData)
-    return
 
 #// A6 12 家族捐献货币 #tagCMFamilyMoneyDonate
 #
 #struct     tagCMFamilyMoneyDonate
 #{
 #    tagHead        Head;
-#    BYTE        MoneyType;    // 捐献货币类型
+#    BYTE        DonateType;    // 捐献类型
 #};
 def OnFamilyMoneyDonate(index, clientData, tick):
+    #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    #DonateType = clientData.DonateType
+    #playerID = curPlayer.GetPlayerID()
+    # 先屏蔽,等功能定了再改
+    return
+
+
+#---------------------------------------------------------------------
+def AddPlayerFamilyActiveValue(curPlayer, addValue, sendPackGameServer = False, reason = 0, isSysMsg=False):
+    # 多个地方用到,先保留,之后删除统一修改
+    return True
+def SendPack_GameServer_AddFamilyDetail(curPlayer, addFamilyHornor = 0, addFamilyMoney = 0, addFamilyActiveValue = 0, resion=0):
+    return
+def SendPack_GameServer_AddFamilyDetailEx(curPlayer, addPlayerActiveValue, addFamilyMoney = 0, addFamilyHornor = 0, resion=0):
+    return
+
+## ------------------------------------------------------------------------------------------------
+
+#// A6 17 查询家族行为信息 #tagCMQueryFamilyAction
+#
+#struct    tagCMQueryFamilyAction
+#{
+#    tagHead        Head;
+#    BYTE        ActionType;        // 行为类型
+#    DWORD        FamilyID;         // 家族ID,发0默认自己家族
+#};
+def OnQueryFamilyAction(index, cliendData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    moneyType = clientData.MoneyType
-    playerID = curPlayer.GetPlayerID()
     
-    dailyDonateCountMax = IpyGameDataPY.GetFuncCfg('FamilyDonate', 3)
-    donateCount = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyMoneyDonateCount)
-    if dailyDonateCountMax and donateCount >= dailyDonateCountMax:
-        GameWorld.DebugLog("今日货币捐献次数已达上限. donateCount=%s" % donateCount, playerID)
+    if not curPlayer:
         return
     
-    donatePrizeInfo = IpyGameDataPY.GetFuncEvalCfg('FamilyDonate', 4, {})
-    if str(moneyType) not in donatePrizeInfo:
-        GameWorld.DebugLog("不存在该货币类型捐献: moneyType=%s" % moneyType, playerID)
-        return
-    needMoney, contribution, familyActivity = donatePrizeInfo[str(moneyType)]
-    if not PlayerControl.PayMoney(curPlayer, moneyType, needMoney, "FamilyMoneyDonate"):
-        return
-    
-    updDonateCount = donateCount + 1
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FamilyMoneyDonateCount, updDonateCount)
-    Sync_FamilyDayRewardState(curPlayer)
-    GameWorld.DebugLog("货币捐献: moneyType=%s,needMoney=%s,updDonateCount=%s,contribution=%s,familyActivity=%s" 
-                       % (moneyType, needMoney, updDonateCount, contribution, familyActivity), playerID)
-    
-    if contribution > 0:
-        AddPlayerFamilyActiveValue(curPlayer, contribution, True, ShareDefine.Def_AddFAVReason_FamilyDonateItem, True)
+    actionType = cliendData.ActionType
+    familyID = cliendData.FamilyID
+    if not familyID:
+        familyID = curPlayer.GetFamilyID()
         
-    if familyActivity > 0:
-        PlayerControl.GiveMoney(curPlayer, ShareDefine.TYPE_Price_FamilyActivity, familyActivity)
+    SendFamilyActionInfo(curPlayer, familyID, actionType)
+    return
+
+def SendFamilyActionInfo(curPlayer, familyID, actionType):
+    ## 发送家族行为
+    # @param curPlayer: 为None时通知该仙盟所有成员
+    
+    familyAction = DBDataMgr.GetFamilyActionMgr().GetFamilyAction(familyID, actionType)
+    
+    clientPack = ChPyNetSendPack.tagMCFamilyActionInfo()
+    clientPack.FamilyID = familyID
+    clientPack.ActionType = actionType
+    clientPack.FamilyActionList = []
+    
+    for index in xrange(familyAction.Count()):
+        familyActionData = familyAction.At(index)
         
+        actionData = ChPyNetSendPack.tagMCFamilyAction()
+        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.GetUserData()
+        actionData.UseDataLen = len(actionData.UseData)
+        clientPack.FamilyActionList.append(actionData)
+        
+    clientPack.Count = len(clientPack.FamilyActionList)
+    
+    if curPlayer:
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+        return
+    Broadcast_FamilyPack(familyID, clientPack)
+    return
+
+def SendFamilyAction(actionDataList, curPlayer=None):
+    ## 同步指定仙盟action
+    # @param actionDataList: 支持列表或指定actionData
+    # @param curPlayer: 为None时通知该仙盟所有成员
+    if not isinstance(actionDataList, list):
+        actionDataList = [actionDataList]
+    if not actionDataList:
+        return
+    familyActionData = actionDataList[0]
+    familyID = familyActionData.GetFamilyID()
+    actionType = familyActionData.GetActionType()
+    
+    clientPack = ChPyNetSendPack.tagMCFamilyActionInfo()
+    clientPack.FamilyID = familyID
+    clientPack.ActionType = actionType
+    clientPack.FamilyActionList = []
+    for familyActionData in actionDataList:
+        actionData = ChPyNetSendPack.tagMCFamilyAction()
+        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.GetUserData()
+        actionData.UseDataLen = len(actionData.UseData)
+        clientPack.FamilyActionList.append(actionData)
+    clientPack.Count = len(clientPack.FamilyActionList)
+    
+    if curPlayer:
+        NetPackCommon.SendFakePack(curPlayer, clientPack)
+        return
+    Broadcast_FamilyPack(familyID, clientPack)
+    return
+
+def GetFamilyDayAward(curPlayer):
+    ##领取仙盟每日奖励 2小时脱机挂时间
+    return
+
+def Sync_FamilyDayRewardState(curPlayer):
+    clientPack = ChPyNetSendPack.tagMCFamilyDayAward()
+    clientPack.GetState = 0
+    clientPack.MoneyDonateCount = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FamilyDonateRecord)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+def AddFamilyActivity(curPlayer, actionid, addCnt=1):
     return
 
 
@@ -1195,222 +1677,3 @@
     clientPack.Count = len(clientPack.AffairInfoList)
     NetPackCommon.SendFakePack(curPlayer, clientPack)
     return
-
-##--------------------------------------------------------------------------------------------------
-##--------------------------------------- 仙盟传功 --------------------------------------------------
-#// A6 15 传功操作 #tagCMChuangongOP
-#
-#struct    tagCMChuangongOP
-#{
-#    tagHead        Head;
-#    BYTE        OPType;        // 操作类型:1-邀请;2-回应;3-领奖;
-#    DWORD        PlayerID;        // 目标玩家ID;回应时为邀请方玩家ID
-#    BYTE        OPData;        // 操作数据,可选:回应时为是否同意
-#};
-def OnChuangongOP(index, clientData, tick):
-    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
-    opType = clientData.OPType
-    tagPlayerID = clientData.PlayerID
-    opData = clientData.OPData
-    
-    if tagPlayerID and curPlayer.GetPlayerID() == tagPlayerID:
-        GameWorld.DebugLog("不能自己传功")
-        return
-    
-    if opType == 1:
-        __Chuangong_Invite(curPlayer, tagPlayerID)
-    elif opType == 2:
-        __Chuangong_Response(curPlayer, tagPlayerID, opData)
-    elif opType == 3:
-        __Chuangong_GetAward(curPlayer)
-    return
-
-def SendGameServer_FamilyChuangong(curPlayer, msgType, msgData):
-    playerID = curPlayer.GetPlayerID()
-    GameWorld.DebugLog("传功同步GameServer: msgType=%s,%s" % (msgType, msgData), playerID)
-    msgInfo = str([msgType, msgData])
-    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "FamilyChuangong", msgInfo, len(msgInfo))
-    return
-
-def __CheckCanChuangong(curPlayer):
-    playerID = curPlayer.GetPlayerID()
-    remainCnt = PlayerActivity.GetDailyActionrRemainCnt(curPlayer, ShareDefine.DailyActionID_FamilyChuanGong)
-    if remainCnt <= 0:
-        GameWorld.DebugLog("没有传功次数了", playerID)
-        return
-    openServerDayLimit = IpyGameDataPY.GetFuncCfg("FamilyChuangong", 1)
-    if openServerDayLimit:
-        openServerDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
-        if openServerDay > openServerDayLimit:
-            GameWorld.DebugLog("当前开服天不能传功: openServerDay=%s > %s" % (openServerDay, openServerDayLimit), playerID)
-            return
-    return True
-
-def __Chuangong_Invite(curPlayer, tagPlayerID):
-    ## 传功邀请
-    if not __CheckCanChuangong(curPlayer):
-        return
-    SendGameServer_FamilyChuangong(curPlayer, "Invite", [tagPlayerID])
-    return
-
-def __Chuangong_Response(curPlayer, tagPlayerID, isOK):
-    ## 传功回应
-    SendGameServer_FamilyChuangong(curPlayer, "Response", [tagPlayerID, isOK])
-    return
-
-def __Chuangong_GetAward(curPlayer):
-    ## 传功领奖
-    if not __CheckCanChuangong(curPlayer):
-        return
-    PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_FamilyChuanGong, 1)
-    
-    playerID = curPlayer.GetPlayerID()
-    fromLV = curPlayer.GetLV()
-    
-    # 给经验
-    totalExp = 0
-    giveRound = IpyGameDataPY.GetFuncCfg("FamilyChuangong", 3)
-    worldlv = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
-    playerControl = PlayerControl.PlayerControl(curPlayer)
-    for index in range(giveRound):
-        reLV = curPlayer.GetLV()
-        reExp = PlayerControl.GetPlayerReExp(curPlayer)
-        giveExp = eval(IpyGameDataPY.GetFuncCompileCfg("FamilyChuangong", 2))
-        finalAddExp = playerControl.AddExp(giveExp, ShareDefine.Def_ViewExpType_Chuangong)
-        totalExp += finalAddExp
-        GameWorld.DebugLog("传功经验: 轮次=%s,reLV=%s,reExp=%s,finalAddExp=%s, %s" % (index, reLV, reExp, finalAddExp, totalExp), playerID)
-        
-    PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_FamilyChuanGong, 1)
-    PlayerTongTianLing.AddTongTianTaskValue(curPlayer, ChConfig.TTLTaskType_ChuanGong, 1)
-    
-    # 给物品
-    giveItemList = IpyGameDataPY.GetFuncEvalCfg("FamilyChuangong", 4)
-    ItemControler.GivePlayerItemOrMail(curPlayer, giveItemList)
-    
-    # 同步结果
-    syncItemList = []
-    for itemID, itemCount, _ in giveItemList:
-        syncItem = ChPyNetSendPack.tagMCChuangongItem()
-        syncItem.Clear()
-        syncItem.ItemID = itemID
-        syncItem.ItemCount = itemCount
-        syncItemList.append(syncItem)
-        # 有协助感谢礼盒
-        if IpyGameDataPY.GetIpyGameDataNotLog("AssistThanksGift", itemID):
-            SendGameServer_FamilyChuangong(curPlayer, "ThanksGift", [itemID])
-    clientPack = ChPyNetSendPack.tagMCChuangongResult()
-    clientPack.Clear()
-    clientPack.FromLV = fromLV
-    clientPack.ToLV = curPlayer.GetLV()
-    clientPack.Exp = totalExp % ChConfig.Def_PerPointValue
-    clientPack.ExpPoint = totalExp / ChConfig.Def_PerPointValue
-    clientPack.AwardItemList = syncItemList
-    clientPack.ItemCount = len(clientPack.AwardItemList)
-    NetPackCommon.SendFakePack(curPlayer, clientPack)
-    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, {}], isNotifyAward=False)
-        ItemControler.NotifyGiveAwardInfo(curPlayer, giveItemList, "Zhenbaoge", moneyInfo={moneyType:0 if nowPrice > 0 else -nowPrice})
-        
-        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
-
-##--------------------------------------------------------------------------------------------------

--
Gitblit v1.8.0