From 40482e1a851925b325dc085aef3058303730e287 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 17 十月 2025 11:44:46 +0800
Subject: [PATCH] 66 【公会】基础主体-服务端(公会加入改为官职限制;增加退出公会惩罚机制;)

---
 /dev/null                                                                                       |   47 -----------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py |   26 +++---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py      |   80 +++++++++++++++++---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py       |   19 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py     |   17 ++++
 5 files changed, 114 insertions(+), 75 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
index beee8be..7d3c042 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/CreateFamily.py
@@ -32,7 +32,7 @@
     if not gmList:
         #GameWorld.DebugAnswer(curPlayer, "创建跨服假仙盟: CreatFamily c 个数 [总战力 ServerID 等级 成员数]")
         #GameWorld.DebugAnswer(curPlayer, "删除跨服假仙盟: CreatFamily c 0")
-        GameWorld.DebugAnswer(curPlayer, "建本服假仙盟: CreatFamily 个数 [总战力 ServerID 等级 成员数]")
+        GameWorld.DebugAnswer(curPlayer, "建本服假仙盟: CreatFamily 个数 [总战力 ServerID 等级 成员数  是否审核 官职限制]")
         GameWorld.DebugAnswer(curPlayer, "删本服假仙盟: CreatFamily 0")
         GameWorld.DebugAnswer(curPlayer, "输出仙盟列表: CreatFamily pl [条数 从第x名]")
         GameWorld.DebugAnswer(curPlayer, "输出仙盟明细: CreatFamily pf 仙盟ID")
@@ -99,14 +99,14 @@
     familyMgr = DBDataMgr.GetFamilyMgr()
     familyMgr.Sort()
     familyCnt = familyMgr.GetCount()
-    GameWorld.DebugAnswer(curPlayer, "仙盟总数: %s" % familyCnt)
+    GameWorld.DebugAnswer(curPlayer, "----- 仙盟总数: %s -----" % (familyCnt))
     for index in range(fromIndex, fromIndex + printCnt):
         if index >= familyCnt:
             break
         family = familyMgr.GetAt(index)
         rank = index + 1
         
-        text = "%s,ID:%s,LV:%s,战力:%s,成员:%s" % (rank, family.GetID(), family.GetLV(), family.GetFightPowerTotal(), family.GetCount())
+        text = "%s,ID:%s,LV:%s,战:%s,成:%s,审:%s,官:%s" % (rank, family.GetID(), family.GetLV(), family.GetFightPowerTotal(), family.GetCount(), family.GetJoinReview(), family.GetJoinLVMin())
         printAnswerCnt += 1
         if printAnswerCnt <= 100:
             GameWorld.DebugAnswer(curPlayer, text)
@@ -125,17 +125,17 @@
         return
     
     GameWorld.DebugAnswer(curPlayer, "----- 【%s】 -----" % (GameWorld.CodeToGbk(family.GetName())))
-    GameWorld.DebugAnswer(curPlayer, "仙盟ID:%s,ServerID:%s" % (familyID, family.GetServerID()))
-    GameWorld.DebugAnswer(curPlayer, "LV:%s,Exp:%s" % (family.GetLV(), family.GetExp()))
-    GameWorld.DebugAnswer(curPlayer, "审核:%s,等级条件:%s,申请数:%s" % (family.GetJoinReview(), family.GetJoinLVMin(), len(family.GetReqJoinPlayerInfo())))
-    GameWorld.DebugAnswer(curPlayer, "徽章:%s,%s" % (family.GetEmblemID(), GameWorld.CodeToGbk(family.GetEmblemWord())))
-    GameWorld.DebugAnswer(curPlayer, "总战力:%s,人数:%s" % (family.GetFightPowerTotal(), family.GetCount()))
-    GameWorld.DebugAnswer(curPlayer, "盟主:%s" % (family.GetLeaderID()))
+    GameWorld.DebugAnswer(curPlayer, "仙盟ID:%s, ServerID:%s" % (familyID, family.GetServerID()))
+    GameWorld.DebugAnswer(curPlayer, "LV:%s, Exp:%s" % (family.GetLV(), family.GetExp()))
+    GameWorld.DebugAnswer(curPlayer, "审核:%s, 官职条件:%s, 申请数:%s" % (family.GetJoinReview(), family.GetJoinLVMin(), len(family.GetReqJoinPlayerInfo())))
+    GameWorld.DebugAnswer(curPlayer, "战旗:%s, 旗号【%s】" % (family.GetEmblemID(), GameWorld.CodeToGbk(family.GetEmblemWord())))
+    GameWorld.DebugAnswer(curPlayer, "总战力:%s, 人数:%s" % (family.GetFightPowerTotal(), family.GetCount()))
+    GameWorld.DebugAnswer(curPlayer, "盟主ID:%s" % (family.GetLeaderID()))
     for index in range(family.GetCount()):
         member = family.GetAt(index)
         playerID = member.GetPlayerID()
         fightPower = member.GetFightPowerTotal()
-        GameWorld.DebugAnswer(curPlayer, "%s,%s,职位:%s,战力:%s" % (index, playerID, member.GetFmLV(), fightPower))
+        GameWorld.DebugAnswer(curPlayer, "%s,ID:%s,职位:%s,战力:%s" % (index, playerID, member.GetFmLV(), fightPower))
         
     return
 
@@ -164,6 +164,8 @@
     serverID = gmList[2] if len(gmList) > 2 else random.randint(1, 200)
     familyLV = gmList[3] if len(gmList) > 3 else 1 # 默认1级
     memberCnt = gmList[4] if len(gmList) > 4 else random.randint(1, 10)
+    joinReview = gmList[5] if len(gmList) > 5 else 1
+    joinLVMin = gmList[6] if len(gmList) > 6 else random.randint(1, 10)
     
     FakeFamilyName = GameWorld.GbkToCode("神秘军团")
     FakeEmblemWord = GameWorld.GbkToCode("神")
@@ -199,8 +201,8 @@
         fackFamily.SetFightPowerTotal(familyFightPower)
         fackFamily.SetEmblemID(1)
         fackFamily.SetEmblemWord(FakeEmblemWord)
-        fackFamily.SetJoinReview(1) # 设置需要审核
-        fackFamily.SetJoinLVMin(random.randint(0, 1000))
+        fackFamily.SetJoinReview(joinReview) # 设置需要审核
+        fackFamily.SetJoinLVMin(joinLVMin) # 官职
         
         GameWorld.DebugLog("创建假仙盟: fackFamilyID=%s,serverID=%s,familyFightPower=%s,memberCnt=%s" 
                            % (fackFamilyID, serverID, familyFightPower, memberCnt))
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py
index a90b3c5..7dd7dcd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/Family.py
@@ -20,13 +20,28 @@
 import PlayerFamilyEmblem
 import PlayerFamily
 import DBDataMgr
+import PlayerControl
+import time
 
 def OnExec(curPlayer, msgList):
     
     if not msgList:
         GameWorld.DebugAnswer(curPlayer, "设置等级: Family lv 等级 经验")
         GameWorld.DebugAnswer(curPlayer, "设置徽章: Family e 徽章ID [剩余时间秒]")
+        GameWorld.DebugAnswer(curPlayer, "设置离开: Family l 主动离开次数 被踢次数 上次是否主动  离开多久了")
         GameWorld.DebugAnswer(curPlayer, "创建仙盟相关使用命令: CreateFamily")
+        return
+    
+    value = msgList[0]
+    
+    if value == "l":
+        leaveCnt = msgList[1] if len(msgList) > 1 else 0
+        kickedCnt = msgList[2] if len(msgList) > 2 else 0
+        lastVoluntarily = msgList[3] if len(msgList) > 3 else 0
+        leavePassMinutes = msgList[4] if len(msgList) > 4 else 0
+        leaveInfo = PlayerControl.SetLeaveFamilyInfo(curPlayer, leaveCnt, kickedCnt, lastVoluntarily)
+        leaveTime = PlayerControl.SetLeaveFamilyTimeEx(curPlayer, int(time.time()) - leavePassMinutes * 60)
+        GameWorld.DebugAnswer(curPlayer, "设置离开: Info=%s,%s" % (leaveInfo, GameWorld.ChangeTimeNumToStr(leaveTime)))
         return
     
     familyID = curPlayer.GetFamilyID()
@@ -35,8 +50,6 @@
     if not curFamily:
         GameWorld.DebugAnswer(curPlayer, "玩家未加入仙盟!")
         return
-    
-    value = msgList[0]
     
     if value == "lv":
         lv = msgList[1] if len(msgList) > 1 else 1
@@ -57,7 +70,7 @@
             return
         endTime = PlayerFamilyEmblem.GetActionEmblemEndTime(emblemActionObj)
         GameWorld.DebugAnswer(curPlayer, "添加徽章(%s)到期:%s" % (emblemID, GameWorld.ChangeTimeNumToStr(endTime)))
-        return 
+        return
     
     PlayerFamily.Sync_FamilyInfo(curPlayer)
     return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index d4fde0d..3d75dfe 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -33,6 +33,7 @@
 import PlayerBillboard
 import GameServerRefresh
 import IPY_GameWorld
+import IPY_PlayerDefine
 import ChPyNetSendPack
 import NetPackCommon
 import DataRecordPack
@@ -4513,13 +4514,27 @@
     ## 获取玩家在本地图中的境界难度层级,必须在境界地图且有选择境界难度才算,否则为默认0;该难度值同时也是视野层级
     return 0
 
+
+##玩家退出仙盟信息: 主动离开次数*100 + 被踢次数*10  + 最后一次是否主动离开的
+def GetLeaveFamilyInfo(curPlayer):
+    # @return: 主动离开次数, 最后一次是否主动离开的
+    value = curPlayer.GetExAttr12()
+    leaveCnt = value / 100
+    kickedCnt = value % 100 / 10
+    lastVoluntarily = value % 10
+    return leaveCnt, kickedCnt, lastVoluntarily
+def SetLeaveFamilyInfo(curPlayer, leaveCnt, kickedCnt, lastVoluntarily):
+    value = min(9, leaveCnt) * 100 + min(9, kickedCnt) * 10 + lastVoluntarily
+    curPlayer.SetExAttr12(value) # IPY_PlayerDefine.CDBPlayerRefresh_ExAttr12
+    GameWorld.DebugLog("    SetLeaveFamilyInfo: value=%s" % (value))
+    return value
 ##玩家离开仙盟时间(主动或被踢都算)
 def GetLeaveFamilyTimeEx(curPlayer):return curPlayer.GetExAttr19()
 def SetLeaveFamilyTimeEx(curPlayer, value):
     curPlayer.SetExAttr19(value)
     #curPlayer.SendGameServerRefreshState(ShareDefine.CDBPlayerRefresh_ExAttr19, value, 0)
     curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ExAttr19, value, 0, False)
-    return
+    return value
 
 ##总战斗力,支持超过20E = 各模块战力总和
 def GetFightPower(curPlayer): return curPlayer.GetFightPowerEx() * ChConfig.Def_PerPointValue + curPlayer.GetFightPower()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
index 2c45798..f493192 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFamily.py
@@ -394,9 +394,10 @@
             setFunc(value)
     return True
 
-def MapServer_FamilyRefresh(curPlayer, refreshFamilyID):
+def MapServer_FamilyRefresh(curPlayer, refreshFamilyID, isVoluntarily=0):
     ''' 相当于GameServer调用 curPlayer.MapServer_FamilyRefresh()
     @param familyID: 玩家更新的familyID
+    @param isVoluntarily: 是否自愿离开的,仅离开刷新时有效
     '''
     
     tick = GameWorld.GetGameWorld().GetTick()
@@ -443,7 +444,7 @@
         
     if lastFamilyID != 0 and curPlayer.GetFamilyID() == 0:
         #玩家离开家族
-        __OnLeaveFamily(curPlayer, tick)
+        __OnLeaveFamily(curPlayer, isVoluntarily, tick)
         
     elif lastFamilyID == 0 and curPlayer.GetFamilyID() != 0:
         #刚进家族并为族长,触发建家族事件
@@ -464,7 +465,7 @@
     Sync_RequestAddFamilyInfo(curPlayer)
     return
 
-def __OnLeaveFamily(curPlayer, tick):
+def __OnLeaveFamily(curPlayer, isVoluntarily, tick):
     ## 退出家族触发事件
     #---清空家族相关信息---
     curPlayer.SetPerExp(0)
@@ -473,7 +474,29 @@
     curPlayer.SetLastWeekFamilyActiveValue(0)
     curPlayer.SetFamilyLV(0)
     PlayerControl.SetLeaveFamilyTimeEx(curPlayer, int(time.time()))
-    
+    leaveCnt, kickedCnt, _ = PlayerControl.GetLeaveFamilyInfo(curPlayer)
+    GameWorld.DebugLog("__OnLeaveFamily: isVoluntarily=%s,leaveCnt=%s,kickedCnt=%s" % (isVoluntarily, leaveCnt, kickedCnt))
+    delMoneyType, delMoneyPer = IpyGameDataPY.GetFuncCfg("FamilyLeave", 3), 0
+    if isVoluntarily:
+        delMoneyPerList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 4)
+        if delMoneyPerList:
+            delMoneyPer = delMoneyPerList[leaveCnt] if len(delMoneyPerList) > leaveCnt else delMoneyPerList[-1]
+            
+        leaveCnt += 1
+        GameWorld.DebugLog("    增加主动离开次数: leaveCnt=%s" % (leaveCnt))
+    else:
+        delMoneyPerList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 5)
+        if delMoneyPerList:
+            delMoneyPer = delMoneyPerList[kickedCnt] if len(delMoneyPerList) > kickedCnt else delMoneyPerList[-1]
+            
+        kickedCnt += 1
+        GameWorld.DebugLog("    增加被踢离开次数: kickedCnt=%s" % (kickedCnt))
+    PlayerControl.SetLeaveFamilyInfo(curPlayer, leaveCnt, kickedCnt, isVoluntarily)
+    if delMoneyType and delMoneyPer:
+        nowMoney = PlayerControl.GetMoney(curPlayer, delMoneyType)
+        delMoney = int(nowMoney * delMoneyPer / 100.0)
+        GameWorld.DebugLog("    扣除货币: delMoneyType=%s,delMoneyPer=%s,nowMoney=%s,delMoney=%s" % (delMoneyType, delMoneyPer, nowMoney, delMoney))        
+        PlayerControl.PayMoney(curPlayer, delMoneyType, delMoney, "LeaveFamily")
     FBLogic.OnLeaveFamily(curPlayer, tick)
     return
 
@@ -645,12 +668,43 @@
         
     return
 
+def CheckInJoinCD(curPlayer):
+    ## 检查是否加入仙盟CD中
+    leaveFamilyTime = PlayerControl.GetLeaveFamilyTimeEx(curPlayer)
+    if not leaveFamilyTime:
+        return False
+    
+    leaveCnt, kickedCnt, lastVoluntarily = PlayerControl.GetLeaveFamilyInfo(curPlayer)
+    joinCDMinute = 0
+    if lastVoluntarily:
+        if leaveCnt <= 0:
+            return False
+        joinCDMinuteList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 1)
+        if joinCDMinuteList:
+            joinCDMinute = joinCDMinuteList[leaveCnt - 1] if len(joinCDMinuteList) >= leaveCnt else joinCDMinuteList[-1]
+    else:
+        if kickedCnt <= 0:
+            return False
+        joinCDMinuteList = IpyGameDataPY.GetFuncEvalCfg("FamilyLeave", 2)
+        if joinCDMinuteList:
+            joinCDMinute = joinCDMinuteList[kickedCnt - 1] if len(joinCDMinuteList) >= kickedCnt else joinCDMinuteList[-1]
+    if joinCDMinute:
+        cdTimes = joinCDMinute * 60
+        passTimes = int(time.time()) - leaveFamilyTime
+        if passTimes < cdTimes:
+            GameWorld.DebugLog("加入仙盟CD中: leaveCnt=%s,kickedCnt=%s,lastVoluntarily=%s,leaveFamilyTime=%s(%s),passTimes=%s < %s" 
+                   % (leaveCnt, kickedCnt, lastVoluntarily, leaveFamilyTime, GameWorld.ChangeTimeNumToStr(leaveFamilyTime), passTimes, cdTimes))
+            return True
+    return False
+
 def AutoJoinFamily(curPlayer):
     if curPlayer.GetFamilyID():
         return
     playerID = curPlayer.GetPlayerID()
-    playerLV = curPlayer.GetLV()
-    GameWorld.DebugLog("玩家一键自动加入家族! playerLV=%s" % playerLV, playerID)
+    realmLV = curPlayer.GetOfficialRank()
+    GameWorld.DebugLog("玩家一键自动加入家族! realmLV=%s" % realmLV, playerID)
+    if CheckInJoinCD(curPlayer):
+        return
     
     familyMgr = DBDataMgr.GetFamilyMgr()
     indexList = range(familyMgr.GetCount())
@@ -661,8 +715,8 @@
             continue
         familyID = family.GetID()
         lvMin = family.GetJoinLVMin()
-        if lvMin and playerLV < lvMin:
-            GameWorld.DebugLog("    等级不足的不处理! familyID=%s,lvMin=%s" % (familyID, lvMin), playerID)
+        if lvMin and realmLV < lvMin:
+            GameWorld.DebugLog("    官职不足的不处理! familyID=%s,lvMin=%s" % (familyID, lvMin), playerID)
             continue
         if family.GetJoinReview():
             GameWorld.DebugLog("    需要审核的不处理! familyID=%s" % familyID, playerID)
@@ -694,6 +748,8 @@
 
 def RequestJoinTagFamily(curPlayer, familyID):
     ## 申请加入
+    if CheckInJoinCD(curPlayer):
+        return
     playerID = curPlayer.GetPlayerID()
     if curPlayer.GetFamilyID():
         GameWorld.DebugLog('已经有仙盟不能再申请加入! familyID=%s' % curPlayer.GetFamilyID(), playerID)
@@ -714,8 +770,8 @@
         return
     
     lvMin = tagFamily.GetJoinLVMin()
-    if curPlayer.GetLV() < lvMin:
-        GameWorld.DebugLog('等级未达到该仙盟加入最低等级限制! lv=%s < %s' % (curPlayer.GetLV(), lvMin), playerID)
+    if curPlayer.GetOfficialRank() < lvMin:
+        GameWorld.DebugLog('官职未达到该仙盟加入最低限制! realmLV=%s < %s' % (curPlayer.GetOfficialRank(), lvMin), playerID)
         return
     
     # 需要审核,满员后端不限制申请,由前端自行决定是否可申请
@@ -912,7 +968,7 @@
 def OnChangeFamilyJoin(index, clientData, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
     joinReview = clientData.JoinReview
-    joinLVMin = clientData.JoinLVMin
+    joinLVMin = clientData.JoinLVMin # 官职
     
     playerID = curPlayer.GetPlayerID()
     familyID = curPlayer.GetFamilyID()
@@ -1164,7 +1220,7 @@
     #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)
+    MapServer_FamilyRefresh(curPlayer, 0, 1)
     
     if family.GetCount() == 0:
         #玩家离开后, 家族没有人了 , 删除这个家族
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_SetLeaveFamilyTime.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_SetLeaveFamilyTime.py
deleted file mode 100644
index 1463978..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_SetLeaveFamilyTime.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#---------------------------------------------------------------------
-#
-#---------------------------------------------------------------------
-##@package GY_Query_SetLeaveFamilyTime
-# @todo: 设置玩家主动退出仙盟时间(<100代表退出次数)
-#
-# @author: xdh
-# @date 2018-12-04
-# @version 1.0
-#
-# @note: 
-#---------------------------------------------------------------------
-"""Version = 2018-12-04 15:30"""
-#---------------------------------------------------------------------
-import GameWorld
-#---------------------------------------------------------------------
-#全局变量
-#---------------------------------------------------------------------
-
-#---------------------------------------------------------------------
-#逻辑实现
-## 请求逻辑
-#  @param query_Type 请求类型
-#  @param query_ID 请求的玩家ID
-#  @param packCMDList 发包命令 [GM账户]
-#  @param tick 当前时间
-#  @return '' or None
-#  @remarks 函数详细说明.
-def DoLogic(query_Type, query_ID, packCMDList, tick):
-    return
-#---------------------------------------------------------------------
-#执行结果
-## 执行结果
-#  @param curPlayer 发出请求的玩家
-#  @param callFunName 功能名称
-#  @param funResult 查询的结果
-#  @param tick 当前时间
-#  @return None
-#  @remarks 函数详细说明.
-def DoResult(curPlayer, callFunName, funResult, tick):
-    value = GameWorld.ToIntDef(funResult, None)
-    if value == None:
-        return
-    curPlayer.SetExAttr12(value)
-    return

--
Gitblit v1.8.0