----------------------------------
-- 对象选择
----------------------------------
local CombatImpl = require("combat.CombatImpl")
local CombatObj = require("combat.CombatObj")
local CombatDefine = require("combat.CombatDefine")
local RoleDefine = require("role.RoleDefine")
local CombatBuff = require("combat.CombatBuff")
local SkillExcel = require("excel.skill").skill
local Skill = require("combat.Skill")


local targets = {}
local handler = {}	--选择策略
--对象选择器begin
--[[
	ret = 0,1,2 // 0:需要继承skilltargets  1:敌方  2 ： 己方
]]
local function getTargetSide(attacker,targetMode)
	if  not targetMode[2] or targetMode[2] == 0 then
		return 0
	elseif targetMode[2] == 1 then
		if attacker.side == CombatDefine.ATTACK_SIDE then
			return CombatDefine.DEFEND_SIDE
		else
			return CombatDefine.ATTACK_SIDE
		end
	elseif targetMode[2] == 2 then
		return attacker.side
	end
end

local function CheckbuffCanChose(attacker, objTarget)
	if not attacker or not objTarget then
		return true
	end

	if attacker.isElf then
		return true
	end

	-- 同阵营可以选择
	if objTarget.pos == attacker.pos then
		return true
	end

	local bHaveTrueVision = CombatBuff.isStatus(attacker, {"truevision"})
	local bHaveQianXing = CombatBuff.isStatus(objTarget, {"qianxing"})
	-- 无真视
	if not bHaveTrueVision then
		if not bHaveQianXing then	-- 无潜行
			return true
		else						-- 有潜行不可选中
			return false
		end
	else
		return true
	end
end

local function canTarget(obj)
	if obj and obj.hp and  obj.hp > 0 
		and not CombatBuff.isStatus(obj,{"revive"}) 
		and CombatDefine.isBackup(obj) ~= CombatDefine.BACKUP_TYPE1  then
		return true
	end
end

local function getObj(pos)
    -- 不能直接取 援军对象
    if pos == CombatDefine.BACKUP_POS[1] or  pos == CombatDefine.BACKUP_POS[2] then return end

	local obj = CombatImpl.objList[pos]
	local backupPos = pos < CombatDefine.COMBAT_HERO_CNT and CombatDefine.BACKUP_POS[1] or CombatDefine.BACKUP_POS[2]
	local backupObj = CombatImpl.objList[backupPos]
    -- 援军已上场
	if backupObj and backupObj.backupPos == pos then
		return backupObj
	end
	return obj
end

local function handlerInit(attacker, targetMode)
    -- 清除分摊标志
    attacker.handBuffCalcType = nil
    for _, pos in ipairs(CombatDefine.SIDE2POS[0]) do
       local obj = getObj(pos)
       if obj then
           obj.fentq = nil
		   obj.addByfentan = nil --更新标识
       end
    end
end

-- 处理所有对象是否需要分摊
local function handlerFenTan(attacker, targetMode, skillTargets, cmdTargets, skillID)
    if #targets <= 0 then return end

    if skillID then
       --local skillConfig = SkillExcel[skillID]
	   local skillConfig = Skill.GetSkillConfig(skillID)
       if skillConfig then 
          if skillConfig.otherArgs and skillConfig.otherArgs.hurtFenTan then
             return 
          end
       end 
    end

    local tagObj = targets[1]
    local targetSide = tagObj.side
    local fentq = {}
    local fentCnt = 0
    for _, pos in ipairs(CombatDefine.SIDE2POS[targetSide]) do
       local obj = getObj(pos)
       if obj and canTarget(obj) and obj.bufferCmd["fentan"] then
           fentq[pos] = 1
           fentCnt = fentCnt + 1
       end
    end

    -- 分摊比列
    for _, pos in ipairs(CombatDefine.SIDE2POS[targetSide]) do
       local obj = getObj(pos)
       if obj and canTarget(obj) and obj.bufferCmd["fentan"] then
           obj.fentq = fentCnt

           -- 把不在队列的分摊对象加入到队列当中
           local find = false
           for _, tarobj in ipairs(targets) do
              if tarobj.pos == obj.pos then
                 find = true
              end
           end

           if not find then
				obj.addByfentan = true --增加一个标识，表示是该对象是由于拥有"fentan" buff 额外加入对象列表的
              	targets[#targets + 1] = obj
           end
       end
    end
              
end

local function handlerHunluan(attacker,targetMode)
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
    local len = 0
    local selectList = {}
	for pos = 1,CombatDefine.COMBAT_HERO_ALL_CNT do
		local obj = getObj(pos)
		if canTarget(obj) then 
            len = len + 1
            selectList[len] = obj
		end
	end
   
    -- 混乱要随机选择目标 modify buy dxzeng
    local randomLen = #selectList
    if randomLen <= 0 or cnt <= 0 then return end
    
    if cnt > randomLen then 
       cnt = randomLen
    end
    
    for index = 1, cnt do
       local len = 0
       local tempRandom = {} 
       for k, v in pairs(selectList) do
          len = len + 1
          tempRandom[len] = k
       end
       
       local randomIndex = math.random(1, len)
       local selectIndex = tempRandom[randomIndex]
       targets[#targets+1] = selectList[selectIndex]
       selectList[selectIndex] = nil
    end
end

local function handlerStatus(attacker,status)
	local targetSide
	if attacker.side == CombatDefine.ATTACK_SIDE then
		targetSide = CombatDefine.DEFEND_SIDE
	else
		targetSide = CombatDefine.ATTACK_SIDE
	end
	for _,pos in ipairs(CombatDefine.SIDE2POS[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) and CombatBuff.isStatus(obj,status) then 
			targets[#targets+1] = obj
			return
		end
	end
end
--
CAN_EMPTY_TARGET = { 
	[22] = 1,
	[37] = 1,
}
function getTargets(attacker, targetMode, skillTargets, cmdTargets, checkChaofen, isNormalAtk, skillID, isNeedFentanObjs)
    for i = 1, #targets do
        targets[i] = nil
    end
    
	if isNeedFentanObjs then
		handlerInit(attacker, targetMode)
	end


    if isNormalAtk then
        local isStatus, cmd, ind = CombatBuff.isStatus(attacker, { "tiaoxin" })
        if isStatus then
            local buffer = attacker.buffer[ind]
            local target = buffer.attackPos and getObj(buffer.attackPos)
            if canTarget(target) then
                targets[#targets + 1] = target
            end
        elseif attacker.normalTarget and attacker.normalTarget.status then
            handlerStatus(attacker, attacker.normalTarget.status)
        end
    end
    if targets[1] == nil then
        if checkChaofen then
            -- 检查是否被嘲讽
            local chaofen, fromPos = CombatBuff.isChaofen(attacker)
            if chaofen then
                local obj = getObj(fromPos)
                if canTarget(obj) and obj.pos ~= attacker.pos then
                    return { obj }, true
                end
            end
        end
        
        if skillID and CombatBuff.isStatus(attacker, { "hunluan" }) and CombatImpl.isFanji == false then
            handlerHunluan(attacker, targetMode)
        elseif handler[targetMode[1]] then
            handler[targetMode[1]](attacker, targetMode, skillTargets, cmdTargets, skillID)
        end

        if not CAN_EMPTY_TARGET[targetMode[1]] and targetMode[2] == 1 and targets[1] == nil and targetMode[1] ~= 32 then
            handler[1](attacker, targetMode, skillTargets)
        end

		--战斗对象有分摊buff后导致会分摊debuff的修改, 如果需要更新到线上就把注释打开
		if isNeedFentanObjs then
			handlerFenTan(attacker, targetMode, skillTargets, cmdTargets, skillID)
		end
    end
	
    local ret = { }
    for _, v in ipairs(targets) do
		if true == CheckbuffCanChose(attacker, v) then
			ret[#ret + 1] = v
		end
    end
    return ret
end

local function getTargetList(side,isSkillTarget,exclude,skillTargets)
	-- print("[getTargetList] ",side , isSkillTarget,exclude)
	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[side]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			-- print("[getTargetList] 加入目标表 id = "..obj.id)
			targetList[#targetList+1] = obj
		end
	end
	if isSkillTarget ~= 1 then 
		-- print("[getTargetList] 111111111")
		local skillTargetList = {}
		for _,obj in ipairs(skillTargets) do 
			skillTargetList[#skillTargetList + 1] = obj
		end
		if exclude == 1 then 
			targetList = skillTargetList
		else
			--从targetList中剔除skillTargetList
			for _,obj in ipairs(skillTargetList) do 
				for i = 1,#targetList do 
					if targetList[i].pos == obj.pos then 
						table.remove(targetList,i)
						break
					end
				end
			end
		end
	end
	return targetList
end

local function getAllTargetList(side)
	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[side]) do
		local obj = getObj(pos)
		if obj then 
			targetList[#targetList+1] = obj
		end
	end
	return targetList
end

-- 全体目标
--[[
	@param2 = {
		handlerID,
		side    0: 全部双方  1：敌方 2: 己方
		isSkillTarget  1：非 2：是；默认1
		exclude        1: 否 2：是 和isSkillTarget关联，是skillTarget还是取非skillTarget	
	}
	@param3 = targetObjList 技能目标（所有目标）
]]
local function handler2(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	-- 如果传入有skillTarget 优先使用技能所带的target集合
	local isSkillTarget = targetMode[3] or 1
	local exclude = targetMode[4] or 1
	local targetList = getTargetList(targetSide,isSkillTarget,exclude,skillTargets)
	-- 转化为目标target
	for _,obj in ipairs (targetList) do
		targets[#targets + 1] = obj
	end
end

-- 自己
local function handler10(attacker)
	--if canTarget(obj) then
		targets[1] = attacker
	--end
end

-- 选择指定排号
--[[
	@param2 = {
		handlerID,
		side,
		cnt,
		{1,2}
	}
]]
local function handler28(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	
	-- 若没有配置默认攻击全部排
	local rowList = targetMode[4] or {1,2,3}
	local targetPosList = {}
	-- 待优化@mafei
	for row,list in pairs(CombatDefine.ROW2POS[targetSide]) do
		if table.find(rowList,row) then 
			for _,pos in pairs(list) do 
				table.insert(targetPosList,pos)
			end
		end
	end
	local cnt = targetMode[3]
	-- 随机打乱排序
	table.shuffle(targetPosList)
	for _,pos in ipairs(targetPosList) do
		local obj = getObj(pos)
		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then 
			return
		end
	end
end

-- 随机选择X个目标
--[[
	@param2 = {
		handlerID,
		side,
		cnt,     选择的数量 默认为1
		isSelf   0/默认:不做判定 1:不能选择自己， 2:必须有自己
	}
]]
local function handler6(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	-- 默认选择一个
	local cnt = targetMode[3] or 1
	local noSelf = targetMode[4] or 0
	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			targetList[#targetList+1] = obj
		end
	end
	if noSelf == 2 then 
		targets[#targets+1] = attacker
	end
	table.shuffle(targetList)
	for _,obj in ipairs(targetList) do 
		if #targets >= cnt then 
			break
		end
		if obj.pos ~= attacker.pos  or noSelf == 0 then 
			targets[#targets+1] = obj
		end
		
	end
end

-- 按照属性X排序，选择前Y个目标  @mafei 还未实现当前hp和mp筛选
--[[
	@param2 = {
		handlerID,
		side,
		cnt,     选择的数量 默认为1
		attrID,  属性ID
		order,   排序方式 0 升序， 1 降序 默认为升序  
	}
]]
local function handler7(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local attrID = targetMode[4] or RoleDefine.HP -- 默认是HP
	local order = targetMode[5] or 0 -- 默认升序
	local targetList = {}
	local targetSide = getTargetSide(attacker,targetMode)
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			targetList[#targetList+1] = obj
		end
	end 
	table.sort(targetList,function(a,b)
		
		local a_attr = CombatObj.getValue(a,attrID)
		local b_attr = CombatObj.getValue(b,attrID)
		-- 血量计算比较特殊, HPLimit * HPPercent
		-- if attrID == RoleDefine then 
		-- 	a_attr = CombatObj.getHpMax(a)
		-- 	b_attr = CombatObj.getHpMax(b)
		-- end 
		local ret  = a_attr < b_attr
		if order ~= 0 then 
			ret = a_attr > b_attr
		end
		return ret
	end)
	for i = 1,cnt do 
		targets[#targets + 1] = targetList[i]
		if #targets >= cnt then 
			break
		end
	end
end

--当前最低
--[[
	@param2 = {
		handlerID,
		side,
		cnt,
		hp/mp, -- 血量还是蓝量
		order,
	}
]]
local statusMap = {
	[RoleDefine.HP] = "hp",
}
local function handler8(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local status =  statusMap[targetMode[4]] or "hp" -- 默认是HP
	local order = targetMode[5] or 0 -- 默认升序
	local targetSide = getTargetSide(attacker,targetMode)
	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			targetList[#targetList+1] = obj
		end
	end 
	table.sort(targetList,function(a,b)
		local a_value = a[status] or 0
		local b_value = b[status] or 0
		local ret  = a_value < b_value
		if order ~= 0 then 
			ret = a_value > b_value
		end
		return ret
	end)
	for i = 1,cnt do 
		targets[#targets + 1] = targetList[i]
		if #targets >= cnt then 
			break
		end
	end
end

 -- 选择正前方一列的X目标
 --[[
	@param2 = {
		handlerID,
		side,
		cnt,
		col,   默认正前方，否则选择colList行数
	}
	-- 改为优先打前排＞中排＞后排，同一排多个目标则优先打对位
 ]]
 local function handler26(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local targetCol = targetMode[4]
	local targetSide = getTargetSide(attacker,targetMode)
	-- 没有targetCol默认选取目标正前方的列数 warning: 检测是否援军情况 @mafei
	if not targetCol then 
		for col,list in pairs(CombatDefine.COLUMN2POS[attacker.side]) do 
			if table.find(list,attacker.pos) then 
				targetCol = col
				break
			end
		end
	end
	
	-- -- 筛选出前后排
	-- local nLen = #CombatDefine.ROW2POS[targetSide]
	-- local tChoseObj, nChoseCol = {}, nil
	-- -- 从后往前才是前，中，后排
	-- for i = 1, nLen, 1 do
	-- 	local tPosList = CombatDefine.ROW2POS[targetSide][i]
	-- 	for j = 1, #tPosList, 1 do
	-- 		local nPos = tPosList[j]
	-- 		local tObj = getObj(nPos)
	-- 		if canTarget(tObj) then
	-- 			table.insert(tChoseObj, tObj)
	-- 		end
	-- 	end

	-- 	if nil ~= _G.next(tChoseObj) then
	-- 		nChoseCol = i
	-- 		break
	-- 	end
	-- end

	-- if nil == _G.next(tChoseObj) then
	-- 	return
	-- end

	-- local bChosePos = nChoseCol == targetCol and true or false
	-- local nChoseLen = 0
	-- local nDuiWeiPos = (attacker.pos - 10 > 0) and attacker.pos - 10 or attacker.pos + 10
	-- local tChoseIndex = {}
	-- for i, v in ipairs(tChoseObj) do
	-- 	if false == bChosePos then
	-- 		tChoseIndex[i] = true
	-- 		nChoseLen = nChoseLen + 1
	-- 		targets[#targets+1] = v
	-- 	else
	-- 		if v.pos and v.pos == nDuiWeiPos then
	-- 			nChoseLen = nChoseLen + 1
	-- 			targets[#targets+1] = v
	-- 			bChosePos = false
	-- 			tChoseIndex[i] = true
	-- 		end
	-- 	end

	-- 	if nChoseLen >= cnt then
	-- 		break
	-- 	end
	-- end

	-- -- 特殊处理，当bChosePos==true没有选择到对应的obj就任意选即可
	-- if nChoseLen < cnt then
	-- 	for i, v in ipairs(tChoseObj) do
	-- 		if not tChoseIndex[i] then
	-- 			tChoseIndex[i] = true
	-- 			nChoseLen = nChoseLen + 1
	-- 			targets[#targets+1] = v
	-- 		end

	-- 		if nChoseLen >= cnt then
	-- 			break
	-- 		end
	-- 	end
	-- end

	-- 筛选出还存在的列
	local colList = {}
	for col,list in pairs(CombatDefine.COLUMN2POS[targetSide]) do 
		local colObjList = {}
		for i = 1,#list do 
			local obj = getObj(list[i])
			if canTarget(obj) then 
				table.insert(colObjList,obj)
			end
		end
		if #colObjList > 0 then 
			table.insert(colList,colObjList)
		end
	end
	-- 没有可选的列
	if #colList == 0 then 
		return
	end
	local targetList 
	for col,list in ipairs(colList) do 
		if col == targetCol then 
			targetList = list
			break
		end
	end
	if not targetList then 
		table.shuffle(colList)
		targetList = colList[1]
	end	
	for _,obj in ipairs(targetList) do 
		targets[#targets+1] = obj
		if #targets >= cnt then 
			break
		end
	end
	
end

-- 选择英雄数量最多的一列或者一行
--[[
	@param2 = {
		handlerID,
		side,
		cnt,
		col     1表示列，2表示行，默认为1
	}
]]
local function handler31(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local mode = targetMode[4] or 1
	local targetSide = getTargetSide(attacker,targetMode)
	local posList = CombatDefine.COLUMN2POS
	if mode ~= 1 then 
		posList = CombatDefine.ROW2POS
	end
	local targetObjList = {}
	for _,list in ipairs(posList[targetSide]) do
		local objList = {}
		for i = 1,#list do 
			local obj = getObj(list[i])
			-- 确认是武将(英雄)
			if canTarget(obj) and not obj.isPet then
				table.insert(objList,obj)
			end
		end
		if #targetObjList <= #objList then 
			targetObjList = objList
		end
	end


	-- 筛选最后的targets
	table.shuffle(targetObjList)
	for i = 1,#targetObjList do
		targets[#targets+1] = targetObjList[i]
		if #targets >= cnt then
			break
		end
	end
end

--随机 选择目标 多次
--[[
	@param2 = {
		handlerID,
		side,
		cnt,       随机选择的次数, 默认一次
		maxCnt     同一目标最多的次数，默认一次
	}
]]
local function handler29(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local maxCnt = targetMode[4] or 1
	local targetSide = getTargetSide(attacker,targetMode)

	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			table.insert(targetList,obj)
		end
	end

	if #targetList <= 0 then
		return
	end

	local cntMap = {}
	for i = 1,cnt do 
		local obj = table.shuffle(targetList)[#targetList]
		local objPos = obj.pos
		cntMap[objPos] = cntMap[objPos] or 0
		targets[#targets + 1] = obj
		cntMap[objPos] = cntMap[objPos] + 1
		if cntMap[objPos] >= maxCnt then 
			table.remove(targetList,#targetList)
		end
		if #targetList <= 0 then 
			break
		end
	end	
end

--随机选择属性列表中一项最高的角色
--[[
	@param2 = {
		handlerID,
		side
		cnt,         选择的数量，默认为1
		attrList,    属性列表
		order        排序方式 0 升序， 1 降序 默认为升序  
	}
]]
local function handler33(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local attrList = targetMode[4] or {}
	local order = targetMode[5] or 0 -- 默认升序
	local targetSide = getTargetSide(attacker,targetMode)
	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			table.insert(targetList,obj)
		end
	end
	-- 随机出一个属性
	local attr = table.shuffle(attrList)[1] or RoleDefine.ATK
	table.sort(targetList,function(a,b)
		local a_attr = CombatObj.getValue(a,attr)
		local b_attr = CombatObj.getValue(b,attr)
		local ret  = a_attr < b_attr
		if order ~= 0 then 
			ret = a_attr > b_attr
		end
		return ret
	end)

	for _, obj in ipairs(targetList) do
		if #targets >= cnt then
			break
		end
		targets[#targets+1] = obj
	end
end

-- 根据自身指定buff层数选择x个目标
--[[
	@param2 = {
		handlerID,
		side,
		buffID    buff ID
		count,    buff层数 默认为1
		cnt,      选择几个目标 默认为1
		isSkillTarget  1：非 2：是；默认1
		exclude        1: 否 2：是 和isSkillTarget关联，是skillTarget还是取非skillTarget	
	}
]]
local function handler32(attacker, targetMode, skillTargets)
	local buffID = assert(targetMode[3],"invalid config")
    local targetSide = getTargetSide(attacker,targetMode)
	local isSkillTarget = targetMode[6] or 1
	local exclude = targetMode[7] or 1
	local targetList = getTargetList(targetSide,isSkillTarget,exclude,skillTargets)
	local exist,buffLayer =  CombatBuff.isStatus(attacker,{buffID})
	if not exist then 
		return
	end
	local count = math.floor(buffLayer/(targetMode[4] or 1 ))
	local maxHit = targetMode[5] or 1
	local hitObjMap = {}
	-- 打乱targetList表
	table.shuffle(targetList)
	-- 筛选targets
	while true do 
		if #targetList <= 0 or count <= 0 then 
			break	
		end
		local r = math.random(#targetList)
		local obj = targetList[r]
		hitObjMap[obj.pos] = hitObjMap[obj.pos] or 0
		-- 如果有重复的obj应该也删除
		if hitObjMap[obj.pos] >= maxHit then 
			table.remove(targetList,r)
		else 
			hitObjMap[obj.pos] = hitObjMap[obj.pos] + 1
			targets[#targets+1] = obj
			count = count - 1
		end
	end
end

-- 复活x个单位
--[[
	@param2 = {
		handlerID,
		side,
		cnt,   选择复活的数量 默认为1
	}
]]
local function handler21(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local targetSide = getTargetSide(attacker,targetMode)
	local targetList = getAllTargetList(targetSide)
	table.shuffle(targetList)
	for _,obj in ipairs(targetList) do 
		-- 判断能否复活
		if CombatBuff.canRevive(obj) then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then 
			break
		end
	end
end

--职业+攻击力排名
--[[
	@param2 = {
		handlerID,
		side
		cnt,
		jobs,    职业列表
	}
]]
local function handler24(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	local targetList = {}
	local jobs = targetMode[4] or {}
	local cnt = targetMode[3] or 1
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			table.insert(targetList,obj)
		end
	end
	local attr = RoleDefine.ATK
	-- 降序排列
	table.sort(targetList,function(a,b)
		local a_attr = CombatObj.getValue(a,attr)
		local b_attr = CombatObj.getValue(b,attr) 
		local ret = a_attr > b_attr
		if a_attr== b_attr then 
			local a_idx = table.find(jobs,a.job) or (#jobs+1)
			local b_idx = table.find(jobs,b.job) or (#jobs+1)
			if a_idx ~= b_idx then 
				return a_idx < b_idx
			end
		end
		return ret
	end)
	for _,obj in ipairs(targetList) do 
		targets[#targets+1] = obj
		if #targets >= cnt then 
			break
		end
	end
end

--选取百分比生命值最低cnt个目标
--[[
	@param2 = {
		handlerID,
		side,
		cnt,
		limit 百分比
	}
]]
local function  handler14(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local targetList = {}
	local limit = targetMode[4]  or 100
	local cnt = targetMode[3] or 1
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) then 
			local obj_hp_limit = CombatObj.getValue(obj,RoleDefine.HP)
			if (obj.hp/obj_hp_limit) < (limit / 100) then 
				table.insert(targetList,obj)
			end
		end
	end
	table.shuffle(targetList)
	for _,obj in ipairs(targetList) do 
		targets[#targets+1] = obj
		if #targets >= cnt then 
			break
		end
	end
end

--职业优先
--[[
	@param2 = {
		handlerID,
		side,
		cnt,
		jobs    -- 职业集合
	}
]]
local function handler25(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
		assert()
	end
	local cnt = targetMode[3] or 1
	local job = targetMode[4] or {}
	local temp = {}
	for _,pos in ipairs(CombatDefine.SIDE2POS[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) and table.find(job,obj.job) then
			targets[#targets + 1] = obj
		end

		if #targets >= cnt then
			break
		end
	end
	-- 没有职业可选 则随机选择
	if #targets == 0 then
		handler6(attacker,{
			targetMode[1],
			targetMode[2],
			cnt
		})
	end
end

-- 技能选取
local function handler0(_,_,skillTargets)
	for _,obj in ipairs (skillTargets) do 
		targets[#targets + 1] = obj
	end
end

--技能目标（所有目标）
local function handler11(_,_,skillTargets)
	-- abandon
	return handler0(_,_,skillTargets)
end
------------------------------------ 未实现功能 分界线   ------------------------------------

--默认顺序位置
local function handler1(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--最近一列
local function handler4(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--随机前，中，后排
local function handler5(attacker,targetMode)
	-- abandon
end

--攻击最高
--[[
	attacker = {
		backupPos,
		pos,
	}
	targetMode = [9,2,3] 选择类型，side(地方或者己方)，选择人数
]]
local function handler9(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end

end



--技能目标（指定第几个目标）
local function handler12(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--被击时攻击者
local function handler13(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--技能目标(生命高于或者低于攻击方)
local function handler15(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--技能目标(护甲高于或者低于攻击方)
local function handler16(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end


--血量百分比最少
local function handler17(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end


--血量最少,优先选择非满血的英雄
local function handler18(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--随机后排,优先选择非满血的英雄
local function handler19(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--随机,优先选择非满血的英雄
local function handler20(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end



--非技能目标
local function handler22(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--技能目标(速度高于或者低于攻击方)
local function handler23(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--默认顺序位置2
local function handler27(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end


--攻击最高
local function handler30(attacker,targetMode)
	local targetSide = getTargetSide(attacker,targetMode)
	--if targetSide ~= CombatDefine.ATTACK_SIDE and targetSide ~= CombatDefine.DEFEND_SIDE then
	--	assert()
	--end
	local cnt = targetMode[3] or CombatDefine.COMBAT_HERO_ALL_CNT
	local atkPos = attacker.backupPos or attacker.pos
	atkPos = atkPos % CombatDefine.COMBAT_HERO_ALL_CNT
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)

		if canTarget(obj)  and obj.pos ~= attacker.pos then 
			targets[#targets+1] = obj
		end
		if #targets >= cnt then
			return 
		end
	end
end

--从技能目标中根据职业选择
--[=[
		@param2 = {
		handlerID,
		jobs    -- 职业集合
		cnt,
	}
]=]--

local function handler34(attacker,targetMode, skillTargets)
	local job = targetMode[2] or {}
	local cnt = targetMode[3] or 1
	local targetObjList = {}

	for _,obj in ipairs (skillTargets) do
		if canTarget(obj) and table.find(job,obj.job) then
			targetObjList[#targetObjList + 1] = obj
		end
	end

	-- 筛选最后的targets
	table.shuffle(targetObjList)
	for i = 1,#targetObjList do
		targets[#targets+1] = targetObjList[i]
		if #targets >= cnt then
			break
		end
	end
end



-- 从全体中根据种族选择
--[[
	@param2 = {
		handlerID,
		side    0: 全部双方  1：敌方 2: 己方
		campList    -- 种族集合
		onjCnt 目标数量, 默认1
	}
]]
local function handler35(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	local campList = targetMode[3] or {}
	local cnt = targetMode[4] or 1

	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) and table.find(campList, obj.camp) then
			targetList[#targetList+1] = obj
		end
	end


	for _, obj in ipairs (targetList) do
		if #targets >= cnt then
			break
		end

		targets[#targets + 1] = obj
	end
end



-- 按照属性X排序，选择前Y个目标, 且排除技能施放者，属性值需要比技能施放者高/低
--[[
	@param2 = {
		handlerID,
		side,
		cnt,     选择的数量 默认为1
		attrID,  属性ID
		cmpType,   比技能施放者属性高/低, 1 高， 0 低
	}
]]
local function handler36(attacker,targetMode)
	local cnt = targetMode[3] or 1
	local attrID = targetMode[4] or RoleDefine.HP -- 默认是HP
	local cmpType = targetMode[5] or 0 --默认是比施放者属性低

	local targetList = {}
	local targetSide = getTargetSide(attacker,targetMode)
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) and obj.pos ~= attacker.pos then
			targetList[#targetList+1] = obj
		end
	end 
	table.sort(targetList,function(a,b)
		local a_attr = CombatObj.getValue(a,attrID)
		local b_attr = CombatObj.getValue(b,attrID)
		local ret  = a_attr < b_attr
		return ret
	end)

	local attackerVal = CombatObj.getValue(attacker, attrID)

	for i = 1,cnt do
		local targetObjVal = CombatObj.getValue(targetList[i], attrID)
		if cmpType == 0 then --比施放者低
			if targetObjVal > attackerVal then
				break
			end
			targets[#targets + 1] = targetList[i]
		else
			if targetObjVal > attackerVal then
				targets[#targets + 1] = targetList[i]
			end
		end

		if #targets >= cnt then
			break
		end
	end
end

-- 在技能目标中选择友方/敌方
local function handler37(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	for _,obj in ipairs (skillTargets) do
		if obj.side == targetSide then
			targets[#targets + 1] = obj
		end
	end
end


-- 从全体中根据职业选择
--[[
	@param2 = {
		handlerID,
		side    0: 全部双方  1：敌方 2: 己方
		jobList    -- 职业集合
		onjCnt 目标数量, 默认1
	}
]]
local function handler38(attacker,targetMode,skillTargets)
	local targetSide = getTargetSide(attacker,targetMode)
	local jobList = targetMode[3] or {}
	local cnt = targetMode[4] or 1

	local targetList = {}
	for _,pos in ipairs(CombatDefine.DEFAULT_TARGET_POS3[targetSide]) do
		local obj = getObj(pos)
		if canTarget(obj) and table.find(jobList, obj.job) then
			targetList[#targetList+1] = obj
		end
	end


	for _, obj in ipairs (targetList) do
		if #targets >= cnt then
			break
		end

		targets[#targets + 1] = obj
	end
end


------------------------------ 分界线 ------------------------------
-- 目前是一样了，等策划配置好skill表后删掉 @mafei
local function handler3(attacker,targetMode)
	return handler28(attacker,targetMode)
end
--------------------------------------------------------------------

handler[1] = handler1	--1 默认顺序位置
handler[2] = handler2	--2 全体
handler[3] = handler3	--3 前排，中排，后排
handler[4] = handler4	--4 前方一列
handler[5] = handler5	--5 随机前排，中排，后排
handler[6] = handler6	--6 随机
handler[7] = handler7	--7 血量最少
handler[8] = handler8	--8 血量最高
handler[9] = handler9	--9 攻击最高
handler[10] = handler10	--10 自己
handler[11] = handler11	--11 技能目标（所有目标）
handler[12] = handler12	--12 技能目标（指定第几个目标）
handler[13] = handler13	--13 被击时攻击者
handler[14] = handler14	--14 额外作用目标
handler[15] = handler15	--15 技能目标(生命高于或者低于攻击方)
handler[16] = handler16	--16 技能目标(护甲高于或者低于攻击方)
handler[17] = handler17	--17 技能目标(血量百分比最少)
handler[18] = handler18	--18 技能目标(血量最少,优先选择非满血的英雄)
handler[19] = handler19	--19 随机后排,优先选择非满血的英雄
handler[20] = handler20	--20 随机,优先选择非满血的英雄
handler[21] = handler21	--21 死亡武将
handler[22] = handler22	--22 非技能目标
handler[23] = handler23	--23 技能目标(速度高于或者低于攻击方)
handler[24] = handler24	--24 职业+攻击力排名
handler[25] = handler25	--25 职业优先
handler[26] = handler26	--26 同一列
handler[27] = handler27	--27 同一列
handler[28] = handler28	--27 同一列
handler[29] = handler29	--27 同一列
handler[30] = handler30	--30 自己跟目标攻击最高
handler[31] = handler31	--31 同行人数最多
handler[32] = handler32	--32 指定buff选择
handler[33] = handler33	--32 指定buff选择
handler[0] = handler0 -- 技能选取 和11相同
handler[34] = handler34	--从技能目标中根据职业选择
handler[35] = handler35	--从全体中根据种族选择
handler[36] = handler36	--按照属性X排序，选择前Y个目标, 且排除技能施放者，属性值需要比技能施放者高/低
handler[37] = handler37 -- 在技能目标中选择友方/敌方
handler[38] = handler38	--从全体中根据职业选择

--对象选择器end