6805 【后端】【2.0】副本前端化(优化前端本状态逻辑,召唤木桩增加可指定血量,增加可设置玩家血量)
16个文件已修改
337 ■■■■ 已修改文件
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SummonNPC.py 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_FairyTreasure.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_PersonalBoss.py 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMagicWeapon.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -14514,6 +14514,58 @@
#------------------------------------------------------
# B4 0E 设置玩家自身血量 #tagCMSetRoleHP
class  tagCMSetRoleHP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("HP", c_int),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB4
        self.SubCmd = 0x0E
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB4
        self.SubCmd = 0x0E
        self.HP = 0
        return
    def GetLength(self):
        return sizeof(tagCMSetRoleHP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B4 0E 设置玩家自身血量 //tagCMSetRoleHP:
                                Cmd:%s,
                                SubCmd:%s,
                                HP:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.HP
                                )
        return DumpString
m_NAtagCMSetRoleHP=tagCMSetRoleHP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMSetRoleHP.Cmd,m_NAtagCMSetRoleHP.SubCmd))] = m_NAtagCMSetRoleHP
#------------------------------------------------------
# B4 0C 召唤私有专属木桩怪 #tagCMSummonPriWoodPile
class  tagCMSummonPriWoodPile(Structure):
@@ -14523,6 +14575,8 @@
                  ("SubCmd", c_ubyte),
                  ("NPCID", c_int),    
                  ("Count", c_ubyte),    #默认1个,最多5个
                  ("HP", c_int),    #默认0取最大值,其中一个血量数值大于0则用指定血量
                  ("HPEx", c_int),    #默认0取最大值,其中一个血量数值大于0则用指定血量
                  ]
    def __init__(self):
@@ -14541,6 +14595,8 @@
        self.SubCmd = 0x0C
        self.NPCID = 0
        self.Count = 0
        self.HP = 0
        self.HPEx = 0
        return
    def GetLength(self):
@@ -14554,13 +14610,17 @@
                                Cmd:%s,
                                SubCmd:%s,
                                NPCID:%d,
                                Count:%d
                                Count:%d,
                                HP:%d,
                                HPEx:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.NPCID,
                                self.Count
                                self.Count,
                                self.HP,
                                self.HPEx
                                )
        return DumpString
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -375,7 +375,7 @@
Writer = hxp
Releaser = hxp
RegType = 0
RegisterPackCount = 21
RegisterPackCount = 22
PacketCMD_1 = 0xA5
PacketSubCMD_1 = 0x04
@@ -461,6 +461,10 @@
PacketSubCMD_21=0x07
PacketCallFunc_21=OnResetAttrPoint
PacketCMD_22=0xB4
PacketSubCMD_22=0x0E
PacketCallFunc_22=OnSetRoleHP
;购买相关的
[BuySomething]
ScriptName = Event\EventSrc\Operate_PlayerBuyZhenQi.py
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3069,8 +3069,6 @@
Def_Player_RefreshAttrByBuff = "PlayerAttrByBuff"   # 玩家属性刷新功能属性缓存,便于buff刷新计算, 间隔刷新
Def_Player_HadRefreshAttr = "HadRefreshAttr"   # 玩家在本地图是否刷新过属性
Def_PlayerKey_ClientCustomScene = "ClientCustomScene"     # 客户端自定义场景状态
Def_PlayerKey_ClientCustomSceneMapID = "ClientCustomSceneMapID"     # 客户端自定义场景地图ID
Def_PlayerKey_ClientCustomSceneLineID = "ClientCustomSceneLineID"     # 客户端自定义场景功能线路ID
Def_PlayerKey_ChangeMapID = "ChangeMapID"     # 请求切换的地图ID
Def_PlayerKey_ResetFBLinePosX = "ResetFBLinePosX"     # 请求切换副本多合一地图功能线路ID
Def_PlayerKey_ResetFBLinePosY = "ResetFBLinePosY"     # 请求切换副本多合一地图功能线路ID
@@ -3377,7 +3375,7 @@
Def_Player_Dict_ReqFBMissionID = "ReqFBMissionID" # 请求进入副本的任务ID
Def_Player_Dict_ReqFBMissionType = "ReqFBMissionType" # 请求进入副本的任务类型
Def_Player_Dict_PlayerFBStar_MapId = "FBStar_%s_%s"  # 副本星级星级信息, 参数为[mapID, key编号], 按位存储每个lineID对应的星级
Def_Player_Dict_CustomSceneStartTime = "ClientFBStartTime_%s_%s"  # 前端自定义场景开始time, 参数(mapID, lineID), 0-无,2-已结束,其他-time值
Def_Player_Dict_CustomMapStep = "CustomMapStep_%s_%s"  # 前端自定义场景阶段, 参数(mapID, lineID),对应 CustomMapStep_Fight ...
Def_Player_Dict_EnterFbCntDay = "EnterFbCntDay_%s"  # 今日进入副本次数, 参数为副本ID
Def_Player_Dict_BuyFbCntDay = "BuyFbCntDay_%s" # 今日购买副本进入次数, 参数为副本ID
Def_Player_Dict_RecoverFbCnt = "RecoverFbCnt_%s"  # 今日找回的副本次数, 参数为副本ID
@@ -4907,9 +4905,8 @@
##==================================================================================================
# 前端自定义场景状态
CustomSceneState_None = 0 # 无
CustomSceneState_Fight = 1 # 战斗进行中
CustomSceneState_Over = 2 # 已结束
CustomMapStep_Over = 0 # 没有或已结束
CustomMapStep_Fight = 1 # 战斗进行中
# 副本参与类型
FB_JoinType = (
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -14514,6 +14514,58 @@
#------------------------------------------------------
# B4 0E 设置玩家自身血量 #tagCMSetRoleHP
class  tagCMSetRoleHP(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("HP", c_int),
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB4
        self.SubCmd = 0x0E
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB4
        self.SubCmd = 0x0E
        self.HP = 0
        return
    def GetLength(self):
        return sizeof(tagCMSetRoleHP)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B4 0E 设置玩家自身血量 //tagCMSetRoleHP:
                                Cmd:%s,
                                SubCmd:%s,
                                HP:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.HP
                                )
        return DumpString
m_NAtagCMSetRoleHP=tagCMSetRoleHP()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMSetRoleHP.Cmd,m_NAtagCMSetRoleHP.SubCmd))] = m_NAtagCMSetRoleHP
#------------------------------------------------------
# B4 0C 召唤私有专属木桩怪 #tagCMSummonPriWoodPile
class  tagCMSummonPriWoodPile(Structure):
@@ -14523,6 +14575,8 @@
                  ("SubCmd", c_ubyte),
                  ("NPCID", c_int),    
                  ("Count", c_ubyte),    #默认1个,最多5个
                  ("HP", c_int),    #默认0取最大值,其中一个血量数值大于0则用指定血量
                  ("HPEx", c_int),    #默认0取最大值,其中一个血量数值大于0则用指定血量
                  ]
    def __init__(self):
@@ -14541,6 +14595,8 @@
        self.SubCmd = 0x0C
        self.NPCID = 0
        self.Count = 0
        self.HP = 0
        self.HPEx = 0
        return
    def GetLength(self):
@@ -14554,13 +14610,17 @@
                                Cmd:%s,
                                SubCmd:%s,
                                NPCID:%d,
                                Count:%d
                                Count:%d,
                                HP:%d,
                                HPEx:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.NPCID,
                                self.Count
                                self.Count,
                                self.HP,
                                self.HPEx
                                )
        return DumpString
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SummonNPC.py
@@ -17,6 +17,8 @@
import GameWorld
import NPCCommon
import PlayerFB
import PlayerControl
import ShareDefine
#
#逻辑实现
@@ -29,7 +31,7 @@
    #输入命令格式错误
    if not paramList:
        GameWorld.DebugAnswer(curPlayer, "SummonNPC npcID 个数")
        GameWorld.DebugAnswer(curPlayer, "SummonNPC npcID 个数 前端场景ID lineID")
        GameWorld.DebugAnswer(curPlayer, "SummonNPC npcID 个数 前端场景ID lineID 血量")
        return
    
    #NPC对象ID
@@ -44,18 +46,22 @@
    if npcType in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:
        mapID = paramList[2] if len(paramList) > 2 else 0
        lineID = paramList[3] if len(paramList) > 3 else 0
        setHP = paramList[4] if len(paramList) > 4 else 0
        if not mapID:
            GameWorld.DebugAnswer(curPlayer, "木桩怪必须指定地图ID才能召唤!")
            return
        
        sceneMapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
        sceneLineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
        if mapID != sceneMapID or lineID != sceneLineID:
            if sceneMapID:
        customMapID = PlayerControl.GetCustomMapID(curPlayer)
        customLineID = PlayerControl.GetCustomLineID(curPlayer)
        if mapID != customMapID or lineID != customLineID:
            if customMapID:
                PlayerFB.DoExitCustomScene(curPlayer)
            tick = GameWorld.GetGameWorld().GetTick()
            PlayerFB.DoEnterCustomScene(curPlayer, mapID, lineID, tick)
        NPCCommon.SummonPriWoodPile(curPlayer, npcID, npcCount)
        hp = setHP % ShareDefine.Def_PerPointValue
        hpEx = setHP / ShareDefine.Def_PerPointValue
        NPCCommon.SummonPriWoodPile(curPlayer, npcID, npcCount, hp, hpEx)
        return
    
    for _ in range(npcCount):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBLogic.py
@@ -272,8 +272,8 @@
#  @return None
#  @remarks 函数详细说明.
def DoFB_Player_KillNPC(curPlayer , curNPC , tick):
    mapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
    lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    if mapID:
        DoCustomScene_Player_KillNPC(curPlayer, curNPC, mapID, lineID)
        return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
@@ -473,36 +473,13 @@
    GameWorld.GetGameFB().SetPlayerGameFBDict(curPlayer.GetID(), ChConfig.FBPlayerDict_IsDelTicket, delSign)
    return
def SetCustomSceneStart(curPlayer, mapID, lineID):
    ''' 设置前端自定义场景副本开始时间
            某些自定义场景进入可能需要处理某些逻辑,比如扣门票、设置某些状态、完成成就等,这些逻辑在单次进入只能触发一次
            需要记录一个开始状态,只在设置成功的时候进行处理这些逻辑,防止断线重连或重登重新进入自定义场景时,重复执行逻辑
            该状态设置了一个有效期,暂时设定为15分钟,未完成场景有效期内重复进入不会重复触发
            做超时是为了防止玩家没有正常结束场景导致未来的某个时间再次进入场景时无法正常触发进入需要额外处理的逻辑
            需根据副本结束时机配置函数 SetCustomSceneOver 设置结束状态
    @return: 设置成功返回True
    '''
    if GetCustomSceneState(curPlayer, mapID, lineID) == ChConfig.CustomSceneState_Fight:
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_CustomSceneStartTime % (mapID, lineID), int(time.time()))
    return True
def GetCustomSceneState(curPlayer, mapID, lineID):
    '''获取前端自定义场景状态
    @return: 0-无,1-进行中,2-已结束
    '''
    startTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_CustomSceneStartTime % (mapID, lineID))
    if not startTime:
        return ChConfig.CustomSceneState_None
    if startTime == ChConfig.CustomSceneState_Over:
        return ChConfig.CustomSceneState_Over
    # 保留15分钟
    curTime = int(time.time())
    return ChConfig.CustomSceneState_Fight if curTime - startTime < 15 * 60 else ChConfig.CustomSceneState_None
def SetCustomSceneOver(curPlayer, mapID, lineID):
    ## 设置前端自定义场景副本结束
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_CustomSceneStartTime % (mapID, lineID), ChConfig.CustomSceneState_Over)
## 自定义场景阶段
def GetCustomMapStep(curPlayer, mapID, lineID):
    return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_CustomMapStep % (mapID, lineID))
def SetCustomMapStep(curPlayer, mapID, lineID, step):
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_CustomMapStep % (mapID, lineID), step)
    if step == ChConfig.CustomMapStep_Over:
        PlayerControl.SetCustomMap(curPlayer, 0, 0)
    return
def GetCurSingleFBPlayer():
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py
@@ -299,6 +299,7 @@
        GameWorld.DebugLog("    非寻访中,不能掉落!", playerID)
        return
    PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, funcLineID, PlayerFairyDomain.FDEventState_Visited)
    PlayerControl.SetCustomMap(curPlayer, 0, 0)
    
    isOwner = True
    giveItemList = __GetDemonKingPrizeItemList(curPlayer, mapID, funcLineID, eventID, isOwner)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py
@@ -233,13 +233,13 @@
def GetGrasslandMapID(curPlayer):
    grasslandMapIDList = [ChConfig.Def_FBMapID_CrossGrasslandLing, ChConfig.Def_FBMapID_CrossGrasslandXian]
    crossMapID = PlayerControl.GetCrossMapID(curPlayer)
    clientCustomSceneMapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
    customMapID = PlayerControl.GetCustomMapID(curPlayer)
    if crossMapID in grasslandMapIDList:
        mapID = crossMapID
        lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ReqCrossFBFuncLine)
    elif clientCustomSceneMapID in grasslandMapIDList:
        mapID = clientCustomSceneMapID
        lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
    elif customMapID in grasslandMapIDList:
        mapID = customMapID
        lineID = PlayerControl.GetCustomLineID(curPlayer)
    else:
        return 0, 0
    return mapID, lineID
@@ -284,6 +284,7 @@
            return
        
    PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visited)
    PlayerControl.SetCustomMap(curPlayer, 0, 0)
    GameWorld.DebugLog("设置草园已完成!mapID=%s, lineID=%s" % (mapID, lineID))
    
    # 通知结算
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_FairyTreasure.py
@@ -21,6 +21,7 @@
import GameWorld
import IpyGameDataPY
import PlayerFairyDomain
import PlayerControl
import ItemCommon
import NPCCommon
import ChConfig
@@ -46,6 +47,7 @@
    ipyData = IpyGameDataPY.GetIpyGameDataByCondition('FairyDomain', {'MapID':ChConfig.Def_FBMapID_FairyTreasure, 'LineID':lineID})
    fdeventID = ipyData.GetID()
    PlayerFairyDomain.SetFairyDomainEventState(curPlayer, fdeventID, PlayerFairyDomain.FDEventState_Visited)
    PlayerControl.SetCustomMap(curPlayer, 0, 0)
    
    giveItemList = PlayerFairyDomain.GetFairyAppointAward(curPlayer, fdeventID)
    if not giveItemList:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_PersonalBoss.py
@@ -30,7 +30,7 @@
## 是否需要做进入副本通用检查条件逻辑,默认需要检查
def OnNeedCheckCanEnterFBComm(curPlayer, mapID, lineID):
    ## 进行中的不需要重复检查,防止断线重连被禁止进入
    if FBCommon.GetCustomSceneState(curPlayer, mapID, lineID) == ChConfig.CustomSceneState_Fight:
    if FBCommon.GetCustomMapStep(curPlayer, mapID, lineID) == ChConfig.CustomMapStep_Fight:
        GameWorld.DebugLog("VIPBoss已经在进行中,本次进入不需要重新检查!")
        return False
    return True
@@ -38,7 +38,8 @@
## 客户端进入自定义场景
def OnEnterCustomScene(curPlayer, mapID, lineID):
    
    if FBCommon.SetCustomSceneStart(curPlayer, mapID, lineID):
    if FBCommon.GetCustomMapStep(curPlayer, mapID, lineID) != ChConfig.CustomMapStep_Fight:
        FBCommon.SetCustomMapStep(curPlayer, mapID, lineID, ChConfig.CustomMapStep_Fight)
        FBCommon.DelFBEnterTicket(curPlayer, ChConfig.Def_FBMapID_PersonalBoss)
        #增加进入次数
        FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_PersonalBoss)
@@ -58,9 +59,9 @@
    if npcID != bossID:
        return
    
    if FBCommon.GetCustomSceneState(curPlayer, mapID, lineID) != ChConfig.CustomSceneState_Fight:
    if FBCommon.GetCustomMapStep(curPlayer, mapID, lineID) != ChConfig.CustomMapStep_Fight:
        return
    FBCommon.SetCustomSceneOver(curPlayer, mapID, lineID)
    FBCommon.SetCustomMapStep(curPlayer, mapID, lineID, ChConfig.CustomMapStep_Over)
    
    npcCountDict = {bossID:1}
    dropItemMapInfo = [0, 0]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -621,8 +621,8 @@
def DoGiveItemByVirtualDrop(curPlayer, giveItemList, npcID, dropPosX=0, dropPosY=0, isDropDisperse=True, mailTypeKey="ItemNoPickUp"):
    ## 给物品并且做假掉落表现,直接先堆叠给物品,再拆开做虚假掉落表现
    
    mapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
    lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    if not mapID:
        mapID = GameWorld.GetGameWorld().GetMapID()
        
@@ -2024,15 +2024,19 @@
#    tagHead        Head;
#    DWORD        NPCID;
#    BYTE        Count;    //默认1个,最多5个
#    DWORD        HP;    //默认0取最大值,其中一个血量数值大于0则用指定血量
#    DWORD        HPEx;    //默认0取最大值,其中一个血量数值大于0则用指定血量
#};
def OnSummonPriWoodPile(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    npcID = clientData.NPCID
    count = clientData.Count
    SummonPriWoodPile(curPlayer, npcID, count)
    hp = clientData.HP
    hpEx = clientData.HPEx
    SummonPriWoodPile(curPlayer, npcID, count, hp, hpEx)
    return
def SummonPriWoodPile(curPlayer, npcID, count):
def SummonPriWoodPile(curPlayer, npcID, count, hp=0, hpEx=0):
    ''' 召唤私有专属木桩怪
    '''
    
@@ -2040,12 +2044,15 @@
        GameWorld.DebugLog("玩家当前不是在自定义场景中,不允许招木桩!")
        return
    
    mapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
    lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    if mapID:
        if not FBLogic.OnCanSummonPriWoodPile(curPlayer, mapID, lineID, npcID, count):
            GameWorld.ErrLog("无法召唤木桩怪!mapID=%s,lineID=%s,npcID=%s,count=%s" % (mapID, lineID, npcID, count))
            return
    if count != 1:
        hp, hpEx = 0, 0 # 指定血量的暂仅适用于单只的
        
    maxCount = 10
    nowCount = 0
@@ -2064,8 +2071,8 @@
            nowCount += 1
            
    summonCount = min(count, maxCount - nowCount)
    #GameWorld.DebugLog("召唤: count=%s,maxCount=%s,nowCount=%s,summonCount=%s"
    #                   % (count, maxCount, nowCount, summonCount))
    #GameWorld.DebugLog("召唤: count=%s,maxCount=%s,nowCount=%s,summonCount=%s,hp=%s,hpEx=%s"
    #                   % (count, maxCount, nowCount, summonCount, hp, hpEx))
    if summonCount <= 0:
        return
    
@@ -2085,26 +2092,29 @@
        #玩家周围随机出生点
        #技能召唤坐标 ChConfig.Def_SummonAppearDist
        summonPos = GameMap.GetEmptyPlaceInArea(curPlayer.GetPosX(), curPlayer.GetPosY(), 3)
        summonNPC.Reborn(summonPos.GetPosX(), summonPos.GetPosY())
        if not curPlayer.GetSight():
            summonNPCAppear = ChNetSendPack.tagPlayerSummonNPCAppear()
            summonNPCAppear.Clear()
            summonNPCAppear.PlayerID = curPlayer.GetPlayerID()
            summonNPCAppear.ObjID = summonNPC.GetID()
            summonNPCAppear.NPCID = summonNPC.GetNPCID()
            summonNPCAppear.PosX = summonNPC.GetPosX()
            summonNPCAppear.PosY = summonNPC.GetPosY()
            summonNPCAppear.HP = summonNPC.GetHP()
            summonNPCAppear.HPEx = summonNPC.GetHPEx()
            summonNPCAppear.MaxHP = summonNPC.GetMaxHP()
            summonNPCAppear.MaxHPEx = summonNPC.GetMaxHPEx()
            summonNPCAppear.Speed = summonNPC.GetSpeed()
            summonNPCAppear.LV = GetNPCLV(summonNPC)
            summonNPCAppear.OwnerName = curPlayer.GetPlayerName()
            summonNPCAppear.OwnerNameLen = len(summonNPCAppear.OwnerName)
            NetPackCommon.SendFakePack(curPlayer, summonNPCAppear)
        summonNPC.Reborn(summonPos.GetPosX(), summonPos.GetPosY(), False)
        if hp or hpEx:
            summonNPC.SetHP(hp)
            summonNPC.SetHPEx(hpEx)
            
        #if not curPlayer.GetSight():
        summonNPCAppear = ChNetSendPack.tagPlayerSummonNPCAppear()
        summonNPCAppear.Clear()
        summonNPCAppear.PlayerID = curPlayer.GetPlayerID()
        summonNPCAppear.ObjID = summonNPC.GetID()
        summonNPCAppear.NPCID = summonNPC.GetNPCID()
        summonNPCAppear.PosX = summonNPC.GetPosX()
        summonNPCAppear.PosY = summonNPC.GetPosY()
        summonNPCAppear.HP = summonNPC.GetHP()
        summonNPCAppear.HPEx = summonNPC.GetHPEx()
        summonNPCAppear.MaxHP = summonNPC.GetMaxHP()
        summonNPCAppear.MaxHPEx = summonNPC.GetMaxHPEx()
        summonNPCAppear.Speed = summonNPC.GetSpeed()
        summonNPCAppear.LV = GetNPCLV(summonNPC)
        summonNPCAppear.OwnerName = curPlayer.GetPlayerName()
        summonNPCAppear.OwnerNameLen = len(summonNPCAppear.OwnerName)
        NetPackCommon.SendFakePack(curPlayer, summonNPCAppear)
    return
def ClearPriWoodPile(curPlayer):
@@ -5862,12 +5872,12 @@
    if not curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        GameWorld.DebugLog("非自定义场景中,无法获取定义采集奖励!")
        return
    mapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
    lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    GameWorld.DebugLog("前端场景采集: mapID=%s,lineID=%s,npcID=%s" % (mapID, lineID, npcID))
    
    if mapID:
        #if FBCommon.GetCustomSceneState(curPlayer, mapID, lineID) != ChConfig.CustomSceneState_Fight:
        #if FBCommon.GetCustomMapStep(curPlayer, mapID, lineID) != ChConfig.CustomMapStep_Fight:
        #    return
        FBLogic.OnCustomSceneCollectOK(curPlayer, mapID, lineID, npcID)
                
@@ -6419,7 +6429,7 @@
    if not dropItemList:
        return
    
    mapID = attackPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
    mapID = PlayerControl.GetCustomMapID(attackPlayer)
    if mapID:
        DoGiveItemByVirtualDrop(attackPlayer, dropItemList, npcID)
        GameLogic_CrossGrassland.RecordGrasslandAward(attackPlayer, dropItemList)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -5819,3 +5819,19 @@
    sendPack.NPCID = npcID
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
#// B4 0E 设置玩家自身血量 #tagCMSetRoleHP
#
#struct    tagCMSetRoleHP
#{
#    tagHead        Head;
#    DWORD        HP;
#};
def OnSetRoleHP(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    if not curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        GameWorld.DebugLog("玩家当前不是在自定义场景中,不允许设置自身血量!")
        return
    setHP = max(1, min(clientData.HP, curPlayer.GetMaxHP()))
    curPlayer.SetHP(setHP)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -5805,6 +5805,16 @@
        CrossPlayerData.ClearCrossSyncDataCache(curPlayer)
    return
## 前端自定义场景
def GetCustomMapID(curPlayer): return curPlayer.GetExAttr14() / 1000
def GetCustomLineID(curPlayer): return curPlayer.GetExAttr14() % 1000
## 自定义场景后端判断已结算后需直接重置为0,防止前端没有退出场景直接下线导致数据没有重置,可能引发可以重复进
def SetCustomMap(curPlayer, mapID, lineID):
    value = mapID * 1000 + lineID
    if value != curPlayer.GetExAttr14():
        curPlayer.SetExAttr14(value, False, True)
    return
## 铜钱点, 支持铜钱超20亿
def GetSilver(curPlayer): return curPlayer.GetExAttr6() * ChConfig.Def_PerPointValue + curPlayer.GetSilver()
def SetSilver(curPlayer, totalSilver):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py
@@ -493,6 +493,7 @@
        if PlayerControl.CheckMoveToFB(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData, tick) != ShareDefine.EntFBAskRet_OK:
            resultPack.Result = 0
            NetPackCommon.SendFakePack(curPlayer, resultPack)
            PlayerControl.SetCustomMap(curPlayer, 0, 0)
            return
    
    curPlayer.SetCanAttack(False)
@@ -503,8 +504,7 @@
        curPet.SetVisible(False)
        
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 1) # 由于前端不一定有发mapID,所以这里额外记录这个状态,不能直接用mapID判断
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneMapID, mapID)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneLineID, lineID)
    PlayerControl.SetCustomMap(curPlayer, mapID, lineID)
    GameWorld.Log("玩家开始自定义场景!mapID=%s,lineID=%s" % (mapID, lineID), curPlayer.GetPlayerID())
    if mapID:
        FBLogic.OnEnterCustomScene(curPlayer, mapID, lineID)
@@ -525,13 +525,12 @@
    curPet = curPlayer.GetPetMgr().GetFightPet()
    if curPet:
        curPet.SetVisible(True)
    mapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
    lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 0)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneMapID, 0)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneLineID, 0)
    if mapID and curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_CustomSceneStartTime % (mapID, lineID)) == ChConfig.CustomSceneState_Over:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_CustomSceneStartTime % (mapID, lineID), ChConfig.CustomSceneState_None)
    PlayerControl.SetCustomMap(curPlayer, 0, 0)
    if mapID and FBCommon.GetCustomMapStep(curPlayer, mapID, lineID) != ChConfig.CustomMapStep_Over:
        FBCommon.SetCustomMapStep(curPlayer, mapID, lineID, ChConfig.CustomMapStep_Over)
    NPCCommon.ClearPriWoodPile(curPlayer)
    GameWorld.Log("玩家退出自定义场景!", curPlayer.GetPlayerID())
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerMagicWeapon.py
@@ -340,6 +340,7 @@
                return
    elif mwID == 101: #定海神针特殊 可直接获得
        FBCommon.Notify_FB_Over(curPlayer, {FBCommon.Over_dataMapID:ChConfig.Def_FBMapID_MagicWeapon,FBCommon.Over_isPass:1})
        PlayerControl.SetCustomMap(curPlayer, 0, 0)
    else:
        return
    DoActiveMW(curPlayer, mwID)