hxp
2022-08-23 5fa02b1adbf1900358ab44a915cd9e841dcdf45f
9687 【后端】【越南】【主干】【BT7】野外根据境界动态刷怪

# Conflicts:
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
# ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
14个文件已修改
1个文件已添加
635 ■■■■■ 已修改文件
PySysDB/PySysDBPY.h 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestRunner.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItem.py 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py 125 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCRealmRefresh.py 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerVip.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -496,6 +496,27 @@
    DWORD        SuppressFightPower;    //推荐/压制战力
};
//成长型境界怪物表
struct tagNPCRealmStrengthen
{
    DWORD        _NPCID;    //NPCID
    BYTE        _RealmDifficulty;    //境界难度
    DWORD        MapID;
    DWORD        LV;    //NPC等级
    DWORD        Exp;//基础经验
    WORD        MaxDrapLV;//玩家最大可掉落等级
    BYTE        EquipClassLV;    //掉落装备阶
    DWORD        DropMoneyMin;//最小金币
    DWORD        DropMoneyMax;//最大金币
    WORD        LowLV;    // 推荐最低等级
    WORD        HighestLV;    // 推荐最高等级
    DWORD        Defense;    // 推荐防御
    DWORD        MDef;    // 标准击杀时间/毫秒
    DWORD        FireDef;    // 脱机挂经验计算战力
    DWORD        SP;    // SP
};
//成长型怪物参数公式表
struct tagNPCStrengthen
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -6550,6 +6550,58 @@
#------------------------------------------------------
# A2 35 选择境界难度层级 #tagCMSelectRealmDifficulty
class  tagCMSelectRealmDifficulty(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("RealmDifficulty", c_ubyte),    #境界难度 = 100 + 所选境界等级,如境界13,则发113
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA2
        self.SubCmd = 0x35
        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 = 0xA2
        self.SubCmd = 0x35
        self.RealmDifficulty = 0
        return
    def GetLength(self):
        return sizeof(tagCMSelectRealmDifficulty)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A2 35 选择境界难度层级 //tagCMSelectRealmDifficulty:
                                Cmd:%s,
                                SubCmd:%s,
                                RealmDifficulty:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.RealmDifficulty
                                )
        return DumpString
m_NAtagCMSelectRealmDifficulty=tagCMSelectRealmDifficulty()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMSelectRealmDifficulty.Cmd,m_NAtagCMSelectRealmDifficulty.SubCmd))] = m_NAtagCMSelectRealmDifficulty
#------------------------------------------------------
# A2 30 设置聊天气泡框 #tagCMSetChatBubbleBox
class  tagCMSetChatBubbleBox(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3045,6 +3045,7 @@
Def_NPC_Dict_FromRefreshValue = 'FromRefreshValue'
#召唤地图NPC的玩家ID
Def_NPC_Dict_SummonMapNPCPlayerID = 'SummonMapNPCPlayerID'
Def_NPC_Dict_SummonRefreshID = 'SummonRefreshID'
Def_NPC_Dict_PriWoodPilePlayerID = 'PriWoodPilePlayerID'
#NPC技能已使用次数
Def_NPC_Dict_SkillUseCnt = 'NPCSkillUseCnt_%s' # 参数skillTypeID
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -6550,6 +6550,58 @@
#------------------------------------------------------
# A2 35 选择境界难度层级 #tagCMSelectRealmDifficulty
class  tagCMSelectRealmDifficulty(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("RealmDifficulty", c_ubyte),    #境界难度 = 100 + 所选境界等级,如境界13,则发113
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xA2
        self.SubCmd = 0x35
        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 = 0xA2
        self.SubCmd = 0x35
        self.RealmDifficulty = 0
        return
    def GetLength(self):
        return sizeof(tagCMSelectRealmDifficulty)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// A2 35 选择境界难度层级 //tagCMSelectRealmDifficulty:
                                Cmd:%s,
                                SubCmd:%s,
                                RealmDifficulty:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.RealmDifficulty
                                )
        return DumpString
m_NAtagCMSelectRealmDifficulty=tagCMSelectRealmDifficulty()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMSelectRealmDifficulty.Cmd,m_NAtagCMSelectRealmDifficulty.SubCmd))] = m_NAtagCMSelectRealmDifficulty
#------------------------------------------------------
# A2 30 设置聊天气泡框 #tagCMSetChatBubbleBox
class  tagCMSetChatBubbleBox(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Event/EventSrc/QuestRunner.py
@@ -3848,7 +3848,8 @@
    
    effIndex = GameWorld.ToIntDef((curActionNode.GetAttribute("effIndex")), 0)
    
    curMapItem = ChItem.AddMapDropItem(dropPos.GetPosX(), dropPos.GetPosY(), curItem, effIndex)
    sightLevel = PlayerControl.GetMapRealmDifficulty(curPlayer)
    curMapItem = ChItem.AddMapDropItem(dropPos.GetPosX(), dropPos.GetPosY(), curItem, effIndex, sightLevel=sightLevel)
    curMapItem.SetOwnerType(ChConfig.Def_NPCHurtTypePlayer)
    curMapItem.SetOwnerID(killPlayerID)
            
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/MakeItem.py
@@ -23,6 +23,7 @@
import GameWorld
import ChConfig
import ChItem
import PlayerControl
## GM命令执行入口
#  @param curPlayer 当前玩家
@@ -53,6 +54,7 @@
    doCount = 0
    dropCount = 0
    index = 0
    sightLevel = PlayerControl.GetMapRealmDifficulty(curPlayer)
    for posX, posY in ChConfig.Def_DropItemAreaMatrix:
        doCount += 1
        resultX = dropPosX + posX
@@ -72,7 +74,7 @@
            continue
        
        # 在地上添加物品
        ChItem.AddMapDropItem(resultX, resultY, curItem, ownerInfo=[dropType, ownerID, specOwnerIDList])
        ChItem.AddMapDropItem(resultX, resultY, curItem, ownerInfo=[dropType, ownerID, specOwnerIDList], sightLevel=sightLevel)
        dropCount += 1
    
    GameWorld.DebugAnswer(curPlayer, "检测坐标数:%s 掉落数: %s" % (doCount, dropCount))
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/GameWorldProcess.py
@@ -50,6 +50,7 @@
import PyGameData
import PlayerTeam
import GameMap
import NPCRealmRefresh
#---------------------------------------------------------------------
## 副本开启
#  @param gameWorld IPY_GameWorld
@@ -558,6 +559,7 @@
    
    #地图自定义随机刷怪
    NPCCustomRefresh.ProcessMapRandomRefreshNPC(gameWorld, tick)
    NPCRealmRefresh.ProcessRealmNPCRefresh(gameWorld, tick)
    return
## 通知RouteServer 消息
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -412,6 +412,24 @@
                        ("DWORD", "SuppressFightPower", 0),
                        ),
                "NPCRealmStrengthen":(
                        ("DWORD", "NPCID", 1),
                        ("BYTE", "RealmDifficulty", 1),
                        ("DWORD", "MapID", 0),
                        ("DWORD", "LV", 0),
                        ("DWORD", "Exp", 0),
                        ("WORD", "MaxDrapLV", 0),
                        ("BYTE", "EquipClassLV", 0),
                        ("DWORD", "DropMoneyMin", 0),
                        ("DWORD", "DropMoneyMax", 0),
                        ("WORD", "LowLV", 0),
                        ("WORD", "HighestLV", 0),
                        ("DWORD", "Defense", 0),
                        ("DWORD", "MDef", 0),
                        ("DWORD", "FireDef", 0),
                        ("DWORD", "SP", 0),
                        ),
                "NPCStrengthen":(
                        ("DWORD", "NPCID", 1),
                        ("BYTE", "IsStrengthenByPlayerCount", 0),
@@ -2774,6 +2792,43 @@
    def GetNPCID(self): return self.NPCID # NPCID
    def GetFightPowerLackAtkLimit(self): return self.FightPowerLackAtkLimit # 战力不足限制攻击
    def GetSuppressFightPower(self): return self.SuppressFightPower # 推荐/压制战力
# 成长型境界怪物表
class IPY_NPCRealmStrengthen():
    def __init__(self):
        self.NPCID = 0
        self.RealmDifficulty = 0
        self.MapID = 0
        self.LV = 0
        self.Exp = 0
        self.MaxDrapLV = 0
        self.EquipClassLV = 0
        self.DropMoneyMin = 0
        self.DropMoneyMax = 0
        self.LowLV = 0
        self.HighestLV = 0
        self.Defense = 0
        self.MDef = 0
        self.FireDef = 0
        self.SP = 0
        return
    def GetNPCID(self): return self.NPCID # NPCID
    def GetRealmDifficulty(self): return self.RealmDifficulty # 境界难度
    def GetMapID(self): return self.MapID
    def GetLV(self): return self.LV # NPC等级
    def GetExp(self): return self.Exp # 基础经验
    def GetMaxDrapLV(self): return self.MaxDrapLV # 玩家最大可掉落等级
    def GetEquipClassLV(self): return self.EquipClassLV # 掉落装备阶
    def GetDropMoneyMin(self): return self.DropMoneyMin # 最小金币
    def GetDropMoneyMax(self): return self.DropMoneyMax # 最大金币
    def GetLowLV(self): return self.LowLV #  推荐最低等级
    def GetHighestLV(self): return self.HighestLV #  推荐最高等级
    def GetDefense(self): return self.Defense #  推荐防御
    def GetMDef(self): return self.MDef #  标准击杀时间/毫秒
    def GetFireDef(self): return self.FireDef #  脱机挂经验计算战力
    def GetSP(self): return self.SP #  SP
# 成长型怪物参数公式表
class IPY_NPCStrengthen():
@@ -6165,6 +6220,8 @@
        self.ipyGMAttrLen = len(self.ipyGMAttrCache)
        self.ipyNPCExCache = self.__LoadFileData("NPCEx", IPY_NPCEx)
        self.ipyNPCExLen = len(self.ipyNPCExCache)
        self.ipyNPCRealmStrengthenCache = self.__LoadFileData("NPCRealmStrengthen", IPY_NPCRealmStrengthen)
        self.ipyNPCRealmStrengthenLen = len(self.ipyNPCRealmStrengthenCache)
        self.ipyNPCStrengthenCache = self.__LoadFileData("NPCStrengthen", IPY_NPCStrengthen)
        self.ipyNPCStrengthenLen = len(self.ipyNPCStrengthenCache)
        self.ipyNPCTimeLostHPCache = self.__LoadFileData("NPCTimeLostHP", IPY_NPCTimeLostHP)
@@ -6733,6 +6790,8 @@
    def GetGMAttrByIndex(self, index): return self.ipyGMAttrCache[index]
    def GetNPCExCount(self): return self.ipyNPCExLen
    def GetNPCExByIndex(self, index): return self.ipyNPCExCache[index]
    def GetNPCRealmStrengthenCount(self): return self.ipyNPCRealmStrengthenLen
    def GetNPCRealmStrengthenByIndex(self, index): return self.ipyNPCRealmStrengthenCache[index]
    def GetNPCStrengthenCount(self): return self.ipyNPCStrengthenLen
    def GetNPCStrengthenByIndex(self, index): return self.ipyNPCStrengthenCache[index]
    def GetNPCTimeLostHPCount(self): return self.ipyNPCTimeLostHPLen
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -1078,7 +1078,8 @@
    
    #删除物品
    #ItemManager.DeleteItem(curItem)
    curMapItem = AddMapDropItem(dropPosX, dropPosY, curItem.GetItem())
    sightLevel = PlayerControl.GetMapRealmDifficulty(curPlayer)
    curMapItem = AddMapDropItem(dropPosX, dropPosY, curItem.GetItem(), sightLevel=sightLevel)
    curMapItem.SetOwnerType(ChConfig.Def_NPCHurtTypePlayer)
    curMapItem.SetOwnerID(curPlayer.GetPlayerID())    
    
@@ -1807,6 +1808,7 @@
    index = 0
    playerID = curPlayer.GetPlayerID()
    gameMap = GameWorld.GetMap()
    sightLevel = PlayerControl.GetMapRealmDifficulty(curPlayer)
    for posX, posY in ChConfig.Def_DropItemAreaMatrix:
        resultX = dropPosX + posX
        resultY = dropPosY + posY
@@ -1828,7 +1830,7 @@
            continue
        
        AddMapDropItem(resultX, resultY, curItem, ownerInfo=[ChConfig.Def_NPCHurtTypePlayer, playerID], 
                       dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee)
                       dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee, sightLevel=sightLevel)
    return
## 在地上添加物品(统一接口)
@@ -1838,7 +1840,7 @@
#  @param effIndex 要显示的特效索引
#  @param ownerInfo 掉落归属信息[归属类型, 归属ID, [特殊归属玩家ID列表]]
#  @return 返回值无意义
def AddMapDropItem(itemPosX, itemPosY, curItem, effIndex=0, ownerInfo=[], dropNPCID=0, isOnlySelfSee=False):
def AddMapDropItem(itemPosX, itemPosY, curItem, effIndex=0, ownerInfo=[], dropNPCID=0, isOnlySelfSee=False, sightLevel=0):
    itemDataStr = GetMapDropItemDataStr(curItem, effIndex, ownerInfo, dropNPCID, isOnlySelfSee)
    
    curMapItem = GameWorld.GetMapItemManager().AddDropItem(itemPosX, itemPosY, curItem,
@@ -1848,6 +1850,9 @@
        curMapItem.SetOwnerType(ownerType)
        curMapItem.SetOwnerID(ownerID)
        
    if sightLevel > 0:
        curMapItem.SetSightLevel(sightLevel)
    if dropNPCID:
        itemNoteDict = ItemCommon.GetItemNoteDict(curItem, curItem.GetCount())
        GameWorld.Log("AddMapDropItem mapItemID=%s,ownerType=%s,ownerID=%s,mapItemDataStr=%s,itemNoteDict=%s" 
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -59,6 +59,7 @@
import PlayerFeastTravel
import PlayerGoldInvest
import PlayerWeekParty
import NPCRealmRefresh
import NPCHurtManager
import PlayerActLogin
import FamilyRobBoss
@@ -187,7 +188,15 @@
        randMinLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMinLV)
        randMaxLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV)
        strengthenLV = random.randint(randMinLV, randMaxLV)
    # 根据境界难度
    elif lvStrengthenType == 5:
        realmLV = PlayerControl.GetDifficultyRealmLV(curNPC.GetSightLevel())
        realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, realmLV)
        if realmNPCIpyData:
            strengthenLV = realmNPCIpyData.GetLV()
        else:
            lvStrengthenType = 0
    # 木桩怪最大、平均成长等级处理,直接取归属玩家等级
    if lvStrengthenType in [1, 2] and curNPC.GetType() in [ChConfig.ntPriWoodPilePVE, ChConfig.ntPriWoodPilePVP]:
        owner = None
@@ -599,6 +608,7 @@
    index = 0
    playerID = curPlayer.GetPlayerID()
    gameMap = GameWorld.GetMap()
    sightLevel = PlayerControl.GetMapRealmDifficulty(curPlayer)
    for posX, posY in ChConfig.Def_DropItemAreaMatrix:
        resultX = dropPosX + posX
        resultY = dropPosY + posY
@@ -620,7 +630,7 @@
            continue
        
        ChItem.AddMapDropItem(resultX, resultY, curItem, ownerInfo=[ChConfig.Def_NPCHurtTypePlayer, playerID], 
                              dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee)
                              dropNPCID=npcID, isOnlySelfSee=isOnlySelfSee, sightLevel=sightLevel)
    return
def DoGiveItemByVirtualDrop(curPlayer, giveItemList, npcID, dropPosX=0, dropPosY=0, isDropDisperse=True, mailTypeKey="ItemNoPickUp", extraVirtualItemList=[]):
@@ -749,6 +759,15 @@
    if not ipyDrop:
        return
    
    realmNPCIpyData = None
    realmMapIDList = IpyGameDataPY.GetFuncEvalCfg("RealmDifficulty", 1)
    realmDifficulty = PlayerControl.GetRealmDifficulty(dropPlayer)
    if mapID in realmMapIDList and realmDifficulty:
        realmLV = PlayerControl.GetDifficultyRealmLV(realmDifficulty)
        realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, realmLV)
        #if realmNPCIpyData:
        #    maxDropLV = realmNPCIpyData.GetMaxDrapLV()
    #脱机暂不限制最大等级掉落
    #playerLV = dropPlayer.GetLV()
    #maxDropLV = ipyDrop.GetMaxDropLV()
@@ -820,6 +839,9 @@
    colorSuitPlaceKeyInfoDict = ipyDrop.GetEquipPartKeyRateInfo() # 装备部位集合信息 {(颜色,是否套装):部位集合key, ...}
    dropEquipIDDict = {}
    for classLV, color, dropCount in dropEquipInfoList:
        if realmNPCIpyData:
            classLV = realmNPCIpyData.GetEquipClassLV()
            GameWorld.DebugLog("    脱机掉落对应难度境界装备: classLV=%s" % classLV, playerID)
        suitCountDict = {} # {套装:件数, ...}
        if color in colorSuitRateDict:
            suitRate = colorSuitRateDict[color]
@@ -882,7 +904,7 @@
        dropMoneyCnt += 1
    dropMoney = 0
    if dropMoneyCnt:
        dropMoney = __GetDropMoneyValue(dropPlayer, ipyDrop) * dropMoneyCnt
        dropMoney = __GetDropMoneyValue(dropPlayer, ipyDrop, realmNPCIpyData) * dropMoneyCnt
        GameWorld.DebugLog("    金币掉率: dropMoneyRate=%s,moneyTotalRate=%s,dropMoneyCnt=%s,dropMoney=%s" 
                           % (dropMoneyRate, moneyTotalRate, dropMoneyCnt, dropMoney), playerID)
    dropIDCountDict = {}
@@ -937,6 +959,16 @@
    playerID = dropPlayer.GetPlayerID()
    playerLV = dropPlayer.GetLV()
    maxDropLV = ipyDrop.GetMaxDropLV()
    realmNPCIpyData = None
    realmMapIDList = IpyGameDataPY.GetFuncEvalCfg("RealmDifficulty", 1)
    realmDifficulty = PlayerControl.GetRealmDifficulty(dropPlayer)
    if mapID in realmMapIDList and realmDifficulty:
        realmLV = PlayerControl.GetDifficultyRealmLV(realmDifficulty)
        realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, realmLV)
        if realmNPCIpyData:
            maxDropLV = realmNPCIpyData.GetMaxDrapLV()
    if maxDropLV and playerLV > maxDropLV:
        GameWorld.DebugLog("超过最大可掉落等级,不掉落物品!npcID=%s,playerLV(%s) > maxDropLV(%s)" % (npcID, playerLV, maxDropLV))
        return
@@ -1066,6 +1098,10 @@
    
    for dropEquipInfo in dropEquipInfoList:
        classLV, color = dropEquipInfo[:2]
        if realmNPCIpyData:
            classLV = realmNPCIpyData.GetEquipClassLV()
            GameWorld.DebugLog("掉落对应难度境界装备: classLV=%s" % classLV, playerID)
        if color in colorMaxDropCntDict:
            maxCount = colorMaxDropCntDict[color]
            dropCount = colorDropCntDict.get(color, 0)
@@ -1179,7 +1215,7 @@
                
    #GameWorld.DebugLog("NPCID=%s,金币掉率: %s, 执行次数=%s, 掉落金币数=%s" % (npcID, dropMoneyRate, dropMoneyDoCnt, dropMoneyCnt))
    if dropMoneyCnt:
        moneyValue = __GetDropMoneyValue(dropPlayer, ipyDrop)
        moneyValue = __GetDropMoneyValue(dropPlayer, ipyDrop, realmNPCIpyData)
        #GameWorld.DebugLog("    掉落金币value=%s" % (moneyValue))
        
    if dropIDList:
@@ -1597,12 +1633,15 @@
    #GameWorld.DebugLog("独立概率装备掉落结果: doCnt=%s, %s" % (doCnt, dropEquipInfoList))
    return dropEquipInfoList
def __GetDropMoneyValue(curPlayer, ipyDrop):
def __GetDropMoneyValue(curPlayer, ipyDrop, realmNPCIpyData):
    baseMoney = FBLogic.OnGetNPCDropMoney(curPlayer)
    if baseMoney <= 0:
        # 获得掉落数量
        baseMoney = random.randint(ipyDrop.GetDropMoneyMin(), ipyDrop.GetDropMoneyMax())
        if realmNPCIpyData:
            baseMoney = random.randint(realmNPCIpyData.GetDropMoneyMin(), realmNPCIpyData.GetDropMoneyMax())
        else:
            baseMoney = random.randint(ipyDrop.GetDropMoneyMin(), ipyDrop.GetDropMoneyMax())
    if baseMoney <= 0:
        return 0
    
@@ -2140,7 +2179,7 @@
# @param aiType: AI类型
# @return 如果召唤失败返回None 否则返回召唤的NPC的实例
# @remarks 在地图里召唤NPC 根据NPCID 出生点 AI类型 和TICK
def SummonMapNpc(npcId, rebornX, rebornY, aiType=0, lastTime=0, playerID=0):
def SummonMapNpc(npcId, rebornX, rebornY, aiType=0, lastTime=0, playerID=0, sightLevel=0, refreshID=0):
    curSummon = GameWorld.GetNPCManager().AddPlayerSummonNPC()
    if not curSummon:
        return
@@ -2159,9 +2198,17 @@
    if playerID > 0:
        curSummon.SetDict(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID, playerID)
        
    if sightLevel > 0:
        curSummon.SetSightLevel(sightLevel)
    if refreshID > 0:
        curSummon.SetDict(ChConfig.Def_NPC_Dict_SummonRefreshID, refreshID)
    if curSummon.GetType() == ChConfig.ntRobot:
        __OnFBRobotReborn(curSummon, curSummon.GetLV())
    curSummon.Reborn(rebornX, rebornY)
    curSummon.Reborn(rebornX, rebornY, False)
    NPCControl(curSummon).DoNPCRebornCommLogic(tick)
    
    FBLogic.DoFBRebornSummonNPC(curSummon, tick)
    #__NotifyMapPlayerSummonMapNPC(npcId, rebornX, rebornY)
@@ -2318,7 +2365,11 @@
    summonPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID)
    if summonPlayerID > 0:
        curNPC.SetDict(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID, 0)
    refreshObj = NPCRealmRefresh.GetTagNPCRefresh(curNPC)
    if refreshObj:
        refreshObj.SetDead(GameWorld.GetGameWorld().GetTick())
    # 暗金boss
    if ChConfig.IsGameBoss(curNPC): 
        # 通知GameServer boss状态 封魔坛在副本里单独处理
@@ -3516,7 +3567,7 @@
    def __Func_GetRandPosInRefreshArea(self):
        curNPC = self.__Instance
        #得到地图刷新点
        posMap = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        posMap = self.GetRefreshPoint()
        #范围校验
        if not posMap:
            GameWorld.ErrLog("__Func_GetRandPosInRefreshArea GetRefreshPosAt error: return None! npcID=%s" % curNPC.GetNPCID())
@@ -3538,6 +3589,15 @@
        return posX, poxY
    #---------------------------------------------------------------------
    def GetRefreshPoint(self):
        curNPC = self.__Instance
        refreshObj = NPCRealmRefresh.GetTagNPCRefresh(curNPC)
        if refreshObj:
            refreshPoint = refreshObj.GetRefreshPoint()
        else:
            refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        return refreshPoint
    ## 是否在移动范围内
    #  @param self 类实例
    #  @return 返回值真, 在移动范围内
@@ -3545,7 +3605,7 @@
    def IsInRefreshArea(self):
        #这个NPC是否在移动范围内
        curNPC = self.__Instance
        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
        refreshPoint = self.GetRefreshPoint()
        #GameWorld.Log("posX = %d posY = %d, dist = %d"%(refreshPoint.GetPosX(), refreshPoint.GetPosY(), refreshPoint.GetMoveDist()))
        if self.GetIsInRefreshPoint(curNPC.GetPosX() , curNPC.GetPosY() , refreshPoint):
            return True
@@ -4170,11 +4230,11 @@
        npcID = curNPC.GetNPCID()
        specDropItemList = []
        
        playerLV = dropPlayer.GetLV()
        maxDropLV = ipyDrop.GetMaxDropLV()
        if maxDropLV and playerLV > maxDropLV:
            GameWorld.DebugLog("超过最大可掉落等级,不掉落物品,特殊掉落!npcID=%s,playerLV(%s) > maxDropLV(%s)" % (npcID, playerLV, maxDropLV))
            return specDropItemList
        #playerLV = dropPlayer.GetLV()
        #maxDropLV = ipyDrop.GetMaxDropLV()
        #if maxDropLV and playerLV > maxDropLV:
        #    GameWorld.DebugLog("超过最大可掉落等级,不掉落物品,特殊掉落!npcID=%s,playerLV(%s) > maxDropLV(%s)" % (npcID, playerLV, maxDropLV))
        #    return specDropItemList
        
        auctionItemCanSell = ipyDrop.GetAucionItemCanSell()
        # 击杀次数掉落算摸怪
@@ -4250,8 +4310,10 @@
            dropIDList += [moneyID] * dropMoneyCnt
            
        specItemSign = "SpecItem"
        playerSpecDropList = self.__NPCSpecialDropItem(dropPlayer, ownerPlayerList, ipyDrop) # 特殊掉落 [[ownerPlayer, itemID, isAuctionItem, isDropInItemPack], ...]  私有特殊掉落 + 击杀次数特殊掉落
        dropIDList += [specItemSign] * len(playerSpecDropList)
        playerSpecDropList = []
        if dropInfo:
            playerSpecDropList = self.__NPCSpecialDropItem(dropPlayer, ownerPlayerList, ipyDrop) # 特殊掉落 [[ownerPlayer, itemID, isAuctionItem, isDropInItemPack], ...]  私有特殊掉落 + 击杀次数特殊掉落
            dropIDList += [specItemSign] * len(playerSpecDropList)
        
        if len(dropIDList) > 5:
            #打乱物品顺序
@@ -4262,6 +4324,7 @@
            GameWorld.ErrLog("Boss没有掉落: dropPlayerLV=%s,ipyWorldLV=%s,maxDropLV=%s" 
                             % (dropPlayer.GetLV(), ipyDrop.GetMaxWorldLV(), ipyDrop.GetMaxDropLV()), dropPlayer.GetPlayerID())
            
        sightLevel = PlayerControl.GetMapRealmDifficulty(dropPlayer)
        gameMap = GameWorld.GetMap()
        dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY() # 以NPC为中心点开始掉落
        index = 0
@@ -4312,7 +4375,7 @@
                    SendVirtualItemDrop(ownerPlayer, itemID, resultX, resultY, dropItemDataStr)
                    
            else:
                self.__MapCreateItem(curItem, resultX, resultY, ownerType, ownerID, isOnlySelfSee=isOnlySelfSee)
                self.__MapCreateItem(curItem, resultX, resultY, ownerType, ownerID, isOnlySelfSee=isOnlySelfSee, sightLevel=sightLevel)
        return
    #---------------------------------------------------------------------
    ## NPC被杀死逻辑处理
@@ -4568,7 +4631,7 @@
        curNPC = self.__Instance
        
        # VIP杀怪加攻
        PlayerVip.DoAddVIPKillLVExp(lastHurtPlayer, curNPC)
        PlayerVip.DoAddVIPKillLVExp(lastHurtPlayer, GetNPCLV(curNPC))
        
        # SPֵ
        PlayerControl.AddZhenQiByKillNPC(lastHurtPlayer, curNPC.GetSP())
@@ -5109,7 +5172,14 @@
        if baseExp > 0:
            return baseExp
        
        baseExp = curNPC.GetExp()
        npcID = curNPC.GetNPCID()
        realmLV = PlayerControl.GetDifficultyRealmLV(curNPC.GetSightLevel())
        realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, realmLV)
        if realmNPCIpyData:
            baseExp = realmNPCIpyData.GetExp()
        else:
            baseExp = curNPC.GetExp()
        if baseExp == 0:
            #GameWorld.Log("杀怪经验异常,该NPC = %s,无经验"%(curNPC.GetID()))
            return 0
@@ -5143,7 +5213,7 @@
    #  @param dropType: 掉落类型
    #  @param ownerID: 归属者
    #  @return: None
    def __MapCreateItem(self, curItem, posX, posY, dropType, ownerID, isOnlySelfSee=False):
    def __MapCreateItem(self, curItem, posX, posY, dropType, ownerID, isOnlySelfSee=False, sightLevel=0):
        if not curItem:
            return
        
@@ -5162,7 +5232,7 @@
        # 在地上添加物品(统一接口)
        dropNPCID = 0 if not ChConfig.IsGameBoss(curNPC) else curNPCID
        specOwnerIDList = [player.GetPlayerID() for player in self.__ownerPlayerList] if dropType == ChConfig.Def_NPCHurtTypeSpecial else []
        curMapItem = ChItem.AddMapDropItem(posX, posY, curItem, ownerInfo=[dropType, ownerID, specOwnerIDList], dropNPCID=dropNPCID, isOnlySelfSee=isOnlySelfSee)
        curMapItem = ChItem.AddMapDropItem(posX, posY, curItem, ownerInfo=[dropType, ownerID, specOwnerIDList], dropNPCID=dropNPCID, isOnlySelfSee=isOnlySelfSee, sightLevel=sightLevel)
        
        #设置该物品生前拥有者(那个NPC掉落的)
        if curMapItem == None:
@@ -5555,7 +5625,12 @@
    npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)
    if not npcData:
        return 0
    baseExp = npcData.GetExp()
    needRealmLV = PlayerControl.GetDifficultyRealmLV(PlayerControl.GetRealmDifficulty(curPlayer))
    realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, needRealmLV)
    if realmNPCIpyData:
        baseExp = realmNPCIpyData.GetExp()
    else:
        baseExp = npcData.GetExp()
    if not baseExp:
        return 0
    npcLV = npcData.GetLV()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCRealmRefresh.py
New file
@@ -0,0 +1,210 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package NPCRealmRefresh
#
# @todo:境界NPC刷怪
# @author hxp
# @date 2022-08-23
# @version 1.0
#
# 详细描述: tagNPCRefresh.txt py读取该表刷怪规则
#
#-------------------------------------------------------------------------------
#"""Version = 2022-08-23 19:00"""
#-------------------------------------------------------------------------------
import GameWorld
import PyGameData
import IpyGameDataPY
import PlayerControl
import NPCCommon
import ChConfig
import os
class IPY_ChRefreshPos():
    def __init__(self):
        self.posX = 0
        self.posY = 0
        self.area = 0
        self.moveDist = 0
        return
    def GetRandPosX(self): return self.posX
    def GetRandPosY(self): return self.posY
    def GetPosX(self): return self.posX
    def GetPosY(self): return self.posY
    def GetArea(self): return self.area
    def GetMoveDist(self): return self.moveDist
class tagNPCRefresh():
    def __init__(self, RefreshID):
        self.RefreshID = RefreshID
        self.NPCID = 0
        self.RefreshPoint = IPY_ChRefreshPos()
        self.RefreshTotal = 0
        self.RefreshCount = 0
        self.RefreshTime = 0
        self.RebornState = 0 # 是否复活状态
        self.DeadTick = 0 # 上次死亡tick
        return
    def GetRefreshID(self): return self.RefreshID
    def GetNPCID(self): return self.NPCID
    def GetRefreshPoint(self): return self.RefreshPoint
    def GetRefreshTotal(self): return self.RefreshTotal
    def GetRefreshCount(self): return self.RefreshCount
    def GetRefreshTime(self): return self.RefreshTime
    def GetRebornState(self): return self.RebornState
    def GetDeadTick(self): return self.DeadTick
    def SetReborn(self):
        self.RebornState = 1
        return
    def SetDead(self, tick):
        self.RebornState = 0
        self.DeadTick = tick
        return
def GetTagNPCRefresh(curNPC):
    realmDiff = curNPC.GetSightLevel()
    refreshID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SummonRefreshID)
    obj = None
    if realmDiff in PyGameData.g_realmDiffNPCRefresh:
        mapNPCRefresh = PyGameData.g_realmDiffNPCRefresh[realmDiff]
        if refreshID in mapNPCRefresh:
            obj = mapNPCRefresh[refreshID]
    else:
        if False:
            obj = tagNPCRefresh(refreshID) # 这两行代码无用,只是为了方便 . 出代码提示
    return obj
def GetMapRealmNPCRefresh(realm):
    ''' 加载本地图  tagNPCRefresh.txt 刷怪规则
    '''
    if realm in PyGameData.g_realmDiffNPCRefresh:
        return PyGameData.g_realmDiffNPCRefresh[realm]
    filePath = os.path.join(ChConfig.GetDBPath(), "SysDB", "tagNPCRefresh.txt")
    if not os.path.isfile(filePath):
        GameWorld.ErrLog("can not find file = %s" % filePath)
        raise Exception("can not find file = %s" % filePath)
    mapNPCRefresh = {}
    curMapID = GameWorld.GetMap().GetMapID()
    fileObj = open(filePath, 'rb')
    content = fileObj.read()
    fileObj.close()
    infoList = content.split('\r\n')
    for line in xrange(len(infoList)):
        if line == 0:
            continue
        if not infoList[line]:
            continue
        rowList = infoList[line].split('\t')
        if len(rowList) != 17:
            continue
        try:
            MapID = int(rowList[2])
            if curMapID != MapID:
                continue
            RefreshID = int(rowList[0])
            NPCID = int(rowList[1])
            if not NPCID:
                continue
            RefreshPos = eval(rowList[4])
            RefreshTotal = int(rowList[5])
            RefreshCount = int(rowList[6])
            RefreshTime = int(rowList[8])
            if not (type(RefreshPos) in [list, tuple] and len(RefreshPos) == 4 and isinstance(RefreshPos[0], int)):
                GameWorld.ErrLog("tagNPCRefresh.txt line(%s) not processed." % (line + 1))
                continue
            refreshObj = tagNPCRefresh(RefreshID)
            refreshObj.NPCID = NPCID
            refreshObj.RefreshPoint.posX = RefreshPos[0]
            refreshObj.RefreshPoint.posY = RefreshPos[1]
            refreshObj.RefreshPoint.area = RefreshPos[2]
            refreshObj.RefreshPoint.moveDist = RefreshPos[3]
            refreshObj.RefreshTotal = RefreshTotal
            refreshObj.RefreshCount = RefreshCount
            refreshObj.RefreshTime = RefreshTime
            mapNPCRefresh[RefreshID] = refreshObj
        except:
            GameWorld.ErrLog("tagNPCRefresh.txt line(%s) error." % (line + 1))
            continue
    PyGameData.g_realmDiffNPCRefresh[realm] = mapNPCRefresh
    GameWorld.Log("LoadMapRealmNPCRefresh mapID=%s,realm=%s,refreshIDList=%s" % (curMapID, realm, mapNPCRefresh.keys()))
    return mapNPCRefresh
def ProcessRealmNPCRefresh(gameWorld, tick):
    mapID = gameWorld.GetMapID()
    mapIDList = IpyGameDataPY.GetFuncEvalCfg("RealmDifficulty", 1)
    if mapID not in mapIDList:
        return
    playerDict = {}
    copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
    for realmDiff, playerIDList in PyGameData.g_realmDiffPlayerDict.items():
        if not playerIDList:
            continue
        mapNPCRefresh = GetMapRealmNPCRefresh(realmDiff)
        if not mapNPCRefresh:
            continue
        for refreshID, refreshObj in mapNPCRefresh.items():
            if not refreshObj:
                continue
            if refreshObj.GetRebornState():
                continue
            DeadTick = refreshObj.GetDeadTick()
            RefreshTime = refreshObj.GetRefreshTime()
            if DeadTick and RefreshTime:
                if (tick - DeadTick) < RefreshTime:
                    continue
            NPCID = refreshObj.GetNPCID()
            npcData = GameWorld.GetGameData().FindNPCDataByID(NPCID)
            if not npcData:
                continue
            refreshPoint = refreshObj.GetRefreshPoint()
            posX, posY = refreshPoint.GetPosX(), refreshPoint.GetPosY()
            canRefresh = False
            # 判断玩家是否可视
            for playerID in playerIDList:
                if playerID in playerDict:
                    player = playerDict[playerID]
                else:
                    player = copyPlayerMgr.FindPlayerByID(playerID)
                if not player:
                    continue
                playerDict[playerID] = player
                playerRealm = PlayerControl.GetRealmDifficulty(player)
                if playerRealm != realmDiff:
                    continue
                sight = player.GetSight()
                playerPosX, playerPosY = player.GetPosX(), player.GetPosY()
                if GameWorld.GetDist(posX, posY, playerPosX, playerPosY) <= sight:
                    canRefresh = True
                    break
            if not canRefresh:
                continue
            if NPCCommon.SummonMapNpc(NPCID, posX, posY, npcData.GetAIType(), sightLevel=realmDiff, refreshID=refreshID):
                refreshObj.SetReborn()
                #GameWorld.DebugLog("ProcessNPCRefresh realmDiff=%s,NPCID=%s,posX=%s,posY=%s" % (realmDiff, NPCID, posX, posY), refreshID)
                continue
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -1215,6 +1215,12 @@
    if not GameWorld.IsCrossServer() and (PlayerControl.GetCrossMapID(curPlayer) or PlayerControl.GetCustomMapID(curPlayer)):
        GameWorld.DebugLog("===登录本服地图时,处于跨服或自定义场景状态,不刷新视野!", curPlayer.GetPlayerID())
        PlayerControl.SetPlayerSightLevel(curPlayer, curPlayer.GetID())
    elif not GameWorld.IsCrossServer():
        realmDifficulty = PlayerControl.GetMapRealmDifficulty(curPlayer)
        if realmDifficulty:
            GameWorld.DebugLog("===登录本服地图时,处于境界难度地图,自动设置难度! realmDifficulty=%s" % realmDifficulty, curPlayer.GetPlayerID())
            PlayerControl.SetRealmDifficulty(curPlayer, realmDifficulty)
    PlayerState.ChangePlayerSigh(curPlayer, tick)
    
    if GameWorld.IsCrossServer():
@@ -1573,6 +1579,12 @@
        if not GameWorld.IsCrossServer() and (PlayerControl.GetCrossMapID(curPlayer) or curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene)):
            GameWorld.DebugLog("===本服LoadMapOK时玩家处于跨服或自定义场景状态,不设置可见!", curPlayer.GetPlayerID())
            PlayerControl.SetPlayerSightLevel(curPlayer, curPlayer.GetID())
        elif not GameWorld.IsCrossServer():
            realmDifficulty = PlayerControl.GetMapRealmDifficulty(curPlayer)
            if realmDifficulty:
                GameWorld.DebugLog("===本服LoadMapOK时玩家处于境界难度地图,自动设置难度!realmDifficulty=%s" % realmDifficulty, curPlayer.GetPlayerID())
                PlayerControl.SetRealmDifficulty(curPlayer, realmDifficulty)
        curPlayer.RefreshView()
        curPlayer.SetVisible(True)
        
@@ -6164,3 +6176,16 @@
        GameObj.SetHP(curPlayer, updHP)
        
    return
#// A2 35 选择境界难度层级 #tagCMSelectRealmDifficulty
#
#struct    tagCMSelectRealmDifficulty
#{
#    tagHead        Head;
#    BYTE        RealmDifficulty;    //境界难度 = 100 + 所选境界等级,如境界13,则发113
#};
def OnSelectRealmDifficulty(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    PlayerControl.SetRealmDifficulty(curPlayer, clientData.RealmDifficulty)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTJG.py
@@ -299,7 +299,7 @@
    SetTJGTime(curPlayer, min(GetTJGTime(curPlayer) + addTime, maxTime))
    return
def CalcTJGExp(curPlayer, times, npcData):
def CalcTJGExp(curPlayer, times, npcData, realmNPCIpyData):
    lvIpyData = PlayerControl.GetPlayerLVIpyData(curPlayer.GetLV())
    if not lvIpyData:
        return 0
@@ -327,9 +327,19 @@
    aReFightPower = lvIpyData.GetReFightPower() # 等级表对应的战力
    aNPCHurtAddPer = PlayerControl.GetNPCHurtAddPer(curPlayer) #PVE 伤害加成万分率
    
    npcExp = npcData.GetExp()
    npcMaxHP = GameObj.GetHP(npcData)
    npcCommendFightPower = NPCCommon.GetCommendFightPower(npcData)
    npcID = npcData.GetNPCID()
    if realmNPCIpyData:
        attrDict = NPCCommon.GetNPCStrengthenAttrDict(npcID, realmNPCIpyData.GetLV())
        npcExp = realmNPCIpyData.GetExp()
        npcMaxHP = attrDict.get("MaxHP", GameObj.GetHP(npcData))
        npcCommendFightPower = realmNPCIpyData.GetFireDef()
        GameWorld.DebugLog("CalcTJGExp realmNPC npcID=%s,npcExp=%s,npcMaxHP=%s,npcCommendFightPower=%s" % (npcID, npcExp, npcMaxHP, npcCommendFightPower))
    else:
        npcExp = npcData.GetExp()
        npcMaxHP = GameObj.GetHP(npcData)
        npcCommendFightPower = NPCCommon.GetCommendFightPower(npcData)
        GameWorld.DebugLog("CalcTJGExp npcID=%s,npcExp=%s,npcMaxHP=%s,npcCommendFightPower=%s" % (npcID, npcExp, npcMaxHP, npcCommendFightPower))
    petSkillLV = 1
    petSkillPer = 10000
    
@@ -365,7 +375,7 @@
        aNPCHurtAddPer:%s, aFinalHurtPer:%s, 
        aIceAtk:%s, aDamagePVE:%s, aSkillAtkRate:%s, petMinAtk:%s, petMaxAtk:%s, petDamPer:%s, atkSpeed:%s,
        aIgnoreDefRate:%s, aLuckyHit:%s, aLuckyHitRate:%s, aBleedDamage:%s, aFinalHurt:%s, npcExp:%s, npcMaxHP:%s, npcCommendFightPower:%s,
        petSkillLV:%s, petSkillPer:%s, skill:%s, petSkill:%s"""%(curPlayer.GetID(), curPlayer.GetLV(), times, npcData.GetNPCID(),
        petSkillLV:%s, petSkillPer:%s, skill:%s, petSkill:%s"""%(curPlayer.GetID(), curPlayer.GetLV(), times, npcID,
            reExp, attackEff, aMinAtk, aMaxAtk, aSuperHitRate, aSuperHit, aNPCHurtAddPer, aFinalHurtPer,
            aIceAtk, aDamagePVE, aSkillAtkRate, petMinAtk, petMaxAtk, petDamPer,
            atkSpeed, aIgnoreDefRate, aLuckyHit, aLuckyHitRate, aBleedDamage, aFinalHurt, npcExp, npcMaxHP, npcCommendFightPower, petSkillLV,
@@ -418,8 +428,21 @@
    if not npcData:
        return finalAddExp
    
    realmLV = PlayerControl.GetDifficultyRealmLV(PlayerControl.GetRealmDifficulty(curPlayer))
    realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, realmLV)
    if realmNPCIpyData:
        mDef = realmNPCIpyData.GetMDef()
        npcLV = realmNPCIpyData.GetLV()
        sp = realmNPCIpyData.GetSP()
        GameWorld.DebugLog("OnTJGKillNPCByTimes npcID=%s,npcLV=%s,mDef=%s,sp=%s,realmLV=%s" % (npcID, npcLV, mDef, sp, realmLV))
    else:
        mDef = npcData.GetMDef()
        npcLV = npcData.GetLV()
        sp = npcData.GetSP()
        GameWorld.DebugLog("OnTJGKillNPCByTimes npcID=%s,npcLV=%s,mDef=%s,sp=%s" % (npcID, npcLV, mDef, sp))
    # 1. 经验
    exp = CalcTJGExp(curPlayer, times, npcData)
    exp = CalcTJGExp(curPlayer, times, npcData, realmNPCIpyData)
    playerControl = PlayerControl.PlayerControl(curPlayer)
    if exp > 0:
        finalAddExp = playerControl.AddExp(exp, ShareDefine.Def_ViewExpType_KillNPC)
@@ -430,10 +453,10 @@
    
    # GetMDef 用于 NPC被击杀时间效率 毫秒
    if npcData.GetMDef() == 0:
    if mDef == 0:
        return finalAddExp
    
    killCnt = times*1000/npcData.GetMDef()
    killCnt = times*1000/mDef
    if not killCnt:
        return finalAddExp
    
@@ -442,18 +465,18 @@
    # 2.物品
    OnTJGDropItems(curPlayer, npcID, killCnt)
    #任务道具
    OnTJGDropTaskItems(curPlayer, npcData.GetLV(), killCnt)
    OnTJGDropTaskItems(curPlayer, npcLV, killCnt)
    # VIP杀怪加攻
    PlayerVip.DoAddVIPKillLVExp(curPlayer, npcData, killCnt)
    PlayerVip.DoAddVIPKillLVExp(curPlayer, npcLV, killCnt)
    
    # SPֵ
    PlayerControl.AddZhenQiByKillNPC(curPlayer, npcData.GetSP(), killCnt)
    PlayerControl.AddZhenQiByKillNPC(curPlayer, sp, killCnt)
    
    # 击杀特定NPC成就
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillSpecificNPC, killCnt, [npcID])
    # 日常活动
    if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDictType_TJGOnDayEx):
        if npcData.GetLV()>=curPlayer.GetLV() - IpyGameDataPY.GetFuncCfg('DailyQuestKillMonster'):
        if npcLV>=curPlayer.GetLV() - IpyGameDataPY.GetFuncCfg('DailyQuestKillMonster'):
            PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_KillNPC, killCnt)
    # 击杀任务怪, 杀怪日常已经没有了,暂时屏蔽
    #for _ in xrange(killCnt):
@@ -775,8 +798,11 @@
    if not npcData:
        return
    
    realmLV = PlayerControl.GetDifficultyRealmLV(PlayerControl.GetRealmDifficulty(curPlayer))
    realmNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("NPCRealmStrengthen", npcID, realmLV)
    # 1. 经验 
    exp = CalcTJGExp(curPlayer, times, npcData)
    exp = CalcTJGExp(curPlayer, times, npcData, realmNPCIpyData)
    expRate = PlayerControl.GetLimitExpRate(curPlayer, ChConfig.ExpRateLimitType_Recover)
    exp = int(exp * expRate / float(ChConfig.Def_MaxRateValue))
    # 通知脱机挂被杀是的时间 和 被杀后的脱机挂时间可获得的经验
@@ -984,14 +1010,23 @@
        maxMapID = mapID
        
    GameWorld.DebugLog("FindTJGNPC maxMapID=%s" % maxMapID)
    if not maxMapID:
        return 0
    
    # ---找到挂机等级点---
    lv = curPlayer.GetLV()
    myPoint = None
    mapList = IpyGameDataPY.GetIpyGameDataByCondition("MapEventPoint", {"MapID":maxMapID}, True)
    # 注: NPCRealmStrengthen MapEventPoint 这两张配置表需要确保相关共用字段命名一样
    realmMapIDList = IpyGameDataPY.GetFuncEvalCfg("RealmDifficulty", 1)
    realmDifficulty = PlayerControl.GetRealmDifficulty(curPlayer)
    if maxMapID in realmMapIDList and realmDifficulty:
        realmLV = PlayerControl.GetDifficultyRealmLV(realmDifficulty)
        mapList = IpyGameDataPY.GetIpyGameDataByCondition("NPCRealmStrengthen", {"MapID":maxMapID, "RealmDifficulty":realmLV}, True)
    else:
        mapList = IpyGameDataPY.GetIpyGameDataByCondition("MapEventPoint", {"MapID":maxMapID}, True)
    mapEffList = []  # 有效挂机点,同地图中存在不需要挂机的NPC点
    for mapInfo in mapList:
        if mapInfo.GetLowLV() == 0:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerVip.py
@@ -538,7 +538,7 @@
    GameWorld.DebugLog("VIP杀怪等级信息同步开关, isOn=%s" % isOn, curPlayer.GetPlayerID())
    return
def DoAddVIPKillLVExp(curPlayer, curNPC, killCount=1):
def DoAddVIPKillLVExp(curPlayer, npcLV, killCount=1):
    ''' 击杀NPC增加VIP杀怪等级经验,只算击杀的,队员击杀无效
    '''
    
@@ -549,7 +549,6 @@
    if not mwID or not PlayerMagicWeapon.GetIsActiveMagicWeapon(curPlayer, mwID):
        return
    
    npcLV = NPCCommon.GetNPCLV(curNPC)
    addExp = eval(IpyGameDataPY.GetFuncCompileCfg("VIPAddAtkEXP", 1))
    addExp *= killCount
    if not addExp:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -15,6 +15,8 @@
#"""Version = 2017-09-05 21:30"""
#-------------------------------------------------------------------------------
g_mapIDTxtInfo = {} # MapID.txt 加载的信息
g_realmDiffPlayerDict = {} # 境界难度玩家信息 {realm:[playerID, ...], ...}
g_realmDiffNPCRefresh = {} # {realm:{refreshID:tagNPCRefresh, ...}}
g_commMapLinePlayerCountDict = {} # 常规地图分线人数 {mapID:{lineID:人数, ...}}
g_needRefreshMapServerState = True # 常规地图分线人数是否有变更需要通知