hxp
2019-12-20 b82e6dbda1129a3f55d0177964a35d77feff7c77
8360 【主干】仙界秘境修改(改为击杀固定怪物数模式)
5个文件已修改
450 ■■■■ 已修改文件
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetXJMJExpTime.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_BZZD.py 445 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3618,7 +3618,6 @@
# 百战之地
Def_PDict_BZZD_TotalFightExp = "BZZD_TExp" # 最后一次进入副本挑战获得总经验, 领取多倍奖励时用
Def_PDict_BZZD_TotalFightExpPoint = "BZZD_TExpPoint" # 最后一次进入副本挑战获得总经验点, 领取多倍奖励时用
Def_PDict_BZZD_FirstEnterExpTime = "BZZD_FirstEnterExpTime" # 首次进入经验保底补差时长,可用于判断是否首次进入
Def_PDict_BZZD_HistoryEnterCnt = "BZZD_HistoryEnterCnt" # 历史进入总次数
# 公共CD副本扫荡
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetXJMJExpTime.py
@@ -30,7 +30,6 @@
        GameWorld.DebugAnswer(curPlayer, 'SetXJMJExpTime 秒')
        return
    expTime = cmdList[0]
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, expTime)
    GameWorld.DebugAnswer(curPlayer, '设置经验补时秒: %s' % expTime)
    if not expTime:
        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_GuideState, ChConfig.GuideState_BZZDShow, 0)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
@@ -58,6 +58,7 @@
Help_wheel = 'wheel' #当前波数(关卡编号),从1开始,1~n
Help_npc = 'npc' #NPC已击杀个数 [{"NPCID":150,"killCnt":100}]
Help_npcTotal = 'npcTotal' #NPC总已击杀个数
Help_npcTotalNeed = 'npcTotalNeed' #NPC总需击杀个数
Help_exp = 'exp' #已获得经验
Help_expPoint = 'expPoint' #已获得经验点
Help_money = 'money' #已获得钱 [{"moneyType":3,"moneyValue":1000}]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_BZZD.py
@@ -25,10 +25,6 @@
import EventReport
import ChConfig
import IpyGameDataPY
import AttackCommon
import PyGameData
import NPCCommon
import GameObj
import PlayerSuccess
import PlayerBossReborn
import PlayerFairyCeremony
@@ -40,9 +36,8 @@
import SkillShell
import BuffSkill
import EventShell
import PyGameData
import random
import math
#---副本配置对应key值---
(
@@ -60,125 +55,38 @@
FB_Step_Close, # 副本关闭
) = range(5)
BZZD_LastCheckExpTick = 'BZZD_LastCheckExpTick'   # 上次检查保底奖励tick
BZZD_LastCheckTick = 'BZZD_LastCheckTick'   # 上次检查npc刷新时间
#BZZD_KillCnt = 'BZZD_KillCnt'   # 击杀数
BZZD_WaveIndex = 'BZZD_WaveIndex'   # 波数
BZZD_TotalNPCCount = 'BZZD_TotalNPCCount'   # 总需击杀NPC数量
BZZD_ReExp = 'BZZD_ReExp_%s' # 参考经验, 参数 (npcLV)
BZZD_NPCMaxHP = 'BZZD_NPCMaxHP_%s_%s' # NPC最大生命值, 参数(npcID, enterLV)
FBPlayerDict_KillCnt = 'FBPlayerDict_KillCnt'   # 击杀数
FBPlayerDict_EnterLV = 'FBPlayerDict_EnterLV'   # 进入副本时的等级
FBPlayerDict_TotalExp = 'FBPlayerDict_TotalExp'   # 获得的总经验
FBPlayerDict_TotalExpPoint = 'FBPlayerDict_TotalExpPoint'   # 获得的总经验点
FBPlayerDict_EncourageLV = 'FBPlayerDict_EncourageLV'   # 鼓舞等级
FirstEnterExpTimeMax = 99999 # 当单次补时满时记录的一个特殊数值,防止策划调整单次战斗时长时,老号可能会多余补经验
def GetBZZDNPCID(passSecond):
    ##当前应该刷新的NPCID
    curNpcid = 0
    curIndex = 0
    fairylandNPCList = IpyGameDataPY.GetFuncEvalCfg('FairylandNPC', 1)
    for i, info in enumerate(fairylandNPCList, 1):
        timeRange, npcid = info
        if timeRange[0] <= passSecond <= timeRange[1]:
            curNpcid = npcid
            curIndex = i
            break
    return curNpcid, curIndex
## OnDay处理
#  @param curPlayer
#  @return None
def BZZDOnDay(curPlayer):
#    joinLineID = __GetPlayerFBLineID(curPlayer)
#    if joinLineID == None:
#        GameWorld.DebugLog("BZZDOnDay() level(%s) no enough" % curPlayer.GetLV())
#        return
#
#    hadEnterCnt = FBCommon.GetEnterFBCount(curPlayer, ChConfig.Def_FBMapID_BZZD)
#    maxEnterCnt = GetMaxEnterCnt(curPlayer)
    return
def OnFBPlayerOnLogin(curPlayer):
    playerID = curPlayer.GetPlayerID()
    historyEnterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_HistoryEnterCnt)
    expPerSecondDict = IpyGameDataPY.GetFuncEvalCfg("XjmjFirstEnter", 2, {})
    if historyEnterCnt not in expPerSecondDict:
        return
    playerExpTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_FirstEnterExpTime)
    if not playerExpTime:
        #GameWorld.DebugLog("还没进入过仙界秘境,不处理经验补时!", playerID)
        return
    mapID = GameWorld.GetMap().GetMapID()
    mapID = FBCommon.GetRecordMapID(mapID)
    if mapID == ChConfig.Def_FBMapID_BZZD:
        GameWorld.DebugLog("仙界秘境副本中,不处理经验补时!", playerID)
        return
    fbCfg = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_BZZD)
    fightTime = fbCfg[Def_FightTime]
    giveTime = max(0, fightTime - playerExpTime)
    if not giveTime:
        #GameWorld.DebugLog("经验补时时间已超过单次挑战时长,不处理经验补时!playerExpTime=%s" % playerExpTime, playerID)
        return
    expPerSecond = expPerSecondDict[historyEnterCnt]
    giveExp = expPerSecond * giveTime
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, FirstEnterExpTimeMax)
    if giveExp:
        giveExp = PlayerControl.PlayerControl(curPlayer).AddExp(giveExp, ShareDefine.Def_ViewExpType_Sys)
        GameWorld.DebugLog("玩家首次仙界秘境经验补时:%s秒,giveExp=%s" % (giveTime, giveExp), playerID)
    return
## 是否能够通过活动查询进入
#  @param curPlayer 玩家实例
#  @param mapID 地图ID
#  @param lineID 线路id
#  @param tick 时间戳
#  @return 布尔值
def OnEnterFBEvent(curPlayer, mapID, lineID, tick):
    return __CheckCanEnterBZZD(curPlayer, mapID, lineID)
## 检查可否进入百战之地
def __CheckCanEnterBZZD(curPlayer, mapID, lineID, enterCnt=1):
    return True
## 进入传送点
#  @param curPlayer
#  @param mapID 地图ID
#  @param lineId 分线ID
#  @param tick
#  @return 坐标列表(X,Y)
def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):
    if len(ipyEnterPosInfo) == 3:
        return ipyEnterPosInfo
    return ipyEnterPosInfo + [3]
##查询是否可以进入地图
# @param ask:请求结构体(IPY_BMChangeMapAsk)
# @param tick:时间戳
# @return IPY_GameWorld.cme 枚举
## 查询是否可以进入地图
def OnChangeMapAsk(ask, tick):
    return IPY_GameWorld.cmeAccept
## 开启副本
def OnOpenFB(tick):
    return
## 进副本
#  @param curPlayer
#  @param tick
#  @return None
def DoEnterFB(curPlayer, tick):
    playerID = curPlayer.GetPlayerID()
    playerLV = curPlayer.GetLV()
    curCopyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    teamID = curPlayer.GetTeamID()
    GameWorld.Log("DoEnterFB...playerCopyMapID=%s,curCopyMapID=%s,playerLV=%s,teamID=%s"
                  % (curPlayer.GetCopyMapID(), curCopyMapID, playerLV, teamID), playerID)
    lineID = GameWorld.GetGameWorld().GetLineID()
    GameWorld.Log("DoEnterFB..lineID=%s,playerLV=%s" % (lineID, playerLV), playerID)
    gameFB = GameWorld.GetGameFB()
    hadDelTicket = FBCommon.GetHadDelTicket(curPlayer)
    if not hadDelTicket:
@@ -199,29 +107,28 @@
        EventShell.EventRespons_FBEvent(curPlayer, 'passxjmj')
        FBCommon.UpdateFBEnterTick(curPlayer)
        gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_EnterLV, playerLV)
        PyGameData.g_bzzdPlayerKillNPCCntDict.pop(playerID, 0)
        
        logType = FBCommon.GetFBJoinType(curPlayer, False)
        EventReport.WriteEvent_FB(curPlayer, ChConfig.Def_FBMapID_BZZD, 0, ChConfig.CME_Log_Start, logType)
        historyEnterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_HistoryEnterCnt)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_HistoryEnterCnt, min(historyEnterCnt+1, 999))
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, 1)
        __GiveFirstEnterPrize(curPlayer, historyEnterCnt+1)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_HistoryEnterCnt, min(historyEnterCnt + 1, 999))
        __GiveFirstEnterPrize(curPlayer, historyEnterCnt + 1)
        
        # 初始化所需击杀NPC
        fairylandNPCList = IpyGameDataPY.GetFuncEvalCfg('FairylandNPC', 1)
        refreshNPCList = []
        for npcID, npcCount in fairylandNPCList:
            refreshNPCList += [npcID] * npcCount
        PyGameData.g_bzzdRefreshNPCListDict[lineID] = refreshNPCList
        gameFB.SetGameFBDict(BZZD_TotalNPCCount, len(refreshNPCList))
        
    fbPlayerCnt = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt)
    isTeamEnter = (teamID and fbPlayerCnt > 1)
    if not isTeamEnter:
        CheckHurtBuff(curPlayer, tick)
    CheckHurtBuff(curPlayer, tick)
    showState = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_GuideState, ChConfig.GuideState_BZZDShow)
    if not showState:
        if not isTeamEnter:
            FBCommon.SendFBEncourageInfo(curPlayer, 0)
            GameWorld.Log("首次单人进入该副本,需要等前端播完副本场景引导秀才正常进入准备阶段!", playerID)
            return
        else:
            GameWorld.Log("队伍方式进入该副本,不播放副本场景引导秀!", playerID)
        FBCommon.SendFBEncourageInfo(curPlayer, 0)
        GameWorld.Log("前端场景秀还没播完,需要等前端播完副本场景引导秀才正常进入准备阶段!", playerID)
        return
    fbStep = gameFB.GetFBStep()
    if fbStep < FB_Step_Prepare:
        FBCommon.SetFBStep(FB_Step_Prepare, tick)
@@ -236,15 +143,16 @@
        mapID = GameWorld.GetMap().GetMapID()
        notify_tick = FBCommon.GetFBLineStepTime(mapID)[Def_FightTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
        curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, max(notify_tick, 0), True)
        FBCommon.UpdateFBGrade(tick, FBCommon.GetFBLineGrade(mapID), curPlayer)
    # 上鼓舞buff
    encourageLV = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EncourageLV)
    if encourageLV > 0:
        FBCommon.AddFbEncourageBuff(curPlayer, FBPlayerDict_EncourageLV, tick)
    else:
        FBCommon.SendFBEncourageInfo(curPlayer, encourageLV)
    DoFBHelp(curPlayer, tick)
    return
def __GiveFirstEnterPrize(curPlayer, historyEnterCnt):
@@ -263,7 +171,7 @@
    return
def CheckHurtBuff(curPlayer, tick, isAdd=True):
    #人物等级低于世界等级X级,单人挑战仙界密境获得伤害BUFF加成
    ## 人物等级低于世界等级X级,单人挑战仙界密境获得伤害BUFF加成
    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_WorldLV):
        return
    playerID = curPlayer.GetID()
@@ -273,8 +181,8 @@
    curLV = curPlayer.GetLV()
    worldlv = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
    buffID = IpyGameDataPY.GetFuncCfg('XjmjAddHarm', 2)
    lvRange = IpyGameDataPY.GetFuncCfg('XjmjAddHarm')
    if isAdd and worldlv - curLV >=lvRange:
    lvRange = IpyGameDataPY.GetFuncCfg('XjmjAddHarm', 1)
    if isAdd and worldlv - curLV >= lvRange:
        curSkill = GameWorld.GetGameData().GetSkillBySkillID(buffID)
        SkillShell.__DoLogic_AddBuff(curPlayer, curPlayer, curSkill, False, tick, 0, 0)
    if not isAdd and worldlv - curLV < lvRange:
@@ -296,18 +204,16 @@
    curPlayer.Sync_TimeTick(IPY_GameWorld.tttAddUpTime, 0, max(notify_tick, 0), True)
    curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, max(notify_tick, 0), True)
    DoFBHelp(curPlayer, tick)
#
#    isFirstEnter = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_FirstEnterExpTime)
#    # 没有首次进入经验时间记录,可视为首次进入
#    if not isFirstEnter:
#        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, 1)
#        __GiveFirstEnterPrize(curPlayer)
    return
##玩家退出副本
# @param curPlayer 玩家实例
# @param tick 时间戳
# @return 无意义
## 关闭副本
def OnCloseFB(tick):
    #GameWorld.GetGameWorld().SetPropertyID(0)
    lineID = GameWorld.GetGameWorld().GetLineID()
    PyGameData.g_bzzdRefreshNPCListDict.pop(lineID, None)
    return
## 玩家退出副本
def DoExitFB(curPlayer, tick):
    # 清除鼓舞buff
    FBCommon.ClearEncourageBuff(curPlayer, tick)
@@ -316,47 +222,35 @@
    FBCommon.UpdFBLineNPCStrengthenLV(curPlayer.GetPlayerID(), True)
    return
##玩家主动离开副本.
# @param curPlayer 玩家实例
# @param tick 时间戳
# @return 返回值无意义
## 玩家主动离开副本
def DoPlayerLeaveFB(curPlayer, tick):
    return
## 玩家升级
def OnPlayerLVUp(curPlayer):
    CheckHurtBuff(curPlayer, GameWorld.GetGameWorld().GetTick(), False)
    FBCommon.UpdFBLineNPCStrengthenLV(curPlayer.GetPlayerID(), False)
    return
## 获得副本帮助信息
#  @param curPlayer 当前玩家(被通知对象)
#  @param tick 当前时间
#  @return None
def DoFBHelp(curPlayer, tick):
    gameFB = GameWorld.GetGameFB()
    playerID = curPlayer.GetID()
    
    # 获得副本信息
    #killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, BZZD_KillCnt)
    killNPCCnt = int(PyGameData.g_bzzdPlayerKillNPCCntDict.get(playerID, 0))
    passCnt = gameFB.GetGameFBDictByKey(BZZD_WaveIndex)
    passAllCnt = len(IpyGameDataPY.GetFuncEvalCfg('FairylandNPC'))
    killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_KillCnt)
    totalNPCCount = gameFB.GetGameFBDictByKey(BZZD_TotalNPCCount)
    exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)
    expPoint = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExpPoint)
    #副本帮助
    helpDict = {FBCommon.Help_npcTotal:killNPCCnt, FBCommon.Help_exp:exp, FBCommon.Help_expPoint:expPoint, FBCommon.Help_wheel:passCnt, 'passAllCnt':passAllCnt}
    helpDict = {FBCommon.Help_npcTotal:killNPCCnt, FBCommon.Help_npcTotalNeed:totalNPCCount,
                FBCommon.Help_exp:exp, FBCommon.Help_expPoint:expPoint}
    GameWorld.DebugLog("DoFBHelp %s" % str(helpDict))
    FBCommon.Notify_FBHelp(curPlayer, helpDict)
    return
##---副本总逻辑计时器---
# @param tick:时间戳
# @return 无意义
# @remarks 副本总逻辑计时器
def OnProcess(tick):
    fbStep = GameWorld.GetGameFB().GetFBStep()
    
@@ -373,8 +267,6 @@
    return
## 副本准备逻辑
#  @param tick:时间戳
#  @return 无意义
def __DoLogic_FB_Prepare(tick):
    #gameFB = GameWorld.GetGameFB()
    mapID = GameWorld.GetMap().GetMapID()
@@ -385,138 +277,54 @@
    
    # 设置开始刷怪
    CheckNPCRefresh(tick)
    
    # 副本开始
    FBCommon.SetFBStep(FB_Step_Fighting, tick)
    FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttTowerTake, fbCfg[Def_FightTime] * 1000)
    return
def CheckNPCRefresh(tick):
    #npc刷新检查
    gameFB = GameWorld.GetGameFB()
    lastCheckTick = gameFB.GetGameFBDictByKey(BZZD_LastCheckTick)
    playerManager = GameWorld.GetMapCopyPlayerManager()
    heroCnt = playerManager.GetPlayerCount()
    checkCD = eval(IpyGameDataPY.GetFuncCompileCfg('FairylandNPC', 2))
    
    if lastCheckTick and tick - lastCheckTick < checkCD:
    lineID = GameWorld.GetGameWorld().GetLineID()
    if lineID not in PyGameData.g_bzzdRefreshNPCListDict:
        return
    gameFB.SetGameFBDict(BZZD_LastCheckTick, tick)
    passSecond = (tick - GameWorld.GetGameFB().GetFBStepTick())/1000
    npcID, waveIndex = GetBZZDNPCID(passSecond)
    if not npcID:
    refreshNPCList = PyGameData.g_bzzdRefreshNPCListDict[lineID]
    if not refreshNPCList:
        return
    if gameFB.GetGameFBDictByKey(BZZD_WaveIndex) != waveIndex:
        gameFB.SetGameFBDict(BZZD_WaveIndex, waveIndex)
        for i in range(playerManager.GetPlayerCount()):
            curPlayer = playerManager.GetPlayerByIndex(i)
            DoFBHelp(curPlayer, tick)
    rMarkList = IpyGameDataPY.GetFuncEvalCfg('FairylandPoint')
    maxCnt = IpyGameDataPY.GetFuncCfg('FairylandPoint',2)
    firstRMarkList = IpyGameDataPY.GetFuncEvalCfg('FairylandPoint',3)
    allRmark = rMarkList+firstRMarkList
    npcCntDict = {mark:0 for mark in allRmark} #标识点对应数量
    npcCnt = 0
    gameNPC = GameWorld.GetNPCManager()
    for i in range(0, gameNPC.GetCustomNPCRefreshCount()):
    customNPCRefreshCount = gameNPC.GetCustomNPCRefreshCount()
    for i in xrange(customNPCRefreshCount):
        npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)
        npcCnt += npcRefresh.GetCount()
        rmark = npcRefresh.GetRefreshMark()
        npcCntDict[rmark] = npcCntDict.get(rmark, 0)+npcRefresh.GetCount()
    if not lastCheckTick:
        needAddCnt = IpyGameDataPY.GetFuncCfg('FairylandNPC', 3)
    else:
        needAddCnt = eval(IpyGameDataPY.GetFuncCompileCfg('FairylandNPCCnt'))
    if not needAddCnt:
        return
    markCntList = sorted(npcCntDict.iteritems(), key=lambda asd:asd[1])
    #GameWorld.Log('11111111111111111markCntList=%s'%markCntList)
    hasRefreshCnt = 0
    for rMark, curCnt in markCntList:
        if hasRefreshCnt >=needAddCnt:
        if npcRefresh.GetCount():
            continue
        rMark = npcRefresh.GetRefreshMark()
        npcID = refreshNPCList.pop(0) # 直接按顺序取NPCID
        NPCCustomRefresh.SetNPCRefresh(rMark, [npcID])
        if not refreshNPCList:
            GameWorld.DebugLog("怪全部刷完了,没怪了!")
            break
        cnt = min(maxCnt, needAddCnt-hasRefreshCnt)
        hasRefreshCnt +=cnt
        curMaxCnt = curCnt+cnt
        NPCCustomRefresh.SetNPCRefresh(rMark, [(npcID, cnt)], curMaxCnt, cnt)
    NPCCustomRefresh.ProcessAllNPCRefresh(tick) # 立即出发一次标识点刷新
    return
def CheckFirstEnterExp(tick, isOver=False):
    gameFB = GameWorld.GetGameFB()
    if not isOver:
        lastCheckExpTick = gameFB.GetGameFBDictByKey(BZZD_LastCheckExpTick)
        if not lastCheckExpTick:
            gameFB.SetGameFBDict(BZZD_LastCheckExpTick, tick)
            return
        if tick - lastCheckExpTick < 5000:
            return
    gameFB.SetGameFBDict(BZZD_LastCheckExpTick, tick) # 这个全局tick只是处理多久执行一次而已,不参与其他逻辑
    fightTime = int(math.ceil((tick - GameWorld.GetGameFB().GetFBStepTick()) / 1000.0)) # 已经战斗时长,秒
    expPerSecondDict = IpyGameDataPY.GetFuncEvalCfg("XjmjFirstEnter", 2, {})
    playerManager = GameWorld.GetMapCopyPlayerManager()
    playerCount = playerManager.GetPlayerCount()
    for i in xrange(playerCount):
        curPlayer = playerManager.GetPlayerByIndex(i)
        if not curPlayer:
            continue
        playerID = curPlayer.GetPlayerID()
        historyEnterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_HistoryEnterCnt)
        if historyEnterCnt not in expPerSecondDict:
            continue
        playerExpTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_FirstEnterExpTime)
        if playerExpTime >= fightTime:
            #GameWorld.DebugLog("已经处理完保底经验时间,不再处理!", playerID)
            continue
        
        updExpTime = FirstEnterExpTimeMax if isOver else fightTime
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, updExpTime)
        exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)
        expPoint = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExpPoint)
        playerTotalExp = expPoint * ChConfig.Def_PerPointValue + exp
        expPerSecond = expPerSecondDict[historyEnterCnt]
        minTotalExp = expPerSecond * fightTime # 理论保底最少经验
        giveExp = max(0, minTotalExp - playerTotalExp)
        if giveExp > 0:
            giveExp = PlayerControl.PlayerControl(curPlayer).AddExp(giveExp, ShareDefine.Def_ViewExpType_Sys)
            __RecordAddExp(curPlayer, giveExp, True)
        GameWorld.DebugLog("保底经验: updExpTime=%s,minTotalExp=%s,playerTotalExp=%s,giveExp=%s"
                           % (updExpTime, minTotalExp, playerTotalExp, giveExp), playerID)
    NPCCustomRefresh.ProcessAllNPCRefresh(tick) # 立即出发一次标识点刷新
    return
## 副本进行中
#  @param tick:时间戳
#  @return 无意义
def __DoLogic_FB_Fighting(tick):
    #gameFB = GameWorld.GetGameFB()
    mapID = GameWorld.GetMap().GetMapID()
    FBCommon.UpdateFBGrade(tick, FBCommon.GetFBLineGrade(mapID))
    fbCfg = FBCommon.GetFBLineStepTime(mapID)
    # 间隔未到
    if tick - GameWorld.GetGameFB().GetFBStepTick() < fbCfg[Def_FightTime] * 1000:
        CheckNPCRefresh(tick)
        CheckFirstEnterExp(tick)
        return
    __DoBZZDOver()
    return
        
##副本关闭中
# @param tick:时间戳
# @return 无意义
# @remarks 副本关闭中
def __DoLogic_FB_Over(tick):
    #gameFB = GameWorld.GetGameFB()
@@ -532,9 +340,6 @@
    return
## 检查是否可攻击, 主判定不可攻击的情况,其他逻辑由外层决定
#  @param attacker 攻击方
#  @param defender 防守方
#  @return bool
def CheckCanAttackTagObjInFB(attacker, defender):
    gameFB = GameWorld.GetGameFB()
    if gameFB.GetFBStep() != FB_Step_Fighting:
@@ -546,73 +351,30 @@
def OnGetNPCExp(curPlayer, curNPC):
    if not curPlayer:
        return 0
    #参数
    #baseExp     基础值
    #expMulti    仙界秘境经验效率
    #hurtValue   伤害值
    #npcMaxHP    怪物血量, 玩家进入副本时的等级对应怪物成长血量
    #reExp       等级经验效率, 取副本NPC等级
    #playerCnt   队员人数
    playerID = curPlayer.GetPlayerID()
    npcLV = max(curNPC.GetCurLV(), curNPC.GetLV())
    npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    gameFB = GameWorld.GetGameFB()
    reExp = gameFB.GetGameFBDictByKey(BZZD_ReExp % npcLV)
    if not reExp:
        lvIpyData = PlayerControl.GetPlayerLVIpyData(npcLV)
        reExp = 0 if not lvIpyData else lvIpyData.GetReExp()
        gameFB.SetGameFBDict(BZZD_ReExp % npcLV, reExp)
        GameWorld.DebugLog("初始化参数: npcID=%s,npcLV=%s,reExp=%s" % (npcID, npcLV, reExp), playerID)
    playerCnt = max(1, gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt))
    enterLV = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EnterLV)
    npcMaxHP = gameFB.GetGameFBDictByKey(BZZD_NPCMaxHP % (npcID, enterLV))
    if not npcMaxHP:
        enterLVAttrDict = NPCCommon.GetNPCStrengthenAttrDict(npcID, enterLV)
        npcMaxHP = enterLVAttrDict.get("MaxHP", 0)
        gameFB.SetGameFBDict(BZZD_NPCMaxHP % (npcID, enterLV), npcMaxHP)
        GameWorld.DebugLog("初始化参数: npcID=%s,enterLV=%s,npcMaxHP=%s" % (npcID, enterLV, npcMaxHP), playerID)
        if not npcMaxHP:
            GameWorld.ErrLog("无法获得NPC最大生命值,npcID=%s,enterLV=%s" % (npcID, enterLV), playerID)
            return 0
    reExp = PlayerControl.GetPlayerReExp(curPlayer)
    baseExp = curNPC.GetExp()
    expMulti = IpyGameDataPY.GetFuncCfg("XjmjMonsterExp", 2)
    curNPCMaxHP = GameObj.GetMaxHP(curNPC)
    teamPlayerHurtValue = AttackCommon.GetTeamPlayerHurtValue(curPlayer, curNPC)
    hurtValue = npcMaxHP if not curPlayer.GetTeamID() else teamPlayerHurtValue
    #GameWorld.DebugLog("击杀NPC: npcID=%s,baseExp=%s,expMulti=%s,hurtValue=%s,npcMaxHP=%s,curNPCMaxHP=%s,playerCnt=%s"
    #                   % (npcID, baseExp, expMulti, hurtValue, npcMaxHP, curNPCMaxHP, playerCnt), playerID)
    addExp = eval(IpyGameDataPY.GetFuncCompileCfg("XjmjMonsterExp", 1))
    
    addExp = eval(IpyGameDataPY.GetFuncCompileCfg("XjmjMonsterExp"))
    #GameWorld.DebugLog("    addExp=%s" % (addExp), playerID)
    if addExp <= 0:
        GameWorld.ErrLog("经验计算异常:  npcID=%s,npcLV=%s,reExp=%s,baseExp=%s,expMulti=%s,hurtValue=%s,npcMaxHP=%s,curNPCMaxHP=%s,playerCnt=%s"
                         % (npcID, npcLV, reExp, baseExp, expMulti, hurtValue, npcMaxHP, curNPCMaxHP, playerCnt), playerID)
    #GameWorld.DebugLog("击杀NPC: npcID=%s,reExp=%s,baseExp=%s,expMulti=%s,addExp=%s"
    #                   % (npcID, reExp, baseExp, expMulti, addExp), playerID)
    #累计击杀数
    curHurtValue = curNPCMaxHP if not curPlayer.GetTeamID() else teamPlayerHurtValue
    addKillCnt = curHurtValue / float(curNPCMaxHP)
    PyGameData.g_bzzdPlayerKillNPCCntDict[playerID] = PyGameData.g_bzzdPlayerKillNPCCntDict.get(playerID, 0) + addKillCnt
    #GameWorld.DebugLog("    增加玩家杀怪数: %s / %s = %s, %s" % (curHurtValue, curNPCMaxHP, addKillCnt, PyGameData.g_bzzdPlayerKillNPCCntDict), playerID)
    killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_KillCnt) + 1
    gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_KillCnt, killNPCCnt)
    DoFBHelp(curPlayer, GameWorld.GetGameWorld().GetTick())
    return addExp
## 获得经验
#  @param curPlayer 当前玩家
#  @param addExp 获得的经验
#  @param expViewType 经验类型
#  @return True or False
def OnGetExp(curPlayer, addExp, expViewType):
    
    if expViewType != ShareDefine.Def_ViewExpType_KillNPC:
        return
    
    __RecordAddExp(curPlayer, addExp)
    return
def __RecordAddExp(curPlayer, addExp, isSys=False):
    playerID = curPlayer.GetID() 
    gameFB = GameWorld.GetGameFB()
    exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)
@@ -624,37 +386,18 @@
    gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_TotalExp, updExp)
    gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_TotalExpPoint, updExpPoint)
    
    GameWorld.DebugLog("OnGetExp() totalExp=%s,addExp=%s,updTotalExp=%s,isSys=%s"
                       % (totalExp, addExp, updTotalExp, isSys), playerID)
    #GameWorld.DebugLog("OnGetExp() totalExp=%s,addExp=%s,updTotalExp=%s" % (totalExp, addExp, updTotalExp), playerID)
    killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_KillCnt)
    totalNPCCount = gameFB.GetGameFBDictByKey(BZZD_TotalNPCCount)
    if killNPCCnt >= totalNPCCount:
        GameWorld.DebugLog("怪物已全部杀完,结算副本!")
        __DoBZZDOver()
    return
### 执行副本杀怪逻辑
##  @param curPlayer 杀怪的人
##  @param curNPC 被杀的怪
##  @param tick 当前时间
##  @return None
#def DoFB_DropOwner(curPlayer, curNPC):
#    playerID = curPlayer.GetID()
#    gameFB = GameWorld.GetGameFB()
#    killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, BZZD_KillCnt)
#    gameFB.SetPlayerGameFBDict(playerID, BZZD_KillCnt, killNPCCnt + 1)
#
#    DoFBHelp(curPlayer, GameWorld.GetGameWorld().GetTick())
#    return
#关系有3层,无-友好-敌人
##判断是否可释放(增/减)技能或普攻
# @param curPlayer 玩家实例
# @param curTagPlayer 目标玩家实例
# @return 布尔值
def CheckPlayersRelation_IsNone(curPlayer, curTagPlayer):
    #PlayerControl.NotifyCode(curPlayer, "PK_lhs_272921")
    return True
## 副本结束处理
def __DoBZZDOver():
    tick = GameWorld.GetGameWorld().GetTick()
    CheckFirstEnterExp(tick, True) # 结算前强制处理一次
    
    playerManager = GameWorld.GetMapCopyPlayerManager()
    playerCount = playerManager.GetPlayerCount()
@@ -665,6 +408,10 @@
    fbCfg = FBCommon.GetFBLineStepTime(mapID)
    gameFB = GameWorld.GetGameFB()
    costTime = tick - gameFB.GetFBStepTick()
    FBCommon.UpdateFBGrade(tick, FBCommon.GetFBLineGrade(mapID)) # 结算前强制刷新一次评级
    grade = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade)
    rewardRateList = FBCommon.GetFBGradeRewardRateList(mapID)
    maxGrade = len(rewardRateList)
    
    for i in xrange(playerCount):
        curPlayer = playerManager.GetPlayerByIndex(i)
@@ -676,6 +423,12 @@
        exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)
        expPoint = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExpPoint)
        totalExp = expPoint * ChConfig.Def_PerPointValue + exp
        gradeAddExpRate = rewardRateList[maxGrade - grade]
        gradeExp = int(totalExp * gradeAddExpRate / 100.0)
        totalExp += gradeExp
        playerControl = PlayerControl.PlayerControl(curPlayer)
        playerControl.AddExp(gradeExp)
        
        expRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_TotalFightExp)
        expPointRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_TotalFightExpPoint)
@@ -684,23 +437,26 @@
        if totalExp > totalExpRecord:#超过旧记录
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_TotalFightExp, exp)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_TotalFightExpPoint, expPoint)
            upPer = (totalExp - totalExpRecord)*100/totalExpRecord if totalExpRecord else 0
            upPer = (totalExp - totalExpRecord) * 100 / totalExpRecord if totalExpRecord else 0
            #单场总经验成就
            PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_XJMJGetExp, 1, [expPoint])
            
        #killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, BZZD_KillCnt)
        killNPCCnt = int(PyGameData.g_bzzdPlayerKillNPCCntDict.get(playerID, 0))
        killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_KillCnt)
        
        # 通知结果
        enterLV = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EnterLV)
        __SendBZZDOverInfo(curPlayer, {FBCommon.Over_enterLV:enterLV,FBCommon.Over_exp:exp, FBCommon.Over_expPoint:expPoint,FBCommon.Over_costTime:costTime, FBCommon.Over_npcTotal:killNPCCnt, 'upPer':upPer})
        overDict = {FBCommon.Over_enterLV:enterLV, FBCommon.Over_exp:exp, FBCommon.Over_expPoint:expPoint, 'gradeExp':gradeExp,
                    FBCommon.Over_costTime:costTime, FBCommon.Over_npcTotal:killNPCCnt, 'upPer':upPer, FBCommon.Over_grade:grade}
        __SendBZZDOverInfo(curPlayer, overDict)
    # 进入离开阶段
    FBCommon.SetFBStep(FB_Step_Over, tick)
    FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttLeaveMap, fbCfg[Def_LeaveTime] * 1000)
    
    rMarkList = IpyGameDataPY.GetFuncEvalCfg('FairylandPoint')
    for rMark in rMarkList:
    gameNPC = GameWorld.GetNPCManager()
    for i in xrange(gameNPC.GetCustomNPCRefreshCount()):
        npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)
        rMark = npcRefresh.GetRefreshMark()
        NPCCustomRefresh.CloseNPCRefresh(rMark, tick)
    return
@@ -714,16 +470,11 @@
## 副本行为
#  @param curPlayer 玩家
#  @param actionType 行为类型
#  @param actionInfo 行为信息
#  @param tick 当前时间
#  @return None
def DoFBAction(curPlayer, actionType, actionInfo, tick):
    if actionType == 0:
        #第一次在百战之地鼓舞一次就满级
        FBCommon.FbEncourageBuff(curPlayer, FBPlayerDict_EncourageLV, actionInfo, tick)
        return
        return
    
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -62,7 +62,7 @@
g_delaySuccessDict = {} # 延迟处理成就
g_bzzdPlayerKillNPCCntDict = {} #仙界秘境玩家击杀NPC计数,支持小数点 {playerID:击杀数, }
g_bzzdRefreshNPCListDict = {} # 仙界秘境所需击杀的NPC队列 {lineID:[npcID, npcID, ...], ...}
g_operationActionDict = {} # {actName:actInfo, ...}