From 35c596a6ed34680d9af09788274051c1c212d4eb Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 07 七月 2025 15:05:03 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(优化战斗武将跟NPC独立处理;去除程序无技能普攻,增加反击普攻;新增回合主动普攻技能功能类型23;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTask.py                 |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                   |   12 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py                 |   81 ++++++++++++++-----
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py   |   28 ++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py          |   11 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py                 |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                     |   28 +++---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BaseAttack.py                 |    3 
 PySysDB/PySysDBPY.h                                                                                      |    9 +-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py              |    7 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py      |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                          |   11 ++
 13 files changed, 151 insertions(+), 55 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 7c2cc68..28a3114 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -32,7 +32,8 @@
 	DWORD		_HeroID;	//英雄ID
 	BYTE		Country;	// 国家
 	BYTE		Quality;	// 品质
-	list		SkinNPCIDList;	// 皮肤NPCID列表
+	BYTE		AtkDistType;	//远近类型;1-近战;2-远程
+	list		SkinIDList;	// 皮肤ID列表
 	DWORD		NormalSkillID;	//普攻技能ID
 	DWORD		AngerSkillID;	//怒气技能ID
 	WORD		AtkInheritPer;	//攻击继承
@@ -83,10 +84,10 @@
 	list		AttrValueList;	// 属性值列表
 };
 
-//武将皮肤表
+//皮肤表
 struct	HeroSkin
 {
-	DWORD		_SkinNPCID;	//皮肤NPCID
+	DWORD		_SkinID;	//皮肤NPCID
 	list		WearAttrIDList;	// 穿戴属性ID列表
 	list		WearAttrValueList;	// 穿戴属性值列表
 	list		AllBatAttrIDList;	// 全体上阵属性ID列表
@@ -888,7 +889,7 @@
 	DWORD		_NPCID;	//NPCID
 	BYTE		FightPowerLackAtkLimit;	//战力不足限制攻击
 	DWORD		SuppressFightPower;	//推荐/压制战力
-	BYTE		AtkDictType;	//远近类型;1-近战;2-远程
+	BYTE		AtkDistType;	//远近类型;1-近战;2-远程
 	DWORD		Atk;	//攻击力
 	DWORD		Def;	//防御值
 	DWORD		MaxHP;	//最大生命值,可超过20E
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
index 389e148..7c2c9c7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
@@ -448,6 +448,28 @@
     #NPC读表取
     return attack.GetHurtType()
 
+def GetAtkDistType(curObj):
+    ## 获取是近战还是远程,默认近战
+    if curObj.GetGameObjType() != IPY_GameWorld.gotNPC:
+        return ChConfig.AtkDistType_Short
+    
+    playerID = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_LineupPlayerID)
+    if not playerID:
+        return ChConfig.AtkDistType_Short
+    
+    heroID = curObj.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
+    if heroID:
+        heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
+        if heroIpyData:
+            return heroIpyData.GetAtkDistType()
+        
+    npcID = curObj.GetNPCID()
+    npcDataEx = NPCCommon.GetNPCDataEx(npcID)
+    if npcDataEx:
+        return npcDataEx.GetAtkDistType()
+    
+    return ChConfig.AtkDistType_Short
+
 ## 输入基础数值,返回增强后的值 - 技能加强
 #  @param value 基础值
 #  @param skill 技能
@@ -1624,7 +1646,7 @@
         return
     
     if curSkill and curSkill.GetFuncType() not in [ChConfig.Def_SkillFuncType_FbSkill,
-                                          ChConfig.Def_SkillFuncType_NormalAttack]:
+                                          ChConfig.Def_SkillFuncType_TurnNormaAttack]:
         return
     
     if attacker.GetDictByKey(ChConfig.Def_PlayerKey_FirstDefender):
@@ -2075,7 +2097,7 @@
     
     # --- 新增普通攻击的数值和技能攻击的数值,根据类型各自计算
     if atkObjType == IPY_GameWorld.gotPlayer:
-        if not curSkill or curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_NormalAttack:
+        if not curSkill or curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_TurnNormaAttack:
             atkSkillPer += PlayerControl.GetNormalHurtPer(atkObj)
             atkSkillValue += PlayerControl.GetNormalHurt(atkObj)
         elif curSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_FbSkill, ChConfig.Def_SkillFuncType_FbPassiveSkill]:
@@ -2211,7 +2233,7 @@
     elif not curSkill:
         hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 3))
         GameWorld.DebugLog("    普攻伤害=%s" % (hurtValue))
-    elif SkillCommon.isNormalAtkSkill(curSkill):
+    elif SkillCommon.isTurnNormalAtkSkill(curSkill):
         hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 1))
         GameWorld.DebugLog("    普攻技能伤害=%s" % (hurtValue))
     elif SkillCommon.isXPSkill(curSkill):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BaseAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BaseAttack.py
index dbd61de..6069518 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BaseAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BaseAttack.py
@@ -1672,7 +1672,8 @@
     if not curSkill or (curSkill.GetSkillType() == ChConfig.Def_SkillType_Atk and\
                          curSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_FbSkill,
                                                     ChConfig.Def_SkillFuncType_PetSkill,
-                                                    ChConfig.Def_SkillFuncType_NormalAttack]):
+                                                    ChConfig.Def_SkillFuncType_NormalAttack,
+                                                    ChConfig.Def_SkillFuncType_TurnNormaAttack]):
         # 攻击减层级 优先处理,因为同个技能触发buff后,会再处理层级,导致立即减层级
         PassiveBuffEffMng.OnPassiveBuffTrigger(attacker, defender, curSkill, ChConfig.TriggerType_Buff_AttackSubLayer, tick)
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
index f0fb744..6520bac 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -35,12 +35,13 @@
 import ItemControler
 import SkillCommon
 import SkillShell
-import BaseAttack
+import AttackCommon
 
 import random
 import time
 import json
 
+FighterNPCID = 100 # 战斗NPCID,仅后端用,除怪物外,所有玩家武将均使用该NPCID
 PosNumMax = 10 # 最大站位编号
 ActionNumStart = -1 # 起始行动位置编号,一般是从1开始,如果有加主公、红颜等则扣除相应位置值,如从0或-1开始
 
@@ -374,6 +375,8 @@
                     tfObj = ChPyNetSendPack.tagSCTurnFightObj()
                     tfObj.ObjID = curNPC.GetID()
                     tfObj.NPCID = curNPC.GetNPCID()
+                    tfObj.HeroID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
+                    tfObj.SkinID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_SkinID)
                     tfObj.HP = curNPC.GetHP()
                     tfObj.HPEx = curNPC.GetHPEx()
                     tfObj.MaxHP = curNPC.GetMaxHP()
@@ -571,12 +574,15 @@
         heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
         if not heroIpyData:
             continue
-        
-        npcID = heroIpyData.GetSkinNPCIDList()[0]
+        skinIDList = heroIpyData.GetSkinIDList()
+        skinIndex = heroItem.GetUserAttr(ShareDefine.Def_IudetHeroSkin)
+        if skinIndex < 0 or skinIndex >= len(skinIDList):
+            continue
+        skinID = skinIDList[skinIndex]
         heroDict[str(posNum)] = {
-                                 "ID":heroID,
+                                 "HeroID":heroID,
+                                 "SkinID":skinID,
                                  "Data":heroItem.GetUserData(),
-                                 "NPCID":npcID
                                  }
         
         heroCount += 1
@@ -656,27 +662,33 @@
     tick = GameWorld.GetGameWorld().GetTick()
     
     initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
+    baseAtkSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 3)
     tfMgr = GetTurnFightMgr()
     space = 3
     for posNumKey, heroInfo in heroDict.items():
         posNum = int(posNumKey)
         
+        heroID, skinID = 0, 0
+        baseAtkSkillID = 0 # 基础普攻ID
         skillIDList = []
         if lineupPlayerID:
-            heroID = heroInfo.get("ID", 0)
-            npcID = heroInfo.get("NPCID", 0)
+            heroID = heroInfo.get("HeroID", 0)
+            skinID = heroInfo.get("SkinID", 0)
+            npcID = FighterNPCID
             heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
             if not heroIpyData:
                 continue
             normalSkillID = heroIpyData.GetNormalSkillID()
             angerSkillID = heroIpyData.GetAngerSkillID()
             skillIDList += [normalSkillID, angerSkillID]
+            atkDistType = heroIpyData.GetAtkDistType()
         else:
             npcID = heroInfo.get("NPCID", 0)
             npcDataEx = NPCCommon.GetNPCDataEx(npcID)
             if not npcDataEx:
                 continue
             skillIDList += npcDataEx.GetSkillIDList()
+            atkDistType = npcDataEx.GetAtkDistType()
             
         if not npcID:
             continue
@@ -701,19 +713,28 @@
         curSummon.SetVisible(True)
         curSummon.SetDict(ChConfig.Def_Obj_Dict_TurnFightPosInfo, num * 100 + posNum)
         curSummon.SetDict(ChConfig.Def_Obj_Dict_LineupPlayerID, lineupPlayerID)
+        curSummon.SetDict(ChConfig.Def_Obj_Dict_HeroID, heroID)
+        curSummon.SetDict(ChConfig.Def_Obj_Dict_SkinID, skinID)
         GameObj.SetFaction(curSummon, faction)
         GameObj.SetXP(curSummon, initXP, False)
         
+        if atkDistType == ChConfig.AtkDistType_Short:
+            baseAtkSkillID = baseAtkSkillIDList[0] if len(baseAtkSkillIDList) > 0 else 0
+        elif atkDistType == ChConfig.AtkDistType_Long:
+            baseAtkSkillID = baseAtkSkillIDList[1] if len(baseAtkSkillIDList) > 1 else 0
+            
         skillManager = curSummon.GetSkillManager()
         #有指定的技能,重新学习
         if skillIDList:
             skillManager.ResetSkill()
             for skillID in skillIDList:
                 skillManager.LVUPSkillByID(skillID)
-                
+        if baseAtkSkillID:
+            skillManager.LVUPSkillByID(baseAtkSkillID)
+            
         rebornX = posX - space + (faction - 1) * space * 3 + ((posNum - 1) / 3 * space * 2 * (-1 if faction == 1 else 1))
         rebornY = posY + (posNum - 1) % 3 * space
-        #GameWorld.DebugLog("Reborn ID:%s, faction:%s,posNum=%s, (%s,%s), %s" % (curSummon.GetID(), faction, posNum, rebornX, rebornY, skillIDList))
+        GameWorld.DebugLog("SummonNPC ID:%s,faction:%s,num=%s,posNum=%s,baseAtkSkillID=%s,%s" % (curSummon.GetID(), faction, num, posNum, baseAtkSkillID, skillIDList))
         curSummon.Reborn(rebornX, rebornY, False)
         NPCCommon.NPCControl(curSummon).DoNPCRebornCommLogic(tick)
         
@@ -1200,8 +1221,10 @@
     objName = gameObj.GetName()
     faction = GameObj.GetFaction(gameObj)
     posInfo = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo)
-    npcID = gameObj.GetNPCID()
-    return "%s%s %s[%s-%s]" % ("A" if faction == Def_FactionA else "B", posInfo, objName, gameObj.GetID(), npcID)
+    heroID = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
+    if not heroID:
+        heroID = gameObj.GetNPCID()
+    return "%s%s %s[%s-%s]" % ("A" if faction == Def_FactionA else "B", posInfo, objName, gameObj.GetID(), heroID)
 
 def EntryLogic(turnFight):
     ## 执行进场逻辑
@@ -1325,7 +1348,7 @@
     ## 攻击方增加的XP值根据主动普攻技能获得
     if not curSkill:
         return 0
-    if not SkillCommon.isNormalAtkSkill(curSkill):
+    if not SkillCommon.isTurnNormalAtkSkill(curSkill):
         return 0
     return IpyGameDataPY.GetFuncCfg("AngerXP", 3)
 
@@ -1363,7 +1386,16 @@
     if turnBattleType == ChConfig.TurnBattleType_AtkBack:
         if not tagObj:
             return
-        atkOK = BaseAttack.Attack(curNPC, tagObj, None, tick) # 反击为单体普攻
+        skillManager = curNPC.GetSkillManager()
+        for index in range(0, skillManager.GetSkillCount()):
+            skill = skillManager.GetSkillByIndex(index)
+            #已经到尾部了
+            if not skill or skill.GetSkillTypeID() == 0:
+                break
+            if skill.GetFuncType() == ChConfig.Def_SkillFuncType_NormalAttack:
+                useSkill = skill
+                break
+        atkOK = SkillShell.DoLogic_UseSkill(curNPC, tagObj, useSkill, tick)
     elif turnBattleType == ChConfig.TurnBattleType_Combo:
         if not tagObj:
             return
@@ -1373,12 +1405,15 @@
         xpMax = IpyGameDataPY.GetFuncCfg("AngerXP", 2) 
         skillManager = curNPC.GetSkillManager()
         useSkillList = []
-        GameWorld.DebugLog('skillCount=%s' % skillManager.GetSkillCount(), npcID)
+        #GameWorld.DebugLog('skillCount=%s' % skillManager.GetSkillCount(), npcID)
         for index in range(0, skillManager.GetSkillCount()):
             useSkill = skillManager.GetSkillByIndex(index)
             #已经到尾部了
             if not useSkill or useSkill.GetSkillTypeID() == 0:
                 break
+            if useSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_NormalAttack]:
+                #基础普攻不能主动释放,目前仅用于反击
+                continue
             #被动技能无法使用
             if SkillCommon.isPassiveSkill(useSkill):
                 continue
@@ -1406,12 +1441,6 @@
                 AddTurnFightXP(curNPC, __GetAddXP_Attack(curNPC, useSkill), "skillID:%s" % skillID)
                 break
             
-        if not atkOK:
-            tagObj = GetEnemyObj(curNPC)
-            if tagObj:
-                GameWorld.DebugLog('    无技能可攻击,直接使用普攻! tagID=%s(%s)' % (tagObj.GetID(), GetObjName(tagObj)), npcID)
-                atkOK = BaseAttack.Attack(curNPC, tagObj, None, tick)
-                
     curNPC.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0) # 无论攻击成功与否都重置战斗类型
     
     tagID = 0
@@ -1454,6 +1483,11 @@
     if posNum <= 0:
         GameWorld.DebugLog("            被非主战单位攻击时无法触发反击: atkID=%s,posNum=%s" % (atkObj.GetID(), posNum))
         return False
+    atkDistType = AttackCommon.GetAtkDistType(defObj)
+    if atkDistType == ChConfig.AtkDistType_Long:
+        if not IpyGameDataPY.GetFuncCfg("ParryCfg", 2):
+            GameWorld.DebugLog("            远程单位不可反击: defID=%s" % (defObj.GetID()))
+            return False
     defAtkBackRate = GameObj.GetAtkBackRate(defObj) # 防方反击率
     atkBackNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) # 已反击次数
     if atkBackNum > 10:
@@ -1707,12 +1741,13 @@
             for posNum, curNPC in batLineup.npcPosDict.items():
                 objID = curNPC.GetID()
                 npcID = curNPC.GetNPCID()
+                heroID = curNPC.GetDictByKey(ChConfig.Def_Obj_Dict_HeroID)
                 atkHurt = hurtStatDict.get(objID, 0)
                 defHurt = defStatDict.get(objID, 0)
                 cureHP = cureStatDict.get(objID, 0)
-                GameWorld.DebugLog("    Pos:%s ID=%s-%s,,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" 
-                                   % (posNum, objID, npcID, GameObj.GetHP(curNPC), GameObj.GetMaxHP(curNPC), atkHurt, defHurt, cureHP))
-                lineupStatInfo[str(posNum)] = {"ObjID":objID, "NPCID":npcID, "AtkHurt":atkHurt, "DefHurt":defHurt, "CureHP":cureHP}
+                GameWorld.DebugLog("    Pos:%s ID=%s-%s-%s,,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" 
+                                   % (posNum, objID, npcID, heroID, GameObj.GetHP(curNPC), GameObj.GetMaxHP(curNPC), atkHurt, defHurt, cureHP))
+                lineupStatInfo[str(posNum)] = {"ObjID":objID, "HeroID":heroID, "NPCID":npcID, "AtkHurt":atkHurt, "DefHurt":defHurt, "CureHP":cureHP}
                 
     awardItemList = []
     playerID = turnFight.playerID
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 577ddea..27b0449 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -2946,6 +2946,8 @@
 #---Obj字典-------
 Def_Obj_Dict_Faction = 'Faction' # 所属阵营
 Def_Obj_Dict_LineupPlayerID = 'LineupPlayerID' # 阵容所属玩家ID,可用于判断是否玩家阵容,PVP或PVE
+Def_Obj_Dict_HeroID = 'HeroID' # 该战斗NPC所绑定的武将ID,一般仅玩家阵容有
+Def_Obj_Dict_SkinID = 'SkinID' # 该战斗NPC所绑定的武将皮肤ID,一般仅玩家阵容有
 Def_Obj_Dict_TurnFightPosInfo = 'TurnFightPosInfo' # 回合制站位: 阵营编号*100+阵型站位,阵型站位为0时代表非主战单位
 Def_Obj_Dict_TurnFightTimeline = 'TurnFightTimeline' # 回合制战斗时间线: 回合数*100+行动编号节点
 Def_Obj_Dict_TurnComboNum = 'TurnComboNum' # 单次累计连击次数
@@ -5782,7 +5784,8 @@
 Def_SkillFuncType_ShentongSkill,     #20 神通技能
 Def_SkillFuncType_ElfSkill,     #21 精怪技能
 Def_SkillFuncType_GatherTheSoul,     #22 聚魂技能
-) = range(23)
+Def_SkillFuncType_TurnNormaAttack,  #23 回合普攻技能
+) = range(24)
 
 # 受技能效果完全影响的怪, 对应 Def_BattleRelationType_CommNoBoss
 Def_SkillAttack_NPCIsBoss = [ Def_NPCType_Ogre_Normal     ,  #平凡小怪 0    # c++ 定义为普通NPC视野刷新
@@ -5798,6 +5801,12 @@
 Def_BattleRelationType_CommNoBoss,   # 除了(指定)BOSS,可对其释放技能,但是无实际效果
 ) = range(0, 4)
 
+# 近战远程
+AtkDistTypeList = (
+AtkDistType_Short, # 近战
+AtkDistType_Long, # 远程
+) = range(1, 1 + 2)
+
 # 经验倍率限制类型
 (
 ExpRateLimitType_Recover, # 资源找回
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 6908bca..ee8d2b0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -50732,8 +50732,10 @@
 class  tagSCTurnFightObj(Structure):
     _pack_ = 1
     _fields_ = [
-                  ("ObjID", c_int),    # 实例唯一ID
-                  ("NPCID", c_int),    # 绑定的NPCID,不同的实例ID对应的NPCID可能一样
+                  ("ObjID", c_int),    # 战斗单位唯一ID
+                  ("NPCID", c_int),    # 战斗NPCID,不同的实例ID对应的NPCID可能一样
+                  ("HeroID", c_int),    # 玩家武将ID,仅玩家阵容有
+                  ("SkinID", c_int),    # 玩家武将皮肤ID,仅玩家阵容有
                   ("HP", c_int),    # 当前血量,求余20亿部分
                   ("HPEx", c_int),    # 当前血量,整除20亿部分
                   ("MaxHP", c_int),    # 最大血量,求余20亿部分
@@ -50755,6 +50757,8 @@
     def Clear(self):
         self.ObjID = 0
         self.NPCID = 0
+        self.HeroID = 0
+        self.SkinID = 0
         self.HP = 0
         self.HPEx = 0
         self.MaxHP = 0
@@ -50774,6 +50778,8 @@
         DumpString = '''// B4 24 回合战斗初始化 //tagSCTurnFightInit:
                                 ObjID:%d,
                                 NPCID:%d,
+                                HeroID:%d,
+                                SkinID:%d,
                                 HP:%d,
                                 HPEx:%d,
                                 MaxHP:%d,
@@ -50785,6 +50791,8 @@
                                 %(
                                 self.ObjID,
                                 self.NPCID,
+                                self.HeroID,
+                                self.SkinID,
                                 self.HP,
                                 self.HPEx,
                                 self.MaxHP,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
index 32d0998..eba6320 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
@@ -167,6 +167,8 @@
 def IsFBPass(curPlayer, mapID, lineID):
     ## 副本线路是否已过关
     passLineID = 0
+    if mapID == ChConfig.Def_FBMapID_Main:
+        return PlayerControl.IsMainLevelPass(curPlayer, lineID)
     if mapID == ChConfig.Def_FBMapID_RealmTower:
         passLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RealmTowerFloor)
     elif mapID == ChConfig.Def_FBMapID_SkyTower:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index c8f801b..926dbf3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -60,7 +60,8 @@
                         ("DWORD", "HeroID", 1),
                         ("BYTE", "Country", 0),
                         ("BYTE", "Quality", 0),
-                        ("list", "SkinNPCIDList", 0),
+                        ("BYTE", "AtkDistType", 0),
+                        ("list", "SkinIDList", 0),
                         ("DWORD", "NormalSkillID", 0),
                         ("DWORD", "AngerSkillID", 0),
                         ("WORD", "AtkInheritPer", 0),
@@ -104,7 +105,7 @@
                         ),
 
                 "HeroSkin":(
-                        ("DWORD", "SkinNPCID", 1),
+                        ("DWORD", "SkinID", 1),
                         ("list", "WearAttrIDList", 0),
                         ("list", "WearAttrValueList", 0),
                         ("list", "AllBatAttrIDList", 0),
@@ -713,7 +714,7 @@
                         ("DWORD", "NPCID", 1),
                         ("BYTE", "FightPowerLackAtkLimit", 0),
                         ("DWORD", "SuppressFightPower", 0),
-                        ("BYTE", "AtkDictType", 0),
+                        ("BYTE", "AtkDistType", 0),
                         ("DWORD", "Atk", 0),
                         ("DWORD", "Def", 0),
                         ("DWORD", "MaxHP", 0),
@@ -2835,13 +2836,14 @@
     def GetHeroID(self): return self.attrTuple[0] # 英雄ID DWORD
     def GetCountry(self): return self.attrTuple[1] #  国家 BYTE
     def GetQuality(self): return self.attrTuple[2] #  品质 BYTE
-    def GetSkinNPCIDList(self): return self.attrTuple[3] #  皮肤NPCID列表 list
-    def GetNormalSkillID(self): return self.attrTuple[4] # 普攻技能ID DWORD
-    def GetAngerSkillID(self): return self.attrTuple[5] # 怒气技能ID DWORD
-    def GetAtkInheritPer(self): return self.attrTuple[6] # 攻击继承 WORD
-    def GetDefInheritPer(self): return self.attrTuple[7] # 防御继承 WORD
-    def GetHPInheritPer(self): return self.attrTuple[8] # 生命继承 WORD
-    def GetBatAttrDict(self): return self.attrTuple[9] # 其他战斗属性字典 {"属性ID":值, ...} dict
+    def GetAtkDistType(self): return self.attrTuple[3] # 远近类型;1-近战;2-远程 BYTE
+    def GetSkinIDList(self): return self.attrTuple[4] #  皮肤ID列表 list
+    def GetNormalSkillID(self): return self.attrTuple[5] # 普攻技能ID DWORD
+    def GetAngerSkillID(self): return self.attrTuple[6] # 怒气技能ID DWORD
+    def GetAtkInheritPer(self): return self.attrTuple[7] # 攻击继承 WORD
+    def GetDefInheritPer(self): return self.attrTuple[8] # 防御继承 WORD
+    def GetHPInheritPer(self): return self.attrTuple[9] # 生命继承 WORD
+    def GetBatAttrDict(self): return self.attrTuple[10] # 其他战斗属性字典 {"属性ID":值, ...} dict
 
 # 武将星级天赋表
 class IPY_HeroTalent():
@@ -2897,14 +2899,14 @@
     def GetAttrIDList(self): return self.attrTuple[2] #  属性ID列表 list
     def GetAttrValueList(self): return self.attrTuple[3] #  属性值列表 list
 
-# 武将皮肤表
+# 皮肤表
 class IPY_HeroSkin():
     
     def __init__(self):
         self.attrTuple = None
         return
         
-    def GetSkinNPCID(self): return self.attrTuple[0] # 皮肤NPCID DWORD
+    def GetSkinID(self): return self.attrTuple[0] # 皮肤NPCID DWORD
     def GetWearAttrIDList(self): return self.attrTuple[1] #  穿戴属性ID列表 list
     def GetWearAttrValueList(self): return self.attrTuple[2] #  穿戴属性值列表 list
     def GetAllBatAttrIDList(self): return self.attrTuple[3] #  全体上阵属性ID列表 list
@@ -3833,7 +3835,7 @@
     def GetNPCID(self): return self.attrTuple[0] # NPCID DWORD
     def GetFightPowerLackAtkLimit(self): return self.attrTuple[1] # 战力不足限制攻击 BYTE
     def GetSuppressFightPower(self): return self.attrTuple[2] # 推荐/压制战力 DWORD
-    def GetAtkDictType(self): return self.attrTuple[3] # 远近类型;1-近战;2-远程 BYTE
+    def GetAtkDistType(self): return self.attrTuple[3] # 远近类型;1-近战;2-远程 BYTE
     def GetAtk(self): return self.attrTuple[4] # 攻击力 DWORD
     def GetDef(self): return self.attrTuple[5] # 防御值 DWORD
     def GetMaxHP(self): return self.attrTuple[6] # 最大生命值,可超过20E DWORD
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index e839b60..b1839ac 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -5934,6 +5934,13 @@
         SendPropertyRefresh(curPlayer, ShareDefine.CDBPlayerRefresh_ForbidenTalk, 0)
     return
 
+def IsMainLevelPass(curPlayer, lvID):
+    ## 判断玩家是否过关某个主线关卡ID
+    # @param lvID: 关卡唯一ID,与策划约定好 = 章节*100+关卡编号
+    passChapterID, passLevelNum, _ = GetMainLevelPassInfo(curPlayer)
+    passValue = passChapterID * 100 + passLevelNum # 因为pass的记录是带波数的,即当前关卡boss还没过关,所以只有大于该记录值的才算过关
+    return passValue > lvID
+
 ## 主线关卡过关进度值 = 章节*10000+关卡编号*100+第x波
 def GetMainLevelPassValue(curPlayer): return curPlayer.GetExAttr1()
 def SetMainLevelPassValue(curPlayer, value): curPlayer.SetExAttr1(value, False, False) # 不通知GameServer
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
index d842b7d..efac7e6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerHero.py
@@ -869,9 +869,9 @@
     heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
     if not heroIpyData:
         return
-    skinNPCIDList = heroIpyData.GetSkinNPCIDList()
+    skinIDList = heroIpyData.GetSkinIDList()
     if skinIndex > 0: # 0的为默认皮肤,不做限制
-        if skinIndex >= len(skinNPCIDList):
+        if skinIndex >= len(skinIDList):
             GameWorld.DebugLog("该武将不存在该皮肤! heroID=%s,skinIndex=%s" % (heroID, skinIndex))
             return
         skinState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_HeroSkin % heroID)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py
index 4bd10bc..e1d4b11 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerPrestigeSys.py
@@ -37,7 +37,8 @@
 RealmTaskType_LV, # 等级 1
 RealmTaskType_PassMap, # 过关关卡 2
 RealmTaskType_UseXiantao, # 消耗战锤 3
-) = range(1, 1 + 3)
+RealmTaskType_TreeLV, # 仙树等级 4
+) = range(1, 1 + 4)
 
 # 需要记录任务值的任务类型列表
 NeedTaskValueTypeList = [RealmTaskType_UseXiantao]
@@ -178,6 +179,14 @@
                                % (realmLV, taskID, taskType, mapID, lineID), playerID)
             return
         
+    # 仙树等级
+    elif taskType == RealmTaskType_TreeLV:
+        treeLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreeLV)
+        if treeLV < needValueA:
+            GameWorld.DebugLog('境界任务领奖,仙树在祝福等级不足! realmLV=%s,taskID=%s,taskType=%s,treeLV=%s < %s' 
+                               % (realmLV, taskID, taskType, treeLV, needValueA), playerID)
+            return
+        
     # 根据记录任务进度值    
     elif taskType in NeedTaskValueTypeList:
         curValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_RealmTaskValue % taskID)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTask.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTask.py
index c068b95..0d8eef3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTask.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTask.py
@@ -25,6 +25,7 @@
 import GameFuncComm
 import ShareDefine
 import ChConfig
+import FBCommon
 
 def GetTaskIDList(taskGroup):
     ## 获取某个任务分组所有任务ID列表
@@ -148,8 +149,7 @@
         if len(conds) != 2:
             return 0
         mapID, lineID = conds
-        passLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FBPassLineID % mapID)
-        taskValue = 1 if passLineID >= lineID else 0
+        taskValue = 1 if FBCommon.IsFBPass(curPlayer, mapID, lineID) else 0
         
     elif taskType == ChConfig.TaskType_TreeLV:
         taskValue = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_TreeLV)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
index 25f8750..ab93e74 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
@@ -1975,9 +1975,9 @@
     ## 是否xp怒气技能
     return curSkill and curSkill.GetXP() > 0
 
-def isNormalAtkSkill(curSkill):
-    ## 是否普攻技能,区别与无技能的普通A一下,该普攻同样可以有各种技能效果,只是他属于普攻
-    return curSkill and curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_NormalAttack
+def isTurnNormalAtkSkill(curSkill):
+    ## 是否回合普攻技能,区别与无技能的普通A一下,该普攻同样可以有各种技能效果,只是他属于普攻
+    return curSkill and curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_TurnNormaAttack
 
 ## 检查技能是否为被动技能, 用于控制不可释放技能
 def isPassiveSkill(curSkill):

--
Gitblit v1.8.0