----------------------------------------------------------------------------------------------------
--- 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'] = {0, 10},
						['t20'] = {10, 0},
						['t15'] = {10, 0},
						['t10'] = {10, 0},
}

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

local nTalentBuildList = J.Skill.GetTalentBuild( tTalentTreeList )

local tOutFitList = {}

tOutFitList['outfit_carry'] = {

	"item_ranged_carry_outfit",
	"item_maelstrom",
	"item_mask_of_madness",
	"item_dragon_lance",
	"item_black_king_bar",
	"item_travel_boots",
	"item_monkey_king_bar",
	"item_hurricane_pike",
	"item_mjollnir",
	"item_moon_shard",
	"item_travel_boots_2",

}

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

tOutFitList['outfit_priest'] = {

	"item_priest_outfit",
	"item_mekansm",
	"item_shadow_amulet",
	"item_guardian_greaves",
	"item_spirit_vessel",
	"item_cyclone",
	"item_wind_waker",
	"item_glimmer_cape",
	"item_shivas_guard",
	"item_mystic_staff",
	"item_sheepstick",

}

tOutFitList['outfit_mage'] = tOutFitList['outfit_priest']

tOutFitList['outfit_tank'] = tOutFitList['outfit_priest']

X['sBuyList'] = tOutFitList[sOutfitType]

X['sSellList'] = {

	"item_travel_boots",
	"item_quelling_blade",

	"item_black_king_bar",
	"item_magic_wand",
	
	"item_travel_boots",
	"item_magic_wand",
	
	"item_assault",
	"item_ancient_janggo",

}

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'] = false
X['bDeafaultItem'] = false

function X.MinionThink( hMinionUnit )

	if Minion.IsValidUnit( hMinionUnit )
	then
		Minion.IllusionThink( hMinionUnit )
	end

end

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

local castQDesire, castQTarget, castQVector
local castWDesire, castWLocation
local castEDesire, castETarget
local castRDesire

local nKeepMana, nMP, nHP, nLV, hEnemyList, hAllyList, botTarget, sMotive
local aetherRange = 0


function X.SkillsComplement()

	J.ConsiderForMkbDisassembleMask( bot )

	if bot.theRole == 'support' and nAbilityBuildList[1]==3 then
		nAbilityBuildList = {2,1,1,2,1,6,1,2,2,3,6,3,3,3,6}
		tTalentTreeList = {
			['t25'] = {0, 10},
			['t20'] = {0, 10},
			['t15'] = {0, 10},
			['t10'] = {0, 10},
		}
		nTalentBuildList = J.Skill.GetTalentBuild( tTalentTreeList )
		X['sSkillList'] = J.Skill.GetSkillList( sAbilityList, nAbilityBuildList, sTalentList, nTalentBuildList )
	end

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

	nKeepMana = 400
	aetherRange = 0
	nLV = bot:GetLevel()
	nMP = bot:GetMana() / bot:GetMaxMana()
	nHP = bot:GetHealth() / bot:GetMaxHealth()
	botTarget = J.GetProperTarget( bot )
	hEnemyList = bot:GetNearbyHeroes( 1600, true, BOT_MODE_NONE )
	hAllyList = J.GetAlliesNearLoc( bot:GetLocation(), 1600 )

	--计算天赋可能带来的通用变化
	
	aetherRange = J.GetBonusCastRange( bot )

	--无论如何，大招期间绝不逃跑
	if bot:HasModifier('modifier_muerta_pierce_the_veil_buff') and not bot:IsDisarmed() then

		--释放BKB
		local abilityBKB = J.IsItemAvailable( "item_black_king_bar" )
		if abilityBKB ~= nil 
			and abilityBKB:IsFullyCastable()
			and bot:GetMana() > abilityBKB:GetManaCost()
		then
			bot:Action_UseAbility( abilityBKB )
		end

		--释放疯脸
		local abilityMoM = J.IsItemAvailable( "item_mask_of_madness" )
		if abilityMoM ~= nil 
			and abilityMoM:IsFullyCastable()
			and bot:GetMana() > abilityMoM:GetManaCost()
		then
			bot:Action_UseAbility( abilityMoM )
		end

		local attackList = J.FilterGroup(hEnemyList,function(u)
			return not u:IsMagicImmune() and GetUnitToUnitDistance(bot,u)<=bot:GetAttackRange()+200
		end)
		if #attackList>0 then
			bot:ActionQueue_AttackUnit(attackList[1],true)
			return
		end
	end
	
	castRDesire, sMotive = X.ConsiderR()
	if castRDesire > 0 then
		J.SetReportMotive( bDebugMode, sMotive )

		J.SetQueuePtToINT( bot, true )

		bot:ActionQueue_UseAbility( abilityR )
		return
	end

	castQDesire, castQTarget, castQVector, sMotive = X.ConsiderQ()
	--no way to use castQVector for now
	if castQDesire > 0 then
		J.SetReportMotive( bDebugMode, sMotive )

		J.SetQueuePtToINT( bot, true )

		bot:ActionQueue_UseAbilityOnEntity(abilityQ, castQTarget)
		return
	end
	
	castWDesire, castWLocation, sMotive = X.ConsiderW()
	if castWDesire > 0 then
		J.SetReportMotive( bDebugMode, sMotive )

		J.SetQueuePtToINT( bot, true )

		bot:ActionQueue_UseAbilityOnLocation( abilityW, castWLocation )
		return
	end

end

function X.ConsiderQ()

	if not abilityQ:IsFullyCastable() then return 0 end

	local nSkillLV = abilityQ:GetLevel()
	local nCastRange = abilityQ:GetCastRange()
	local nCastPoint = abilityQ:GetCastPoint()
	local nManaCost = abilityQ:GetManaCost()
	local nDamage = nSkillLV * 75
	local nDamageType = DAMAGE_TYPE_MAGICAL
	local nInRangeEnemyList = J.GetAroundEnemyHeroList( nCastRange )
	local hCastTarget = nil
	local sCastMotive = nil
	
	--击杀
	for _, npcEnemy in pairs( nInRangeEnemyList )
	do
		if J.IsValidHero( npcEnemy )
			and J.CanCastOnNonMagicImmune( npcEnemy )
			and J.WillMagicKillTarget( bot, npcEnemy, nDamage, nCastPoint ) then
			return BOT_ACTION_DESIRE_HIGH, npcEnemy,nil, 'Q-击杀'..J.Chat.GetNormName( npcEnemy )
		end
	end

	--团战
	if J.IsInTeamFight( bot, 1200 ) then
		local npcEnemy = J.GetLeastHpUnit(nInRangeEnemyList)
		if npcEnemy then
			return BOT_ACTION_DESIRE_HIGH, npcEnemy, "Q-团战"..J.Chat.GetNormName( npcEnemy )
		end
	end

	--通常
	if nSkillLV>1 and J.IsAllowedToSpam(bot, nManaCost) then
		local npcEnemy = J.GetLeastHpUnit(nInRangeEnemyList)
		if npcEnemy then
			return BOT_ACTION_DESIRE_HIGH, npcEnemy, "Q-通常"..J.Chat.GetNormName( npcEnemy )
		end
	end

	return BOT_ACTION_DESIRE_NONE

end

function X.GetWCastSilentLocation(vLocation)
	local nRadius = 320
	local locations={ J.GetVectorFromVectorToAngleWithDistance(vLocation,0,nRadius),
	J.GetVectorFromVectorToAngleWithDistance(vLocation,90,nRadius),
	J.GetVectorFromVectorToAngleWithDistance(vLocation,270,nRadius),
	J.GetVectorFromVectorToAngleWithDistance(vLocation,360,nRadius),
	}
	if nLV>=25 then
		locations= { J.GetVectorFromVectorToAngleWithDistance(vLocation,30,nRadius),
		J.GetVectorFromVectorToAngleWithDistance(vLocation,90,nRadius),
		J.GetVectorFromVectorToAngleWithDistance(vLocation,150,nRadius),
		J.GetVectorFromVectorToAngleWithDistance(vLocation,210,nRadius),
		J.GetVectorFromVectorToAngleWithDistance(vLocation,270,nRadius),
		J.GetVectorFromVectorToAngleWithDistance(vLocation,330,nRadius),
		}
	end
	for _,vLoc in pairs(locations) do
		if GetUnitToLocationDistance(bot,vLoc) < abilityW:GetCasterRange() then
			return vLoc
		end
	end
	return nil
end

function X.ConsiderW()

	if not abilityW:IsFullyCastable() then return 0 end

	local nSkillLV = abilityW:GetLevel()
	local nCastRange = abilityW:GetCastRange() + aetherRange
	local nRadius = abilityW:GetAOERadius()
	local nCastPoint = abilityW:GetCastPoint()
	local nManaCost = abilityW:GetManaCost()
	local nDamage = abilityW:GetAbilityDamage()
	local nDamageType = DAMAGE_TYPE_MAGICAL
	local nInRangeEnemyList = bot:GetNearbyHeroes( nCastRange, true, BOT_MODE_NONE )
	local nTargetLocation = nil

	--打断施法
	for _, npcEnemy in pairs( hEnemyList )
	do
		if npcEnemy:IsChanneling()
			and not npcEnemy:HasModifier( 'modifier_teleporting' )
			and J.IsInRange( bot, npcEnemy, nCastRange + nRadius )
			and J.CanCastOnNonMagicImmune( npcEnemy )
		then
			nTargetLocation = X.GetWCastSilentLocation(npcEnemy:GetLocation())
			if nTargetLocation then
				return BOT_ACTION_DESIRE_HIGH, nTargetLocation, "W-打断施法:"..J.Chat.GetNormName( npcEnemy )
			end
		end
	end

	if J.IsGoingOnSomeone( bot )then
		--AOE
		local nAoeLoc = J.GetAoeEnemyHeroLocation( bot, nCastRange, nRadius, 2 )
		if nAoeLoc ~= nil
		then
			nTargetLocation = nAoeLoc
			return BOT_ACTION_DESIRE_HIGH, nTargetLocation, 'W-Aoe'
		end

		--攻击
		if J.IsValidHero( botTarget )
			and J.IsInRange( bot, botTarget, nCastRange + nRadius - 200 )
			and not botTarget:IsMagicImmune()
			and ( J.IsInRange( bot, botTarget, nCastRange ) or botTarget:IsFacingLocation( bot:GetLocation(), 40 ) )
			and not J.IsDisabled( botTarget )
		then
			nTargetLocation = J.GetCastLocation( bot, botTarget, nCastRange, nRadius )
			if nTargetLocation ~= nil
			then
				return BOT_ACTION_DESIRE_HIGH, nTargetLocation, "W-Attack:"..J.Chat.GetNormName( botTarget )
			end
		end
	end

	return BOT_ACTION_DESIRE_NONE

end

function X.ConsiderR()

	if not abilityR:IsFullyCastable() then
		return 0
	end

	local nEnemysHerosInBonus = bot:GetNearbyHeroes( bot:GetAttackRange() + 150, true, BOT_MODE_NONE )

	--打架时
	if J.IsGoingOnSomeone( bot )
	then
		local npcTarget = J.GetProperTarget( bot )
		if J.IsValidHero( npcTarget )
			and ( J.GetHP( npcTarget ) > 0.25 or #nEnemysHerosInBonus >= 2 )
			and ( J.IsInRange( npcTarget, bot, 300 )
				or #nEnemysHerosInBonus >= 2 )
		then
			return BOT_ACTION_DESIRE_HIGH
		end
	end

	if J.IsRetreating(bot) and bot:WasRecentlyDamagedByAnyHero(2.0) and nHP<0.6 and #hEnemyList>0 then
		return BOT_ACTION_DESIRE_HIGH
	end

	return 0
end

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

