hxp
12 小时以前 dc0b92c1e2fe9f3d24c183b325dad54d088735c1
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
##--------------------------------------------------------------------------------------------------