From 7e0ecb9fda366097e9cb0bc3a79cb52c03da67f5 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 15 十一月 2022 18:11:05 +0800
Subject: [PATCH] 9727 【BT7】【主干】【越南】【后端】查看玩家装备缓存扩展到20阶(支持查看射雕装备17阶)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_21.py |  279 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 222 insertions(+), 57 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_21.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_21.py
index ac0b481..2d04ffc 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_21.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_21.py
@@ -1,63 +1,60 @@
 #!/usr/bin/python
 # -*- coding: GBK -*-
-#---------------------------------------------------------------------
-##@package AIType_21
-#巡逻守卫AI,攻击非本国家玩家,和红名玩家
+#-------------------------------------------------------------------------------
 #
-# @author PanWei
-# @date 2010-4-28下午06:01:33
-# @version 1.4
+##@package NPCAI.AIType_21
 #
-#模块详细说明.
-# @change: "2010-05-12 18:30" zhengyang 添加注释
-# @change: "2010-06-09 09:50" zhengyang 守卫npc加入异常状态眩晕判断 
-# @change: 2010-06-14 16:00 zhengyang 修正普攻参数传错
-# @change: "2010-11-22 12:15" Alee 删除异常/沉默判定
-#---------------------------------------------------------------------
-"""Version = 2010-11-22 12:15"""
-#---------------------------------------------------------------------
-import IPY_GameWorld
-import GameWorld
-import NPCCommon
-import BaseAttack
+# @todo:副本活动机器人
+# @author hxp
+# @date 2018-12-06
+# @version 1.0
+#
+# 详细描述: 副本活动机器人
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2018-12-06 20:00"""
+#-------------------------------------------------------------------------------
+
 import ChConfig
 import AICommon
+import NPCCommon
+import BaseAttack
+import IpyGameDataPY
+import IPY_GameWorld
+import GameWorld
+import FBCommon
 import GameObj
+
+import random
+#---------------------------------------------------------------------
+
 #---------------------------------------------------------------------
 ## 初始化
-#  @param curNPC NPC实例
+#  @param curNPC 当前npc
 #  @return None
 #  @remarks 函数详细说明.
 def DoInit(curNPC):
-    curNPC.GetNPCAngry().Init(ChConfig.Def_BossAngryCount)
+    curNPC.GetNPCAngry().Init(ChConfig.Def_SuperFBBossAngryCount)
+    return
 
-#---------------------------------------------------------------------
-##正常AI逻辑处理
-#@param curNPC NPC实例
-#@param tick 时间戳
-#@return 返回值无意义
-#@remarks 正常AI逻辑处理
+def OnNPCReborn(curNPC):
+    curNPC.SetIsNeedProcess(True)
+    return
+
+## 执行AI
+#  @param curNPC 当前npc
+#  @param tick 当前时间
+#  @return None
+#  @remarks 函数详细说明.
 def ProcessAI(curNPC, tick):
     npcControl = NPCCommon.NPCControl(curNPC)
     if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
-        #NPC死亡, 进入死亡倒计时
-        if npcControl.DieTick(tick) == 0:
-            return
-        
-    #刷新自己的buff
-    npcControl.RefreshBuffState(tick)
-    if GameObj.GetHP(curNPC) == 0 :
-        # BUFF刷新中可能会导致NPC死亡
         return
     
-#    #判断异常状态
-#    if curNPC.GetAbnormalState() == IPY_GameWorld.sctFaint:
-#        return 
-    
-    curNPCAction = curNPC.GetCurAction()
-    #NPC快速奔跑中, 处理
-    if curNPCAction == IPY_GameWorld.laNPCMove and curNPC.GetCurMoveType() == IPY_GameWorld.mtRun :
-        AICommon.NormalNPCFast_Move(curNPC , tick)
+    #刷新自己的buff
+    npcControl.RefreshBuffState(tick)
+    if GameObj.GetHP(curNPC) == 0:
+        # BUFF刷新中可能会导致NPC死亡
         return
     
     #刷新自己仇恨度列表
@@ -65,35 +62,170 @@
     curNPCAngry = npcControl.GetMaxAngryTag()
     
     #仇恨度列表中的人为空
-    if curNPCAngry == None :
-        AICommon.NormalNPCFree_Move(curNPC , tick)
+    if curNPCAngry == None:
+        if curNPC.GetSpeed() != 0:
+            __RobotMove(curNPC)
         return
     
     #仇恨对象类型,仇恨对象ID
     curNPCAngryType = curNPCAngry.GetObjType()
     curNPCAngryID = curNPCAngry.GetObjID()
-    #战斗中回血
-    npcControl.ProcessBattleHPRestore(tick)
+    
     #执行攻击逻辑
     __NPCFight(curNPC, curNPCAngryID, curNPCAngryType, tick)
+    return
+
+def __RobotMove(curNPC):
+    if curNPC.GetCurAction() == IPY_GameWorld.laNPCMove:
+        #GameWorld.DebugLog("移动中不处理!(%s,%s)" % (curNPC.GetPosX(), curNPC.GetPosY()))
+        return
+    mapID = GameWorld.GetMap().GetMapID()
+    lineID = FBCommon.GetFBPropertyMark()
+    dataMapID = FBCommon.GetRecordMapID(mapID)
+    fbRandMovePosDict = IpyGameDataPY.GetFuncEvalCfg("AI198Point", 2, {})
+    if str(dataMapID) in fbRandMovePosDict:
+        __RobotMove2(curNPC, fbRandMovePosDict[str(dataMapID)])
+        return
+    posKey = "%d%02d" % (mapID, lineID)
+    fbMovePosDict = IpyGameDataPY.GetFuncCfg("AI198Point", 1)
+    if posKey not in fbMovePosDict:
+        posKey = "%d%02d" % (mapID, 0)
+        if posKey not in fbMovePosDict:
+            return
+        
+    posList = fbMovePosDict[posKey]
+    Key_PosIndex = "RobotMovePosIndex" # NPC上次移动的坐标索引,存值+1
+    posIndex =  curNPC.GetDictByKey(Key_PosIndex) - 1
+    if posIndex < 0:
+        # 还没有走过点的,寻找所有点中最近的点
+        posIndex = random.randint(0, len(posList) - 1)
+    else:
+        tagPosX, tagPosY = posList[posIndex]
+        tagDist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), tagPosX, tagPosY)
+        if tagDist < 2:
+            posIndex += 1
+            
+    if posIndex < 0 or posIndex >= len(posList):
+        posIndex = random.randint(0, len(posList) - 1)
+        
+    curNPC.SetDict(Key_PosIndex, posIndex + 1)
+    tagPosX, tagPosY = posList[posIndex]
+    curNPC.Move(tagPosX, tagPosY)
+    return
+
+def __RobotMove2(curNPC, randPosList):
+    ''' 根据多条路径随机移动,不同路径间如果存在交叉点,那么可能随机改变路径
+    @param randPosList: [[[路径A点1x,y],[路径A点2x,y],...], [[路径B点1x,y],[路径B点2x,y],...], ...]
+    '''
+    if not randPosList:
+        return
+    
+    #objID = curNPC.GetID()
+    #npcID = curNPC.GetNPCID()
+    RobotMoveIndexInfo = "RobotMoveIndexInfo" # 上次移动目标坐标点索引信息  i * 100 + j
+    RobotMovePosInfo = "RobotMovePosInfo" # 上次移动目标坐标点 posX * 10000 + posY
+    indexInfo =  curNPC.GetDictByKey(RobotMoveIndexInfo)
+    posInfo =  curNPC.GetDictByKey(RobotMovePosInfo)
+    tagI, tagJ = indexInfo / 100, indexInfo % 100
+    tagPosX, tagPosY = posInfo / 10000, posInfo % 10000
+    curPosX, curPosY = curNPC.GetPosX(), curNPC.GetPosY()
+    
+    
+    resetPosPath = True # 重置坐标路径,为True时重新搜索路径
+    # 已经有目标点
+    if tagPosX and tagPosY:
+        # 理论上配置没重读
+        if tagI < len(randPosList) and type(randPosList[tagI]) in [list, tuple] and tagJ < len(randPosList[tagI]) \
+            and randPosList[tagI][tagJ] == [tagPosX, tagPosY]:
+            resetPosPath = False
+            
+    #GameWorld.DebugLog("__RobotMove2: objID=%s,npcID=%s,curPos(%s,%s),tagPos(%s,%s),tagIndex(%s,%s)" 
+    #                   % (objID, npcID, curPosX, curPosY, tagPosX, tagPosY, tagI, tagJ))
+    #GameWorld.DebugLog("    resetPosPath=%s,randPosList=%s" % (resetPosPath, randPosList))
+    
+    # 重置路径,先走向最近的点
+    if resetPosPath:
+        nearestDist = 99999999
+        for i, pathList in enumerate(randPosList):
+            for j, pos in enumerate(pathList):
+                posX, posY = pos
+                tagDist = GameWorld.GetDist(curPosX, curPosY, posX, posY)
+                if tagDist < nearestDist:
+                    nearestDist = tagDist
+                    tagI, tagJ = i, j
+                    tagPosX, tagPosY = posX, posY
+        #GameWorld.DebugLog("    nearestDist=%s" % nearestDist)
+    else:
+        tagDist = GameWorld.GetDist(curPosX, curPosY, tagPosX, tagPosY)
+        #GameWorld.DebugLog("    tagDist=%s" % (tagDist))
+        # 快到达目标点了,预先寻找下个点
+        if tagDist < 2:
+            nearPosIndexList = __getNearPosIndexList(randPosList, tagI, tagJ)
+            #GameWorld.DebugLog("    nearPosIndexList=%s" % nearPosIndexList)
+            if nearPosIndexList:
+                tagI, tagJ = random.choice(nearPosIndexList)
+                tagPosX, tagPosY = randPosList[tagI][tagJ]
+            
+    #GameWorld.DebugLog("    tagPos(%s,%s),tagIndex(%s,%s)" % (tagPosX, tagPosY, tagI, tagJ))
+    curNPC.SetDict(RobotMoveIndexInfo, tagI * 100 + tagJ)
+    curNPC.SetDict(RobotMovePosInfo, tagPosX * 10000 + tagPosY)
+    curNPC.Move(tagPosX, tagPosY)
+    return
+
+def __getNearPosIndexList(randPosList, tagI, tagJ):
+    ## 获取多条路径上相邻的点
+    pathPosList = randPosList[tagI]
+    if not pathPosList or len(pathPosList) <= 1:
+        return
+    
+    tagPosX, tagPosY = randPosList[tagI][tagJ]
+    nearPosIndexList = __getNearIndexByPath(pathPosList, tagI, tagJ)
+    # 检查其他路径交叉点
+    for i, pathList in enumerate(randPosList):
+        if i == tagI:
+            # 本路径不处理
+            continue
+        for j, pos in enumerate(pathList):
+            posX, posY = pos
+            if posX == tagPosX and posY == tagPosY:
+                for ni, nj in __getNearIndexByPath(pathList, i, j):
+                    if [ni, nj] not in nearPosIndexList:
+                        nearPosIndexList.append([ni, nj])
+    return nearPosIndexList
+
+def __getNearIndexByPath(pathPosList, tagI, tagJ):
+    ## 获取某条路径上的相邻点索引信息
+    nearPosIndexList = []
+    # 起始点 或 最终点
+    if tagJ == 0 or tagJ == len(pathPosList) - 1:
+        # 起点=终点
+        if pathPosList[0] == pathPosList[-1]:
+            nearPosIndexList.append([tagI, 1])
+            nearPosIndexList.append([tagI, -2])
+        # 起点
+        elif tagJ == 0:
+            nearPosIndexList.append([tagI, 1])
+        else:
+            nearPosIndexList.append([tagI, -2])
+            
+    # 中间点,取前后两点
+    else:
+        nearPosIndexList.append([tagI, tagJ - 1])
+        nearPosIndexList.append([tagI, tagJ + 1])
+    return nearPosIndexList
 
 #---------------------------------------------------------------------
-## npc攻击战斗
+## npc攻击逻辑
 #  @param curNPC 当前npc
 #  @param tagID curNPCAngryID
 #  @param tagType curNPCAngryType 
 #  @param tick 当前时间
 #  @return None
-#  @remarks 战斗逻辑实现
+#  @remarks 函数详细说明.
 def __NPCFight(curNPC, tagID, tagType, tick):
     #设置进入战斗状态
     NPCCommon.SetNPCInBattleState(curNPC)
     npcControl = NPCCommon.NPCControl(curNPC)
-    #NPC的打怪AI
-    if not npcControl.IsInRefreshArea():
-        #追击返回
-        npcControl.MoveBack()
-        return
     
     #开始攻击
     curTag = GameWorld.GetObj(tagID, tagType)
@@ -103,10 +235,37 @@
     
     tagDist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), curTag.GetPosX(), curTag.GetPosY())
     
-    if tagDist > curNPC.GetAtkDist() :
-        npcControl.MoveToObj_Detel(curTag)
+    #---优先释放技能---
+    if AICommon.DoAutoUseSkill(curNPC, curTag, tagDist, tick):
         return
     
+    #---释放普通攻击---
+    
+    if curNPC.GetSpeed() == 0:
+        # 不可移动NPC
+        if tagDist > curNPC.GetAtkDist():
+            return
+        
+        if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():
+            #攻击间隔没有到, 返回
+            return
+        
+        #普通攻击
+        BaseAttack.Attack(curNPC, curTag, None, tick)
+        return
+    
+    #超过攻击距离,移动过去
+    if tagDist > curNPC.GetAtkDist():
+
+        destDist = GameWorld.GetDist(curNPC.GetDestPosX() , curNPC.GetDestPosY(), curTag.GetPosX(), curTag.GetPosY())
+        if destDist <= curNPC.GetAtkDist() and curNPC.GetCurAction() == IPY_GameWorld.laNPCMove:
+            # 目标在移动的攻击范围内,不改变目标点
+            return
+        npcControl.MoveToObj_Detel(curTag)
+        return
+    else:
+        curNPC.StopMove()
+        
     if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():
         #攻击间隔没有到, 返回
         return
@@ -118,7 +277,13 @@
     #普通攻击
     BaseAttack.Attack(curNPC, curTag, None, tick)
     return
-    
 
+## NPC死亡
+#  @param curNPC 当前npc
+#  @param hurtType 伤害者的obj类型
+#  @param hurtID 伤害者的objID
+#  @return None
+def OnDie(curNPC, hurtType, hurtID):
+    AICommon.DoNPCUseSkillOnDie(curNPC)
+    return
 
-       

--
Gitblit v1.8.0