2025-06-04 05:02:57 +08:00

755 lines
26 KiB
Plaintext

AutoBattle = class("AutoBattle")
-- static method begin
-- function AutoBattle.SortTargetList(rolePosition, roleList)
-- local rolePositionXZ = Vector2(rolePosition.x, rolePosition.z)
-- local time = Time.time
-- if nil ~= AutoBattle.currentCreature then
-- AutoBattle.currentCreature:RemoveInvalidHatred()
-- end
-- LuaUtils.SortRoleList(roleList, function(role1, role2)
-- local creature1 = role1.data.custom
-- local creature2 = role2.data.custom
-- if nil ~= AutoBattle.currentCreature then
-- if AutoBattle.currentCreature:CheckHatred(creature1.id, time) then
-- return -1
-- end
-- if AutoBattle.currentCreature:CheckHatred(creature2.id, time) then
-- return 1
-- end
-- end
-- if nil ~= creature1 and nil ~= creature2 then
-- -- Full HP First
-- local maxHP1 = creature1.props.MaxHp:GetValue()
-- local HP1 = creature1.props.Hp:GetValue()
-- local maxHP2 = creature2.props.MaxHp:GetValue()
-- local HP2 = creature2.props.Hp:GetValue()
-- if HP1 == maxHP1 and HP2 ~= maxHP2 then
-- return -1
-- elseif HP1 ~= maxHP1 and HP2 == maxHP2 then
-- return 1
-- end
-- end
-- local p1 = role1.position
-- local p2 = role2.position
-- local d1 = Vector2.Distance(rolePositionXZ, Vector2(p1.x, p1.z))
-- local d2 = Vector2.Distance(rolePositionXZ, Vector2(p2.x, p2.z))
-- if d1 < d2 then
-- return -1
-- end
-- return 1
-- end)
-- end
-- static method end
local tempCreatureArray = {}
AutoBattle.SearchRandomDistance = 5
AutoBattle.currentCreature = nil
AutoBattle.searchPosition = nil
AutoBattle.searchRange = nil
AutoBattle.randomTarget = nil
AutoBattle.hatredTarget = nil
AutoBattle.hatredMinDistance = 999999999
local function TargetFilter(targetCreature, searchTargetArgs)
if nil ~= targetCreature.data and targetCreature.data:NoAutoAttack() then
return false
end
return true
end
AutoBattle.TargetFilter = TargetFilter
local function SearchRandomTarget(targetCreature, skillInfo)
local dist = VectorUtility.DistanceXZ(AutoBattle.searchPosition, targetCreature:GetPosition())
if nil ~= AutoBattle.searchRange and dist > AutoBattle.searchRange then
return false
end
if AutoBattle.SearchRandomDistance > dist
and TargetFilter(targetCreature)
and skillInfo:CheckTarget(AutoBattle.currentCreature, targetCreature) then
AutoBattle.randomTarget = targetCreature
-- LogUtility.InfoFormat("<color=yellow>SearchRandomTarget: </color>{0}",
-- targetCreature.data:GetName())
return RandomUtil.Range(1, 10) < 5
end
return false
end
local function SearchHatredTarget(targetCreature, hatredTime, skillInfo)
if TargetFilter(targetCreature)
and skillInfo:CheckTarget(AutoBattle.currentCreature, targetCreature) then
local dist = VectorUtility.DistanceXZ(AutoBattle.searchPosition, targetCreature:GetPosition())
if nil ~= AutoBattle.searchRange and dist > AutoBattle.searchRange then
return false
end
if AutoBattle.hatredMinDistance > dist then
AutoBattle.hatredTarget = targetCreature
AutoBattle.hatredMinDistance = dist
-- LogUtility.InfoFormat("<color=yellow>SearchHatredTarget: </color>{0}, {1}",
-- targetCreature.data:GetName(), dist)
end
end
return false
end
function AutoBattle.SeartTarget(creature, skillInfo)
local teamFirst = skillInfo:TeamFirst(creature)
local lockedTarget = creature:GetLockTarget()
if nil ~= lockedTarget then
if not teamFirst or lockedTarget:IsInMyTeam() then
if skillInfo:CheckTarget(creature, lockedTarget)
and TargetFilter(creature, nil) then
return lockedTarget
end
end
end
local searchRange = 40
if creature:IsAutoBattleStanding() then
searchRange = skillInfo:GetLaunchRange(creature)
AutoBattle.searchRange = searchRange
end
if not teamFirst then
AutoBattle.currentCreature = creature
AutoBattle.searchPosition = creature:GetPosition()
AutoBattle.randomTarget = nil
SceneCreatureProxy.ForEachCreature(SearchRandomTarget, skillInfo)
AutoBattle.currentCreature = nil
AutoBattle.searchPosition = nil
AutoBattle.searchRange = nil
if nil ~= AutoBattle.randomTarget then
local targetCreature = AutoBattle.randomTarget
AutoBattle.randomTarget = nil
return targetCreature
end
end
local sortComparator = teamFirst
and SkillLogic_Base.SortComparator_TeamFirstDistance
or SkillLogic_Base.SortComparator_Distance
SkillLogic_Base.SearchTargetInRange(
tempCreatureArray,
creature:GetPosition(),
searchRange,
skillInfo,
creature,
TargetFilter,
sortComparator)
local targetCreature = tempCreatureArray[1]
TableUtility.ArrayClear(tempCreatureArray)
return targetCreature
end
function AutoBattle:ctor()
-- self.skillTargetFilter = function(role)
-- local creature = role.data.custom
-- if nil == creature then
-- return true
-- end
-- local detailedType = creature:GetDetailedType()
-- if nil == detailedType then
-- return true
-- end
-- if LNpc.NpcDetailedType.MINI ~= detailedType
-- and LNpc.NpcDetailedType.MVP ~= detailedType then
-- return true
-- end
-- return false
-- end
self:Reset()
end
function AutoBattle:Reset()
self.skillIndex = nil
if nil ~= self.skillStatus then
TableUtility.TableClear(self.skillStatus)
else
self.skillStatus = {}
end
end
function AutoBattle:Update(creature, skillFilter, onlyNoTargetAutoCast, allowResearch)
self:Attack(creature, nil, skillFilter, onlyNoTargetAutoCast, allowResearch)
end
function AutoBattle:Attack(creature, targetCreature, skillFilter, onlyNoTargetAutoCast, allowResearch)
local creaturePosition = creature:GetPosition()
if nil == creaturePosition then
return false
end
if creature.data:NoAttack() then
return false
end
local ret, skillIDAndLevel, noTarget, forceLockCreature, skillInfo = self:Attack_Step1(
creature,
skillFilter,
onlyNoTargetAutoCast)
if not ret then
return false
end
-- LogUtility.InfoFormat("<color=green>AutoBattle selected: </color>{0}, {1}",
-- skillIDAndLevel, noTarget)
return self:Attack_Step2(
creature,
targetCreature,
skillIDAndLevel,
noTarget,
forceLockCreature,
skillInfo,
onlyNoTargetAutoCast,
allowResearch)
end
function AutoBattle:Attack_Step1(creature, skillFilter, onlyNoTargetAutoCast)
local skillIDAndLevel, noTarget, forceLockCreature = self:SelectSkill(creature, skillFilter, onlyNoTargetAutoCast)
if nil == skillIDAndLevel then
return false
end
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
return true, skillIDAndLevel, noTarget, forceLockCreature, skillInfo
end
function AutoBattle:Attack_Step2(creature, targetCreature, skillIDAndLevel, noTarget, forceLockCreature, skillInfo, onlyNoTargetAutoCast, allowResearch)
local noSearch = false
-- if onlyNoTargetAutoCast or (not noTarget and nil ~= targetCreature) then
if onlyNoTargetAutoCast or nil ~= targetCreature then
noSearch = true
end
if nil == forceLockCreature then
forceLockCreature = targetCreature
-- hatred first
local hatredFirst = creature:IsAutoBattleProtectingTeam()
if hatredFirst and skillInfo:TargetEnemy(creature) then
-- hatred first
AutoBattle.currentCreature = creature
AutoBattle.searchPosition = creature:GetPosition()
AutoBattle.searchRange = creature:IsAutoBattleStanding() and skillInfo:GetLaunchRange(creature) or nil
AutoBattle.hatredTarget = nil
AutoBattle.hatredMinDistance = 999999999
Game.LogicManager_Hatred:ForEach(SearchHatredTarget, skillInfo)
AutoBattle.currentCreature = nil
AutoBattle.searchPosition = nil
AutoBattle.searchRange = nil
AutoBattle.hatredMinDistance = 999999999
if nil ~= AutoBattle.hatredTarget then
forceLockCreature = AutoBattle.hatredTarget
AutoBattle.hatredTarget = nil
noSearch = true
end
end
end
local forceTargetCreature = false
local targetPosition = nil
local skillTargetType = skillInfo:GetTargetType(creature)
if SkillTargetType.Point == skillTargetType then
if noTarget and nil == forceLockCreature then
targetPosition = creature:GetPosition()
else
forceTargetCreature = true
end
elseif (SkillTargetType.None == skillTargetType and not noTarget) then
forceTargetCreature = true
end
if forceTargetCreature and nil == forceLockCreature then
if noSearch then
return false
end
forceLockCreature = AutoBattle.SeartTarget(creature, skillInfo)
if nil == forceLockCreature then
-- LogUtility.InfoFormat("<color=yellow>AutoBattle No Target Creature: </color>{0}",
-- skillIDAndLevel)
return false
end
end
if nil ~= forceLockCreature
and (SkillTargetType.Creature == skillTargetType or forceTargetCreature)
and noSearch
and forceLockCreature == targetCreature
and not skillInfo:CheckTarget(creature, forceLockCreature) then
return false
end
-- LogUtility.InfoFormat("<color=green>AutoBattle Use Skill: </color>{0}, {1}, {2}",
-- skillIDAndLevel,
-- forceLockCreature and forceLockCreature.data:GetName() or "NoTarget",
-- noSearch)
if nil == targetPosition and nil ~= forceLockCreature then
targetPosition = forceLockCreature:GetPosition()
end
creature:Client_UseSkill(
skillIDAndLevel,
forceLockCreature,
targetPosition,
forceTargetCreature,
noSearch,
TargetFilter,
allowResearch)
local skillStatus = self.skillStatus[skillIDAndLevel]
if nil == skillStatus then
skillStatus = {}
self.skillStatus[skillIDAndLevel] = skillStatus
end
skillStatus.lastLaunchTime = Time.time
return true
end
function AutoBattle:SelectSkill(creature, filter, onlyNoTargetAutoCast)
local skillProxy = SkillProxy.Instance
if nil ~= skillProxy then
local skillItems = skillProxy:GetAutoBattleSkillsWithCombo()
local startIndex = 1
if nil ~= self.skillIndex then
startIndex = self.skillIndex + 1
-- LogUtility.InfoFormat("<color=yellow>SelectSkill: </color>startIndex={0}", startIndex)
end
-- print ("<color=blue>AutoBattle SelectSkill: </color>startIndex="..startIndex)
local skillItem, skillIndex, noTarget, forceLockCreature = self:LoopGetValidSkill(creature, skillItems, startIndex, filter, onlyNoTargetAutoCast)
if nil ~= skillItem then
-- LogUtility.InfoFormat("<color=blue>AutoBattle SelectSkill: </color>selectedIndex={0}", skillIndex)
if nil ~= skillIndex then
self.skillIndex = skillIndex
end
return skillItem:GetID(), noTarget, forceLockCreature
end
end
-- 2016.3.31. remove default attack
-- local attackSkillIDAndLevel = AutoBattle.GetAttackSkillIDAndLevel(role)
-- if nil == filter or filter(attackSkillIDAndLevel) then
-- return attackSkillIDAndLevel
-- end
return nil
end
function AutoBattle:IsSkillAutoBattleValid(creature, originalSkillIDAndLevel, skillIDAndLevel ,autoBattleParams)
local forceLockCreature = nil
if nil ~= autoBattleParams then
if 1 == autoBattleParams.type then
local skillStatus = self.skillStatus[originalSkillIDAndLevel]
if nil ~= skillStatus
and nil ~= skillStatus.lastLaunchTime
and Time.time < (skillStatus.lastLaunchTime+autoBattleParams.time) then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=1, time limit={1}, rest time={2}",
-- skillIDAndLevel,
-- autoBattleParams.time,
-- skillStatus.lastLaunchTime+autoBattleParams.time - Time.time)
return false
end
elseif 2 == autoBattleParams.type then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=2", skillIDAndLevel)
return false
elseif 3 == autoBattleParams.type then
local props = creature.data.props
if nil ~= props then
local maxHP = props.MaxHp:GetValue()
local HP = props.Hp:GetValue()
if HP >= autoBattleParams.value/100.0*maxHP then
-- print(string.format("<color=yellow>IsSkillAutoBattleValid: </color>skill=%d, type=3", skillIDAndLevel))
return false
end
end
elseif 5 == autoBattleParams.type then
local myTeam = TeamProxy.Instance.myTeam
if nil == myTeam then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=5, 1", skillIDAndLevel)
return false
end
local members = myTeam:GetMembersList()
if nil == members then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=5, 2", skillIDAndLevel)
return false
end
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
local skillLaunchRange = skillInfo:GetLaunchRange(creature)
local rolePosition = creature:GetPosition()
local minHPPercent = 1
local minHPCreature = nil
for i=1, #members do
local m = members[i]
local memberCreature = SceneCreatureProxy.FindCreature(m.id)
if nil ~= memberCreature and not memberCreature:IsDead() then
local targetNoBuffId = autoBattleParams.target_noBuff
local targetHasNoBuff = true
if targetNoBuffId ~= nil then
targetHasNoBuff = not memberCreature.data:HasBuffID(targetNoBuffId)
end
-- member must be around me
if targetHasNoBuff and not (VectorUtility.DistanceXZ(rolePosition, memberCreature:GetPosition()) > skillLaunchRange)
and nil ~= m.hpmax and nil ~= m.hp then
local maxHP = m.hpmax
local HP = m.hp
local HPPercent = HP / maxHP
if (nil == minHPCreature or HPPercent < minHPPercent)
and skillInfo:CheckTarget(creature, memberCreature) then
minHPPercent = HPPercent
minHPCreature = memberCreature
end
end
end
end
if nil == minHPCreature
or minHPPercent >= autoBattleParams.teamvalue/100.0 then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=5, 3", skillIDAndLevel)
return false
end
forceLockCreature = minHPCreature
elseif 7 == autoBattleParams.type then
local myTeam = TeamProxy.Instance.myTeam
if nil == myTeam then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=7, 1", skillIDAndLevel)
return false
end
local members = myTeam:GetMembersList()
if nil == members then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=7, 2", skillIDAndLevel)
return false
end
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
local buffs = skillInfo:GetTeamBuffs(creature)
if nil == buffs or 0 >= #buffs then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=7, 3", skillIDAndLevel)
return false
end
local onlyLockTarget = nil
if 1 == autoBattleParams.only_lock_target then
onlyLockTarget = creature:GetLockTarget()
end
local skillLaunchRange = skillInfo:GetLaunchRange(creature)
local rolePosition = creature:GetPosition()
for i=1, #members do
local m = members[i]
local memberCreature = SceneCreatureProxy.FindCreature(m.id)
if nil ~= memberCreature and not memberCreature:IsDead() then
-- member must be around me
if not (VectorUtility.DistanceXZ(rolePosition, memberCreature:GetPosition()) > skillLaunchRange)
and not memberCreature:HasBuffs(buffs)
and skillInfo:CheckTarget(creature, memberCreature)
and (nil == onlyLockTarget or onlyLockTarget == memberCreature) then
forceLockCreature = memberCreature
break
end
end
end
if nil == forceLockCreature then
return false
end
elseif 8 == autoBattleParams.type then
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
local buffs = skillInfo:GetSelfBuffs(creature)
if nil == buffs or 0 >= #buffs then
return false
end
if creature:HasBuffs(buffs) then
return false
end
elseif 9 == autoBattleParams.type then
local myTeam = TeamProxy.Instance.myTeam
if nil == myTeam then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=9, 1", skillIDAndLevel)
return false
end
local members = myTeam:GetMembersList()
if nil == members then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=9, 2", skillIDAndLevel)
return false
end
local buffStateEffects = autoBattleParams.state_effect
if nil == buffStateEffects or 0 >= #buffStateEffects then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=9, 3", skillIDAndLevel)
return false
end
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
local skillLaunchRange = skillInfo:GetLaunchRange(creature)
local rolePosition = creature:GetPosition()
for i=1, #members do
local m = members[i]
local memberCreature = SceneCreatureProxy.FindCreature(m.id)
if nil ~= memberCreature and not memberCreature:IsDead() then
-- member must be around me
if not (VectorUtility.DistanceXZ(rolePosition, memberCreature:GetPosition()) > skillLaunchRange)
and memberCreature:HasBuffStates(buffStateEffects)
and skillInfo:CheckTarget(creature, memberCreature) then
forceLockCreature = memberCreature
break
end
end
end
if nil == forceLockCreature then
return false
end
elseif 10 == autoBattleParams.type then
local myTeam = TeamProxy.Instance.myTeam
if nil == myTeam then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=10, 1", skillIDAndLevel)
return false
end
local members = myTeam:GetMembersList()
if nil == members then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=10, 2", skillIDAndLevel)
return false
end
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
local skillLaunchRange = skillInfo:GetLaunchRange(creature)
local rolePosition = creature:GetPosition()
for i=1, #members do
local m = members[i]
local memberCreature = SceneCreatureProxy.FindCreature(m.id)
if nil ~= memberCreature and memberCreature:IsDead()
and not (VectorUtility.DistanceXZ(rolePosition, memberCreature:GetPosition()) > skillLaunchRange)
and skillInfo:CheckTarget(creature, memberCreature) then
-- member must be around me
forceLockCreature = memberCreature
break
end
end
if nil == forceLockCreature then
return false
end
elseif 11 == autoBattleParams.type then
local props = creature.data.props
if nil ~= props then
local maxHP = props.MaxHp:GetValue()
local HP = props.Hp:GetValue()
if HP <= autoBattleParams.value/100.0*maxHP then
-- print(string.format("<color=yellow>IsSkillAutoBattleValid: </color>skill=%d, type=11", skillIDAndLevel))
return false
end
end
elseif 12 == autoBattleParams.type then
if creature:HasBuff(autoBattleParams.buffid)
and creature:GetBuffLayer(autoBattleParams.buffid) >= autoBattleParams.num then
return false
end
elseif 13 == autoBattleParams.type then
local myTeam = TeamProxy.Instance.myTeam
if nil == myTeam then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=7, 1", skillIDAndLevel)
return false
end
local members = myTeam:GetMembersList()
if nil == members then
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type=7, 2", skillIDAndLevel)
return false
end
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
local onlyLockTarget = nil
if 1 == autoBattleParams.only_lock_target then
onlyLockTarget = creature:GetLockTarget()
end
local skillLaunchRange = skillInfo:GetLaunchRange(creature)
local rolePosition = creature:GetPosition()
for i=1, #members do
local m = members[i]
local memberCreature = SceneCreatureProxy.FindCreature(m.id)
if nil ~= memberCreature and not memberCreature:IsDead() then
-- member must be around me
if not (VectorUtility.DistanceXZ(rolePosition, memberCreature:GetPosition()) > skillLaunchRange)
and memberCreature:GetBuffLayer(autoBattleParams.buffid) < autoBattleParams.num
and skillInfo:CheckTarget(creature, memberCreature)
and (nil == onlyLockTarget or onlyLockTarget == memberCreature) then
forceLockCreature = memberCreature
break
end
end
end
if nil == forceLockCreature then
return false
end
--備戰精英
elseif 99 == autoBattleParams.type then
local combatEliteValid = self:IsCombatEliteValid(creature, skillIDAndLevel);
if combatEliteValid ~= true then
return false
end
end
end
-- LogUtility.InfoFormat("<color=yellow>IsSkillAutoBattleValid: </color>skill={0}, type={1}, {2}", skillIDAndLevel, autoBattleParams and autoBattleParams.type or -1, forceLockCreature and forceLockCreature.name or "nil")
return true, forceLockCreature
end
function AutoBattle:IsCombatEliteValid(creature, skillIDAndLevel)
local skills = SkillProxy.Instance.GetCombatEliteOptionSkills();
local combatEliteValid = false;
for i=1,#skills do
local skillData = skills[i];
local autoBattleValid = false
for i=1, #skillData.AutoCondition do
local p = skillData.AutoCondition[i]
local valid, targetCreature = self:IsSkillAutoBattleValid(creature, skillIDAndLevel, skillData.id, p)
if valid then
autoBattleValid = true
break
end
end
if autoBattleValid then
combatEliteValid = true
break
end
end
return combatEliteValid;
end
function AutoBattle:IsSkillItemValid(creature, skillItem, filter, onlyNoTargetAutoCast)
if nil == skillItem then
-- LogUtility.Info("<color=yellow>IsSkillItemValid: </color>skillItem is nil")
return false
end
local skillIDAndLevel = skillItem:GetID()
local skillInfo = Game.LogicManager_Skill:GetSkillInfo(skillIDAndLevel)
local noTarget = false
local forceLockCreature = nil
local autoBattlePriority = 0
local autoBattleParams = skillInfo:GetAutoCondition(creature)
if nil ~= autoBattleParams and 0 < #autoBattleParams then
local autoBattleValid = false
for i=1, #autoBattleParams do
local p = autoBattleParams[i]
local valid, targetCreature = self:IsSkillAutoBattleValid(creature, skillIDAndLevel, skillIDAndLevel, p)
if valid then
autoBattleValid = true
noTarget = (1 == p.no_target)
forceLockCreature = targetCreature
if nil ~= p.priority then
autoBattlePriority = p.priority
end
break
end
end
if not autoBattleValid then
-- LogUtility.Info("<color=yellow>IsSkillItemValid: </color>autoBattleValid=false")
return false
end
end
if(skillItem:IsAutoShortCutLocked()) then
return false
end
if not SkillProxy.Instance:SkillCanBeUsed(skillItem) then
-- LogUtility.InfoFormat("<color=yellow>IsSkillItemValid: </color>skill={0}, SkillCanBeUsed=false", skillIDAndLevel)
return false
end
if nil ~= filter and not filter(skillIDAndLevel) then
-- LogUtility.InfoFormat("<color=yellow>IsSkillItemValid: </color>skill={0}, filter=false", skillIDAndLevel)
return false
end
if nil == forceLockCreature
and onlyNoTargetAutoCast
and not skillInfo:NoTargetAutoCast(creature) then
return false
end
return true, noTarget, forceLockCreature, autoBattlePriority
end
function AutoBattle:LoopGetValidSkill(creature, skillItems, startIndex, filter, onlyNoTargetAutoCast)
local attackSkillIDAndLevel = creature.data:GetAttackSkillIDAndLevel()
local attackSkillItem = nil
local attackSkillIndex = nil
local attackSkillNoTarget = false
local attackSkillForceLockCreature = nil
local selectedSkillItem = nil
local selectedIndex = nil
local selectedNoTarget = false
local selectedForceLockCreature = nil
local selectedPriority = -1
if nil ~= skillItems and 0 < #skillItems then
local skillItemCount = #skillItems
if startIndex <= skillItemCount then
for i = startIndex, skillItemCount do
local skillItem = skillItems[i]
local skillID = skillItem:GetID()
local valid, noTarget, forceLockCreature, priority = self:IsSkillItemValid(creature, skillItem, filter, onlyNoTargetAutoCast)
-- LogUtility.InfoFormat("<color>Try Select Skill(in {0}): </color>{1}{2}",
-- skillItemCount,
-- LogUtility.StringFormat("i={0},valid={1},noTarget={2},",i,valid,noTarget),
-- LogUtility.StringFormat("forceLockCreature={0},priority={1}",forceLockCreature,priority))
if valid then
if attackSkillIDAndLevel ~= skillID then
if not creature.data:NoSkill() then
if selectedPriority < priority then
selectedSkillItem = skillItem
selectedIndex = i
selectedNoTarget = noTarget
selectedForceLockCreature = forceLockCreature
selectedPriority = priority
end
-- return skillItem, i, noTarget, forceLockCreature
end
else
attackSkillItem = skillItem
attackSkillIndex = i
attackSkillNoTarget = noTarget
attackSkillForceLockCreature = forceLockCreature
end
end
end
end
local endIndex = math.min(startIndex, skillItemCount)
if 0 < endIndex and 1 < startIndex then
for i = 1, endIndex do
local skillItem = skillItems[i]
local skillID = skillItem:GetID()
local valid, noTarget, forceLockCreature, priority = self:IsSkillItemValid(creature, skillItem, filter, onlyNoTargetAutoCast)
-- LogUtility.InfoFormat("<color>Try Select Skill(in {0}): </color>{1}{2}",
-- skillItemCount,
-- LogUtility.StringFormat("i={0},valid={1},noTarget={2},",i,valid,noTarget),
-- LogUtility.StringFormat("forceLockCreature={0},priority={1}",forceLockCreature,priority))
if valid then
if attackSkillIDAndLevel ~= skillID then
if not creature.data:NoSkill() then
if selectedPriority < priority then
selectedSkillItem = skillItem
selectedIndex = i
selectedNoTarget = noTarget
selectedForceLockCreature = forceLockCreature
selectedPriority = priority
end
-- return skillItem, i, noTarget, forceLockCreature
end
else
attackSkillItem = skillItem
attackSkillIndex = i
attackSkillNoTarget = noTarget
attackSkillForceLockCreature = forceLockCreature
end
end
end
end
end
if nil ~= selectedSkillItem then
return selectedSkillItem, selectedIndex, selectedNoTarget, selectedForceLockCreature
end
-- return attackSkillItem, attackSkillIndex, attackSkillNoTarget, forceLockCreature
return attackSkillItem, nil, attackSkillNoTarget, forceLockCreature
end