--小兵ai单decision模拟 (原AIID为8) local Base = require("Battle/Logic/AI/Decision/Decision_Base") local Decision_WanderFleeFriend = require "Battle/Logic/AI/Decision/Decision_WanderFleeFriend" local Decision_WanderToGroupLeader = require "Battle/Logic/AI/Decision/Decision_WanderToGroupLeader" local Decision_MinionAi8 = class("Decision_MinionAi8", Base) local PHASE_KEY = "phase" local PHASE_START_FRAME_KEY = "phaseStartFrame" --[[ 初始化 --]] function Decision_MinionAi8:initialize(entity) --类型 self.Type = LuaConst.DecisionType.MinionAi8 --瞬时 self.IsOnce = false end --[[ 能否计入 小兵Ai直接进入 --]] function Decision_MinionAi8:CanEnter(entity, decisionData, command) return true end --[[ 能否退出 小兵Ai无法退出 --]] function Decision_MinionAi8:CanExit(entity, decisionData, command) return false end --[[ 退出该Decision --]] function Decision_MinionAi8:DecisionOut(entity, decisionData) entity.components.aiBase:ClearDecisionRecord(decisionData) end local setCommandStackCount = 0 --[[ 输出指令 --]] function Decision_MinionAi8:SetCommand(entity, decisionData, command) setCommandStackCount = setCommandStackCount + 1 if setCommandStackCount >= 3 then logging.error(LTAG.ERROR, "HYW : setCommandStackCount >= 3 Error!") setCommandStackCount = 0 return command end local aiBaseComponent = entity.components.aiBase local recordDic = aiBaseComponent:GetDecisionRecordDic(decisionData) --local curPhase = aiBaseComponent:GetDecisionRecord(decisionData,PHASE_KEY)--dic优化 local curPhase = recordDic.phase or 0 repeat --模拟AI 8,条件都写在decision里,测试性能 --目前很难模拟decision序列的情况。AI 8没有decision序列,所以可以在这模拟 --priority 5 --与目标距离大于12米 local comp_Target = entity.components.target local target = comp_Target.Target local phaseStartFrame = recordDic[PHASE_START_FRAME_KEY] or 999999 if target then if curPhase == 0 or curPhase == 5 then if curPhase == 5 then if FP.LessEquals(comp_Target.ToTargetDisSqr,121) then --模拟DecisionOut curPhase = 0 break end end --与目标距离大于12m if FP.Greater(comp_Target.ToTargetDisSqr,144) --144 暂时写死 or curPhase == 5 and FP.Greater(comp_Target.ToTargetDisSqr,121) then --121暂时写死 --这一行是模拟canExit if curPhase ~= 5 then --切换phase时直接寻一次路 SystemManager.FindPath(entity, target.components.move.LogicPos, true) else --每隔2s重新寻一次路 local passFrame = LogicUpdateManager._clientHandleFrame - phaseStartFrame local passTime = passFrame * LuaConst.TimeSpanMs if passTime % 2000 == 0 then SystemManager.FindPath(entity, target.components.move.LogicPos, true) end end command = self:RunToPathPoint(entity, command,decisionData) curPhase = 5 break end end if curPhase == 0 or curPhase == 4 then if curPhase == 4 then if LogicUpdateManager._clientHandleFrame - phaseStartFrame >= 20 then--模拟DecisionOut curPhase = 0 break end end --priority 4 --与目标距离大于10m if FP.Greater(comp_Target.ToTargetDisSqr,100) --100暂时写死 or (curPhase == 4 and LogicUpdateManager._clientHandleFrame - phaseStartFrame < 20) then -- 20帧=1秒 --20暂时写死 command.DecisionID = decisionData.ID if target then command.RotateDir:Reset(target.components.move.LogicPos):Sub(entity.components.move.LogicPos) end curPhase = 4 break end end if curPhase == 0 or curPhase == 3 then if curPhase == 3 then if LogicUpdateManager._clientHandleFrame - phaseStartFrame >= 20 then--模拟DecisionOut curPhase = 0 break end end --priority 3 --与目标距离小于4m if FP.Less(comp_Target.ToTargetDisSqr,16) --16暂时写死 or (curPhase == 3 and LogicUpdateManager._clientHandleFrame - phaseStartFrame < 20) then -- 20帧=1秒 --20暂时写死 command.DecisionID = decisionData.ID if target then command.RotateDir:Reset(target.components.move.LogicPos):Sub(entity.components.move.LogicPos) end curPhase = 3 break end end else if curPhase == 3 or curPhase == 4 or curPhase == 5 then curPhase = 0 break end end if curPhase == 0 or curPhase == 2 then if curPhase == 2 then if not entity.components.group.LeaderEntity or FP.LessEquals(entity.components.group.ToLeaderDisSqr, 2401) then curPhase = 0 break end end --priority 2 --与所属群组距离大于8m if entity.components.group.LeaderEntity then if FP.Greater(entity.components.group.ToLeaderDisSqr,64) --64暂时写死 or curPhase == 2 and FP.Greater(entity.components.group.ToLeaderDisSqr, 2401) then--2401暂时写死 --Decision_WanderToGroupLeader command.DecisionID = decisionData.ID --始终朝向目标 local target = comp_Target.Target if target then command.RotateDir:Reset(target.components.move.LogicPos):Sub(entity.components.move.LogicPos) end curPhase = 2 break end end end if curPhase == 0 or curPhase == 1 then --priority 1 if curPhase == 1 then if FP.V2.IsDistanceSqrGreater(entity.components.move.LogicPos, comp_Target.NearestFriendEntity.components.move.LogicPos, 2) then--2写死 comp_Target:SetNearestFriendEntity(nil) curPhase = 0 break end else Decision_WanderFleeFriend:SetNearestFriendEntity(entity,FP.Const.Two)--2写死 end if comp_Target.NearestFriendEntity then command.DecisionID = decisionData.ID --始终朝向目标 local target = comp_Target.Target if target then local dir = target.components.move.LogicPos - entity.components.move.LogicPos command.RotateDir:Reset(dir) FP.releaseV2(dir) end curPhase = 1 break elseif curPhase == 1 then curPhase = 0 break end end --priority 0 --兜底idle if target then command.RotateDir:Reset(comp_Target.ToTargetDir) end curPhase = 0 until true --aiBaseComponent:SetDecisionRecord(decisionData,PHASE_KEY,curPhase)--dic优化 if recordDic.phase ~= curPhase then if recordDic.phase ~= nil and recordDic.phase ~= 0 and curPhase == 0 then recordDic.phase = curPhase --这一行不可合并,不要移动,不要上移 recordDic[PHASE_START_FRAME_KEY] = LogicUpdateManager._clientHandleFrame--这一行不可合并,不要上移 --如果从非0改到0,则再递归一次 command = self:SetCommand(entity, decisionData, command) else recordDic.phase = curPhase--这一行不可合并,不要移动,不要上移 recordDic[PHASE_START_FRAME_KEY] = LogicUpdateManager._clientHandleFrame--这一行不可合并,不要上移 end end setCommandStackCount = setCommandStackCount - 1 return command end function Decision_MinionAi8:Handle(entity, decisionData, stateType, animName) local comp_Anim = entity.components.anim local comp_AIBase = entity.components.aiBase local phase = comp_AIBase:GetDecisionRecord(decisionData,PHASE_KEY) if phase == 4 or phase == 3 then --Decision_Wander if phase == 4 then animName = "walk_front_loop" elseif phase == 3 then animName = "walk_back_loop" end if comp_AIBase.CurStateType == LuaConst.StateType.Wander and not comp_Anim.IsCurAnimOver then return LuaConst.StateType.None, nil else return LuaConst.StateType.Wander, animName end elseif phase == 2 then --Decision_WanderToGroupLeader if not LuaConst.WanderAnimNameTable[comp_Anim.CurAnimID] or comp_Anim.IsCurAnimOver then local leader = entity.components.group.LeaderEntity if leader then local target = entity.components.target.Target animName = Decision_WanderToGroupLeader:GetWanderAnimNameByAngle(entity, leader, target) return LuaConst.StateType.Wander, animName end end return LuaConst.StateType.None, nil elseif phase == 1 then local targetComponent = entity.components.target if not LuaConst.WanderAnimNameTable[comp_Anim.CurAnimID] or comp_Anim.IsCurAnimOver then local nearestFriendEntity = targetComponent.NearestFriendEntity if nearestFriendEntity then local target = targetComponent.Target animName = Decision_WanderFleeFriend:GetWanderAnimNameByAngle(entity, nearestFriendEntity, target) return LuaConst.StateType.Common, animName end end return LuaConst.StateType.None, nil end return LuaConst.StateType.None, nil end return Decision_MinionAi8