From ccaefa2a93fb82d0db5fc7e74832a292fb860984 Mon Sep 17 00:00:00 2001
From: xdh <xiefantasy@qq.com>
Date: 星期二, 22 一月 2019 14:23:20 +0800
Subject: [PATCH] 5919 【后端】【1.5.100】诛仙塔功能开发

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianBoss.py  |   63 ++--
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                     |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                                   |   32 ++
 ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py                                                             |    2 
 PySysDB/PySysDBPY.h                                                                                                    |   12 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetZhuXianTower.py                     |   44 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianTower.py |  642 ++++++++++++++++++++++++++++++++++++++++++
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                                          |    6 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                                      |   52 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                        |    6 
 10 files changed, 828 insertions(+), 37 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 10cdeba..58e8825 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1590,4 +1590,16 @@
 	WORD		KillTime;	//击杀总时间秒
 	WORD		RealmLV;	//需要境界
 	DWORD		ZhuXianScore;	//需要诛仙总评分
+};
+
+//诛仙塔表
+
+struct tagZhuXianTower
+{
+	DWORD		_ID;	//塔编号
+	DWORD		NPCID;	//npcid
+	list		FirstAward;	//首次S级奖励
+	dict		GradeAward;	//评级奖励
+	WORD		UnLockEquipPlace;	//解锁的装备位
+	DWORD		NeedPower;	//推荐战力
 };
\ No newline at end of file
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
index 5615d04..e4dbbe7 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChConfig.py
@@ -583,7 +583,7 @@
             ShareDefine.Def_BT_Campaign_PetLV           : 100,           #灵宠等级(开服活动榜)  
             ShareDefine.Def_BT_FCCostGold               : 5,             #消费排行榜(仙界盛典)
             ShareDefine.Def_BT_FBHelpBattle             : 100,           #助战次数榜
-            
+            ShareDefine.Def_BT_ZhuXianTower             : 100,           #诛仙塔榜
             ShareDefine.Def_BT_HighLadder               : 1000,          #玩家天梯竞技场排行
             ShareDefine.Def_BT_HighLadder_Yester        : 1000,          #玩家天梯竞技场昨日排行
             ShareDefine.Def_BT_RechargeTeHuiLast        : 20,            #充值特惠活动排行榜-上一期记录 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 6612111..8d88de9 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -27413,6 +27413,58 @@
 
 
 #------------------------------------------------------
+# B2 13 诛仙塔通关层数 #tagMCZhuXianTowerInfo
+
+class  tagMCZhuXianTowerInfo(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("Floor", c_int),    # 已通关层
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xB2
+        self.SubCmd = 0x13
+        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 = 0xB2
+        self.SubCmd = 0x13
+        self.Floor = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCZhuXianTowerInfo)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// B2 13 诛仙塔通关层数 //tagMCZhuXianTowerInfo:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                Floor:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.Floor
+                                )
+        return DumpString
+
+
+m_NAtagMCZhuXianTowerInfo=tagMCZhuXianTowerInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCZhuXianTowerInfo.Cmd,m_NAtagMCZhuXianTowerInfo.SubCmd))] = m_NAtagMCZhuXianTowerInfo
+
+
+#------------------------------------------------------
 # B4 11 新增恶意攻击玩家 #tagMCAddMaliciousAtkPlayer
 
 class  tagMCAddMaliciousAtkPlayer(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index 84a8327..ab6f754 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -570,6 +570,8 @@
     Def_BT_Campaign_Recharge,                 #累计充值(开服活动榜)
     Def_BT_Campaign_PetLV,                    #灵宠等级(开服活动榜)
     
+    Def_BT_ZhuXianTower,                      #诛仙塔榜
+    
     Def_BT_HighLadder,                        #天梯竞技场排行
     Def_BT_HighLadder_Yester,                 #天梯竞技场昨日排行
     Def_BT_RechargeTeHuiLast,                 #充值特惠活动排行榜-上一期记录
@@ -584,7 +586,7 @@
     Def_BT_CostTeHuiLast,                     #消费特惠排行榜上一期
     
     Def_BT_Max,                               #排行榜最大类型
-) = range(0, 32 + 2) 
+) = range(0, 33 + 2) 
     
 #职业对应战力排行榜类型
 JobFightPowerBillboardDict = {
@@ -596,7 +598,7 @@
 #排行榜Value1存储境界信息的榜单列表
 BTValue1_OfficialRankList = [Def_BT_FightPower, Def_BT_FightPower_Warrior, Def_BT_FightPower_Wizard, Def_BT_FightPower_Assassin, 
                              Def_BT_LV, Def_BT_FightPower_Horse, Def_BT_FightPower_Pet, Def_BT_TrialTower, Def_BT_OffLineEfficient,
-                             Def_BT_FBHelpBattle,
+                             Def_BT_FBHelpBattle, Def_BT_ZhuXianTower,
                              ]
 
 ##---比率---
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 2305cba..e3c76c7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -1809,6 +1809,8 @@
 Def_FBMapID_SealDemonEx = 52020
 #诛仙BOSS
 Def_FBMapID_ZhuXianBoss = 31380
+#诛仙塔
+Def_FBMapID_ZhuXianTower = 31370
 #仙魔之争
 Def_FBMapID_XMZZ = 31010
 #神兽副本
@@ -1918,6 +1920,7 @@
                 'CrossRealmPK':[Def_FBMapID_CrossRealmPK], #跨服竞技场
                 'GatherSoul':[Def_FBMapID_GatherSoul],#聚魂副本
                 'ZhuXianBoss':[Def_FBMapID_ZhuXianBoss],#诛仙BOSS
+                'ZhuXianTower':[Def_FBMapID_ZhuXianTower],#诛仙塔
                 }
 
 #特殊副本ID, 由系统分配, 进入时候不验证IsMapCopyFull
@@ -3644,7 +3647,8 @@
 #试炼之塔
 Def_Player_Dict_TrialTower_PassLV = "TrialTower_PassLV"  # 试炼之塔通关层数
 Def_Player_Dict_TrialTower_LastDayPassLV = "Tower_LastDayPassLV"  # 试炼之塔昨日通关层数
-
+#诛仙塔
+Def_Player_Dict_ZhuXianTowerPassLV = "ZhuXianTowerPassLV"  # 诛仙塔通关层数
 #古神禁地
 Def_Player_Dict_GodArea_Anger = "GodArea_Anger"  # 古神禁地怒气值
 Def_Player_Dict_GodArea_LastAddAngerTime = "GodArea_LastAddAngerTime"  # 古神禁地上一次增加怒气值的时间
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetZhuXianTower.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetZhuXianTower.py
new file mode 100644
index 0000000..3a1bd10
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetZhuXianTower.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.SetZhuXianTower
+#
+# @todo:诛仙塔过关数设置
+# @author xdh
+# @date 2019-01-21 16:10
+# @version 1.0
+#
+#
+# 详细描述: 诛仙塔过关数设置
+#
+#---------------------------------------------------------------------
+#"""Version = 2019-01-21 16:10"""
+#---------------------------------------------------------------------
+
+import GameLogic_ZhuXianTower
+import ShareDefine
+import PlayerBillboard
+import GameWorld
+#---------------------------------------------------------------------
+#全局变量
+#---------------------------------------------------------------------
+
+#---------------------------------------------------------------------
+## 逻辑实现
+## GM命令执行入口
+#  @param curPlayer
+#  @param cmdList 参数列表
+#  @return None
+def OnExec(curPlayer, cmdList):
+    if len(cmdList) != 1:
+        return
+    fbLevel = cmdList[0]
+    GameLogic_ZhuXianTower.SetZhuXianTowerCurPassLV(curPlayer, fbLevel)
+    #更新诛仙塔排行榜
+    PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_ZhuXianTower, fbLevel, 100)
+    GameLogic_ZhuXianTower.SyncZhuXianLevelInfo(curPlayer)
+    GameWorld.DebugAnswer(curPlayer, "诛仙塔过关数设置 floor=%s!"%fbLevel)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianBoss.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianBoss.py
index 83eee3e..19c2e58 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianBoss.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianBoss.py
@@ -27,16 +27,10 @@
 import ItemCommon
 import ChPyNetSendPack
 import ShareDefine
-import EventShell
-import NPCCustomRefresh
 import PlayerSuccess
 import PlayerActivity
 import NetPackCommon
 import ItemControler
-import PlayerMagicWeapon
-import PlayerBossReborn
-import PlayerFairyCeremony
-import PlayerWeekParty
 import EventReport
 
 FBDict_StartTick = 'FBDict_StartTick%s' #开始时间
@@ -48,7 +42,7 @@
 FBPlayerDict_Rank = "FBPlayerDict_Rank" # 玩家排名
 FBDict_BossTotalHP = 'FBDict_BossTotalHP%s' #BOSS血量
 
-g_npcHurtDict = {}
+g_heroHurtDict = {} #{playerID:hurt}
 
 
 def OnFBPlayerOnLogin(curPlayer):
@@ -151,9 +145,9 @@
 #  @param tick
 #  @return None
 def DoEnterFB(curPlayer, tick):
+    global g_heroHurtDict
     playerID = curPlayer.GetPlayerID()
-    mapID = GameWorld.GetMap().GetMapID()
-   
+
     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1    
     
     playerCnt = GameWorld.GetGameWorld().GetMapCopyPlayerManager().GetPlayerCount()
@@ -166,6 +160,7 @@
     if not hadDelTicket:
         FBCommon.SetHadDelTicket(curPlayer)
         PyGameData.g_fbPickUpItemDict.pop(playerID, 0)
+        g_heroHurtDict.pop(playerID, 0)
 #        if playerCnt == 1:
 #            posX, posY = IpyGameDataPY.GetFuncEvalCfg('ZhuXianBossFirstPos')
 #            GameWorld.ResetPlayerPos(curPlayer, posX, posY)
@@ -204,7 +199,6 @@
 # @param tick 时间戳
 # @return 无意义
 def DoExitFB(curPlayer, tick):
-    global g_npcHurtDict
     gameWorld = GameWorld.GetGameWorld()
     # 清除鼓舞buff
     FBCommon.ClearEncourageBuff(curPlayer, tick)
@@ -212,7 +206,6 @@
     if gameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 1:
         lineID = gameWorld.GetPropertyID() - 1
         PyGameData.g_ZhuXianBossPlayerHurtDict[lineID] = {}
-        g_npcHurtDict[lineID] = {}
         gameWorld.SetGameWorldDict(FBDict_StartTick % lineID, 0)
         GameWorld.GetGameFB().ClearGameFBDict()
         GameWorldProcess.CloseFB(tick)
@@ -255,12 +248,13 @@
 #  @return None
 def DoFBHelp(curPlayer, tick):
     #伤害排行信息
+    if GameWorld.GetGameFB().GetGameFBDictByKey(FBDict_IsOver):
+        return
     hurtInfo = []
     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
     playerHurtList = PyGameData.g_ZhuXianBossPlayerHurtDict.get(lineID, {}).items()
-    npcHurtList = g_npcHurtDict.get(lineID, {}).items()
-    
-    syncHurtList = (playerHurtList + npcHurtList)[:5]
+
+    syncHurtList = playerHurtList[:5]
     syncHurtList.sort(key=lambda asd:asd[1][1], reverse=True)
         
     for i, info in enumerate(syncHurtList, 1):
@@ -271,16 +265,16 @@
         hurtDict["hurt"] = hurt % ChConfig.Def_PerPointValue
         hurtDict["hurtEx"] = hurt / ChConfig.Def_PerPointValue
         hurtInfo.append(hurtDict)
-    myRank = __GetSelfHurtRank(curPlayer)
-    if myRank and myRank > 5:
-        hurtDict = {}
-        hurtDict["rank"] = myRank
-        info = playerHurtList[myRank - 1]
-        playerName, hurt = info[1][:2]
-        hurtDict["playerName"] = playerName
-        hurtDict["hurt"] = hurt % ChConfig.Def_PerPointValue
-        hurtDict["hurtEx"] = hurt / ChConfig.Def_PerPointValue
-        hurtInfo.append(hurtDict)
+#    myRank = __GetSelfHurtRank(curPlayer)
+#    if myRank and myRank > 5:
+#        hurtDict = {}
+#        hurtDict["rank"] = myRank
+#        info = playerHurtList[myRank - 1]
+#        playerName, hurt = info[1][:2]
+#        hurtDict["playerName"] = playerName
+#        hurtDict["hurt"] = hurt % ChConfig.Def_PerPointValue
+#        hurtDict["hurtEx"] = hurt / ChConfig.Def_PerPointValue
+#        hurtInfo.append(hurtDict)
     
     curSpeed = GameWorld.GetGameWorld().GetGameWorldDictByKey(FBDict_Speed % lineID) 
     isReduceing = GameWorld.GetGameWorld().GetGameWorldDictByKey(FBDict_IsReduceing % lineID) 
@@ -288,7 +282,11 @@
     totalHP = __GetBossTotalHP(lineID)
     hpReduceSpeed = curSpeed * 10000 / totalHP if totalHP else 0
     remainHPPer = min(100, remainHP * 100 / totalHP) if totalHP else 0
-    fbHelpDict = {FBCommon.Help_lineID:lineID, "hurtInfo":hurtInfo, 'hpReduceSpeed':hpReduceSpeed, 'remainHPPer':remainHPPer, 'isReduceing':isReduceing}
+    myHurt = g_heroHurtDict.get(curPlayer.GetID(), 0)
+    fbHelpDict = {FBCommon.Help_lineID:lineID, "hurtInfo":hurtInfo, 'hpReduceSpeed':hpReduceSpeed, 
+                  'remainHPPer':remainHPPer, 'isReduceing':isReduceing,'myHurt':myHurt % ChConfig.Def_PerPointValue,
+                  'myHurtEx':myHurt / ChConfig.Def_PerPointValue
+                  }
     GameWorld.DebugLog("DoFBHelp: %s" % fbHelpDict, curPlayer.GetPlayerID())
     FBCommon.Notify_FBHelp(curPlayer, fbHelpDict)
     return
@@ -328,6 +326,10 @@
     return
 #
 def UpdateHurtInfo(curPlayer, hurtHP, isAdd=False):
+    global g_heroHurtDict
+    playerID = curPlayer.GetPlayerID()
+    g_heroHurtDict[playerID] = g_heroHurtDict.get(playerID, 0) + hurtHP
+    
     enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % ChConfig.Def_FBMapID_ZhuXianBoss)
     if enterCnt >= FBCommon.GetEnterFBMaxCnt(curPlayer, ChConfig.Def_FBMapID_ZhuXianBoss):
         #没归属的不进伤害榜
@@ -335,7 +337,7 @@
     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
     
     playerName = curPlayer.GetName() 
-    playerID = curPlayer.GetPlayerID()
+    
     familyID = curPlayer.GetFamilyID()
     playerHurtDict = PyGameData.g_ZhuXianBossPlayerHurtDict.get(lineID, {})
     if playerID not in playerHurtDict:
@@ -361,14 +363,13 @@
         GameWorld.Log("强制踢出玩家关闭副本: overTick=%s,tick=%s" % (overTick, tick))
         FBCommon.DoLogic_FBKickAllPlayer()
         return
-    mapID = GameWorld.GetMap().GetMapID()
-   
+
     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
     if lineID <0:
         return
     gameWorld = GameWorld.GetGameWorld()
     startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)
-    if not startTick:
+    if not startTick or overTick:
         return
     FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 5000)
     __CheckBossHP(tick)
@@ -405,7 +406,7 @@
     playerManager = GameWorld.GetMapCopyPlayerManager()#GameWorld.GetPlayerManager()
     firstPlayer = playerManager.FindPlayerByID(firstPlayerID)
     if firstPlayer:
-        #gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_Rank, rank)
+        gameFB.SetPlayerGameFBDict(firstPlayerID, FBPlayerDict_Rank, 1)
         if not dropPosX or not dropPosY:
             dropPosX, dropPosY = firstPlayer.GetPosX(), firstPlayer.GetPosY()
         prizeItemList = GiveZhuXianBossAward(firstPlayer, lineID, dropItemMapInfo=[dropPosX, dropPosY, True])
@@ -548,7 +549,7 @@
             dropPosX, dropPosY = curBoss.GetPosX(), curBoss.GetPosY()
         
         #结束 设置BOSS死亡
-
+        FBCommon.ClearFBNPC()
         FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)
         GameWorld.DebugLog('结束 设置BOSS死亡 lineID=%s' % lineID)
         playerHurtList = __GetSortHurtList(lineID)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianTower.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianTower.py
new file mode 100644
index 0000000..9e58080
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_ZhuXianTower.py
@@ -0,0 +1,642 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+#-------------------------------------------------------------------------------
+#
+##@package GameWorldLogic.FBProcess.GameLogic_ZhuXianTower
+#
+# @todo:诛仙塔
+# @author xdh
+# @date 2019-01-21
+# @version 1.0
+# 详细描述: 诛仙塔
+#
+#---------------------------------------------------------------------
+#"""Version = 2019-01-21 11:00"""
+#---------------------------------------------------------------------
+
+import FBCommon
+import GameWorld
+import IPY_GameWorld
+import PlayerControl
+import NPCCustomRefresh
+import ChPyNetSendPack
+import ItemControler
+import NetPackCommon
+import ShareDefine
+import IpyGameDataPY
+import ItemCommon
+import ChConfig
+import ChPlayer
+import PlayerSuccess
+import GameWorldProcess
+import PlayerBillboard
+import EventReport
+
+import random
+import math
+
+Def_MaxStar = 5  #S级评级
+
+FBDict_Level = 'FBDict_Level'  # 副本关卡
+FBDict_FBStar = 'FBDict_FBStar'  # 当前副本星级
+FBDict_isFirstS= 'FBDict_isFirstS'  # 是否首次S级过关
+FBDict_StartTick = 'FBDict_StartTick'  #开始时间
+FBDict_Speed = 'FBDict_Speed'  #掉血速度 /s
+FBDict_RemainHP = 'FBDict_RemainHP'  #剩余时间
+FBDict_IsReduceing = 'FBDict_IsReduceing'  #是否掉血中
+FBDict_BossTotalHP = 'FBDict_BossTotalHP'  #BOSS血量
+FBDict_LastHurtTick = 'FBDict_LastHurtTick'  #上次伤害时间
+FBDict_HasGiveAward = 'FBDict_HasGiveAward'  # 是否有给奖励
+
+# 副本通用配置
+(
+Def_PrepareTime,  # 每关准备时间,秒
+Def_FightTime,  # 每关战斗时间,秒
+Def_ExitTime,  # 退出时间, 秒
+Def_StarTime,  # 星级对应耗时配置, 秒
+) = range(4)
+
+# 副本状态
+(
+FB_State_Open,  # 副本开启
+FB_State_FightPrepare,  # 战斗准备时间
+FB_State_Fighting,  # 战斗
+FB_State_FreeTime,  # 活动结束准备(胜利/失败)
+FB_State_Close,  # 关闭副本
+) = range(5)
+
+
+## 诛仙塔配置
+def __GetZhuXianCfg(): return FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_ZhuXianTower)
+
+
+def GetTowerIpyData(level):
+    return IpyGameDataPY.GetIpyGameData('ZhuXianTower', level)
+
+
+def OnFBPlayerLogin(curPlayer):
+    SyncZhuXianLevelInfo(curPlayer)
+    return
+
+
+## 同步诛仙塔关卡信息
+#  @fbLevel 为0时默认全部同步,> 0时仅同步该关卡
+def SyncZhuXianLevelInfo(curPlayer):
+    ttInfo = ChPyNetSendPack.tagMCZhuXianTowerInfo()
+    ttInfo.Clear()
+    ttInfo.Floor = __GetZhuXianTowerCurPassLV(curPlayer)
+    NetPackCommon.SendFakePack(curPlayer, ttInfo)
+    return
+
+
+## 获取当前已通关关卡
+def __GetZhuXianTowerCurPassLV(curPlayer):
+    return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ZhuXianTowerPassLV)
+
+
+## 更新当前已通关关卡
+def SetZhuXianTowerCurPassLV(curPlayer, passlv):
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ZhuXianTowerPassLV, passlv)
+    #PlayerRune.DoUnlockRuneHole(curPlayer)
+    
+    #PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_Tower, passlv, False)
+    GameWorld.DebugLog(' 更新诛仙塔已通关数 %s' % passlv)
+    return
+
+
+## 是否可进入
+#  @param curPlayer
+#  @param mapID 地图ID
+#  @param lineId 分线ID
+#  @param tick
+#  @return 是否可进入
+def OnEnterFBEvent(curPlayer, mapID, lineId, tick):    
+    return True
+
+
+## 检查可否进行挑战
+def __CheckCanChallenge(curPlayer):
+    #判断次数
+    enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % ChConfig.Def_FBMapID_ZhuXianTower)
+    if enterCnt >= FBCommon.GetEnterFBMaxCnt(curPlayer, ChConfig.Def_FBMapID_ZhuXianTower):
+        GameWorld.Log('进入次数不足!!')
+        return 0
+
+    curFloor = __GetZhuXianTowerCurPassLV(curPlayer)
+    ipyMgr = IpyGameDataPY.IPY_Data()
+    maxFloor = ipyMgr.GetZhuXianTowerByIndex(ipyMgr.GetZhuXianTowerCount() - 1).GetID()
+    if curFloor >= maxFloor:
+        return maxFloor
+    return curFloor + 1
+    
+##玩家切换地图
+def DoPlayerChangeMapLogic(curPlayer):
+    FBCommon.UpdateFBEnterTick(curPlayer)
+    return
+
+##副本玩家进入点
+# @param curPlayer 玩家实例
+# @param mapID 地图ID
+# @param lineId 分线ID
+# @param ipyEnterPosInfo 功能线路IPY配置坐标信息
+# @param tick 时间戳
+# @return posX, posY, 随机半径(可选)
+def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):
+    return ipyEnterPosInfo
+
+
+## 是否可以进入
+#  @param ask 请求信息
+#  @param tick
+#  @return 回复是否通过请求
+def OnChangeMapAsk(ask, tick):
+    return IPY_GameWorld.cmeAccept
+
+
+## 进副本
+#  @param curPlayer
+#  @param tick
+#  @return None
+def DoEnterFB(curPlayer, tick):
+    # 不做处理,有副本行为客户端发包选择挑战关卡
+    EventReport.WriteEvent_FB(curPlayer, ChConfig.Def_FBMapID_ZhuXianTower, 0, ChConfig.CME_Log_Start)
+    gameFB = GameWorld.GetGameFB()
+    fbStep = gameFB.GetFBStep()
+    ZhuXianCfg = __GetZhuXianCfg()
+    if fbStep <= FB_State_FightPrepare:
+        notify_tick = ZhuXianCfg[Def_PrepareTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
+        curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, max(notify_tick, 0), True)
+        
+    elif fbStep == FB_State_Fighting:
+        notify_tick = ZhuXianCfg[Def_FightTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
+        curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, max(notify_tick, 0), True)
+        __UpdZhuXianTowerFBStar(tick, True, curPlayer)
+    return
+
+
+## 副本时间到关闭
+#  @param tick 当前时间
+#  @return None
+#  @remarks 函数详细说明.
+def OnCloseFB(tick):
+    return
+
+
+##玩家退出副本.
+# @param curPlayer 玩家实例
+# @param tick 时间戳
+# @return 返回值无意义
+# @remarks 玩家主动离开副本.
+def DoExitFB(curPlayer, tick):
+    # 玩家退出默认关闭副本
+    #GameWorldProcess.CloseFB(tick)
+    return
+
+
+##副本总逻辑计时器
+# @param tick 时间戳
+# @return 无意义
+# @remarks 副本总逻辑计时器
+def OnProcess(tick):
+    gameFB = GameWorld.GetGameFB()
+    fbStep = gameFB.GetFBStep()
+    
+    if fbStep == FB_State_FightPrepare:
+        __DoLogic_FightPrepare(tick)
+    elif fbStep == FB_State_Fighting:
+        __DoLogic_Fighting(tick)
+        __CheckBossHP(tick)
+        __UpdZhuXianTowerFBStar(tick)
+        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 5000)
+    elif fbStep == FB_State_FreeTime:
+        __DoLogic_FreeTime(tick)
+    elif fbStep == FB_State_Close:
+        pass
+    
+    return
+
+
+## 更新当前副本星级
+def __UpdZhuXianTowerFBStar(tick, isEnter=False, curPlayer=None):
+    gameFB = GameWorld.GetGameFB()
+    fbStep = gameFB.GetFBStep()
+    if fbStep != FB_State_Fighting:
+        return
+    curStar = gameFB.GetGameFBDictByKey(FBDict_FBStar)
+    if curStar == 1:
+        return curStar
+    
+    mapID = GameWorld.GetMap().GetMapID()
+    useSecond = int(math.ceil((tick - gameFB.GetFBStepTick()) / 1000.0))
+    chaosDemonCfg = FBCommon.GetFBLineStepTime(mapID)
+    starTimeList = chaosDemonCfg[Def_StarTime]
+    diffSecond = 0
+    updStar = 1  # 默认至少1星
+    for star, starTime in enumerate(starTimeList, 2):
+        if useSecond <= starTime:
+            updStar = star
+            diffSecond = starTime - useSecond
+            
+    if curStar == updStar and not isEnter:
+        return curStar
+        
+    gameFB.SetGameFBDict(FBDict_FBStar, updStar)
+    
+    GameWorld.DebugLog("__UpdFBStar useSecond=%s,curStar=%s,updStar=%s, diffSecond=%s" 
+                       % (useSecond, curStar, updStar, diffSecond))
+    
+    if curPlayer:
+        DoFBHelp(curPlayer, tick)
+        if updStar != 1:
+            curPlayer.Sync_TimeTick(IPY_GameWorld.tttFlagTake, 0, diffSecond * 1000, True)
+    else:
+        playerManager = GameWorld.GetMapCopyPlayerManager()
+        for index in xrange(playerManager.GetPlayerCount()):
+            curPlayer = playerManager.GetPlayerByIndex(index)
+            if not curPlayer:
+                continue
+            DoFBHelp(curPlayer, tick)
+            if updStar != 1:
+                curPlayer.Sync_TimeTick(IPY_GameWorld.tttFlagTake, 0, diffSecond * 1000, True)
+            
+    return updStar
+
+
+## 获取BossID
+def __GetZhuXianBossID(fbLevel=-1):
+    gameFB = GameWorld.GetGameFB()
+    if fbLevel == -1:
+        fbLevel = gameFB.GetGameFBDictByKey(FBDict_Level)
+    ipyData = GetTowerIpyData(fbLevel)
+    
+    if not ipyData:
+        GameWorld.ErrLog("__GetZhuXianBossID() can not find %s in tagZhuXianTower.txt" % fbLevel)
+        return 0
+    return ipyData.GetNPCID()
+
+
+##战斗准备时间
+# @param tick  时钟
+# @return 无意义
+def __DoLogic_FightPrepare(tick):
+    gameFB = GameWorld.GetGameFB()
+    ZhuXianCfg = __GetZhuXianCfg()
+    if tick - gameFB.GetFBStepTick() < ZhuXianCfg[Def_PrepareTime] * 1000:
+        return
+    bossID = __GetZhuXianBossID()
+    if not bossID:
+        FBCommon.DoLogic_FBKickAllPlayer()
+        return
+    
+    FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttTowerTake, ZhuXianCfg[Def_FightTime] * 1000)
+    
+    NPCCustomRefresh.SetNPCRefresh(FBCommon.GetFBLineRefreshNPC(ChConfig.Def_FBMapID_ZhuXianTower, 0), [bossID])
+    
+    #转入战斗
+    FBCommon.SetFBStep(FB_State_Fighting, tick)
+    return
+
+
+## 开始副本关卡
+def StartFBLevel(curPlayer, fbLevel, tick):
+    
+    if curPlayer.GetPlayerAction() == IPY_GameWorld.paDie:
+        GameWorld.DebugLog("复活玩家...", curPlayer.GetPlayerID())
+        ChPlayer.PlayerRebornByType(curPlayer, ChConfig.rebornType_City, tick)
+    curPlayer.SetHP(curPlayer.GetMaxHP())
+    FBCommon.ClearFBNPC()
+    
+    gameFB = GameWorld.GetGameFB()
+    gameFB.SetGameFBDict(FBDict_Level, fbLevel)
+    playerPower = curPlayer.GetFightPower()
+    ipyData = GetTowerIpyData(fbLevel)
+    needPower = ipyData.GetNeedPower()
+    totalHP = eval(IpyGameDataPY.GetFuncCompileCfg('ZhuXianTowerBossTime'))
+    gameFB.SetGameFBDict(FBDict_BossTotalHP, totalHP * 1000)
+    gameFB.SetGameFBDict(FBDict_Speed, 1000)  #速度默认1000
+    gameFB.SetGameFBDict(FBDict_RemainHP, totalHP * 1000)
+    prepareTick = __GetZhuXianCfg()[Def_PrepareTime] * 1000
+    FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttAddUpTime, prepareTick)
+    FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttWaitStart, prepareTick)
+    FBCommon.SetFBStep(FB_State_FightPrepare, tick)
+
+    DoFBHelp(curPlayer, tick)
+    GameWorld.DebugLog("StartFBLevel, fbLevel=%s,totalHP=%s" % (fbLevel, totalHP), curPlayer.GetPlayerID())
+    return
+
+
+##战斗时间
+# @param tick  时钟
+# @return 无意义
+def __DoLogic_Fighting(tick):
+    gameFB = GameWorld.GetGameFB()
+    
+    #判断时间结束
+    if tick - gameFB.GetFBStepTick() < __GetZhuXianCfg()[Def_FightTime] * 1000:
+        lastHurtTick = gameFB.GetGameFBDictByKey(FBDict_LastHurtTick)
+        if lastHurtTick and tick - lastHurtTick >= 2000:
+            StopReduceHP(tick)
+            GameWorld.GetGameFB().SetGameFBDict(FBDict_LastHurtTick, 0)
+        return
+    
+    fbLevel = gameFB.GetGameFBDictByKey(FBDict_Level)
+    playerManager = GameWorld.GetMapCopyPlayerManager()
+    for index in xrange(playerManager.GetPlayerCount()):
+        curPlayer = playerManager.GetPlayerByIndex(index)
+        if not curPlayer:
+            continue
+        __SendZhuXianTowerOverInfo(curPlayer, fbLevel, False)
+    
+    #游戏结束
+    __SetFBToFreeTime(tick)
+    return
+
+
+##设置副本进入离开状态
+# @param tick  时钟
+# @return 无意义
+def __SetFBToFreeTime(tick):
+    FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttLeaveMap, __GetZhuXianCfg()[Def_ExitTime] * 1000)
+    FBCommon.SetFBStep(FB_State_FreeTime, tick)
+    return
+
+
+##比赛结束的空闲时间
+# @param tick  时钟
+# @return 无意义
+# @remarks 比赛结束的空闲时间
+def __DoLogic_FreeTime(tick):
+    if tick - GameWorld.GetGameFB().GetFBStepTick() < __GetZhuXianCfg()[Def_ExitTime] * 1000:
+        return
+    
+    #FBCommon.DoLogic_FBKickAllPlayer()
+    return
+
+
+def DoZhuXianTowerOver(tick):
+    gameFB = GameWorld.GetGameFB()
+    fbLevel = gameFB.GetGameFBDictByKey(FBDict_Level)
+    # 过关全服广播
+    ipyData = GetTowerIpyData(fbLevel)
+    if not ipyData:
+        return
+    curPlayer = FBCommon.GetCurSingleFBPlayer()
+    if not curPlayer:
+        GameWorldProcess.CloseFB(tick)
+        return
+    # 记录过关
+    #EventReport.WriteEvent_FB(curPlayer, ChConfig.Def_FBMapID_ZhuXianTower, 0, ChConfig.CME_Log_End, 0, 1)
+    unLockEquipPlace = ipyData.GetUnLockEquipPlace()
+    if unLockEquipPlace:
+        PlayerControl.WorldNotify(0, 'KillGodTowerInfo_1', [curPlayer.GetPlayerName(), fbLevel, unLockEquipPlace])
+    ipyMgr = IpyGameDataPY.IPY_Data()
+    maxFloor = ipyMgr.GetZhuXianTowerByIndex(ipyMgr.GetZhuXianTowerCount() - 1).GetID()
+    # 过关时间
+    costTime = tick - GameWorld.GetGameFB().GetFBStepTick()
+    curStar = gameFB.GetGameFBDictByKey(FBDict_FBStar)
+    isFirstS = 0
+    if fbLevel < maxFloor and curStar == Def_MaxStar:
+        #更新关卡
+        SetZhuXianTowerCurPassLV(curPlayer, fbLevel)
+        #更新诛仙塔排行榜
+        PlayerBillboard.UpdatePlayerBillboard(curPlayer, ShareDefine.Def_BT_ZhuXianTower, fbLevel, costTime/1000)
+        isFirstS = 1  #是否首次S通关
+    gameFB.SetGameFBDict(FBDict_isFirstS, isFirstS)
+    # 给过关奖励
+    prizeItemList = __GiveFBPassPrize(curPlayer, False)
+    
+    prizeDict = {FBCommon.Over_costTime:costTime, FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(prizeItemList)}
+    __SendZhuXianTowerOverInfo(curPlayer, fbLevel, True if prizeItemList else False, prizeDict)
+    
+    #任务
+    #EventShell.EventRespons_ZhuXianTowerCnt(curPlayer, fbLevel)
+    
+    SyncZhuXianLevelInfo(curPlayer)  # 同步最新关卡信息
+    __SetFBToFreeTime(tick)
+    #每日任务
+    #PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_Tower)
+    return
+
+
+## 杀怪
+#  @param curPlayer
+#  @param curNPC 被杀的怪
+#  @param tick
+#  @return None
+def DoFB_Player_KillNPC(curPlayer, curNPC, tick):
+    
+    return
+
+
+## 给过关奖励
+def __GiveFBPassPrize(curPlayer, isGive=True):
+    gameFB = GameWorld.GetGameFB()
+    preFloor = gameFB.GetGameFBDictByKey(FBDict_Level)
+    ipyData = GetTowerIpyData(preFloor)
+    if not ipyData:
+        return []
+    
+    isFirstPass = gameFB.GetGameFBDictByKey(FBDict_isFirstS)  #是否首次s通关
+    if isFirstPass:
+        prizeItemList = ipyData.GetFirstAward()
+    else:
+        curStar = gameFB.GetGameFBDictByKey(FBDict_FBStar)
+        prizeItemList = ipyData.GetGradeAward().get(curStar, [])
+    if not prizeItemList:
+        return []
+    if not isGive:
+        return prizeItemList
+    if gameFB.GetGameFBDictByKey(FBDict_HasGiveAward):
+        GameWorld.Log('本层奖励已给,不能重复给!!', curPlayer.GetID())
+        return
+    
+    # 发邮件或放入背包
+    needSpace = len(prizeItemList)
+    emptySpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)
+    isSendMail = int(needSpace > emptySpace)  # 是否发送邮件
+    if isSendMail:
+        PlayerControl.SendMailByKey('KillGodTowerReward', [curPlayer.GetPlayerID()], prizeItemList)
+        GameWorld.DebugLog("背包空间不够,发送邮件: mailItemList=%s" % str(prizeItemList), curPlayer.GetPlayerID())
+    else:
+        for itemID, itemCnt, isBind in prizeItemList:
+            ItemControler.GivePlayerItem(curPlayer, itemID, itemCnt, isBind, [IPY_GameWorld.rptItem],
+                                            event=["ZhuXianTower", False, {}])
+            
+    FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_ZhuXianTower, 1)
+        
+    gameFB.SetGameFBDict(FBDict_HasGiveAward, 1)
+    
+    return
+
+
+##副本帮助信息
+# @param curPlayer 玩家实例
+# @param tick 时间戳
+# @return 无意义
+# @remarks 用于通知阵营比分条
+def DoFBHelp(curPlayer, tick):
+    gameFB = GameWorld.GetGameFB()
+    star = gameFB.GetGameFBDictByKey(FBDict_FBStar)
+    
+    curSpeed = gameFB.GetGameFBDictByKey(FBDict_Speed) 
+    isReduceing = gameFB.GetGameFBDictByKey(FBDict_IsReduceing) 
+    remainHP = GetBossRemainHP(tick)
+    totalHP = __GetBossTotalHP()
+    hpReduceSpeed = curSpeed * 10000 / totalHP if totalHP else 0
+    remainHPPer = min(100, remainHP * 100 / totalHP) if totalHP else 0
+    fbLevel = gameFB.GetGameFBDictByKey(FBDict_Level)
+    fbHelpDict = {FBCommon.Help_wheel:fbLevel, FBCommon.Help_grade:star, 'hpReduceSpeed':hpReduceSpeed, 'remainHPPer':remainHPPer, 'isReduceing':isReduceing}
+    GameWorld.DebugLog("DoFBHelp: %s" % fbHelpDict, curPlayer.GetPlayerID())
+    FBCommon.Notify_FBHelp(curPlayer, fbHelpDict)
+    return
+
+
+## 发送挑战结果信息
+def __SendZhuXianTowerOverInfo(curPlayer, fbLevel, isPass, overDict={}):
+    
+    overDict[FBCommon.Over_dataMapID] = ChConfig.Def_FBMapID_ZhuXianTower
+    overDict[FBCommon.Over_wheel] = fbLevel
+    overDict[FBCommon.Over_isPass] = int(isPass)
+    GameWorld.DebugLog("__SendZhuXianTowerOverInfo overDict=%s" % (str(overDict)), curPlayer.GetPlayerID())
+    FBCommon.Notify_FB_Over(curPlayer, overDict)
+    return
+
+
+## 检查是否可攻击, 主判定不可攻击的情况,其他逻辑由外层决定
+#  @param attacker 攻击方
+#  @param defender 防守方
+#  @return bool
+def CheckCanAttackTagObjInFB(attacker, defender):
+    gameFB = GameWorld.GetGameFB()
+    if gameFB.GetFBStep() != FB_State_Fighting:
+        return False
+    return True
+
+
+##玩家死亡.
+# @param curPlayer:死亡的玩家 
+# @param tick 时间戳
+# @return 返回值无意义
+# @remarks 玩家主动离开副本.
+def DoPlayerDead(curPlayer):
+    gameFB = GameWorld.GetGameFB()
+    fbLevel = gameFB.GetGameFBDictByKey(FBDict_Level)
+    __SendZhuXianTowerOverInfo(curPlayer, fbLevel, False)
+    tick = GameWorld.GetGameWorld().GetTick()
+    #游戏结束
+    __SetFBToFreeTime(tick)
+    return
+
+
+## 是否副本复活
+#  @param None
+#  @return 是否副本复活
+def OnPlayerReborn():
+    return True
+
+
+## 副本行为
+#  @param curPlayer 玩家
+#  @param actionType 行为类型
+#  @param actionInfo 行为信息
+#  @param tick 当前时间
+#  @return None
+def DoFBAction(curPlayer, actionType, actionInfo, tick):
+    # 默认为选择关卡,由客户端决定,进场及副本选关通用此行为
+    gameFB = GameWorld.GetGameFB()
+    fbStep = gameFB.GetFBStep()
+    if actionType == 0:
+
+        if fbStep in [FB_State_FightPrepare, FB_State_Fighting]:
+            GameWorld.DebugLog("准备或战斗中, 无法变更关卡!")
+            return
+        newFloor = __CheckCanChallenge(curPlayer)
+        if not newFloor:
+            FBCommon.DoLogic_FBKickAllPlayer()
+            return
+        
+        StartFBLevel(curPlayer, newFloor, tick)
+    elif actionType == 1:
+        #领取奖励
+        if fbStep != FB_State_FreeTime:
+            return
+        __GiveFBPassPrize(curPlayer, False)
+    return
+
+
+def __CheckBossHP(tick):
+    gameFB = GameWorld.GetGameFB()
+    fbStep = gameFB.GetFBStep()
+
+    if fbStep == FB_State_Fighting and GetBossRemainHP(tick) == 0:
+        #结束 设置BOSS死亡
+        FBCommon.ClearFBNPC()
+        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)
+        GameWorld.DebugLog('结束 设置BOSS死亡 ')
+        
+        DoZhuXianTowerOver(tick)
+        
+    return
+
+
+def StopReduceHP(tick):
+    ##暂停BOSS血量减少
+    gameFB = GameWorld.GetGameFB()
+    if not gameFB.GetGameFBDictByKey(FBDict_IsReduceing):
+        return
+    remainHP = GetBossRemainHP(tick)
+    if not remainHP:
+        return
+    gameFB.SetGameFBDict(FBDict_IsReduceing, 0)
+    gameFB.SetGameFBDict(FBDict_RemainHP, remainHP)
+    GameWorld.DebugLog('    暂停BOSS血量减少')
+    return
+
+
+def StartReduceHP(tick):
+    ##开始BOSS掉血
+    gameFB = GameWorld.GetGameFB()
+    if gameFB.GetGameFBDictByKey(FBDict_IsReduceing):
+        return
+    gameFB.SetGameFBDict(FBDict_IsReduceing, 1)
+    startTick = gameFB.GetGameFBDictByKey(FBDict_StartTick)
+    if not startTick:
+        gameFB.SetGameFBDict(FBDict_RemainHP, __GetBossTotalHP())
+    gameFB.SetGameFBDict(FBDict_StartTick, tick)
+    GameWorld.DebugLog('    开始BOSS掉血')
+    
+    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)
+    return
+
+
+def __GetBossTotalHP():return GameWorld.GetGameFB().GetGameFBDictByKey(FBDict_BossTotalHP)
+    
+
+def GetBossRemainHP(tick):
+    gameFB = GameWorld.GetGameFB()
+    
+    startTick = gameFB.GetGameFBDictByKey(FBDict_StartTick)
+    lastSpeed = gameFB.GetGameFBDictByKey(FBDict_Speed) 
+    remainHP = gameFB.GetGameFBDictByKey(FBDict_RemainHP)
+    if not gameFB.GetGameFBDictByKey(FBDict_IsReduceing):
+        return remainHP
+    if not startTick:
+        startTick = tick
+        remainHP = __GetBossTotalHP()
+    else:
+        remainHP = max(0, int((remainHP - (tick - startTick) / 1000.0 * lastSpeed)))
+    return remainHP
+
+
+## 玩家对NPC造成伤害
+#  @param curPlayer 当前玩家
+#  @param curNPC 
+#  @param hurtHP 
+#  @return None
+def DoFB_Player_HurtNPC(curPlayer, curNPC, hurtHP):
+    tick = GameWorld.GetGameWorld().GetTick()
+    GameWorld.GetGameFB().SetGameFBDict(FBDict_LastHurtTick, tick)
+    StartReduceHP(tick)
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index 6def013..a7f3b91 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -1249,6 +1249,15 @@
                         ("WORD", "RealmLV", 0),
                         ("DWORD", "ZhuXianScore", 0),
                         ),
+
+                "ZhuXianTower":(
+                        ("DWORD", "ID", 1),
+                        ("DWORD", "NPCID", 0),
+                        ("list", "FirstAward", 0),
+                        ("dict", "GradeAward", 0),
+                        ("WORD", "UnLockEquipPlace", 0),
+                        ("DWORD", "NeedPower", 0),
+                        ),
                 }
 
 
@@ -3806,6 +3815,25 @@
     def GetKillTime(self): return self.KillTime # 击杀总时间秒
     def GetRealmLV(self): return self.RealmLV # 需要境界
     def GetZhuXianScore(self): return self.ZhuXianScore # 需要诛仙总评分
+
+# 诛仙塔表
+class IPY_ZhuXianTower():
+    
+    def __init__(self):
+        self.ID = 0
+        self.NPCID = 0
+        self.FirstAward = []
+        self.GradeAward = {}
+        self.UnLockEquipPlace = 0
+        self.NeedPower = 0
+        return
+        
+    def GetID(self): return self.ID # 塔编号
+    def GetNPCID(self): return self.NPCID # npcid
+    def GetFirstAward(self): return self.FirstAward # 首次S级奖励
+    def GetGradeAward(self): return self.GradeAward # 评级奖励
+    def GetUnLockEquipPlace(self): return self.UnLockEquipPlace # 解锁的装备位
+    def GetNeedPower(self): return self.NeedPower # 推荐战力
 
 
 def Log(msg, playerID=0, par=0):
@@ -4069,6 +4097,8 @@
         self.ipyLoginAwardLen = len(self.ipyLoginAwardCache)
         self.ipyZhuXianBossCache = self.__LoadFileData("ZhuXianBoss", IPY_ZhuXianBoss)
         self.ipyZhuXianBossLen = len(self.ipyZhuXianBossCache)
+        self.ipyZhuXianTowerCache = self.__LoadFileData("ZhuXianTower", IPY_ZhuXianTower)
+        self.ipyZhuXianTowerLen = len(self.ipyZhuXianTowerCache)
         Log("IPY_FuncConfig count=%s" % len(self.ipyFuncConfigDict))
         Log("IPY_DataMgr InitOK!")
         return
@@ -4473,6 +4503,8 @@
     def GetLoginAwardByIndex(self, index): return self.ipyLoginAwardCache[index]
     def GetZhuXianBossCount(self): return self.ipyZhuXianBossLen
     def GetZhuXianBossByIndex(self, index): return self.ipyZhuXianBossCache[index]
+    def GetZhuXianTowerCount(self): return self.ipyZhuXianTowerLen
+    def GetZhuXianTowerByIndex(self, index): return self.ipyZhuXianTowerCache[index]
 
 IPYData = IPY_DataMgr()
 def IPY_Data(): return IPYData
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 84a8327..ab6f754 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -570,6 +570,8 @@
     Def_BT_Campaign_Recharge,                 #累计充值(开服活动榜)
     Def_BT_Campaign_PetLV,                    #灵宠等级(开服活动榜)
     
+    Def_BT_ZhuXianTower,                      #诛仙塔榜
+    
     Def_BT_HighLadder,                        #天梯竞技场排行
     Def_BT_HighLadder_Yester,                 #天梯竞技场昨日排行
     Def_BT_RechargeTeHuiLast,                 #充值特惠活动排行榜-上一期记录
@@ -584,7 +586,7 @@
     Def_BT_CostTeHuiLast,                     #消费特惠排行榜上一期
     
     Def_BT_Max,                               #排行榜最大类型
-) = range(0, 32 + 2) 
+) = range(0, 33 + 2) 
     
 #职业对应战力排行榜类型
 JobFightPowerBillboardDict = {
@@ -596,7 +598,7 @@
 #排行榜Value1存储境界信息的榜单列表
 BTValue1_OfficialRankList = [Def_BT_FightPower, Def_BT_FightPower_Warrior, Def_BT_FightPower_Wizard, Def_BT_FightPower_Assassin, 
                              Def_BT_LV, Def_BT_FightPower_Horse, Def_BT_FightPower_Pet, Def_BT_TrialTower, Def_BT_OffLineEfficient,
-                             Def_BT_FBHelpBattle,
+                             Def_BT_FBHelpBattle, Def_BT_ZhuXianTower,
                              ]
 
 ##---比率---

--
Gitblit v1.8.0