local EventSystem = require('Event/EventSystem') local Base = require("Battle/Logic/Level/LevelItemFactory/LevelItem") local LevelItem_Npc = class("LevelItem_Npc", Base) local SystemManager = SystemManager local LogicUpdateManager = LogicUpdateManager function LevelItem_Npc:initialize(data) Base.initialize(self,data) self._allEntityDict = {} -- 所有出生的entity self._npcData = DataSheetManager.NpcData:GetDataByID(data.NpcID) self._npcRemainNums = 0 self._taskEffect = 0 self._npcInTowardMain = nil --正在看向玩家的NPC字典 end function LevelItem_Npc:OnDestroy() Base.OnDestroy(self) for _,entity in pairs(self._allEntityDict) do SystemManager.OnUnload(entity, true) end self._allEntityDict = nil-- 所有出生的entity self._npcInTowardMain = nil end --region --***************生命周期***************-- function LevelItem_Npc:OnActive() if Base.OnActive(self) then if not self._npcData.TaskBorn or MDL.Task.IsNPCRelatedTask(self.ItemData.NpcID) then self:BornNpc(self.ItemData.Count) end EventSystem.Regist(EventID.ChildTaskStart, self.OnTaskStart, self) EventSystem.Regist(EventID.ChildTaskFinish, self.OnTaskFinish, self) EventSystem.Regist(self.LevelItemID..EventID._EntityDead, self.OnNpcDead, self) if self._npcData.BeChosen then EventSystem.Regist(self.LevelItemID..EventID._EntityVisited, self.OnNpcVisited, self) end if self._npcData.TurnAround then self._npcInTowardMain = {} end return true end end function LevelItem_Npc:OnDeactive() if Base.OnDeactive(self) then EventSystem.UnRegist(EventID.ChildTaskStart, self.OnTaskStart, self) EventSystem.UnRegist(EventID.ChildTaskFinish, self.OnTaskFinish, self) EventSystem.UnRegist(self.LevelItemID..EventID._EntityDead,self.OnNpcDead,self) if self._npcData.BeChosen then EventSystem.UnRegist(self.LevelItemID..EventID._EntityVisited,self.OnNpcVisited,self) end return true end end function LevelItem_Npc:OnUpdate() self:HandleNpcToward() end --endregion 生命周期 --region --***************事件相关***************-- function LevelItem_Npc:DoAction(actionType, match, param1) Base.DoAction(self, actionType,param1) if actionType == LuaConst.LevelActionType.Npc_Active then self:OnActive() elseif actionType == LuaConst.LevelActionType.Delete then for i,entity in pairs(self._allEntityDict) do SystemManager.DeadQuit(entity) end end end function LevelItem_Npc:OnTaskStart(itemId) if itemId ~= self.ItemData.LevelItemID then return end if self._npcData.TaskBorn then if self._npcRemainNums < self.ItemData.Count then local bornCount = self.ItemData.Count - self._npcRemainNums self:BornNpc(bornCount, true) end --[[else for i,entity in pairs(self._allEntityDict) do SystemManager.OnShowEffect(entity, LuaConst.EffectType.TaskSign,true) end ]]-- end end function LevelItem_Npc:OnTaskFinish(itemId) if itemId ~= self.ItemData.LevelItemID then return end if MDL.Task.IsNPCRelatedTask(self.ItemData.NpcID) then return end if self._npcData.TaskBorn then for i,entity in pairs(self._allEntityDict) do SystemManager.DeadQuit(entity) end --[[else for i,entity in pairs(self._allEntityDict) do SystemManager.OnShowEffect(entity, LuaConst.EffectType.TaskSign,false) end]]-- end end function LevelItem_Npc:OnNpcVisited(entity, task) local mainEntityMove = LogicUpdateManager._curEntity.components.move local moveComponent = entity.components.move --主视角调用 SystemManager.StopAutoFightPathInTown(LogicUpdateManager._curEntity) SyncMoveManager.StopFollowNPC(LogicUpdateManager._curEntity) if FP.V2.DistanceSqr(mainEntityMove.LogicPos, moveComponent.LogicPos) < LuaConst.NpcVisitSqrDistance then self:InteractWithNpc(entity, task) else local pos = entity.components.move.LogicPos local callback = function () self:InteractWithNpc(entity, task) end --主视角调用 SystemManager.AutoFindPathInTown(LogicUpdateManager._curEntity, pos, LuaConst.NpcAutoFindDistance,callback) end -- 播放NPC选中特效 SystemManager.OnShowEffect(LevelItemManager.Global:GetCurVisitedEntity(),LuaConst.EffectType.BeingSelected,false) LevelItemManager.Global:Notify_NpcVisited(entity) SystemManager.OnShowEffect(entity,LuaConst.EffectType.BeingSelected,true) end function LevelItem_Npc:OnNpcDead(entity) self._npcRemainNums = self._npcRemainNums - 1 self._allEntityDict[entity._logicInitData.EntityID] = nil end --endregion 事件相关 --region --***************内部方法***************-- --先不做缓存 function LevelItem_Npc:BornNpc(count,byTask) local data = self.ItemData local itemPosV2 = data.ItemPos local forwardV2 = data.ItemDir local rightV2 = FP.V2.GetRightByForward(forwardV2) local layout = data.LayoutType if layout == LuaConst.EntityLayoutType.OriginPos then for i = 1,count do local positionV2 = itemPosV2 self:CreateNpcEntity(positionV2,forwardV2,byTask) end elseif layout == LuaConst.EntityLayoutType.Random_Circle then for i = 1,count do local radian = LogicRandom.GetRangeValue(nil, FP.Const.Zero, FP.Const.PI2 ,40) local radius = LogicRandom.GetRangeValue(nil, FP.Const.Zero, data.Radius ,41) local offX = radius * FP.Math.Cos(radian) local offZ = radius * FP.Math.Sin(radian) local positionV2 = itemPosV2 + FP.newV2(offX,offZ) self:CreateNpcEntity(positionV2,forwardV2,byTask) end elseif layout == LuaConst.EntityLayoutType.Random_Square then for i= 1,count do local halfLength = data.Length / 2 local halfWidth = data.Width / 2 local randLength = LogicRandom.GetRangeValue(nil, -halfLength,halfLength,42) local randWidth = LogicRandom.GetRangeValue(nil, -halfWidth, halfWidth ,43) local positionV2 = itemPosV2 + rightV2 * randLength + forwardV2 * randWidth self:CreateNpcEntity(positionV2,forwardV2,byTask) end elseif layout == LuaConst.EntityLayoutType.Matrix then local orgOffsetCol = data.Gap * (data.Col - 1) / 2 local orgOffsetRow = data.Gap * (data.Row - 1) / 2 local orgPosV2 = itemPosV2 - rightV2 * orgOffsetCol - forwardV2 * orgOffsetRow local index = 0 for i=0,data.Col - 1 do for j = 0,data.Row - 1 do local positionV2 = orgPosV2 + rightV2 * i * data.Gap + forwardV2 * j * data.Gap self:CreateNpcEntity(positionV2,forwardV2,byTask) if index >= count then break end end if index >= count then break end end end end function LevelItem_Npc:CreateNpcEntity(positionV2,forwardV2,byTask) EntityFactory.SetParams("BornItemID", self.LevelItemID) EntityFactory.SetPos_Dir(positionV2, forwardV2) EntityFactory.SetType_ID(LuaConst.CharacterType.NPC, self.ItemData.NpcID) local entity = EntityFactory.DoCreateEntity() --[[if byTask or MDL.Task.GetTaskByNpc(self.ItemData.NpcID) then SystemManager.OnShowEffect(entity, LuaConst.EffectType.TaskSign,true) end]]-- local npcModelData = entity.components.base.CurModelData if npcModelData then local radius = npcModelData.ClickAreaRadius local height = npcModelData.ClickAreaHight if radius > 0 and height > 0 then entity.ExpEntity.RenderEntity:SetColliderParam(radius,height) end end self._allEntityDict[entity._logicInitData.EntityID] = entity self._npcRemainNums = self._npcRemainNums +1 end function LevelItem_Npc.OnTaskCallBack() if LogicUpdateManager._curEntity then SystemManager.AddBuff(LogicUpdateManager._curEntity, LuaConst.SpecialBuffs.CanRide, LogicUpdateManager._curEntity, nil, RuntimeDataManager.New_BuffCtrl()) end end function LevelItem_Npc:InteractWithNpc(entity,task) -- 骑着马点击npc ,到达npc后也需要下马 --local a = LogicUpdateManager._curEntity.components.buff:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) and 1 or 0 --print("命令下马:", LogicUpdateManager._clientHandleFrame , "|" ,LuaInputManager.SpecialCommand , "|" , a) --主视角调用 if LogicUpdateManager._curEntity.components.buff:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) then --LuaInputManager.SpecialCommand = LuaConst.SpecialCommandType.Ride LuaInputManager.SetSpecialCommand(LuaConst.SpecialCommandType.Ride) elseif LuaInputManager.SpecialCommand == LuaConst.SpecialCommandType.Ride then --LuaInputManager.SpecialCommand = LuaConst.SpecialCommandType.None LuaInputManager.SetSpecialCommand(LuaConst.SpecialCommandType.None) end --主视角调用 SystemManager.DeleteBuff(LogicUpdateManager._curEntity,LuaConst.SpecialBuffs.CanRide,LogicUpdateManager._curEntity) LevelItemManager.Global:Notify_NpcInteracted(entity) local npcID = self.ItemData.NpcID local curTask,index = MDL.Task.GetTaskByNpc(npcID) if curTask then EventSystem.Dispatch(EventID.Task_DoTaskAction, curTask, entity, LevelItem_Npc.OnTaskCallBack, index) else if CTL.OfficialPosition.CheckNpcSpecialized(npcID) then if CTL.OfficialPosition.CheckNpcExamDialogue(npcID) then CTL.OfficialPosition.SetOfficialPositionExamNpc(npcID) EventSystem.Dispatch(EventID.UI_MainShowDialogue ,self._npcData.DialogueId, LevelItem_Npc.OnTaskCallBack, self._npcData, entity) elseif CTL.OfficialPosition.CheckNpcPromoteDialogue() then EventSystem.Dispatch(EventID.UI_MainShowDialogue ,self._npcData.DialogueId, LevelItem_Npc.OnTaskCallBack, self._npcData, entity) else LevelItem_Npc.OnTaskCallBack() end else local dialogueId = MDL.Task.GetDailyRingTaskDialogueID(self.LevelItemID) if dialogueId then EventSystem.Dispatch(EventID.UI_MainShowDialogue ,dialogueId, LevelItem_Npc.OnTaskCallBack, self._npcData, entity) else if self._npcData.ID == LuaConst.NpcID.LiuXie and (not MDL.Nobility.GetCanNobility()) then -- 点击皇帝刘协,如果不在进爵阶段就跳过 return end --国战悬赏任务 if CTL.CountryWantedTask.IsCountryWantedTaskNPC(self._npcData.ID) then CTL.CountryWantedTask.OpenWantedTaskPanel() LevelItem_Npc.OnTaskCallBack() return end --组队玩法关闭时,点击破袭曲阳、诸侯讨董两个NPC不弹对话 if self._npcData.ID == LuaConst.NpcID.TeamDungeon and not MDL.Unlock.IsUnlock(MDL.Unlock.FunctionType.TeamDungeon) then return end if self._npcData.ID == LuaConst.NpcID.TeamDungeon2 and not MDL.Unlock.IsUnlock(MDL.Unlock.FunctionType.TeamDungeon2) then return end EventSystem.Dispatch(EventID.UI_MainShowDialogue ,self._npcData.DialogueId, LevelItem_Npc.OnTaskCallBack, self._npcData, entity) end end end end function LevelItem_Npc:HandleNpcToward() if not self._npcInTowardMain then return end local mainEntity = LogicUpdateManager._curEntity if not mainEntity then return end --主视角调用 local mainEntityMove = mainEntity.components.move for k,entity in pairs(self._allEntityDict) do local comp_Move = entity.components.move if not FP.V2.IsDistanceSqrGreater(mainEntityMove.LogicPos, comp_Move.LogicPos, LogicUpdateManager.NPCTurnSqrDistance) then if not self._npcInTowardMain[entity] then SystemManager.LookToEntity(entity,mainEntity) self._npcInTowardMain[entity] = true end else if self._npcInTowardMain[entity] then SystemManager.LookToEntity(entity,nil) self._npcInTowardMain[entity] = nil end end end end --endregion 内部方法 --region --***************外部数据获取***************-- function LevelItem_Npc:GetNPCEntity() local entity for k,v in pairs(self._allEntityDict) do entity = v break end return entity end --endregion return LevelItem_Npc