--过滤层 local FilterManager = {} local EventSystem = require('Event/EventSystem') local private = {} local LuaConst=LuaConst local FP=FP local SpecialCommandType = LuaConst.SpecialCommandType local _tempV1 = FP.newV1(0) --[[ 过滤层(Command转译层)的总入口。 会根据Entity的状态把command转译为stateType,skillID,animName。方便各个系统直接执行 --]] function FilterManager.FilterCommand(entity, command) local components=entity.components local skillBaseComponent = components.skillBase local aiBaseComponent = components.aiBase local buffComponent = components.buff local stateType = LuaConst.StateType.None local animName = nil local skillID = -1 local needReturn = false --死亡->复活 特殊指令 needReturn, skillID, stateType = private.FilterDead(entity, command) if needReturn then return stateType,skillID,animName end --特殊指令 needReturn, stateType ,animName = private.FilterSpecialCommand(entity, command ) if needReturn then return stateType,skillID,animName end -- 死亡后,除了特殊cmd能执行,其他都停止 if not entity.components.attr:IsAlive() then return LuaConst.StateType.None,-1,nil end --特殊决策 - 瞬发的,优先级在攻击之前 needReturn, stateType, animName = SystemManager.FilterDecision(entity, command, true, stateType, animName) if needReturn then --这里实际上永远都会为false,因为目前瞬时decision都不会改变State、释放技能或者播放动画 return stateType,skillID,animName end --失去 能移动 或 能攻击 Buff if aiBaseComponent.CurStateType == LuaConst.StateType.Move or aiBaseComponent.CurStateType == LuaConst.StateType.Wander or aiBaseComponent.CurStateType == LuaConst.StateType.RunStop then if not buffComponent.CurrentBuffStates:Get(LuaConst.SpecialBuffs.CanMove) then stateType = LuaConst.StateType.Idle skillID = -1 return stateType,skillID,animName end elseif aiBaseComponent.CurStateType == LuaConst.StateType.Attack then if not buffComponent.CurrentBuffStates:Get(LuaConst.SpecialBuffs.InSkilling) then stateType = LuaConst.StateType.Idle skillID = -1 return stateType,skillID,animName end end --技能 skillID = SystemManager.OnFilterAttack(entity, command) if skillID < 0 and not skillBaseComponent.CanSwitchAll then --如果当前不释放技能,且正在释放技能,就直接return return stateType,-1,nil end --特殊决策 - 持续性的,优先级在攻击之后,别耽误技能释放 --潜规则:如果持续性 Decision 设置了 command.DecisionID , 那么needReturn会为true,这里就会return,导致技能放不出来 needReturn, stateType, animName = SystemManager.FilterDecision(entity, command, false, stateType, animName) if needReturn then return stateType,skillID,animName end --Attack if skillID > 0 then if buffComponent.CurrentBuffStates:Get(LuaConst.SpecialBuffs.CanSkill) then if entity._logicInitData.IsPlayer or skillBaseComponent.IsSearchTargetWhenSkill then --玩家和副将每次用技能都重新选敌 if not entity.components.skillBase:IsAutoNextSkill(skillID) then --策划需求:如果是AutoNextID引发的技能,不寻找目标 --如果副将技能设置了锁定朝向,且副将的双摇杆无输入 ,此时才能索敌的 if not entity.isAdjuntant or entity._logicInitData.MasterEntity.components.adjutant:GetNeedSearchTarget() then SystemManager.OnSearchTargetBySkill(entity,skillID) end end end --尝试追击技能 skillID = SystemManager.OnCheckNeedCastWhenAttack(entity, command, skillID) stateType = LuaConst.StateType.Attack else if aiBaseComponent.CurStateNode then stateType = aiBaseComponent.CurStateNode:StateUpdateNoCmd(entity) end BattleEventSystem.OnEntitySkillCommandFilterRejected(entity, skillID) end --Move elseif command.MoveDir ~= FP.Const.Vector2_Zero then if buffComponent.CurrentBuffStates:Get(LuaConst.SpecialBuffs.CanMove) and not entity.components.move.forbidJoystick then stateType = LuaConst.StateType.Move --不重复进入 if stateType == aiBaseComponent.CurStateType then stateType = LuaConst.StateType.None end else if aiBaseComponent.CurStateNode then stateType = aiBaseComponent.CurStateNode:StateUpdateNoCmd(entity) else stateType = LuaConst.StateType.None end end else --Idle(无技能,无摇杆输入,无特殊指令) if aiBaseComponent.CurStateNode then stateType = aiBaseComponent.CurStateNode:StateUpdateNoCmd(entity) else stateType = LuaConst.StateType.Idle end end return stateType,skillID,animName end function FilterManager.FilterCommand_NPC(entity, command) local comp_AIBase = entity.components.aiBase local comp_Move = entity.components.move local stateType,animName,skillID = LuaConst.StateType.None, nil, -1 local needReturn = false --特殊决策 needReturn, stateType, animName = SystemManager.FilterDecision_NPC(entity, command, stateType, animName) if needReturn then return stateType,skillID,animName end if command.MoveDir ~= FP.Const.Vector2_Zero then stateType = LuaConst.StateType.Move elseif comp_Move.WantRotateDir ~= FP.Const.Vector2_Zero then if comp_Move.LogicRotateDir ~= comp_Move.WantRotateDir then command.RotateDir:Reset(comp_Move.WantRotateDir) stateType = LuaConst.StateType.Rotate end else if comp_AIBase.CurStateNode then stateType = comp_AIBase.CurStateNode:StateUpdateNoCmd(entity) else stateType = LuaConst.StateType.Idle end end --不重复进入 if stateType == comp_AIBase.CurStateType then stateType = LuaConst.StateType.None end return stateType,skillID,animName end --特殊指令 --注意这里的entity如果在驾驶载具状态时,是载具entity而不是heroEntity了, function private.FilterSpecialCommand(entity, command) local stateType = LuaConst.StateType.None local needReturn = false local animName = nil if command.SpecialCommand ~= SpecialCommandType.None then if command.SpecialCommand == SpecialCommandType.Adjutant then SystemManager.OnReleaseAdjutantSkill(entity, command.SkillJoystickPosX, command.SkillJoystickPosZ) needReturn = true elseif command.SpecialCommand == SpecialCommandType.Stratagem then SystemManager.ReleaseStratagemSkill(entity) needReturn = true elseif command.SpecialCommand == SpecialCommandType.BuffSkill1 then entity.components.skillBase:SetSkillJoystickInfoByCommand(command, true) SystemManager.ReleaseBuffSkill(entity, LuaConst.ESkillKeyPosition.BuffSkill1) needReturn = true elseif command.SpecialCommand == SpecialCommandType.BuffSkill2 then entity.components.skillBase:SetSkillJoystickInfoByCommand(command, true) SystemManager.ReleaseBuffSkill(entity, LuaConst.ESkillKeyPosition.BuffSkill2) needReturn = true elseif command.SpecialCommand == SpecialCommandType.SetBornItemIDByIndex then LevelManager.CurLevelFunc:SetBornItemIDOfPlayerByWeightListWithIndex(entity:GetOriginEntity():GetPlayerID(), command.MoveType) needReturn = true elseif command.SpecialCommand == SpecialCommandType.SkillBtnPointerUp then local curSkillData = entity.components.skillBase.CurSkillData if curSkillData and curSkillData.AutoNextConditionStr == "pointerUp" and curSkillData.AutoNextID == LuaConst.InterruptSkillAutoNextID then SystemManager.InterruptSkill(entity, LuaConst.EInterruptSkillReason.BY_CMD) end elseif command.SpecialCommand == SpecialCommandType.Ride then --print("执行马:", LogicUpdateManager._clientHandleFrame) local dohorse = false if entity.components.buff:CheckHasBuffState(LuaConst.SpecialBuffs.InRiding) then SystemManager.OffHorse(entity) dohorse = true elseif entity:CanRideHorse() then SystemManager.RideHorse(entity) dohorse = true end if dohorse then -- 当骑马发生变化后才改变state if command.MoveDir ~= FP.Const.Vector2_Zero then stateType = LuaConst.StateType.Move else stateType = LuaConst.StateType.Idle end needReturn = true end --驾驶载具 elseif command.SpecialCommand == SpecialCommandType.InDrive then SystemManager.Drive(entity) needReturn = true stateType = LuaConst.StateType.Idle elseif command.SpecialCommand == SpecialCommandType.OffDrive then local driver = entity.components.drive.BeDrivedByEntity if driver == nil then logging.error(LTAG.ERROR, "GWS : 让司机下载具 ,居然司机是nil -可能是玩家没在载具上,但是点了载具按钮 (只报错不阻挡) entity是车=",entity:IsVehicle() ,"entityID= " ,entity.EntityID ," playerID =" ,entity:GetPlayerID()) end SystemManager.OffDrive(driver) needReturn = true stateType = LuaConst.StateType.Idle elseif command.SpecialCommand == SpecialCommandType.JoystickSetTarget then local skillData = entity.components.skillBase:GetSkillDataBySkillIndex(command.SkillIndex) local skillID = skillData and skillData.ID local skillJoyStickData if skillID then skillJoyStickData = entity.components.skillBase:GetSkillJoystickData(skillID) end if skillJoyStickData then local entityPos = entity.components.move.LogicPos local joystickPos = entityPos:cloneV2() joystickPos.x:Add(command.SkillJoystickPosX) joystickPos.z:Add(command.SkillJoystickPosZ) local target = TargetManager.GetTargetByJoystick(entity, skillJoyStickData, joystickPos, nil, skillJoyStickData.IgnoreBeSkillTargetBuff) --new 使用TargetManager里面的公共方法找目标 entity.components.target:SetJoystickTarget(target) entity.ExpEntity:OnCmdJoystickSetTarget(command, entity, target, skillJoyStickData) end command.SkillIndex = 0 -- SpecialCommandType.JoystickSetTarget需要擦除SkillIndex信息 elseif command.SpecialCommand == SpecialCommandType.QuitRoom or command.SpecialCommand == SpecialCommandType.ServerQuitRoom then local handleEntity = entity:GetOriginEntity() local driver = entity.components.drive.BeDrivedByEntity if driver then -- 如果entity 被驾驶 ,则分离开 ,然后再下线 SystemManager.OffDrive(driver) SystemManager.ResetInteractColliderState(entity) -- 车的交互功能变为初始态 end LevelPlayerManager.RecordPlayerQuitRoom(handleEntity) LevelManager.CurLevelFunc:QuitRoom(handleEntity) needReturn = true stateType = LuaConst.StateType.Idle elseif command.SpecialCommand == SpecialCommandType.Interact then needReturn = true local opEntity = entity local driver = entity.components.drive.BeDrivedByEntity if driver then -- 目前写死: 如果驾驶载具时,又点击一个交互功能 ,则这个功能是要应用到驾驶者的,而不是载具上 。如果策划有需求,则要加配置控制了 opEntity = driver end if opEntity.components.aiBase.CurStateType ~= LuaConst.StateType.Interact then -- 如果正在交互中 ,又收到了交互命令 ,则不处理 local interactEntity = opEntity.components.interact:GetCmdOpInteractEntity() if interactEntity then local interactIndex = command.MoveType - LuaConst.CmdMoveTypeBaseEnum.InteractBase local interactData = interactEntity.components.interact:GetInteractData(interactIndex) if interactData then local isConditionMeet = true local tipsIDS = nil local conditionTree = nil for i,conditionData in ipairs(interactData.ConditionData_Table) do conditionTree = ConditionManager.GetConditionDataTree(conditionData.ConditionStr) if not ConditionManager.MeetCondition(opEntity, conditionTree) then isConditionMeet = false tipsIDS = conditionData.NotMeetTipIDS break end end if isConditionMeet then if interactData.InteractTime > 0 then -- 有交互时长才切state ,没有的话直接做交互行为 animName = interactData.InteractAnim local skillBaseComp = opEntity.components.skillBase if skillBaseComp.CanSwitchAll == false then SystemManager.ChangeToSwitchAll(opEntity ,false, LuaConst.SkillInterruptType.StopEffect) end SystemManager.InteractStarted(opEntity, interactData, interactIndex) --备注:这样写的原因:opEntity不确定是人还是车,如果为车,返回state给车使用了这就错了,且不设置人的state也错了 。所以比较好的方案就是直接切位交互state,返回none状态 SystemManager.SetNextState(LuaConst.StateType.Interact,opEntity,-1,interactData.InteractAnim) else SystemManager.InteractSucceed(opEntity, interactData, interactIndex) end else if tipsIDS then ExpLevelManager.ShowTips(opEntity,tipsIDS) end EventSystem.Dispatch(EventID.UI_Interact_Fail , opEntity) end else logging.error(LTAG.ERROR, "HYW : interactData nil Error! LevelID : ", LevelManager.GetCurLevelID()) end end end elseif command.SpecialCommand == SpecialCommandType.JoystickCancel then if command.SkillIndex <= 0 then -- 当释放技能和取消技能同时执行时,优先释放技能(蓄力技能存在诡异问题,先暂定为这种逻辑) entity.ExpEntity:OnCmdJoystickCancel(command) --这个SpecialCommand发送BattleEvent给逻辑层,收到事件如何行为,由buff配置的监听决定(例:糜芳蓄力技能全程buff监听该事件,发动效果:打断技能、设置CD、Interrupt双摇杆) BattleEventSystem.OnEntityCancelJoystick(entity) needReturn = true end elseif command.SpecialCommand == SpecialCommandType.SwitchHeroToIndex2 then entity = entity:GetOriginEntity() if LevelManager.CurLevelCanSwitchHeroByCmd(entity, 2) then LevelPlayerManager.SwitchHero(entity._logicInitData.PlayerIDInRoom, 2, false, LuaConst.ESwitchHeroSource.SPECIAL_COMMAND) needReturn = true end elseif command.SpecialCommand == SpecialCommandType.SwitchHeroToIndex3 then entity = entity:GetOriginEntity() if LevelManager.CurLevelCanSwitchHeroByCmd(entity, 3) then LevelPlayerManager.SwitchHero(entity._logicInitData.PlayerIDInRoom, 3, false, LuaConst.ESwitchHeroSource.SPECIAL_COMMAND) needReturn = true end elseif command.SpecialCommand == SpecialCommandType.AutoFight then SystemManager.SwitchAutoFight(entity) elseif command.SpecialCommand == SpecialCommandType.RunToPosByIndex then _tempV1:Reset(command.SkillJoystickPosX):Mul(100) --这里乘100,因为KCPTransport的private.ChangeCmdNotifyToCommand在接收的时候会除以100(给FP Rawset一个*10的number,等价于除以100) SystemManager.RunToPosByIndex(entity, FP.tonumberV1(_tempV1)) --SkillJoystickPosX作为pos index的数据储存 elseif command.SpecialCommand == SpecialCommandType.StopAutoFight then SystemManager.StopAutoFight(entity) elseif command.SpecialCommand == SpecialCommandType.SoloFightNextRound then LevelManager.CurLevelFunc:SwitchHeroStart() elseif command.SpecialCommand == SpecialCommandType.CameraLockTarget then entity = entity:GetOriginEntity() local high = math.floor(FP.tonumberV1(command.SkillJoystickPosX) * 100 + 0.5) local low = math.floor(FP.tonumberV1(command.SkillJoystickPosZ) * 100 + 0.5) local entityID = high * LuaConst.BinaryFlag.MaxShort + low local target = LogicUpdateManager._entityDic[entityID] SystemManager.SetSkillHighestPriorityTarget(entity:GetPlayerID(), target) needReturn = true elseif command.SpecialCommand == SpecialCommandType.SelectDialogueBranch1 then LevelItemManager.Global:Notify_DialogueCommand(1) needReturn = true elseif command.SpecialCommand == SpecialCommandType.SelectDialogueBranch2 then LevelItemManager.Global:Notify_DialogueCommand(2) needReturn = true elseif command.SpecialCommand == SpecialCommandType.UseBattleProp then local btnIndex = command.MoveType - LuaConst.CmdMoveTypeBaseEnum.UseBattlePropBase SystemManager.UseBattleProp(entity, btnIndex) needReturn = true elseif command.SpecialCommand == SpecialCommandType.AcceptSummon then if LevelManager.CurLevelFunc.SummonAccept then LevelManager.CurLevelFunc:SummonAccept(entity) else logging.error(LTAG.ERROR, "HYW : 视图在没有实现LevelManager.CurLevelFunc.SummonAccept的关卡使用SpecialCommandType.AcceptSummon指令") end elseif command.SpecialCommand >= SpecialCommandType.SetForceTargetOfIndexStart and command.SpecialCommand <= SpecialCommandType.SetForceTargetOfIndexFinish then local index = command.SpecialCommand - SpecialCommandType.SetForceTargetOfIndexStart + 1 SystemManager.SwtichForceTargetByIndex(entity, index, LuaConst.ESwitchFightModeReason.MANUAL) elseif command.SpecialCommand == SpecialCommandType.SwitchFightMode then entity = entity:GetOriginEntity() SystemManager.SwitchFightMode(entity:GetPlayerID(), LuaConst.ESwitchFightModeReason.MANUAL) EventSystem.Dispatch(EventID.BI_LevelMiddle, BIManager.BIType.WorldBossFightMode, entity:GetFightMode()) elseif command.SpecialCommand == SpecialCommandType.ActiveServerPlayerBuff then SystemManager.ActiveServerPlayerBuff(entity) elseif command.SpecialCommand == LuaConst.SpecialCommandType.ServerAction then LevelManager.HandleServerAction(entity ,command) needReturn = true elseif command.SpecialCommand == LuaConst.SpecialCommandType.SetCanShowVictoryPose then if LevelManager.CurLevelFunc.SetShowVictoryPoseFlag then LevelManager.CurLevelFunc:SetShowVictoryPoseFlag(true) else logging.error(LTAG.ERROR, "HYW : 试图在没有SetShowVictoryPoseFlag的玩法调用 LevelManager.CurLevelFunc:SetShowVictoryPoseFlag LevelType: ", LevelManager.GetCurLevelType()) end elseif command.SpecialCommand == SpecialCommandType.SwitchGodBeastSkillLeft then SystemManager.SwitchLeftGodBeastSkillOfPlayer(entity:GetPlayerID()) elseif command.SpecialCommand == SpecialCommandType.SwitchGodBeastSkillRight then SystemManager.SwitchRightGodBeastSkillOfPlayer(entity:GetPlayerID()) elseif command.SpecialCommand == SpecialCommandType.RogueLikeSelect then local btnIndex = command.MoveType - LuaConst.CmdMoveTypeBaseEnum.RogueLikeSelectBase LevelManager.CurLevelFunc:RogueSelectUpgradeSkill(btnIndex) needReturn = true elseif command.SpecialCommand == SpecialCommandType.RogueLikeReRandom then LevelManager.CurLevelFunc:ReRandomSkillList() needReturn = true end end return needReturn, stateType ,animName end --死亡 function private.FilterDead(entity, command) if command.SpecialCommand == SpecialCommandType.ServerRevive then -- 目前这个ServerRevive只使用在了龙脉的复活,其他玩法暂时没用到,故写死为三选一复活方式 if command.SkillIndex and command.SkillIndex > 0 and command.SkillIndex <= 3 then local heroIndex = LevelPlayerManager.GetIndexByArmyPos(entity:GetPlayerID(), (command.SkillIndex - 1) * 2) local reviveSuccess = LevelManager.CurLevelFunc:TryReviveAndSwitchOneHero(entity,heroIndex, false, true) if reviveSuccess then -- 复活成功 return true,entity.components.base.CurCharacterData.GetInSkill,LuaConst.StateType.Attack end end elseif command.SpecialCommand == SpecialCommandType.ReviveOnSite or command.SpecialCommand == SpecialCommandType.ReviveNeerby or command.SpecialCommand == SpecialCommandType.ReviveNeerby_Passive then local isInBornPoint = command.SpecialCommand == LuaConst.SpecialCommandType.ReviveNeerby or command.SpecialCommand == LuaConst.SpecialCommandType.ReviveNeerby_Passive local isSuccess = LevelManager.CurLevelFunc:OnRevive(entity,isInBornPoint,command) if isSuccess then --释放复活技能 return true,entity.components.base.CurCharacterData.GetInSkill,LuaConst.StateType.Attack end elseif command.SpecialCommand == SpecialCommandType.ReviveAndSwitchOneHero then --只复活或使用一个主将 local heroIndex = command.MoveType - LuaConst.CmdMoveTypeBaseEnum.ReviveAndSwitchBase local reviveSuccess = LevelManager.CurLevelFunc:TryReviveAndSwitchOneHero(entity,heroIndex) if reviveSuccess then -- 复活成功 return true,entity.components.base.CurCharacterData.GetInSkill,LuaConst.StateType.Attack end end return false,-1,LuaConst.StateType.None end --关卡层的相关cmd处理(都是服务器插帧过来的) function FilterManager.FilterLevelCommand(command) if command.SpecialCommand == LuaConst.SpecialCommandType.ServerAction then LevelManager.HandleServerAction(nil, command) elseif command.SpecialCommand == LuaConst.SpecialCommandType.ServerTimelineStop then --服务器插帧告知客户端timeline超时结束 SystemManager.OnCmdAllTimelineFinish() elseif command.SpecialCommand == LuaConst.SpecialCommandType.ServerRivalChange then --服务器改变敌对关系 LevelManager.CurLevelFunc:ChangeRival(command.SkillIndex, command.MoveType, command.UseJoyStick) end end return FilterManager