10019 【砍树】回合战斗(每回合攻击顺序改为按攻击速度倒序;每个阵营支持多个战斗实例)
4个文件已修改
192 ■■■■ 已修改文件
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameObj.py 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -77,10 +77,29 @@
def DoTrunFight(curPlayer, mapID, funcLineID, tagPlayerID, tick):
    playerID = curPlayer.GetPlayerID()
    posX, posY = curPlayer.GetPosX(), curPlayer.GetPosY()
    factionListA, factionListB = [], []
    factionListA.append(curPlayer)
    curPet = curPlayer.GetPetMgr().GetFightPet()
    curPet and factionListA.append(curPet)
    # 玩家阵营的其他战斗实例,可扩展...
    assistNPCID = 0 # 协助召唤兽
    if assistNPCID:
        assistNPC = NPCCommon.SummonNPC(curPlayer, assistNPCID, posX, posY)
        assistNPC and factionListA.append(assistNPC)
    tagObj = None
    if tagPlayerID:
        npcID = ChConfig.Def_NPCID_PVP
        tagObj = NPCCommon.SummonMapNpc(npcID, curPlayer.GetPosX(), curPlayer.GetPosY(), sightLevel=playerID, pvpPlayerID=tagPlayerID)
        tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID, pvpPlayerID=tagPlayerID)
        if not tagObj:
            return
        factionListB.append(tagObj)
        # 对手玩家镜像的其他战斗实例...
    else:
        ipyData = IpyGameDataPY.GetIpyGameData("FBTurn", mapID, funcLineID)
        if not ipyData:
@@ -88,40 +107,33 @@
        npcID = ipyData.GetNPCID()
        if not npcID:
            return
        tagObj = NPCCommon.SummonMapNpc(npcID, curPlayer.GetPosX(), curPlayer.GetPosY(), sightLevel=playerID)
        tagObj = NPCCommon.SummonMapNpc(npcID, posX, posY, sightLevel=playerID)
    if not tagObj:
        return
        factionListB.append(tagObj)
        summerNPCID = ipyData.GetSummerNPCID()
        if summerNPCID:
            summerNPC = NPCCommon.SummonNPC(tagObj, summerNPCID, posX, posY)
            summerNPC and factionListB.append(summerNPC)
    if not factionListB:
        return
    for gameObj in factionListA:
        GameObj.SetFaction(gameObj, 1)
    for gameObj in factionListB:
        GameObj.SetFaction(gameObj, 2)
    #一个回合攻击顺序,由攻击速度决定,攻速相同下阵营1先攻击,还相同则由ID决定
    fightObjList = factionListA + factionListB
    fightObjList.sort(key=lambda o: (GameObj.GetAtkSpeed(o), (10 - GameObj.GetFaction(o)), o.GetID()), reverse=True)
    
    turnMax = IpyGameDataPY.GetFuncCfg("TurnFight", 1)
    curPet = curPlayer.GetPetMgr().GetFightPet()
    tagPet = None
    GameWorld.DebugLog("===== 执行回合制战斗: mapID=%s,funcLineID=%s,tagPlayerID=%s,tagObjID=%s" 
                       % (mapID, funcLineID, tagPlayerID, tagObj.GetID()), playerID)
    GameWorld.DebugLog("curPlayer.GetSightLevel=%s,tagObj.GetSightLevel=%s"
                       % (curPlayer.GetSightLevel(), tagObj.GetSightLevel()), playerID)
    #一个回合攻击顺序
    #1. 快方宠物攻击,不存在跳过
    #2. 慢方宠物攻击,不存在跳过
    #3. 快方主体攻击
    #4. 慢方主体攻击
    # 战斗前初始化
    factionObjMax = 0 # 某个阵营的最大战斗实例数
    factionObjDict = {1:[curPet, curPlayer], 2:[tagPet, tagObj]}
    for objList in factionObjDict.values():
        if factionObjMax < len(objList):
            factionObjMax = len(objList)
        for gameObj in objList:
    for gameObj in fightObjList:
            TurnFightObjStartInit(gameObj)
    curAtkSpeed = GameObj.GetAtkSpeed(curPlayer)
    tagAtkSpeed = GameObj.GetAtkSpeed(tagObj)
    orderList = [1, 2] if curAtkSpeed >= tagAtkSpeed else [2, 1]
    GameWorld.DebugLog("playerHP=%s,tagHP=%s,curAtkSpeed=%s,tagAtkSpeed=%s"
                       % (GameObj.GetHP(curPlayer), GameObj.GetHP(tagObj), curAtkSpeed, tagAtkSpeed), playerID)
    
    isWin = None
    for turnNum in range(1, turnMax + 1):
@@ -129,38 +141,38 @@
        SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, FightState_Fighting, turnNum, turnMax)
        
        # 回合开始: 做一些每回合重置逻辑或者某些根据回合触发的效果等
        for objList in factionObjDict.values():
            for gameObj in objList:
                TurnFightObjTurnStart(gameObj, turnNum)
        for gameObj in fightObjList:
            TurnFightObjPerTurnStart(gameObj, turnNum)
                
        # 回合战斗: 轮流依次攻击
        for index in range(factionObjMax):
            for faction in orderList:
                objList = factionObjDict[faction]
                if index >= len(objList):
                    continue
                gameObj = objList[index]
        for actNum, gameObj in enumerate(fightObjList, 1):
                if not gameObj:
                    continue
            faction = GameObj.GetFaction(gameObj)
                tagGameObj = tagObj if faction == 1 else curPlayer
                objType = gameObj.GetGameObjType()
                objID = gameObj.GetID()
                tagObjType = tagGameObj.GetGameObjType()
                tagObjID = tagGameObj.GetID()
                
                GameWorld.DebugLog("    行动: turnNum=%s,index=%s,faction=%s,objType=%s,objID=%s,tagObjType=%s,tagObjID=%s"
                                   % (turnNum, index, faction, objType, objID, tagObjType, tagObjID), playerID)
            GameWorld.DebugLog("    行动: turnNum=%s,actNum=%s,faction=%s,objType=%s,objID=%s,tagObjType=%s,tagObjID=%s"
                               % (turnNum, actNum, faction, objType, objID, tagObjType, tagObjID), playerID)
                DoAttack(gameObj, tagGameObj, tick)
                
                if tagGameObj and GameObj.GetHP(tagGameObj) > 0:
            playerDead = GameObj.GetHP(curPlayer) <= 0
            tagObjDead = (not tagObj or GameObj.GetHP(tagObj) <= 0)
            if not playerDead and not tagObjDead:
                    continue
                
                isWin = faction == 1
                GameWorld.DebugLog("        tagObjType=%s,tagObjID=%s,被击杀,结束战斗: isWin=%s" % (tagObjType, tagObjID, isWin))
                break
            if isWin != None:
            if playerDead and tagObjDead:
                isWin = False # 平局算失败
                GameWorld.DebugLog("        双方被击杀,平局算失败: isWin=%s" % isWin)
            elif playerDead:
                isWin = False
                GameWorld.DebugLog("        玩家被击杀,失败: isWin=%s" % isWin)
            elif tagObjDead:
                isWin = True # 胜利
                GameWorld.DebugLog("        对手被击杀,胜利: isWin=%s" % isWin)
                break
            
        if isWin != None:
@@ -169,8 +181,7 @@
    overState = FightState_Win if isWin else FightState_Fail
    SyncTurnFightState(curPlayer, mapID, funcLineID, tagPlayerID, overState, turnNum, turnMax)
    
    for objList in factionObjDict.values():
        for gameObj in objList:
    for gameObj in fightObjList:
            TurnFightObjOverReset(gameObj)
            
    GameWorld.DebugLog("===== 回合制战斗结束: mapID=%s,funcLineID=%s,tagPlayerID=%s,isWin=%s,overState=%s" 
@@ -187,6 +198,10 @@
    gameObj.RefreshView()
    
    objType = gameObj.GetGameObjType()
    npcID = gameObj.GetNPCID() if objType == IPY_GameWorld.gotNPC else 0
    GameWorld.DebugLog("    初始化实例: objID=%s,npcID=%s,faction=%s,atkSpeed=%s,HP=%s"
                       % (gameObj.GetID(), npcID, GameObj.GetFaction(gameObj), GameObj.GetAtkSpeed(gameObj), GameObj.GetHP(gameObj)))
    # 重置技能CD、战斗buff
    if objType == IPY_GameWorld.gotPlayer:            
        skillManager = gameObj.GetSkillManager()
@@ -198,7 +213,7 @@
        pass
    return
def TurnFightObjTurnStart(gameObj, turnNum):
def TurnFightObjPerTurnStart(gameObj, turnNum):
    ## 回合制战斗实例 - 每回合开始时处理
    if not gameObj:
        return
@@ -223,18 +238,34 @@
        return
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnFightNum, 0)
    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0)
    GameObj.SetFaction(gameObj, 0)
    
    objType = gameObj.GetGameObjType()
    if objType == IPY_GameWorld.gotPlayer:
        pass
    
    elif objType == IPY_GameWorld.gotNPC:
        npcObjType = gameObj.GetGameNPCObjType()
        if npcObjType != IPY_GameWorld.gnotPet and GameObj.GetHP(gameObj):
            NPCCommon.SetDeadEx(gameObj)
        RecycleObj(gameObj)
    return
def RecycleObj(gameObj):
    npcObjType = gameObj.GetGameNPCObjType()
    if npcObjType == IPY_GameWorld.gnotPet:
        #GameWorld.DebugLog("RecycleObj 灵宠不回收 objID=%s,npcObjType=%s,%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID()))
        return
    if npcObjType == IPY_GameWorld.gnotSummon:
        curOwner = NPCCommon.GetSummonOwnerDetel(gameObj)
        if curOwner and curOwner.GetGameObjType() == IPY_GameWorld.gotNPC:
            #GameWorld.DebugLog("RecycleObj 召唤兽主人是NPC不回收 objID=%s,npcObjType=%s,%s,ownerID=%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID(), curOwner.GetID()))
            return
    if GameObj.GetHP(gameObj) <= 0:
        #GameWorld.DebugLog("RecycleObj 已死亡,不用重复回收 objID=%s,npcObjType=%s,%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID()))
        return
    #GameWorld.DebugLog("RecycleObj: objID=%s,npcObjType=%s,%s" % (gameObj.GetID(), npcObjType, gameObj.GetNPCID()))
    NPCCommon.SetDeadEx(gameObj)
    return
def DoAttack(curObj, tagObj, tick):
    curID = curObj.GetID()
    tagID = tagObj.GetID()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3060,6 +3060,7 @@
) = range(3)
#---Obj字典-------
Def_Obj_Dict_Faction = 'Faction' # 所属阵营
Def_Obj_Dict_TurnFightNum = 'TurnFightNum' # 回合制战斗当前轮次
Def_Obj_Dict_TurnComboNum = 'TurnComboNum' # 本回合已累计连击次数
Def_Obj_Dict_TurnAtkBackNum = 'TurnAtkBackNum' # 本回合已累计反击次数
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameObj.py
@@ -179,6 +179,19 @@
    gameObj.SetDict(ChConfig.Def_PlayerKey_BloodShiledHurtEx, value / ShareDefine.Def_PerPointValue)
    return
def GetFaction(gameObj):
    faction = gameObj.GetDictByKey(ChConfig.Def_Obj_Dict_Faction)
    if faction:
        return faction
    if gameObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
        return gameObj.GetFaction()
    return gameObj.GetCountry()
def SetFaction(gameObj, value):
    gameObj.SetDict(ChConfig.Def_Obj_Dict_Faction, value)
    if gameObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
        gameObj.SetFaction(value)
    return
def GetAtkSpeed(gameObj):
    if gameObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
        return gameObj.GetBattleValEx1()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -148,7 +148,7 @@
def SetSuppressFightPower(curNPC, value): return curNPC.SetThunderDef(min(value, ShareDefine.Def_UpperLimit_DWord))
def GetCommendFightPower(curNPC): return curNPC.GetFireDef() # 火防代表推荐战力
def GetDropOwnerType(curNPC): return curNPC.GetThunderAtk() # 雷攻代表掉落归属类型
def GetFaction(curNPC): return curNPC.GetCountry()
def GetFaction(curNPC): return GameObj.GetFaction(curNPC)
def GetSkillAtkRate(curNPC): return curNPC.GetPoisionAtk() # 毒攻代表NPC技能伤害加成万分率
def GetFinalHurt(curNPC): return curNPC.GetFireAtk() # 火攻代表NPC最终固定伤害加成, 普攻也有效果
def SetFinalHurt(curNPC, hurt): return curNPC.SetFireAtk(hurt) # 火攻代表NPC最终固定伤害加成, 普攻也有效果
@@ -2269,6 +2269,10 @@
# @return 如果召唤失败返回None 否则返回召唤的NPC的实例
# @remarks 在地图里召唤NPC 根据NPCID 出生点 AI类型 和TICK
def SummonMapNpc(npcId, rebornX, rebornY, aiType=0, lastTime=0, playerID=0, sightLevel=0, refreshID=0, pvpPlayerID=0):
    npcData = GameWorld.GetGameData().FindNPCDataByID(npcId)
    if not npcData:
        GameWorld.ErrLog("找不到该NPCID: %s" % npcId)
        return
    curSummon = GameWorld.GetNPCManager().AddPlayerSummonNPC()
    if not curSummon:
        return
@@ -2306,6 +2310,43 @@
    #__NotifyMapPlayerSummonMapNPC(npcId, rebornX, rebornY)
    return curSummon
def SummonNPC(gameObj, npcID, rebornX, rebornY):
    ''' 某个实例进行召唤,有从属关系
    '''
    npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)
    if not npcData:
        GameWorld.ErrLog("找不到该NPCID: %s" % npcID)
        return
    if gameObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
        curSummon = gameObj.SummonNewNPC()
        curSummon.SetLV(gameObj.GetLV())
        curSummon.SetCountry(gameObj.GetCountry())
        curSummon.GetNPCAngry().Init(ChConfig.Def_SummonNPC_Angry_Count)
        curSummon.SetOwner(gameObj)
    else:
        sumCount, angryCount = 1, 3
        if not gameObj.AddSummonCount(sumCount, npcID, angryCount):
            return
        #取新增的一只,最后一个
        index = gameObj.GetSummonCount() - 1
        if index < 0:
            return
        curSummon = gameObj.GetSummonNPCAt(index)
    if not curSummon:
        return
    tick = GameWorld.GetGameWorld().GetTick()
    curSummon.SetNPCTypeID(npcID)
    curSummon.SetBornTime(tick)
    InitNPC(curSummon)
    curSummon.SetSightLevel(gameObj.GetSightLevel())
    curSummon.Reborn(rebornX, rebornY, False)
    NPCControl(curSummon).DoNPCRebornCommLogic(tick)
    #curSummon.RefreshView()
    return curSummon
## 通知地图内玩家,地图出现召唤NPC
# @param npcId: NPCID
# @param rebornX: 出生点X