local BuffSkillSystem = require"Battle/Logic/Entity/System/BuffSkillSystem" local base = require("Battle/Logic/AI/Decision/Decision_Base") local Decision_SoloFight = class("Decision_SoloFight", base) local P1_SEARCH_ENEMY_DIS_SQR = FP.newV1(10000) local NEW_WANDER_POS_POSIBILITY = FP.newV1(0.38) local KEY_POS_GODBEAST = LuaConst.ESkillKeyPosition.BuffSkill2 local KEY_POS_SKILL1 = LuaConst.ESkillKeyPosition.Skill1 local KEY_POS_SKILL2 = LuaConst.ESkillKeyPosition.Skill2 local KEY_POS_SKILL3 = LuaConst.ESkillKeyPosition.Skill3 local KEY_POS_MUSOU = LuaConst.ESkillKeyPosition.MusouNormal local IMPOSSIBLE_FRAME = 999999 local IMMORTAL_BUFFID = 500001 local _tempV1 = FP.newV1(0) local FP_Zero = FP.Const.Zero --演武校场(异步1v1) 自动战斗 --[[ 初始化 --]] function Decision_SoloFight:initialize(entity) base.initialize(self,entity) --类型 self.Type = LuaConst.DecisionType.SoloFight --瞬时 self.IsOnce = false self.SCENE_RADIUS = FP.newV1(40) self.CENTER = FP.newV2(58.37773,685.4351) self:InitSkillCDInfo() end function Decision_SoloFight:GetSkillCDDataSheet() return DataSheetManager.SyncSoloData end function Decision_SoloFight:DecisionIn(entity, decisionData) base.DecisionIn(self, entity, decisionData) local decisionRecordDic = entity.components.aiBase:GetDecisionRecordDic(decisionData) if not LevelManager.IsSoloFight() then self:SetSkillCDByElo(entity, decisionRecordDic, LevelPlayerManager.IsWarmUpRobot(entity)) end if LevelManager.IsSoloFight() then --单机1v1(演武校场)在技能CD时不乱跑 decisionRecordDic.shouldWanderWhenInCD = false else --同步1v1(公平竞技1v1)在技能CD时乱跑 decisionRecordDic.shouldWanderWhenInCD = true decisionRecordDic.lastTriggerDodgeTargetSkillData = nil --目标上一次释放会触发闪避的技能的数据 decisionRecordDic.dodgeFrame = IMPOSSIBLE_FRAME --自身下次释放闪避的帧数 decisionRecordDic.dodgeSkillIndex = entity.components.skillBase:GetSkillIndexByKeyPosition(LuaConst.ESkillKeyPosition.Dodge) --decisionRecordDic.switchHeroFrameIndex --当decisionRecordDic.switchHeroCommand不为nil时,这个值表示释放闪避的帧数。如果decisionRecordDic.switchHeroCommand为nil时,表示这个帧数之后才可能会尝试切将 end end --[[ 退出该Decision --]] function Decision_SoloFight:DecisionOut(entity, decisionData) local aiBaseComponent = entity.components.aiBase aiBaseComponent:ClearDecisionRecord(decisionData) end function Decision_SoloFight:IsAuto(entity) local autoFightComponent = entity.components.autoFight if LevelManager.IsSyncLevel() then return autoFightComponent.IsSyncAuto else return autoFightComponent.IsStandaloneAuto end end --[[ 能否进入 --]] function Decision_SoloFight:CanEnter(entity, decisionData, command) return self:IsAuto(entity) end --[[ 能否退出 --]] function Decision_SoloFight:CanExit(entity, decisionData, command) return not self:IsAuto(entity) end function Decision_SoloFight:IsTriggerDodgeTargetSkill(skillData) if skillData then local keyPos = skillData.KeyPosition return keyPos == KEY_POS_SKILL1 or keyPos == KEY_POS_SKILL2 or keyPos == KEY_POS_SKILL3 or keyPos == KEY_POS_MUSOU end return false end -- function Decision_SoloFight:EnterUseSkillDecisionCD(entity ,decisionRecordDic) -- decisionRecordDic[self.USESKILL_CD_OVER_FRAME] = LogicUpdateManager._clientHandleFrame + LogicRandom.GetRangeValue(entity, 20, 45 , 1023) -- end function Decision_SoloFight:TryRefreshTriggerDodgeTargetSkill(entity, decisionRecordDic, targetCurSkillData) if self:CanUseDodgeSkill(entity) and not entity.components.buff:HasBuff(IMMORTAL_BUFFID) then local rand = LogicRandom.GetRandom01(entity, 458349432) if rand <= decisionRecordDic.dodgeReactionChance then decisionRecordDic.lastTriggerDodgeTargetSkillData = targetCurSkillData decisionRecordDic.dodgeFrame = LogicUpdateManager._clientHandleFrame + FP.tonumberV1(LogicRandom.GetRangeValue(entity, decisionRecordDic.dodgeReactionTimeLow, decisionRecordDic.dodgeReactionTimeHigh, 458349433):Div(LuaConst.TimeSpanMs)) if not decisionRecordDic.switchHeroCommand and targetCurSkillData.Type == LuaConst.SkillType.MusouAttack then --如果因为无双闪避了,那么6秒之内不再切将 decisionRecordDic.switchHeroFrameIndex = LogicUpdateManager._clientHandleFrame + 120 decisionRecordDic.switchHeroCommand = nil end return true end end return false end function Decision_SoloFight:TryRefreshTriggerDodgeMissile(entity, decisionRecordDic) local frame = entity.components.record.lastHitByMusouOrAdjutantFrame if frame <= LogicUpdateManager._clientHandleFrame and entity.components.record.lastHitByMusouOrAdjutantFrame + 20 >= LogicUpdateManager._clientHandleFrame then -- 如果最近1秒内被无双或副将技子弹打过(策划没配置,写死1秒) if self:CanUseDodgeSkill(entity) then decisionRecordDic.dodgeFrame = LogicUpdateManager._clientHandleFrame + FP.tonumberV1(LogicRandom.GetRangeValue(entity, decisionRecordDic.dodgeReactionTimeLow, decisionRecordDic.dodgeReactionTimeHigh, 458349436):Div(LuaConst.TimeSpanMs)) --如果因为无双闪避了,那么6秒之内不再切将 decisionRecordDic.switchHeroFrameIndex = LogicUpdateManager._clientHandleFrame + 120 decisionRecordDic.switchHeroCommand = nil end end end function Decision_SoloFight:TryRefreshAdjutantDodge(entity, decisionRecordDic, target) if decisionRecordDic.nextCheckAdjutantDodgeFrame == nil or decisionRecordDic.nextCheckAdjutantDodgeFrame <= LogicUpdateManager._clientHandleFrame then if target.components.adjutant and target.components.adjutant.AdjutantEntity and target.components.adjutant.AdjutantEntity:IsActive() then if self:CanUseDodgeSkill(entity) then decisionRecordDic.nextCheckAdjutantDodgeFrame = LogicUpdateManager._clientHandleFrame + 120 local rand = LogicRandom.GetRandom01(entity, 458349437) if rand <= decisionRecordDic.dodgeReactionChance then decisionRecordDic.dodgeFrame = LogicUpdateManager._clientHandleFrame + FP.tonumberV1(LogicRandom.GetRangeValue(entity, decisionRecordDic.dodgeReactionTimeLow, decisionRecordDic.dodgeReactionTimeHigh, 458349438):Div(LuaConst.TimeSpanMs)) --如果因为副将技闪避了,那么6秒之内不再切将 decisionRecordDic.switchHeroFrameIndex = LogicUpdateManager._clientHandleFrame + 120 decisionRecordDic.switchHeroCommand = nil end end end end end local PAUSE_FRAME_AFTER_USER_INPUT = 50 --有玩家输入后,该Decision暂停几帧 --[[ 输出指令 --]] function Decision_SoloFight:SetCommand(entity, decisionData, command) --ugly 写死前4秒AI不动 if LogicUpdateManager._clientHandleFrame < 80 then return end local aiBaseComponent = entity.components.aiBase local decisionRecordDic = aiBaseComponent:GetDecisionRecordDic(decisionData) if self:HasPlayerInput(command) then --如果有玩家输入,记录这个输入的时间,并跳出AI运行 decisionRecordDic.lastUserInputFrame = LogicUpdateManager._clientHandleFrame return end if decisionRecordDic.lastUserInputFrame and LogicUpdateManager._clientHandleFrame - decisionRecordDic.lastUserInputFrame < PAUSE_FRAME_AFTER_USER_INPUT / entity.components.aiBase:GetAiUpdateInterval() then --策划需求:如果玩家有输入,就得暂停AI运行一段时间 return end if decisionRecordDic.switchHeroCommand and decisionRecordDic.switchHeroFrameIndex and decisionRecordDic.switchHeroFrameIndex <= LogicUpdateManager._clientHandleFrame then command.SpecialCommand = decisionRecordDic.switchHeroCommand decisionRecordDic.switchHeroFrameIndex = nil decisionRecordDic.switchHeroCommand = nil return end --索敌 SystemManager.OnSearchTarget(entity, 1, P1_SEARCH_ENEMY_DIS_SQR, 1, 0) local targetComp = entity.components.target if targetComp.Target then targetComp:SetForceTarget(targetComp.Target) if LevelManager.IsSyncSolo() then local isNeedTrySwitchHeroFrame = decisionRecordDic.switchHeroFrameIndex == nil or decisionRecordDic.switchHeroFrameIndex < LogicUpdateManager._clientHandleFrame local targetCurSkillData = targetComp.Target.components.skillBase.CurSkillData if targetCurSkillData then if isNeedTrySwitchHeroFrame and targetCurSkillData.Type == LuaConst.SkillType.MusouAttack and entity.components.record.SwitchTimer <= 0 and (not entity.components.buff:HasHardControlBuff()) then self:TrySwitchHero(entity, decisionRecordDic, 1) end if decisionRecordDic.dodgeFrame == IMPOSSIBLE_FRAME then _tempV1:Reset(targetCurSkillData.CastRadius):Mul(targetCurSkillData.CastRadius) if targetComp.ToTargetDisSqr <= _tempV1 then if targetCurSkillData ~= decisionRecordDic.lastTriggerDodgeTargetSkillData and self:IsTriggerDodgeTargetSkill(targetCurSkillData) then self:TryRefreshTriggerDodgeTargetSkill(entity, decisionRecordDic, targetCurSkillData) end end end end if decisionRecordDic.switchHeroCommand == nil and isNeedTrySwitchHeroFrame and entity.components.record.SwitchTimer <= 0 then --如果上面的代码没有生成切将指令 for i,v in ipairs(LogicUpdateManager.EntityList_Normal) do if v.CampID ~= entity.CampID and v.isAdjuntant and v:IsActive() then self:TrySwitchHero(entity, decisionRecordDic, 2) end end end if decisionRecordDic.dodgeFrame == IMPOSSIBLE_FRAME then self:TryRefreshTriggerDodgeMissile(entity, decisionRecordDic) end if decisionRecordDic.dodgeFrame == IMPOSSIBLE_FRAME then self:TryRefreshAdjutantDodge(entity, decisionRecordDic, targetComp.Target) end end if LevelManager.IsSoloFight() then BuffSkillSystem.ReleaseBuffSkill(entity, KEY_POS_GODBEAST) --无脑调,如果放不了就不会放 end if LevelManager.IsSyncSolo() and decisionRecordDic.dodgeFrame <= LogicUpdateManager._clientHandleFrame then --释放闪避 if self:CanUseDodgeSkill(entity) then command.SkillIndex = decisionRecordDic.dodgeSkillIndex else decisionRecordDic.dodgeFrame = IMPOSSIBLE_FRAME decisionRecordDic.lastTriggerDodgeTargetSkillData = nil end else --追击目标 self:CommandChaseUseSkill(entity, command, decisionData, decisionRecordDic, decisionRecordDic.shouldWanderWhenInCD) end --else --do nothing end end function Decision_SoloFight:TrySwitchHero(entity, decisionRecordDic, debugFlag) local heroEntitys = LevelPlayerManager.GetPlayerEntitysByPlayerIDInRoom(entity.PlayerID) local aliveHeroIndex = nil local hpPercent2 = heroEntitys[2].components.attr:HitPointPercents() local hpPercent3 = heroEntitys[3].components.attr:HitPointPercents() if hpPercent2 >= hpPercent3 then if hpPercent2 > FP_Zero then aliveHeroIndex = 2 end else if hpPercent3 > FP_Zero then aliveHeroIndex = 3 end end if aliveHeroIndex then local rand = LogicRandom.GetRandom01(entity, 458349434) if rand <= decisionRecordDic.switchReactionChance then decisionRecordDic.switchHeroFrameIndex = LogicUpdateManager._clientHandleFrame + FP.tonumberV1(LogicRandom.GetRangeValue(entity, decisionRecordDic.switchReactionTimeLow, decisionRecordDic.switchReactionTimeHigh, 458349435):Div(LuaConst.TimeSpanMs)) decisionRecordDic.switchHeroCommand = LuaConst.SpecialCommandType.SwitchHeroToIndex2 + aliveHeroIndex - 2 else decisionRecordDic.switchHeroFrameIndex = LogicUpdateManager._clientHandleFrame + 120 decisionRecordDic.switchHeroCommand = nil end end end return Decision_SoloFight