----------------------------------------------------------------------------------------------------
--- The Creation Come From: BOT EXPERIMENT Credit:FURIOUSPUPPY
--- BOT EXPERIMENT Author: Arizona Fauzie 2018.11.21
--- Link:http://steamcommunity.com/sharedfiles/filedetails/?id=837040016
--- Refactor: 决明子 Email: dota2jmz@163.com 微博@Dota2_决明子
--- Link:http://steamcommunity.com/sharedfiles/filedetails/?id=1573671599
--- Link:http://steamcommunity.com/sharedfiles/filedetails/?id=1627071163
----------------------------------------------------------------------------------------------------
local X = {}
local bDebugMode = ( 1 == 10 )
local bot = GetBot()

local J = require( GetScriptDirectory()..'/FunLib/jmz_func' )
local Minion = dofile( GetScriptDirectory()..'/FunLib/aba_minion' )
local sTalentList = J.Skill.GetTalentList( bot )
local sAbilityList = J.Skill.GetAbilityList( bot )
local sOutfitType = J.Item.GetOutfitType( bot )

local tTalentTreeList = {
						['t25'] = {10, 0},
						['t20'] = {10, 0},
						['t15'] = {0, 10},
						['t10'] = {10, 0},
}

local tAllAbilityBuildList = {
	{1,2,3,1,1,6,1,3,2,2,6,3,2,3,6},
}

local nAbilityBuildList = J.Skill.GetRandomBuild( tAllAbilityBuildList )

local nTalentBuildList = J.Skill.GetTalentBuild( tTalentTreeList )

local tOutFitList = {}

tOutFitList['outfit_carry'] = {

	"item_mage_outfit",
	"item_aghanims_shard",
	"item_ancient_janggo",
	"item_desolator",
	"item_boots_of_bearing",
	"item_ultimate_scepter",
	"item_cyclone",
	"item_assault",
	"item_wind_waker",
	"item_gungir",
	"item_moon_shard",
	"item_sheepstick",
}

tOutFitList['outfit_mid'] = tOutFitList['outfit_carry']

tOutFitList['outfit_priest'] = tOutFitList['outfit_carry']

tOutFitList['outfit_mage'] = tOutFitList['outfit_carry']

tOutFitList['outfit_tank'] = tOutFitList['outfit_carry']

X['sBuyList'] = tOutFitList[sOutfitType]

X['sSellList'] = {

	"item_assault",
	"item_magic_wand",
}

if J.Role.IsPvNMode() or J.Role.IsAllShadow() then X['sBuyList'], X['sSellList'] = { 'PvN_tank' }, {"item_power_treads", 'item_quelling_blade'} end

nAbilityBuildList, nTalentBuildList, X['sBuyList'], X['sSellList'] = J.SetUserHeroInit( nAbilityBuildList, nTalentBuildList, X['sBuyList'], X['sSellList'] )

X['sSkillList'] = J.Skill.GetSkillList( sAbilityList, nAbilityBuildList, sTalentList, nTalentBuildList )


X['bDeafaultAbility'] = true
X['bDeafaultItem'] = false

function X.MinionThink( hMinionUnit )

	if Minion.IsValidUnit( hMinionUnit )
	then
		if Minion.IsFamiliar(hMinionUnit:GetUnitName()) then --npc_dota_visage_familiar1,2,3
			Minion.FamiliarThink( hMinionUnit )
		else
			Minion.IllusionThink( hMinionUnit )
		end
	end

end

local abilityQ = bot:GetAbilityByName( sAbilityList[1] )
local abilityW = bot:GetAbilityByName( sAbilityList[2] )
local abilityE = bot:GetAbilityByName( sAbilityList[3] )
local abilityD = bot:GetAbilityByName( sAbilityList[5] )
local abilityR = bot:GetAbilityByName( sAbilityList[6] )

local castQDesire, castQTarget
local castWDesire, castWTarget
local castRDesire
local castEDesire
local castDDesire


local nKeepMana, nMP, nHP, nLV, hEnemyHeroList


function X.SkillsComplement()

	if J.CanNotUseAbility( bot ) or bot:IsInvisible() then return end

	nKeepMana = 450
	nMP = bot:GetMana()/bot:GetMaxMana()
	nHP = bot:GetHealth()/bot:GetMaxHealth()
	nLV = bot:GetLevel()
	hEnemyHeroList = bot:GetNearbyHeroes( 1600, true, BOT_MODE_NONE )


	castRDesire = X.ConsiderR()
	if ( castRDesire > 0 )
	then
		bot:ActionQueue_UseAbility( abilityR )
		return
	end

	castWDesire, castWTarget = X.ConsiderW()
	if ( castWDesire > 0 )
	then

		J.SetQueuePtToINT( bot, false )

		bot:ActionQueue_UseAbilityOnEntity( abilityW, castWTarget )
		return
	end

	castQDesire, castQTarget = X.ConsiderQ()
	if ( castQDesire > 0 )
	then

		J.SetQueuePtToINT( bot, true )

		bot:ActionQueue_UseAbilityOnEntity( abilityQ, castQTarget )
		return
	end

	castEDesire = X.ConsiderE()
	if ( castEDesire > 0 )
	then
		bot:ActionQueue_UseAbility( abilityE )
		return
	end

	castDDesire = X.ConsiderD()
	if ( castDDesire > 0 ) then
		bot:ActionQueue_UseAbility( abilityD )
		return
	end

end

function X.ConsiderD()
	
	if not abilityD:IsTrained()	or abilityD:IsHidden() or not abilityD:IsFullyCastable() then return 0 end

	if J.IsGoingOnSomeone(bot) or J.IsRetreating(bot) then return BOT_ACTION_DESIRE_HIGH end

	return BOT_ACTION_DESIRE_NONE
end

function X.ConsiderE()
	
	if abilityE:IsPassive() then return 0 end

	if nHP<0.5 then return BOT_ACTION_DESIRE_HIGH end

	return BOT_ACTION_DESIRE_NONE
end

function X.ConsiderQ()

	if not abilityQ:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE end

	local nCastRange = abilityQ:GetCastRange()
	local nCastPoint = abilityQ:GetCastPoint()
	local nSkillLV = abilityQ:GetLevel()

	local nEnemysHeroesInCastRange = bot:GetNearbyHeroes( nCastRange + 99, true, BOT_MODE_NONE )
	local nEnemysHeroesInView = bot:GetNearbyHeroes( 880, true, BOT_MODE_NONE )

	--追杀
	if J.IsGoingOnSomeone( bot ) then
		local target = J.GetProperTarget( bot )
		if J.IsValidHero( target )
			and J.CanCastOnNonMagicImmune( target )
			and J.CanCastOnTargetAdvanced( target )
			and J.IsInRange( target, bot, nCastRange ) then
			return BOT_ACTION_DESIRE_HIGH, target
		end
	end

	--逃跑
	if J.IsRetreating( bot )
	then
		if J.IsValid( nEnemysHeroesInCastRange[1] )
			and J.CanCastOnNonMagicImmune( nEnemysHeroesInCastRange[1] )
			and J.CanCastOnTargetAdvanced( nEnemysHeroesInCastRange[1] )
			and not J.IsDisabled( nEnemysHeroesInCastRange[1] )
			and not nEnemysHeroesInCastRange[1]:IsDisarmed()
			and GetUnitToUnitDistance( bot, nEnemysHeroesInCastRange[1] ) <= nCastRange - 60
		then
			return BOT_ACTION_DESIRE_HIGH, nEnemysHeroesInCastRange[1]
		end
	end

	return BOT_ACTION_DESIRE_NONE
end

function X.ConsiderW()

	if not abilityW:IsFullyCastable() or bot:IsRooted()
		or not bot:HasModifier('modifier_visage_soul_assumption') then return BOT_ACTION_DESIRE_NONE end

	local nCastRange = abilityW:GetCastRange()
	local nCastPoint = abilityW:GetCastPoint()
	local nManaCost = abilityW:GetManaCost()
	local nSkillLV = abilityW:GetLevel()
	local nDamage = 70
	if nLV > 27 then nDamage=90 end
	local nSoul = bot:GetModifierStackCount(bot:GetModifierByName( 'modifier_visage_soul_assumption' ))
	nDamage = nSoul * nDamage + 20

	local nEnemysHeroesInCastRange = bot:GetNearbyHeroes( nCastRange, true, BOT_MODE_NONE )

	--击杀
	if #nEnemysHeroesInCastRange > 0 then
		for i=1, #nEnemysHeroesInCastRange do
			if J.IsValid( nEnemysHeroesInCastRange[i] )
				and J.CanCastOnNonMagicImmune( nEnemysHeroesInCastRange[i] )
				and J.CanCastOnTargetAdvanced( nEnemysHeroesInCastRange[i] )
				and J.WillMagicKillTarget( bot, nEnemysHeroesInCastRange[i], nDamage,
					nCastPoint + GetUnitToUnitDistance(bot, nEnemysHeroesInCastRange[i]) / 1000.0 )
				and not J.IsDisabled( nEnemysHeroesInCastRange[i] )
			then
				return BOT_ACTION_DESIRE_HIGH, nEnemysHeroesInCastRange[i]
			end
		end
	end
	if nSoul < 2 + nSkillLV then return BOT_ACTION_DESIRE_NONE end

	--追杀
	if J.IsGoingOnSomeone( bot ) then
		local target = J.GetProperTarget( bot )
		if J.IsValidHero( target )
			and J.IsInRange( target, bot, nCastRange + 50 )
			and ( not J.IsInRange( bot, target, 200 ) or not target:HasModifier( 'modifier_chaos_knight_reality_rift' ) )
			and J.CanCastOnNonMagicImmune( target )
			and J.CanCastOnTargetAdvanced( target )
		then
			return BOT_ACTION_DESIRE_HIGH, target
		end
	end

	--通常
	local valid = J.FilterGroup(nEnemysHeroesInCastRange,function(u)
		return J.IsValid( u )
		and J.CanCastOnNonMagicImmune( u )
		and J.CanCastOnTargetAdvanced( u )
	end)
	
	local target=J.GetLeastHpUnit(valid)
	if target and J.IsAllowedToSpam(bot, nManaCost) then
		return BOT_ACTION_DESIRE_HIGH, target
	end

	--Roshan
	if bot:GetActiveMode() == BOT_MODE_ROSHAN and bot:GetMana() > nKeepMana then
		local target =  bot:GetAttackTarget()
		if target ~= nil then
			return BOT_ACTION_DESIRE_HIGH, target
		end
	end

	return BOT_ACTION_DESIRE_NONE

end

function X.ConsiderR()

	if not abilityR:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE end

	local nMaxUnit = 2
	if nLV >= 25 then nMaxUnit = 3 end

	local listFamiliar = GetUnitList(UNIT_LIST_ALLIES)
	for _,unit in pairs(listFamiliar) do
		if Minion.IsFamiliar(unit:GetUnitName()) and unit:IsAlive() then
			nMaxUnit = nMaxUnit - 1
		end
	end

	if nMaxUnit > 0 then
		return BOT_ACTION_DESIRE_HIGH
	end
	
	return BOT_ACTION_DESIRE_NONE
end


return X
-- dota2jmz@163.com QQ:2462331592..
