6459 【后端】【2.0】缥缈仙域开发单(草园)
| | |
| | | BYTE NotifyCollectResult; //是否通知采集结果
|
| | | };
|
| | |
|
| | | //宝箱怪表
|
| | |
|
| | | struct tagTreasureNPC
|
| | | {
|
| | | DWORD _NPCID; //宝箱怪NPCID
|
| | | dict AttackCountDropWeightInfo; //攻击次数对应掉落权重饼图 {次数:[[权重, [物品ID,个数,是否拍品]], ...], ...}
|
| | | list AttackDropWeightList; //常规攻击权重饼图 [[权重, [物品ID,个数,是否拍品]], ...]
|
| | | list AttackDropWeightListEx; //额外掉落权重饼图库,每次攻击都会掉落 [[权重, [物品ID,个数,是否拍品]], ...]
|
| | | BYTE DropCountEx; //额外库执行次数
|
| | | BYTE AlchemyDiffLV; //过滤炼丹等级差,0-不过滤,>0过滤大于自身炼丹等级X级的物品
|
| | | char NotDropNotify; //没有掉落时提示信息
|
| | | };
|
| | |
|
| | | //宝箱表开启
|
| | |
|
| | | struct tagChests
|
| | |
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # A3 25 NPC已攻击次数信息 #tagMCNPCAttackCountInfo
|
| | |
|
| | | class tagMCNPCAttackCount(Structure):
|
| | | _pack_ = 1
|
| | | _fields_ = [
|
| | | ("NPCID", c_int), |
| | | ("AttackCount", c_ubyte), #已攻击次数
|
| | | ]
|
| | |
|
| | | def __init__(self):
|
| | | self.Clear()
|
| | | 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.NPCID = 0
|
| | | self.AttackCount = 0
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | return sizeof(tagMCNPCAttackCount)
|
| | |
|
| | | def GetBuffer(self):
|
| | | return string_at(addressof(self), self.GetLength())
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''// A3 25 NPC已攻击次数信息 //tagMCNPCAttackCountInfo:
|
| | | NPCID:%d,
|
| | | AttackCount:%d
|
| | | '''\
|
| | | %(
|
| | | self.NPCID,
|
| | | self.AttackCount
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
|
| | | class tagMCNPCAttackCountInfo(Structure):
|
| | | Head = tagHead()
|
| | | Count = 0 #(BYTE Count)
|
| | | NPCAttackCountList = list() #(vector<tagMCNPCAttackCount> NPCAttackCountList)
|
| | | data = None
|
| | |
|
| | | def __init__(self):
|
| | | self.Clear()
|
| | | self.Head.Cmd = 0xA3
|
| | | self.Head.SubCmd = 0x25
|
| | | return
|
| | |
|
| | | def ReadData(self, _lpData, _pos=0, _Len=0):
|
| | | self.Clear()
|
| | | _pos = self.Head.ReadData(_lpData, _pos)
|
| | | self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
|
| | | for i in range(self.Count):
|
| | | temNPCAttackCountList = tagMCNPCAttackCount()
|
| | | _pos = temNPCAttackCountList.ReadData(_lpData, _pos)
|
| | | self.NPCAttackCountList.append(temNPCAttackCountList)
|
| | | return _pos
|
| | |
|
| | | def Clear(self):
|
| | | self.Head = tagHead()
|
| | | self.Head.Clear()
|
| | | self.Head.Cmd = 0xA3
|
| | | self.Head.SubCmd = 0x25
|
| | | self.Count = 0
|
| | | self.NPCAttackCountList = list()
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | length = 0
|
| | | length += self.Head.GetLength()
|
| | | length += 1
|
| | | for i in range(self.Count):
|
| | | length += self.NPCAttackCountList[i].GetLength()
|
| | |
|
| | | return length
|
| | |
|
| | | def GetBuffer(self):
|
| | | data = ''
|
| | | data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
|
| | | data = CommFunc.WriteBYTE(data, self.Count)
|
| | | for i in range(self.Count):
|
| | | data = CommFunc.WriteString(data, self.NPCAttackCountList[i].GetLength(), self.NPCAttackCountList[i].GetBuffer())
|
| | | return data
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''
|
| | | Head:%s,
|
| | | Count:%d,
|
| | | NPCAttackCountList:%s
|
| | | '''\
|
| | | %(
|
| | | self.Head.OutputString(),
|
| | | self.Count,
|
| | | "..."
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
|
| | | m_NAtagMCNPCAttackCountInfo=tagMCNPCAttackCountInfo()
|
| | | ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCNPCAttackCountInfo.Head.Cmd,m_NAtagMCNPCAttackCountInfo.Head.SubCmd))] = m_NAtagMCNPCAttackCountInfo
|
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # A3 26 NPCID已采集次数信息 #tagMCNPCIDCollectionCntInfo
|
| | |
|
| | | class tagMCNPCIDCollectionCnt(Structure):
|
| | |
| | | PlayerFB.CrossServerMsg_EnterFBRet(msgData, tick)
|
| | |
|
| | | # 需要发送到地图服务器处理的
|
| | | elif msgType in [ShareDefine.CrossServerMsg_RebornRet, ShareDefine.CrossServerMsg_CollectNPCOK, ShareDefine.CrossServerMsg_FBEnd]:
|
| | | elif msgType in [ShareDefine.CrossServerMsg_RebornRet, ShareDefine.CrossServerMsg_CollectNPCOK, ShareDefine.CrossServerMsg_FBEnd,
|
| | | ShareDefine.CrossServerMsg_NPCAttackCount]:
|
| | | MapServer_ClientServerReceiveMsg(msgType, msgData)
|
| | |
|
| | | elif msgType == ShareDefine.CrossServerMsg_CrossServerState:
|
| | |
| | | PlayerControl.SetCrossMapID(curPlayer, 0)
|
| | | return
|
| | |
|
| | | def SendCrossRealmReg(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0):
|
| | | def SendCrossRealmReg(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0, lineID=0):
|
| | | # 发送跨服账号注册上传数据
|
| | |
|
| | | # 设置上传数据的活动类型
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_CrossRegisterMap, registerMap)
|
| | | sysMsg = str([registerMap, mapID, dataMapID, copyMapID, posX, posY])
|
| | | sysMsg = str([registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID])
|
| | | curPlayer.MapServer_QueryPlayerResult(0, 0, "CrossRealmReg", sysMsg, len(sysMsg))
|
| | | GameWorld.Log("SendCrossRealmReg registerMap=%s,mapID=%s,dataMapID=%s,copyMapID=%s,posX=%s,posY=%s"
|
| | | % (registerMap, mapID, dataMapID, copyMapID, posX, posY), curPlayer.GetPlayerID())
|
| | |
| | | return
|
| | |
|
| | | playerIDList = [playerID]
|
| | | retInfo = [playerIDList, dataMapID, mapID, copyMapID]
|
| | | retInfo = [playerIDList, dataMapID, mapID, copyMapID, funcLineID]
|
| | | CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_EnterFBRet, retInfo, [serverGroupID])
|
| | | return
|
| | |
|
| | | def CrossServerMsg_EnterFBRet(msgData, tick):
|
| | | ## 收到跨服服务器动态分配的跨服副本进入信息
|
| | |
|
| | | playerIDList, dataMapID, mapID, copyMapID = msgData
|
| | | playerIDList, dataMapID, mapID, copyMapID, funcLineID = msgData
|
| | |
|
| | | dynamicLineMapDict = IpyGameDataPY.GetFuncEvalCfg("CrossDynamicLineMap", 1)
|
| | | if dataMapID not in dynamicLineMapDict:
|
| | |
| | | curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
|
| | | if not curPlayer:
|
| | | continue
|
| | | CrossRealmPlayer.SendCrossRealmReg(curPlayer, dataMapID, mapID, dataMapID, copyMapID, posX, posY)
|
| | | CrossRealmPlayer.SendCrossRealmReg(curPlayer, dataMapID, mapID, dataMapID, copyMapID, posX, posY, lineID=funcLineID)
|
| | |
|
| | | return
|
| | |
|
| | |
| | | return
|
| | | copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]
|
| | | copyMapObj.openState = 1
|
| | | funcLineID = copyMapObj.funcLineID
|
| | |
|
| | | # 通知子服等待中的玩家可以进入副本
|
| | | serverPlayerIDListDict = {}
|
| | |
| | | GameWorld.Log("动态分配虚拟线路启动成功,通知子服等待玩家可进入: dataMapID=%s,mapID=%s,copyMapID=%s,serverPlayerIDListDict=%s"
|
| | | % (dataMapID, mapID, copyMapID, serverPlayerIDListDict))
|
| | | for serverGroupID, playerIDList in serverPlayerIDListDict.items():
|
| | | retInfo = [playerIDList, dataMapID, mapID, copyMapID]
|
| | | retInfo = [playerIDList, dataMapID, mapID, copyMapID, funcLineID]
|
| | | CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_EnterFBRet, retInfo, [serverGroupID])
|
| | |
|
| | | #GameWorld.DebugLog(" PyGameData.g_crossDynamicLineInfo=%s" % PyGameData.g_crossDynamicLineInfo)
|
| | |
| | | CrossServerMsg_CollectNPCOK = "CollectNPCOK" # 采集NPC完成
|
| | | CrossServerMsg_EnterFBRet = "EnterFBRet" # 请求进入跨服副本返回信息
|
| | | CrossServerMsg_FBEnd = "FBEnd" # 完成跨服副本
|
| | | CrossServerMsg_NPCAttackCount = "NPCAttackCount" # 攻击NPC次数记录
|
| | |
|
| | | # 子服发送跨服信息定义
|
| | | ClientServerMsg_ServerInitOK = "ServerInitOK" # 子服启动成功
|
| | |
| | | Def_PlayerKey_CopyFuncAttr = "CopyFuncAttr%s" # 玩家属性刷新中的计算属性缓存,便于buff刷新计算
|
| | | Def_Player_RefreshAttrByBuff = "PlayerAttrByBuff" # 玩家属性刷新功能属性缓存,便于buff刷新计算, 间隔刷新
|
| | | Def_PlayerKey_ClientCustomScene = "ClientCustomScene" # 客户端自定义场景状态
|
| | | Def_PlayerKey_ClientCustomSceneMapID = "ClientCustomSceneMapID" # 客户端自定义场景地图ID
|
| | | Def_PlayerKey_ClientCustomSceneLineID = "ClientCustomSceneLineID" # 客户端自定义场景功能线路ID
|
| | | Def_PlayerKey_ChangeMapID = "ChangeMapID" # 请求切换的地图ID
|
| | | Def_PlayerKey_ResetFBLinePosX = "ResetFBLinePosX" # 请求切换副本多合一地图功能线路ID
|
| | | Def_PlayerKey_ResetFBLinePosY = "ResetFBLinePosY" # 请求切换副本多合一地图功能线路ID
|
| | |
| | | Def_Player_Dict_FBFirstEnterRecord = "FBFEntRec" # 记录副本是否参与过,按位0 1 存储表示
|
| | | Def_FBStar_MaxKeyCnt = 5 # 暂时每个副本ID支持9*5个lineID记录
|
| | | Def_Player_Dict_ReqFBFuncLine = "ReqFBFuncLine" # 请求进入的副本功能线路
|
| | | Def_Player_Dict_ReqCrossFBFuncLine = "ReqCrossFBFuncLine" # 请求进入跨服的副本功能线路
|
| | | Def_Player_Dict_TeamFBAverageLV = "TeamFBAverageLV" # 请求进入的组队副本平均等级, 临时用,进入副本设置完后删除
|
| | | Def_Player_Dict_TeamFBMaxLV = "TeamFBMaxLV" # 请求进入的组队副本最大等级, 临时用,进入副本设置完后删除
|
| | | Def_Player_Dict_TeamFBPlayerCnt = "TeamFBPlayerCnt" # 请求进入的组队副本玩家个数, 临时用,进入副本设置完后删除
|
| | |
| | | Def_PDict_RecoverGainLastTime = "RecoverGainLastTime" # 上一次资源找回时的时间
|
| | |
|
| | | Def_PDict_NPCKillCount = "NPCKillCount_%s" # NPC已击杀次数, 参数(NPCID) CCBBAA, AA存储公共装备次数,BB存储公共ID次数,CC存储私有次数
|
| | | Def_PDict_NPCAttackCount = "NPCAttackCount_%s" # NPC已攻击次数, 参数(NPCID)
|
| | |
|
| | | Def_PDict_RedPacketInviteGet = "RedPacketInviteGet" # 红包邀请领取
|
| | | Def_PDict_RedPacketGetState = "RedPacketGetState" # 红包领取状态
|
| | |
| | | TriggerType_IsDealy, # 是否触发致命一击 72 暂且理解为和概率是独立,有新概念产生则重定义
|
| | | ) = range(1, 73)
|
| | |
|
| | |
|
| | | # NPC功能类型定义
|
| | | Def_NPCFuncType_Goblin = 70 # 盗宝哥布林
|
| | |
|
| | | #不可以佩戴翅膀的地图
|
| | | CanNotWearWingMapIDList = []
|
| | |
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # A3 25 NPC已攻击次数信息 #tagMCNPCAttackCountInfo
|
| | |
|
| | | class tagMCNPCAttackCount(Structure):
|
| | | _pack_ = 1
|
| | | _fields_ = [
|
| | | ("NPCID", c_int), |
| | | ("AttackCount", c_ubyte), #已攻击次数
|
| | | ]
|
| | |
|
| | | def __init__(self):
|
| | | self.Clear()
|
| | | 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.NPCID = 0
|
| | | self.AttackCount = 0
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | return sizeof(tagMCNPCAttackCount)
|
| | |
|
| | | def GetBuffer(self):
|
| | | return string_at(addressof(self), self.GetLength())
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''// A3 25 NPC已攻击次数信息 //tagMCNPCAttackCountInfo:
|
| | | NPCID:%d,
|
| | | AttackCount:%d
|
| | | '''\
|
| | | %(
|
| | | self.NPCID,
|
| | | self.AttackCount
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
|
| | | class tagMCNPCAttackCountInfo(Structure):
|
| | | Head = tagHead()
|
| | | Count = 0 #(BYTE Count)
|
| | | NPCAttackCountList = list() #(vector<tagMCNPCAttackCount> NPCAttackCountList)
|
| | | data = None
|
| | |
|
| | | def __init__(self):
|
| | | self.Clear()
|
| | | self.Head.Cmd = 0xA3
|
| | | self.Head.SubCmd = 0x25
|
| | | return
|
| | |
|
| | | def ReadData(self, _lpData, _pos=0, _Len=0):
|
| | | self.Clear()
|
| | | _pos = self.Head.ReadData(_lpData, _pos)
|
| | | self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
|
| | | for i in range(self.Count):
|
| | | temNPCAttackCountList = tagMCNPCAttackCount()
|
| | | _pos = temNPCAttackCountList.ReadData(_lpData, _pos)
|
| | | self.NPCAttackCountList.append(temNPCAttackCountList)
|
| | | return _pos
|
| | |
|
| | | def Clear(self):
|
| | | self.Head = tagHead()
|
| | | self.Head.Clear()
|
| | | self.Head.Cmd = 0xA3
|
| | | self.Head.SubCmd = 0x25
|
| | | self.Count = 0
|
| | | self.NPCAttackCountList = list()
|
| | | return
|
| | |
|
| | | def GetLength(self):
|
| | | length = 0
|
| | | length += self.Head.GetLength()
|
| | | length += 1
|
| | | for i in range(self.Count):
|
| | | length += self.NPCAttackCountList[i].GetLength()
|
| | |
|
| | | return length
|
| | |
|
| | | def GetBuffer(self):
|
| | | data = ''
|
| | | data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
|
| | | data = CommFunc.WriteBYTE(data, self.Count)
|
| | | for i in range(self.Count):
|
| | | data = CommFunc.WriteString(data, self.NPCAttackCountList[i].GetLength(), self.NPCAttackCountList[i].GetBuffer())
|
| | | return data
|
| | |
|
| | | def OutputString(self):
|
| | | DumpString = '''
|
| | | Head:%s,
|
| | | Count:%d,
|
| | | NPCAttackCountList:%s
|
| | | '''\
|
| | | %(
|
| | | self.Head.OutputString(),
|
| | | self.Count,
|
| | | "..."
|
| | | )
|
| | | return DumpString
|
| | |
|
| | |
|
| | | m_NAtagMCNPCAttackCountInfo=tagMCNPCAttackCountInfo()
|
| | | ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCNPCAttackCountInfo.Head.Cmd,m_NAtagMCNPCAttackCountInfo.Head.SubCmd))] = m_NAtagMCNPCAttackCountInfo
|
| | |
|
| | |
|
| | | #------------------------------------------------------
|
| | | # A3 26 NPCID已采集次数信息 #tagMCNPCIDCollectionCntInfo
|
| | |
|
| | | class tagMCNPCIDCollectionCnt(Structure):
|
| | |
| | | NPCCommon.SyncCollNPCTime(curPlayer, resetNPCIDList)
|
| | |
|
| | | GameWorld.DebugAnswer(curPlayer, "重置采集NPC成功")
|
| | | |
| | | npcID = IpyGameDataPY.GetFuncCfg("CrossGrasslandCfg", 1)
|
| | | NPCCommon.UpdateNPCAttackCount(curPlayer, npcID, 0)
|
| | | return
|
| | |
|
| | |
| | | ownerName = curPlayer.GetPlayerName()
|
| | | giveItemList = __GetDemonKingPrizeItemList(curPlayer, mapID, funcLineID, eventID, isOwner)
|
| | | GameWorld.Log("玩家奖励: %s" % giveItemList, playerID)
|
| | | ChItem.DropItem(curPlayer, giveItemList, bossID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True)
|
| | | ChItem.DoMapDropItem(curPlayer, giveItemList, bossID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True)
|
| | | #curPlayer.Sync_TimeTick(ChConfig.tttPickupItem, 0, ChConfig.Def_FBPickupItemTime, True)
|
| | | if not isCrossServer:
|
| | | __SetDemonKingVisitState(curPlayer, mapID, funcLineID, PlayerFairyDomain.FDEventState_Visited)
|
| | |
| | | import IpyGameDataPY
|
| | | import PyGameData
|
| | | import NPCCommon
|
| | | import PlayerControl
|
| | | import ChConfig
|
| | |
|
| | | def DoResetCrossGrassland(curPlayer, eventType):
|
| | | def DoResetCrossGrassland(curPlayer, eventType, fdeventID):
|
| | | ## 草园重置
|
| | |
|
| | | resetCollectType = 10 + eventType
|
| | | NPCCommon.DoResetCollectNPCTimeByType(curPlayer, [resetCollectType])
|
| | |
|
| | | # 宝箱怪次数重置
|
| | | |
| | | if eventType == PlayerFairyDomain.FDEventType_GrasslandXian:
|
| | | npcID = IpyGameDataPY.GetFuncCfg("CrossGrasslandCfg", 1)
|
| | | if npcID:
|
| | | NPCCommon.UpdateNPCAttackCount(curPlayer, [npcID], 0)
|
| | | |
| | | return
|
| | |
|
| | | def __SetGrasslandVisitState(curPlayer, mapID, lineID, state):
|
| | |
| | | __SetGrasslandVisitState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visiting)
|
| | | return
|
| | |
|
| | | ## 给自定义副本奖励后续处理
|
| | | ## @return: 返回结算副本over信息字典,不含jsonItem信息
|
| | | def OnGiveCustomFBPrizeOK(curPlayer, mapID, lineID):
|
| | | def DoCheckUpdateGrasslandEnd(curPlayer):
|
| | | ## 检查更新草园已拜访完成
|
| | | |
| | | grasslandMapIDList = [ChConfig.Def_FBMapID_CrossGrasslandLing, ChConfig.Def_FBMapID_CrossGrasslandXian]
|
| | | crossMapID = PlayerControl.GetCrossMapID(curPlayer)
|
| | | clientCustomSceneMapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
|
| | | if crossMapID in grasslandMapIDList:
|
| | | mapID = crossMapID
|
| | | lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ReqCrossFBFuncLine)
|
| | | elif clientCustomSceneMapID in grasslandMapIDList:
|
| | | mapID = clientCustomSceneMapID
|
| | | lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
|
| | | else:
|
| | | return
|
| | | |
| | | # 采集次数是否已用完
|
| | | collNPCIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("MapRefreshNPC", mapID)
|
| | | if not collNPCIpyDataList:
|
| | | return
|
| | | |
| | | for collIpyData in collNPCIpyDataList:
|
| | | npcIDList = collIpyData.GetNPCIDList()
|
| | | for npcID in npcIDList:
|
| | | collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID)
|
| | | if not collectNPCIpyData:
|
| | | return
|
| | | limitMaxTime = collectNPCIpyData.GetMaxCollectCount()
|
| | | totalCollTime = NPCCommon.GetTodayCollectCount(curPlayer, npcID)
|
| | | if totalCollTime < limitMaxTime:
|
| | | GameWorld.DebugLog("草园NPC采集次数未用完! npcID=%s,totalCollTime=%s < limitMaxTime=%s" % (npcID, totalCollTime, limitMaxTime))
|
| | | return
|
| | | |
| | | # 宝箱怪攻击次数是否已用完
|
| | | if mapID == ChConfig.Def_FBMapID_CrossGrasslandXian:
|
| | | boxNPCID = IpyGameDataPY.GetFuncCfg("CrossGrasslandCfg", 1)
|
| | | boxNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("TreasureNPC", boxNPCID)
|
| | | if not boxNPCIpyData:
|
| | | return
|
| | | attackCountDropWeightInfo = boxNPCIpyData.GetAttackCountDropWeightInfo()
|
| | | if not attackCountDropWeightInfo:
|
| | | return
|
| | | maxAttackCount = max(attackCountDropWeightInfo)
|
| | | attackCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % boxNPCID)
|
| | | if attackCount < maxAttackCount:
|
| | | GameWorld.DebugLog("草园宝箱怪攻击次数未用完! boxNPCID=%s,attackCount=%s < maxAttackCount=%s" % (boxNPCID, attackCount, maxAttackCount))
|
| | | return
|
| | | |
| | | __SetGrasslandVisitState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visited)
|
| | | overDict = {}
|
| | | return overDict
|
| | | GameWorld.DebugLog("设置草园已完成!mapID=%s, lineID=%s" % (mapID, lineID))
|
| | | return
|
| | |
|
| | |
|
| | |
| | | ("BYTE", "NotifyCollectResult", 0),
|
| | | ),
|
| | |
|
| | | "TreasureNPC":(
|
| | | ("DWORD", "NPCID", 1),
|
| | | ("dict", "AttackCountDropWeightInfo", 0),
|
| | | ("list", "AttackDropWeightList", 0),
|
| | | ("list", "AttackDropWeightListEx", 0),
|
| | | ("BYTE", "DropCountEx", 0),
|
| | | ("BYTE", "AlchemyDiffLV", 0),
|
| | | ("char", "NotDropNotify", 0),
|
| | | ),
|
| | |
|
| | | "Chests":(
|
| | | ("DWORD", "ChestsItemID", 1),
|
| | | ("DWORD", "CostItemID", 0),
|
| | |
| | | def GetAlchemyDiffLV(self): return self.AlchemyDiffLV # 过滤炼丹等级差,0-不过滤,>0过滤大于自身炼丹等级X级的物品
|
| | | def GetNotifyCollectResult(self): return self.NotifyCollectResult # 是否通知采集结果 |
| | | |
| | | # 宝箱怪表 |
| | | class IPY_TreasureNPC(): |
| | | |
| | | def __init__(self): |
| | | self.NPCID = 0
|
| | | self.AttackCountDropWeightInfo = {}
|
| | | self.AttackDropWeightList = []
|
| | | self.AttackDropWeightListEx = []
|
| | | self.DropCountEx = 0
|
| | | self.AlchemyDiffLV = 0
|
| | | self.NotDropNotify = "" |
| | | return |
| | | |
| | | def GetNPCID(self): return self.NPCID # 宝箱怪NPCID
|
| | | def GetAttackCountDropWeightInfo(self): return self.AttackCountDropWeightInfo # 攻击次数对应掉落权重饼图 {次数:[[权重, [物品ID,个数,是否拍品]], ...], ...}
|
| | | def GetAttackDropWeightList(self): return self.AttackDropWeightList # 常规攻击权重饼图 [[权重, [物品ID,个数,是否拍品]], ...]
|
| | | def GetAttackDropWeightListEx(self): return self.AttackDropWeightListEx # 额外掉落权重饼图库,每次攻击都会掉落 [[权重, [物品ID,个数,是否拍品]], ...]
|
| | | def GetDropCountEx(self): return self.DropCountEx # 额外库执行次数
|
| | | def GetAlchemyDiffLV(self): return self.AlchemyDiffLV # 过滤炼丹等级差,0-不过滤,>0过滤大于自身炼丹等级X级的物品
|
| | | def GetNotDropNotify(self): return self.NotDropNotify # 没有掉落时提示信息 |
| | | |
| | | # 宝箱表开启 |
| | | class IPY_Chests(): |
| | | |
| | |
| | | self.ipyResourcesBackLen = len(self.ipyResourcesBackCache)
|
| | | self.ipyCollectNPCCache = self.__LoadFileData("CollectNPC", IPY_CollectNPC)
|
| | | self.ipyCollectNPCLen = len(self.ipyCollectNPCCache)
|
| | | self.ipyTreasureNPCCache = self.__LoadFileData("TreasureNPC", IPY_TreasureNPC)
|
| | | self.ipyTreasureNPCLen = len(self.ipyTreasureNPCCache)
|
| | | self.ipyChestsCache = self.__LoadFileData("Chests", IPY_Chests)
|
| | | self.ipyChestsLen = len(self.ipyChestsCache)
|
| | | self.ipyChestsAwardCache = self.__LoadFileData("ChestsAward", IPY_ChestsAward)
|
| | |
| | | def GetResourcesBackByIndex(self, index): return self.ipyResourcesBackCache[index]
|
| | | def GetCollectNPCCount(self): return self.ipyCollectNPCLen
|
| | | def GetCollectNPCByIndex(self, index): return self.ipyCollectNPCCache[index]
|
| | | def GetTreasureNPCCount(self): return self.ipyTreasureNPCLen
|
| | | def GetTreasureNPCByIndex(self, index): return self.ipyTreasureNPCCache[index]
|
| | | def GetChestsCount(self): return self.ipyChestsLen
|
| | | def GetChestsByIndex(self, index): return self.ipyChestsCache[index]
|
| | | def GetChestsAwardCount(self): return self.ipyChestsAwardLen
|
| | |
| | | import NPCCommon
|
| | | import FBCommon
|
| | |
|
| | | import random
|
| | | import json
|
| | | #---------------------------------------------------------------------
|
| | | #导入
|
| | |
| | |
|
| | | #---------------------------------------------------------------------
|
| | |
|
| | | def DropItem(curPlayer, itemList, npcID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True):
|
| | | def DoMapDropItem(curPlayer, itemList, npcID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True):
|
| | | if not itemList:
|
| | | return
|
| | | if isDropDisperse:
|
| | |
| | | else:
|
| | | dropItemList = itemList
|
| | |
|
| | | random.shuffle(dropItemList) # 打乱顺序
|
| | | index = 0
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | gameMap = GameWorld.GetMap()
|
| | |
| | | itemDict["UserData"] = itemInfo.GetUserData()
|
| | | return itemDict
|
| | |
|
| | | def GetWeightItemListByAlchemyDiffLV(curPlayer, weightList, alchemyDiffLV):
|
| | | ## 根据炼丹等级差异等级过滤权重列表中不满足的物品,返回新的权重列表
|
| | | resultWeightList = []
|
| | | if alchemyDiffLV:
|
| | | curAlchemyLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV)
|
| | | for itemInfo in weightList:
|
| | | itemID = itemInfo[1][0]
|
| | | itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
|
| | | if not itemData:
|
| | | continue
|
| | | if GetItemClassLV(itemData) > curAlchemyLV + alchemyDiffLV:
|
| | | continue
|
| | | resultWeightList.append(itemInfo)
|
| | | else:
|
| | | resultWeightList = weightList
|
| | | return resultWeightList
|
| | |
|
| | | ## =======================================================================================
|
| | |
|
| | | def SyncMakeItemAnswer(curPlayer, makeType, isSuccess, makeItemID):
|
| | |
| | | #!/usr/bin/python
|
| | | # -*- coding: GBK -*-
|
| | | #---------------------------------------------------------------------
|
| | | #-------------------------------------------------------------------------------
|
| | | #
|
| | | #---------------------------------------------------------------------
|
| | | ##@package AIType_196
|
| | | # @todo: 盗宝哥布林AI
|
| | | ##@package NPCAI.AIType_196
|
| | | #
|
| | | # @author: hxp
|
| | | # @date 2013-11-05
|
| | | # @version 1.9
|
| | | # @todo:盗宝哥布林/宝箱怪
|
| | | # @author hxp
|
| | | # @date 2019-04-18
|
| | | # @version 1.0
|
| | | #
|
| | | # @note: |
| | | # @change: "2013-11-08 18:00" hxp 修改逻辑
|
| | | # @change: "2013-11-12 14:50" hxp 掉落矩阵改为按掉落个数掉落
|
| | | # @change: "2013-12-27 12:40" hxp 增加地精夺宝地图不广播 |
| | | # @change: "2014-01-17 11:00" hxp 修改不掉落物品由NPC是否掉落决定,增加指定可掉落配置
|
| | | # @change: "2015-03-05 11:30" hxp 修复可能会停在无法攻击区域的问题
|
| | | # @change: "2015-03-30 19:30" hxp 增加击杀流向; 击杀广播可配置特殊NPCID对应广播
|
| | | # @change: "2015-04-21 16:00" hxp 检查纠正哥布林位置(防止处于安全区或障碍点)
|
| | | # @change: "2015-04-22 11:20" xmnathan NPC死亡时防范取到NPCID为0的情况
|
| | | # @change: "2015-07-13 11:30" ljd 非一线隐藏哥布林
|
| | | #---------------------------------------------------------------------
|
| | | """Version = 2015-07-13 11:30"""
|
| | | #---------------------------------------------------------------------
|
| | | import IPY_GameWorld
|
| | | # 详细描述: 盗宝哥布林/宝箱怪
|
| | | #
|
| | | #-------------------------------------------------------------------------------
|
| | | #"""Version = 2019-04-18 15:00"""
|
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import GameMap
|
| | | import ChConfig
|
| | | import GameWorld
|
| | | import NPCCommon
|
| | | import ChConfig
|
| | | import ReadChConfig
|
| | | import PetControl
|
| | | import GameMap
|
| | | import DataRecordPack
|
| | | import IPY_GameWorld
|
| | | import PlayerControl
|
| | | import IpyGameDataPY
|
| | | import AttackCommon
|
| | | import ItemCommon
|
| | | import GameObj
|
| | | import ChItem
|
| | |
|
| | | import random
|
| | |
|
| | | #---------------------------------------------------------------------
|
| | | #---SetDict NPC字典KEY,不存于数据库---
|
| | |
|
| | | Def_NPCKey_Goblin_AttackedTick = 'Goblin_AttackedTick' # 哥布林被攻击时间
|
| | | Def_NPCKey_Goblin_MoveDir = 'Goblin_MoveDir' # 哥布林移动方向
|
| | |
|
| | | (
|
| | | Def_DropItemType_Money, # 掉落物品类型 - 金钱
|
| | | Def_DropItemType_Goods, # 掉落物品类型 - 道具
|
| | | Def_DropItemType_Equip, # 掉落物品类型 - 装备
|
| | | ) = range(3)
|
| | |
|
| | | (
|
| | | Def_StopTime, # 多长时间未被攻击则进入呆滞状态,毫秒
|
| | | Def_AttackedDropItemCountRate, # 每次被攻击掉落的物品个数饼图概率
|
| | | Def_AttackedDropItemTypeRate, # 每次被攻击掉落的物品类型饼图概率
|
| | | Def_DieDropGoodsCountRate, # 死亡掉落的道具个数饼图概率
|
| | | Def_DieDropEquipCountRate, # 死亡掉落的装备个数饼图概率
|
| | | Def_DieDropCountRate, # 死亡掉落物品总个数饼图概率
|
| | | Def_DropGoodsRate, # 移动/死亡掉落的道具掉落饼图概率及道具id
|
| | | Def_DropEquipModelNum, # 移动/死亡掉落装备规则模板编号,模板文件GoblinDropEquip_模板文件编号.txt
|
| | | ) = range(8)
|
| | |
|
| | |
|
| | | g_filterEquipDict = {} # 装备掉落过滤字典缓存
|
| | | (
|
| | | Def_EquipModel_EquipType, # 掉落装备类型
|
| | | Def_EquipModel_LVLimit, # 掉落装备等级限制
|
| | | Def_EquipModel_QualityRate, # 掉落装备品质概率
|
| | | Def_EquipModel_DropItemList, # NPC不掉落,但这里可掉落的物品id列表
|
| | | ) = range(4)
|
| | |
|
| | |
|
| | | # 移动方向
|
| | | MoveDirList = (
|
| | |
| | | # @remarks 函数详细说明.
|
| | | def DoInit(curNPC):
|
| | | curNPC.GetNPCAngry().Init(ChConfig.Def_NormalNPCAngryCount)
|
| | | curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, 0) # 设置被攻击时间
|
| | | |
| | | DoHideGoblin(curNPC)
|
| | | #curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, 0) # 设置被攻击时间
|
| | | return
|
| | |
|
| | |
|
| | |
| | | # @return None
|
| | | # @remarks 函数详细说明.
|
| | | def ProcessAI(curNPC, tick):
|
| | | if DoHideGoblin(curNPC):
|
| | | return
|
| | |
|
| | | npcControl = NPCCommon.NPCControl(curNPC)
|
| | | if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
|
| | | #NPC死亡, 进入死亡倒计时
|
| | | if npcControl.DieTick(tick) == 0:
|
| | | return
|
| | |
|
| | | |
| | | # 上一次被攻击时间
|
| | | attackedTick = curNPC.GetDictByKey(Def_NPCKey_Goblin_AttackedTick)
|
| | |
|
| | |
| | | __CheckCorrectGoblinPos(curNPC)
|
| | | return
|
| | |
|
| | | aiConfig = __GetGoblinConfig(curNPC.GetNPCID())
|
| | | |
| | | # 一定时间内未被攻击,则停止
|
| | | if tick - attackedTick >= aiConfig[Def_StopTime]:
|
| | | if tick - attackedTick >= 3000:
|
| | | __GoblinStop(curNPC)
|
| | | return
|
| | |
|
| | |
| | | # 如果不是移动状态,则执行移动
|
| | | if curNPCAction != IPY_GameWorld.laNPCMove:
|
| | | __Runaway(curNPC, npcControl, tick)
|
| | |
|
| | | |
| | | return
|
| | |
|
| | |
|
| | |
| | |
|
| | | dist = ChConfig.Def_Screen_Area * 2
|
| | | cPosX, cPosY = 0, 0
|
| | | for i in range(0, dist * dist):
|
| | | for _ in xrange(0, dist * dist):
|
| | | cPosX = random.randint(posX - dist, posX + dist)
|
| | | cPosY = random.randint(posY - dist, posY + dist)
|
| | |
|
| | |
| | | return
|
| | |
|
| | |
|
| | | ## 哥布林移动走开
|
| | | # @param curNPC 当前npc
|
| | | # @param npcControl |
| | | # @param tick |
| | | # @return None
|
| | | ## 移动走开
|
| | | def __Runaway(curNPC, npcControl, tick):
|
| | | posX = curNPC.GetPosX()
|
| | | posY = curNPC.GetPosY()
|
| | |
| | | tagPosX, tagPosY = 0, 0
|
| | |
|
| | | # 寻找目标坐标点
|
| | | for i in range(len(MoveDirList)):
|
| | | for _ in range(len(MoveDirList)):
|
| | | tagPosX, tagPosY = __GetRandomPos(posX, posY, moveArea, moveDir)
|
| | | # 如果返回0,0点,或者位置不变,则改变移动方向
|
| | | if (tagPosX == 0 and tagPosY == 0) or (tagPosX == posX and tagPosY == posY):
|
| | |
| | | GameWorld.ErrLog("moveDir=%s not in MoveDirList" % moveDir)
|
| | | return (0, 0)
|
| | |
|
| | | for i in range(0, dist * dist):
|
| | | for _ in range(0, dist * dist):
|
| | | if moveDir == Def_MoveDir_Up: # 上
|
| | | resultX = posX
|
| | | resultY = posY + dist
|
| | |
| | | # @param tick
|
| | | # @return 具体伤害值
|
| | | def OnAttacked(atkObj, curNPC, skill, tick):
|
| | | npcControl = NPCCommon.NPCControl(curNPC)
|
| | | if GameObj.GetHP(curNPC) < GameObj.GetMaxHP(curNPC) / 2:
|
| | | GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))
|
| | | GameWorld.DebugLog("半血回满血!")
|
| | | curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, tick) # 设置被攻击时间
|
| | |
|
| | | # 每次被攻击掉落物品
|
| | | __OnAttackedDropItem(atkObj, curNPC)
|
| | | __OnAttackedDropItem(atkObj, curNPC, npcControl)
|
| | | return
|
| | |
|
| | | def OnCheckCanDie(atkObj, curNPC, skill, tick):
|
| | | ## 检查NPC是否可死亡
|
| | | GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))
|
| | | GameWorld.DebugLog("死亡回满血!")
|
| | | return False
|
| | |
|
| | |
|
| | | ## 每次被攻击掉落物品
|
| | | # @param atkObj 攻击发起者
|
| | | # @param curNPC 被攻击NPC
|
| | | # @return None
|
| | | def __OnAttackedDropItem(atkObj, curNPC):
|
| | | npcControl = NPCCommon.NPCControl(curNPC)
|
| | | dropType = ChConfig.Def_NPCHurtTypeAll
|
| | | ownerID = 0
|
| | | |
| | | atkObjType = atkObj.GetGameObjType()
|
| | | |
| | | # 如果是玩家,则物品拥有者属于该玩家
|
| | | if atkObjType == IPY_GameWorld.gotPlayer:
|
| | | dropType = ChConfig.Def_NPCHurtTypePlayer
|
| | | ownerID = atkObj.GetPlayerID()
|
| | | |
| | | # 如果是召唤兽或宠物,则物品拥有者属于对应主人
|
| | | elif atkObjType == IPY_GameWorld.gotNPC:
|
| | | npcObjType = atkObj.GetGameNPCObjType()
|
| | | # 判断召唤兽主人
|
| | | if npcObjType == IPY_GameWorld.gnotSummon:
|
| | | curNPCDetail = GameWorld.GetObjDetail(atkObj)
|
| | | |
| | | if curNPCDetail != None:
|
| | | curNPCOwner = curNPCDetail.GetOwner()
|
| | | summonOwner = GameWorld.GetObjDetail(curNPCOwner)
|
| | | if summonOwner != None:
|
| | | # 召唤兽主人为玩家
|
| | | if summonOwner.GetGameObjType() == IPY_GameWorld.gotPlayer:
|
| | | dropType = ChConfig.Def_NPCHurtTypePlayer
|
| | | ownerID = summonOwner.GetPlayerID()
|
| | | |
| | | # 判断宠物主人
|
| | | elif npcObjType == IPY_GameWorld.gnotPet:
|
| | | curPlayer = PetControl.GetPetOwner(atkObj)
|
| | | if curPlayer != None:
|
| | | dropType = ChConfig.Def_NPCHurtTypePlayer
|
| | | ownerID = curPlayer.GetPlayerID()
|
| | | |
| | | aiConfig = __GetGoblinConfig(curNPC.GetNPCID())
|
| | | # 掉落个数
|
| | | dropCount = GameWorld.GetResultByRandomList(aiConfig[Def_AttackedDropItemCountRate])
|
| | | |
| | | ## 掉落规则修改,暂屏蔽,之后有用到该AI再做修改
|
| | | # # 循环掉落
|
| | | # for i in range(dropCount):
|
| | | # dropItemType = GameWorld.GetResultByRandomList(aiConfig[Def_AttackedDropItemTypeRate])
|
| | | # |
| | | # # 金钱
|
| | | # if dropItemType == Def_DropItemType_Money:
|
| | | # npcControl.DropMoney(ChConfig.Def_NPCMapDropRate, dropType, ownerID)
|
| | | # # 道具
|
| | | # elif dropItemType == Def_DropItemType_Goods:
|
| | | # goodsID = GameWorld.GetResultByRandomList(aiConfig[Def_DropGoodsRate])
|
| | | # npcControl.DropItem(goodsID, dropType, ownerID)
|
| | | # # 装备
|
| | | # elif dropItemType == Def_DropItemType_Equip:
|
| | | # equipID = __GetRadomDropEquipID(aiConfig[Def_DropEquipModelNum])
|
| | | # npcControl.DropItem(equipID, dropType, ownerID)
|
| | | return
|
| | |
|
| | |
|
| | | ## NPC死亡处理
|
| | | # @param curNPC 死亡NPC
|
| | | # @param HurtType 掉落类型
|
| | | # @param HurtID 对应拥有者id
|
| | | # @param modulus 掉落系数
|
| | | # @return None
|
| | | def OnDie(curNPC, HurtType, HurtID):
|
| | | #GameWorld.DebugLog("OnDieDropItem...dropType=%s, ownerID=%s" % (dropType, ownerID))
|
| | | # 该死亡掉落无物品保护
|
| | | dropType = ChConfig.Def_NPCHurtTypeAll
|
| | | ownerID = 0
|
| | | npcControl = NPCCommon.NPCControl(curNPC)
|
| | | |
| | | if curNPC.GetNPCID() == 0:
|
| | | GameWorld.ErrLog("AIType_196 OnDie NPCID=0")
|
| | | def __OnAttackedDropItem(atkObj, curNPC, npcControl):
|
| | | attackPlayer, npcObjType = AttackCommon.GetAttackPlayer(atkObj)
|
| | | if npcObjType:
|
| | | return
|
| | | aiConfig = __GetGoblinConfig(curNPC.GetNPCID())
|
| | | dropItemIDList = [] # [[itemID, count],...]
|
| | | if not attackPlayer:
|
| | | return
|
| | | npcID = curNPC.GetNPCID()
|
| | | ipyData = IpyGameDataPY.GetIpyGameDataNotLog("TreasureNPC", npcID)
|
| | | if not ipyData:
|
| | | return
|
| | | attackCountDropWeightInfo = ipyData.GetAttackCountDropWeightInfo()
|
| | | attackDropWeightList = ipyData.GetAttackDropWeightList()
|
| | | attackDropWeightListEx = ipyData.GetAttackDropWeightListEx()
|
| | | dropCountEx = ipyData.GetDropCountEx()
|
| | | alchemyDiffLV = ipyData.GetAlchemyDiffLV()
|
| | |
|
| | | # 道具掉落个数
|
| | | dropGoodsCount = GameWorld.GetResultByRandomList(aiConfig[Def_DieDropGoodsCountRate])
|
| | | for i in range(dropGoodsCount):
|
| | | goodsID = GameWorld.GetResultByRandomList(aiConfig[Def_DropGoodsRate])
|
| | | dropItemIDList.append([goodsID, 1]) # 增加一个掉落道具
|
| | | mainItemWeightList = []
|
| | | if attackCountDropWeightInfo:
|
| | | maxCount = max(attackCountDropWeightInfo)
|
| | | attackCount = attackPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID) + 1
|
| | | if attackCount <= maxCount:
|
| | | if attackCount in attackCountDropWeightInfo:
|
| | | mainItemWeightList = attackCountDropWeightInfo[attackCount]
|
| | | NPCCommon.UpdateNPCAttackCount(attackPlayer, npcID, attackCount, maxCount)
|
| | | |
| | | if not mainItemWeightList and attackDropWeightList:
|
| | | mainItemWeightList = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightList, alchemyDiffLV)
|
| | |
|
| | | # 装备掉落个数
|
| | | dropEquipCount = GameWorld.GetResultByRandomList(aiConfig[Def_DieDropEquipCountRate])
|
| | | for i in range(dropEquipCount):
|
| | | equipID = __GetRadomDropEquipID(aiConfig[Def_DropEquipModelNum])
|
| | | dropItemIDList.append([equipID, 1]) # 增加一个掉落装备
|
| | | mainItemInfo = GameWorld.GetResultByWeightList(mainItemWeightList)
|
| | |
|
| | | # 掉落总个数
|
| | | dropCount = GameWorld.GetResultByRandomList(aiConfig[Def_DieDropCountRate])
|
| | | # npc超爆
|
| | | #npcControl.NPCSuperDropByItemIDExMoney(dropItemIDList, dropType, ownerID, dropCount)
|
| | | # 全服广播
|
| | | mapID = GameWorld.GetMap().GetMapID()
|
| | | if mapID not in []:
|
| | | notifyMarkDict = ReadChConfig.GetEvalChConfig("GoblinNotify")
|
| | | notifyMark = notifyMarkDict.get(curNPC.GetNPCID())
|
| | | if notifyMark:
|
| | | PlayerControl.WorldNotify(0, notifyMark, [GameWorld.GetMap().GetMapID()]) |
| | | if not mainItemInfo:
|
| | | notDropNotify = ipyData.GetNotDropNotify()
|
| | | if notDropNotify:
|
| | | PlayerControl.NotifyCode(attackPlayer, notDropNotify)
|
| | | return
|
| | | |
| | | dropItemList = []
|
| | | if mainItemInfo:
|
| | | dropItemList.append(mainItemInfo)
|
| | | |
| | | if attackDropWeightListEx and dropCountEx:
|
| | | weightListEx = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightListEx, alchemyDiffLV)
|
| | | for _ in xrange(dropCountEx):
|
| | | itemInfo = GameWorld.GetResultByWeightList(weightListEx)
|
| | | if itemInfo:
|
| | | dropItemList.append(itemInfo)
|
| | | |
| | | if not dropItemList:
|
| | | return
|
| | | |
| | | dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY()
|
| | | ChItem.DoMapDropItem(attackPlayer, dropItemList, npcID, dropPosX, dropPosY, isOnlySelfSee=False)
|
| | | return
|
| | |
|
| | |
|
| | | ## 玩家击杀哥布林
|
| | | # @param curNPC
|
| | | # @param curPlayer
|
| | | # @param skill
|
| | | # @return |
| | | def OnAttackDieByPlayer(curNPC, curPlayer, skill):
|
| | | DataRecordPack.DR_KillNPC(curPlayer, "Goblin", curNPC.GetNPCID())
|
| | | return
|
| | |
|
| | |
|
| | | ## 获取对应哥布林配置
|
| | | # @param npcID
|
| | | # @return 配置信息
|
| | | def __GetGoblinConfig(npcID):
|
| | | return ReadChConfig.GetEvalChConfig('Goblin_%s' % npcID)
|
| | |
|
| | |
|
| | | ## 获取随机掉落装备id
|
| | | # @param dropEquipModelNum 装备掉落规则模板编号
|
| | | # @return >0掉落装备id,返回0表示无法获取掉落装备id
|
| | | def __GetRadomDropEquipID(dropEquipModelNum):
|
| | | global g_filterEquipDict
|
| | | |
| | | dropEquipModel = ReadChConfig.GetEvalChConfig('GoblinDropEquip_%s' % dropEquipModelNum)
|
| | | |
| | | filterItemList = g_filterEquipDict.get(dropEquipModelNum)
|
| | | # 如果没有,则加载
|
| | | if not filterItemList:
|
| | | GameWorld.DebugLog("加载哥布林掉落装备模板GoblinDropEquip_%s.txt" % dropEquipModelNum)
|
| | | itemTypeList = dropEquipModel[Def_EquipModel_EquipType]
|
| | | itemMinLV = dropEquipModel[Def_EquipModel_LVLimit][0]
|
| | | itemMaxLV = dropEquipModel[Def_EquipModel_LVLimit][1]
|
| | | dropIDList = dropEquipModel[Def_EquipModel_DropItemList]
|
| | | filterItemList = __FilterItemFromDB(itemTypeList, itemMinLV, itemMaxLV, dropIDList)
|
| | | g_filterEquipDict[dropEquipModelNum] = filterItemList
|
| | | |
| | | # 随机是否卓越
|
| | | quality = GameWorld.GetResultByRandomList(dropEquipModel[Def_EquipModel_QualityRate])
|
| | | |
| | | dropEquipIdList = filterItemList[quality]
|
| | | |
| | | if not dropEquipIdList:
|
| | | GameWorld.ErrLog("__GetRadomDropEquipID() can not find filter equip," + \
|
| | | "please check GoblinDropEquip_%s.txt!!!" % dropEquipModelNum)
|
| | | return 0
|
| | | |
| | | return random.choice(dropEquipIdList)
|
| | |
|
| | |
|
| | | ## 从数据库中查找满足要求的物品ID
|
| | | # @param itemTypeList: 获得的物品类型列表
|
| | | # @param itemMinLV: 获得的物品最低等级
|
| | | # @param itemMaxLV: 获得的物品最高等级
|
| | | # @param dropIDList: NPC不掉落,但这里可掉落的物品id列表
|
| | | # @return 找到的物品ID列表:[[非卓越装id列表], [卓越装id列表]]
|
| | | def __FilterItemFromDB(itemTypeList, itemMinLV, itemMaxLV, dropIDList):
|
| | | findItemIdList = [[], []] # [[非卓越装], [卓越装]]
|
| | | |
| | | for itemType in itemTypeList:
|
| | | |
| | | gameData = GameWorld.GetGameData()
|
| | | gameData.FilterItemByType(itemType) # 过滤物品类型
|
| | | for i in range(0, gameData.GetFilterItemCount()):
|
| | | curFindItem = gameData.GetFilterItem(i)
|
| | | itemID = curFindItem.GetItemTypeID()
|
| | | |
| | | # NPC不掉落的,且不在特定掉落id列表里的不掉落
|
| | | if not curFindItem.GetCanNPCDrop() and itemID not in dropIDList:
|
| | | continue
|
| | | |
| | | # 不在过滤等级内,跳过
|
| | | if curFindItem.GetLV() < itemMinLV or curFindItem.GetLV() > itemMaxLV:
|
| | | continue
|
| | |
|
| | | findItemIdList[1 if curFindItem.GetItemQuality() else 0].append(curFindItem.GetItemTypeID())
|
| | | |
| | | GameWorld.DebugLog("哥布林掉落装备id列表=%s,卓越装备id列表=%s" % (str(findItemIdList[0]), str(findItemIdList[1])))
|
| | | return findItemIdList
|
| | |
|
| | | ## 隐藏NPC
|
| | | def DoHideGoblin(curNPC):
|
| | | |
| | | # 只在一线刷, 非一线设置该NPC隐身
|
| | | lineID = GameWorld.GetGameWorld().GetLineID()
|
| | | if lineID != 0:
|
| | | goblinNPCIDList = [30000,30001,30002,30003,30004,30005,30006,30007,30008,30009]
|
| | | npcID = curNPC.GetNPCID()
|
| | | if npcID in goblinNPCIDList and curNPC.GetVisible():
|
| | | curNPC.SetVisible(False)
|
| | | GameWorld.Log("非一线,隐藏该NPCID=%s!" % npcID)
|
| | | return True
|
| | | |
| | | return False
|
| | |
| | | import PlayerFairyCeremony
|
| | | import PlayerNewFairyCeremony
|
| | | import GameLogic_CrossDemonKing
|
| | | import GameLogic_CrossGrassland
|
| | | import PlayerWeekParty
|
| | | import PlayerActLogin
|
| | | import FamilyRobBoss
|
| | |
| | | if collectCnt <= 0:
|
| | | return
|
| | |
|
| | | isMaxTime = False # 是否达到了采集最大次数
|
| | | limitMaxTime = collectNPCIpyData.GetMaxCollectCount()
|
| | | if limitMaxTime > 0:
|
| | | todayCollTime = GetTodayCollectCount(curPlayer, npcID)
|
| | | canCollectCnt = max(0, limitMaxTime - todayCollTime)
|
| | | collectCnt = min(collectCnt, canCollectCnt)
|
| | | if collectCnt <= 0:
|
| | | GameWorld.DebugLog(" 该NPC已达到最大采集次数: todayCollTime=%s,limitMaxTime=%s" % (todayCollTime, limitMaxTime))
|
| | | GameWorld.DebugLog(" 该NPC已达到最大采集次数: npcID=%s,todayCollTime=%s,limitMaxTime=%s" % (npcID, todayCollTime, limitMaxTime))
|
| | | return
|
| | |
|
| | | updCollTime = todayCollTime + collectCnt
|
| | | curCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)
|
| | | updCollTime = curCollTime + collectCnt
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime)
|
| | | SyncCollNPCTime(curPlayer, [npcID])
|
| | | GameWorld.DebugLog(" 增加采集次数: todayCollTime=%s,updCollTime=%s" % (todayCollTime, updCollTime))
|
| | | GameWorld.DebugLog(" 增加采集次数: npcID=%s,todayCollTime=%s,curCollTime=%s,updCollTime=%s" % (npcID, todayCollTime, curCollTime, updCollTime))
|
| | | isMaxTime = todayCollTime + collectCnt >= limitMaxTime
|
| | |
|
| | | awardIitemList = []
|
| | | awardItemList = []
|
| | | collectAwardCfg = collectNPCIpyData.GetCollectAward()
|
| | | collectAppointAwardCfg = collectNPCIpyData.GetCollectAppointAward()
|
| | | if collectAppointAwardCfg:
|
| | | collTotalTime = min(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID) + 1, ChConfig.Def_UpperLimit_DWord)
|
| | | if collTotalTime in collectAppointAwardCfg:
|
| | | awardIitemList.append(collectAppointAwardCfg[collTotalTime])
|
| | | awardItemList.append(collectAppointAwardCfg[collTotalTime])
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID, collTotalTime)
|
| | | #GameWorld.DebugLog("采集次数定制奖励: collTotalTime=%s,awardIitemList=%s" % (collTotalTime, awardIitemList))
|
| | | #GameWorld.DebugLog("采集次数定制奖励: collTotalTime=%s,awardItemList=%s" % (collTotalTime, awardItemList))
|
| | |
|
| | | if not awardIitemList:
|
| | | if not awardItemList:
|
| | | alchemyDiffLV = collectNPCIpyData.GetAlchemyDiffLV()
|
| | | giveItemWeightList = []
|
| | | if alchemyDiffLV:
|
| | |
| | | giveItemWeightList = collectAwardCfg
|
| | |
|
| | | giveItemInfo = GameWorld.GetResultByWeightList(giveItemWeightList)
|
| | | awardIitemList.append(giveItemInfo)
|
| | | awardItemList.append(giveItemInfo)
|
| | |
|
| | | if awardIitemList:
|
| | | for itemID, itemCount, isAuctionItem in awardIitemList:
|
| | | if awardItemList:
|
| | | for itemID, itemCount, isAuctionItem in awardItemList:
|
| | | ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem])
|
| | | if collectNPCIpyData.GetNotifyCollectResult():
|
| | | awardPack = ChPyNetSendPack.tagMCCollectAwardItemInfo()
|
| | | awardPack.CollectNPCID = npcID
|
| | | for itemID, itemCount, isAuctionItem in awardIitemList:
|
| | | for itemID, itemCount, isAuctionItem in awardItemList:
|
| | | awardItem = ChPyNetSendPack.tagMCCollectAwardItem()
|
| | | awardItem.ItemID = itemID
|
| | | awardItem.Count = itemCount
|
| | |
| | | #采集成就
|
| | | PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, collectCnt, [npcID])
|
| | | #SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID)
|
| | | |
| | | if isMaxTime:
|
| | | GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)
|
| | | |
| | | return
|
| | |
|
| | | ## 采集结果同步
|
| | |
| | | sendPack.Value = speed
|
| | | curNPC.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength())
|
| | | return
|
| | |
|
| | | def UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount=0):
|
| | | ## 更新玩家攻击NPC次数
|
| | | GameWorld.DebugLog("更新玩家攻击NPC次数: npcID=%s,attackCount=%s,maxCount=%s" % (npcID, attackCount, maxCount))
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_NPCAttackCount % npcID, attackCount)
|
| | | |
| | | if GameWorld.IsCrossServer():
|
| | | serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)
|
| | | msgInfo = {"PlayerID":curPlayer.GetPlayerID(), "NPCID":npcID, "AttackCount":attackCount, "MaxCount":maxCount}
|
| | | GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_NPCAttackCount, msgInfo, [serverGroupID])
|
| | | else:
|
| | | SyncNPCAttackCount(curPlayer, [npcID])
|
| | | if attackCount and attackCount >= maxCount:
|
| | | GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)
|
| | | return
|
| | |
|
| | | def CrossServerMsg_NPCAttackCount(curPlayer, msgData):
|
| | | ## 收到跨服服务器同步的攻击NPC次数
|
| | | npcID = msgData["NPCID"]
|
| | | attackCount = msgData["AttackCount"]
|
| | | maxCount = msgData["MaxCount"]
|
| | | UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount)
|
| | | return
|
| | |
|
| | | def SyncNPCAttackCount(curPlayer, npcIDList):
|
| | | ## 同步NPC攻击次数
|
| | | if not npcIDList:
|
| | | return
|
| | | |
| | | clientPack = ChPyNetSendPack.tagMCNPCAttackCountInfo()
|
| | | for npcID in npcIDList:
|
| | | attackCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID)
|
| | | atkCountObj = ChPyNetSendPack.tagMCNPCAttackCount()
|
| | | atkCountObj.NPCID = npcID
|
| | | atkCountObj.AttackCount = attackCount
|
| | | clientPack.NPCAttackCountList.append(atkCountObj)
|
| | | clientPack.Count = len(clientPack.NPCAttackCountList)
|
| | | NetPackCommon.SendFakePack(curPlayer, clientPack)
|
| | | return
|
| | |
|
| | |
|
| | | |
| | |
| | | else:
|
| | | refreshCD = ipyData.GetRefreshSeconds()
|
| | |
|
| | | if not refreshCD:
|
| | | continue
|
| | | if tick - numLastTick < refreshCD * 1000:
|
| | | continue
|
| | | gameFB.SetGameFBDict(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num, tick)
|
| | |
| | | if curPet:
|
| | | curPet.SetVisible(False)
|
| | |
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 1)
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 1) # 由于前端不一定有发mapID,所以这里额外记录这个状态,不能直接用mapID判断
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneMapID, mapID)
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneLineID, lineID)
|
| | | GameWorld.Log("玩家开始自定义场景!", curPlayer.GetPlayerID())
|
| | | if mapID:
|
| | | FBLogic.OnEnterCustomScene(curPlayer, mapID, lineID)
|
| | |
| | | if curPet:
|
| | | curPet.SetVisible(True)
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 0)
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneMapID, 0)
|
| | | curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneLineID, 0)
|
| | | GameWorld.Log("玩家退出自定义场景!", curPlayer.GetPlayerID())
|
| | | return
|
| | |
|
| | |
| | | GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_EnterFB, msgDict)
|
| | | return
|
| | |
|
| | | GY_Query_CrossRealmReg.RegisterEnterCrossServer(curPlayer, mapID)
|
| | | GY_Query_CrossRealmReg.RegisterEnterCrossServer(curPlayer, mapID, lineID=lineID)
|
| | | return
|
| | |
|
| | | ##玩家进入副本
|
| | |
| | |
|
| | | # 草园重置
|
| | | if ipyData.GetEventType() in [FDEventType_GrasslandXian, FDEventType_GrasslandLing]:
|
| | | GameLogic_CrossGrassland.DoResetCrossGrassland(curPlayer, ipyData.GetEventType())
|
| | | GameLogic_CrossGrassland.DoResetCrossGrassland(curPlayer, ipyData.GetEventType(), fdeventID)
|
| | |
|
| | | elif state == FDEventState_Visited:
|
| | | if curState != FDEventState_Visiting:
|
| | |
| | | elif msgType == ShareDefine.CrossServerMsg_CollectNPCOK:
|
| | | NPCCommon.CrossServerMsg_CollectNPCOK(curPlayer, msgData)
|
| | |
|
| | | elif msgType == ShareDefine.CrossServerMsg_NPCAttackCount:
|
| | | NPCCommon.CrossServerMsg_NPCAttackCount(curPlayer, msgData)
|
| | | |
| | | elif msgType == ShareDefine.CrossServerMsg_FBEnd:
|
| | | mapID, lineID = msgData[:2]
|
| | | exData = msgData[2:]
|
| | |
| | | GameWorld.Log("GY_Query_CrossRealmReg DoResult %s" % funResult, curPlayer.GetPlayerID())
|
| | | if not resultInfo:
|
| | | return
|
| | | registerMap, mapID, dataMapID, copyMapID, posX, posY = resultInfo
|
| | | RegisterEnterCrossServer(curPlayer, registerMap, mapID, dataMapID, copyMapID, posX, posY)
|
| | | registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID = resultInfo
|
| | | RegisterEnterCrossServer(curPlayer, registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID)
|
| | | return
|
| | |
|
| | | def RegisterEnterCrossServer(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0):
|
| | | def RegisterEnterCrossServer(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0, lineID=0):
|
| | | '''
|
| | | @param registerMap: 一般是dataMapID
|
| | | '''
|
| | |
| | | prepareEnterCrossServer.DataMapID = registerMap
|
| | | NetPackCommon.SendFakePack(curPlayer, prepareEnterCrossServer)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PlayerKey_CrossRegisterMap, registerMap)
|
| | | PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ReqCrossFBFuncLine, lineID)
|
| | | CrossPlayerData.OnPlayerCrossReg(curPlayer)
|
| | | #curPlayer.SendMergeRegisterPlayer(mapID, dataMapID, copyMapID, posX, posY)
|
| | | curPlayer.SendMergeRegisterPlayerAfterChange(CrossRealmPlayer.GetCrossPlayerName(curPlayer), mapID, dataMapID, copyMapID, posX, posY)
|
| | | GameWorld.Log(" 发送跨服玩家数据注册: registerMap=%s,zoneID=%s,mapID=%s,dataMapID=%s,copyMapID=%s,posX=%s,posY=%s,GetVsRoomId=%s" |
| | | % (registerMap, zoneID, mapID, dataMapID, copyMapID, posX, posY, curPlayer.GetVsRoomId()), playerID)
|
| | | GameWorld.Log(" 发送跨服玩家数据注册: registerMap=%s,lineID=%s,zoneID=%s,mapID=%s,dataMapID=%s,copyMapID=%s,posX=%s,posY=%s,GetVsRoomId=%s" |
| | | % (registerMap, lineID, zoneID, mapID, dataMapID, copyMapID, posX, posY, curPlayer.GetVsRoomId()), playerID)
|
| | | return
|
| | |
|
| | | ## 跨服赛报名结果(上传数据)
|
| | |
| | | CrossServerMsg_CollectNPCOK = "CollectNPCOK" # 采集NPC完成
|
| | | CrossServerMsg_EnterFBRet = "EnterFBRet" # 请求进入跨服副本返回信息
|
| | | CrossServerMsg_FBEnd = "FBEnd" # 完成跨服副本
|
| | | CrossServerMsg_NPCAttackCount = "NPCAttackCount" # 攻击NPC次数记录
|
| | |
|
| | | # 子服发送跨服信息定义
|
| | | ClientServerMsg_ServerInitOK = "ServerInitOK" # 子服启动成功
|
| | |
| | |
|
| | | return
|
| | |
|
| | | ## 获取哥布林功能NPC类型掉血值
|
| | | def GetGoblinLostHP(defender, hurtValue):
|
| | | if not defender:
|
| | | return hurtValue
|
| | | |
| | | defObjType = defender.GetGameObjType()
|
| | | if defObjType == IPY_GameWorld.gotNPC:
|
| | | npcFuncType = defender.GetFunctionType()
|
| | | if npcFuncType == ChConfig.Def_NPCFuncType_Goblin:
|
| | | goblinHurtValue = int(ReadChConfig.GetEvalChConfig('GoblinHurtValue'))
|
| | | hurtValue = min(hurtValue, goblinHurtValue)
|
| | | |
| | | return hurtValue
|
| | |
|
| | | ## 技能伤血
|
| | | # @param curObj 当前对象
|
| | | # @param skillTypeID 技能类型ID
|
| | |
| | | ## 后续有其他情况也应考虑进来,如镖车是否某状态不掉血
|
| | | return
|
| | |
|
| | | #lostValue = GetGoblinLostHP(curObj, lostValue)
|
| | | curObjType = curObj.GetGameObjType()
|
| | | curSkill = GameWorld.GetGameData().FindSkillByType(skillTypeID, 1)
|
| | |
|