diff --git a/ability_item_usage_abaddon.lua b/ability_item_usage_abaddon.lua index aa43e31..cb9f8bb 100644 --- a/ability_item_usage_abaddon.lua +++ b/ability_item_usage_abaddon.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.3 New Structure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local AbilityExtensions = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -59,6 +61,11 @@ local TalentTree = { return Talents[8] end, } +-------------------------------------- +-- Level Ability and Talent +-------------------------------------- + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -72,6 +79,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -108,6 +118,9 @@ local CanCast = { } Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -121,6 +134,10 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -130,6 +147,11 @@ Consider[1] = function() end end end + + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect teammate if npcBot:GetHealth() / npcBot:GetMaxHealth() > (0.4 - #enemys * 0.05) or npcBot:HasModifier("modifier_abaddon_aphotic_shield") or npcBot:HasModifier("modifier_abaddon_borrowed_time") then if WeakestAlly ~= nil then @@ -150,6 +172,8 @@ Consider[1] = function() return BOT_ACTION_DESIRE_MODERATE, WeakestEnemy end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then if npcBot:GetHealth() / npcBot:GetMaxHealth() > (0.5 - #enemys * 0.05) or @@ -163,6 +187,8 @@ Consider[1] = function() end end end + + -- If we're farming if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 2 and npcBot:HasModifier("modifier_abaddon_aphotic_shield") then if ManaPercentage > 0.5 then @@ -170,6 +196,8 @@ Consider[1] = function() end end end + + -- If our mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if ManaPercentage > 0.4 and (npcBot:GetHealth() / npcBot:GetMaxHealth() > 0.75 or npcBot:HasModifier("modifier_abaddon_aphotic_shield")) @@ -185,6 +213,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -199,6 +230,10 @@ Consider[2] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --protect teammate,save allys from control local function Rate(it) local rate = 0 if it == npcBot then @@ -240,6 +275,8 @@ Consider[2] = function() return RemapValClamped(rate, 15, 80, BOT_ACTION_DESIRE_MODERATE - 0.1, BOT_ACTION_DESIRE_VERYHIGH), t end end + + --teamfightUsing if fun1:IsAttackingEnemies(npcBot) then if WeakestAlly ~= nil then if AllyHealth / WeakestAlly:GetMaxHealth() < 0.3 then @@ -257,6 +294,8 @@ Consider[2] = function() end end end + + -- If we're pushing or defending a lane and can hit 3+ creeps, go for it if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -270,6 +309,8 @@ Consider[2] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -281,6 +322,8 @@ Consider[2] = function() end end end + + -- If my mana is enough,use it if npcBot:GetActiveMode() == BOT_MODE_LANING then if #enemys >= 1 and CanCast[abilityNumber](npcBot) then if npcBot:GetMana() > npcBot:GetMaxMana() * 0.7 + AbilitiesReal[2]:GetManaCost() then @@ -289,6 +332,8 @@ Consider[2] = function() end end end + + -- If we're farming if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 2 and CanCast[abilityNumber](npcBot) then if ManaPercentage > 0.5 then @@ -300,6 +345,9 @@ Consider[2] = function() end Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or npcBot:HasModifier("modifier_ice_blast") or not npcBot:WasRecentlyDamagedByAnyHero(1.5) then @@ -315,6 +363,7 @@ Consider[4] = function() end AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -328,6 +377,7 @@ function AbilityUsageThink() mana = npcBot:GetMana() manaPercent = AbilityExtensions:GetManaPercent(npcBot) cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) +---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_arc_warden.lua b/ability_item_usage_arc_warden.lua index 7b0f830..0db95ce 100644 --- a/ability_item_usage_arc_warden.lua +++ b/ability_item_usage_arc_warden.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.1 NewStructure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- if GetBot():IsInvulnerable() or not GetBot():IsHero() or not string.find(GetBot():GetUnitName(), "hero") or GetBot():IsIllusion() then return @@ -62,6 +64,7 @@ local TalentTree = { return Talents[7] end, } +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -75,6 +78,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- function CanCast1(npcTarget) if npcTarget == nil or npcTarget:CanBeSeen() == false then return utility.NCanCast(npcTarget) @@ -115,6 +121,9 @@ local maxMana local manaPercent Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or npcBot:GetMana() < ability:GetManaCost() or not ability:IsCooldownReady() then return BOT_ACTION_DESIRE_NONE, 0 @@ -127,6 +136,9 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if HeroHealth <= WeakestEnemy:GetActualIncomingDamage(Damage, DAMAGE_TYPE_MAGICAL) or @@ -139,7 +151,12 @@ Consider[1] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- local enemys2 = npcBot:GetNearbyHeroes(400, true, BOT_MODE_NONE) + + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if HealthPercentage > 0.6 and (ManaPercentage > 0.6 or npcBot:GetMana() > ComboMana) then if WeakestEnemy ~= nil then @@ -149,6 +166,7 @@ Consider[1] = function() end end end + -- If we're farming and can hit 2+ creeps and kill 1+ if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 1 then if npcBot:GetMana() > ComboMana * 2 and CanCast[abilityNumber](WeakestCreep) then @@ -156,6 +174,8 @@ Consider[1] = function() end end end + + -- If we're pushing or defending a lane if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -170,6 +190,8 @@ Consider[1] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -183,6 +205,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or npcBot:GetMana() < ability:GetManaCost() or not ability:IsCooldownReady() then return BOT_ACTION_DESIRE_NONE, 0 @@ -197,7 +222,14 @@ Consider[2] = function() local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) local towers = npcBot:GetNearbyTowers(CastRange + 300, false) + + -------------------------------------- + -- Mode based usage + -------------------------------------- + + --protect myself local enemys2 = npcBot:GetNearbyHeroes(400, true, BOT_MODE_NONE) + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH or #enemys2 > 0 then for _, npcEnemy in pairs(enemys) do @@ -207,6 +239,8 @@ Consider[2] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local locationAoE = npcBot:FindAoELocation(false, true, npcBot:GetLocation(), CastRange, Radius, 0, 0) @@ -224,6 +258,9 @@ Consider[2] = function() end Consider[3] = function() local abilityNumber = 3 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or npcBot:GetMana() < ability:GetManaCost() or not ability:IsCooldownReady() then return BOT_ACTION_DESIRE_NONE, 0 @@ -240,6 +277,10 @@ Consider[3] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(1600, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -252,6 +293,10 @@ Consider[3] = function() end end end + + -------------------------------------- + -- Mode based usage + -------------------------------------- local enemys2 = npcBot:GetNearbyHeroes(400, true, BOT_MODE_NONE) if npcBot:GetActiveMode() == BOT_MODE_LANING then if ManaPercentage > 0.7 or ManaPercentage >= 0.55 and ability:GetLevel() >= 3 then @@ -280,6 +325,8 @@ Consider[3] = function() end end end + + -- If we're farming and can hit 2+ creeps and kill 1+ if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 2 and ability:GetLevel() >= 3 then if CreepHealth <= WeakestCreep:GetActualIncomingDamage(Damage, DAMAGE_TYPE_MAGICAL) and @@ -288,6 +335,8 @@ Consider[3] = function() end end end + + -- If we're pushing or defending a lane if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -302,6 +351,8 @@ Consider[3] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local locationAoE = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint + Delay @@ -321,6 +372,9 @@ Consider[3] = function() end Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or AbilityExtensions:CannotTeleport(npcBot) or AbilityExtensions:IsTempestDouble(npcBot) then @@ -334,17 +388,27 @@ Consider[4] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(800, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + + -- Stop making a huge bounty for the enemy if (npcBot:GetHealth() <= 450 or HealthPercentage <= 0.3) and ( npcBot:WasRecentlyDamagedByAnyHero(1.5) or AbilityExtensions:CanHardlyMove(npcBot) or AbilityExtensions:CannotTeleport(npcBot)) and not AbilityExtensions:Outnumber(npcBot, allys, enemys) then return 0 end + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then return BOT_ACTION_DESIRE_HIGH end + -------------------------------------- + -- Mode based usage + -------------------------------------- local enemys2 = npcBot:GetNearbyHeroes(400, true, BOT_MODE_NONE) + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH or #enemys2 > 0 then for _, npcEnemy in pairs(enemys) do @@ -354,6 +418,8 @@ Consider[4] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -376,6 +442,8 @@ function AbilityUsageThink() mana = npcBot:GetMana() maxMana = npcBot:GetMaxMana() manaPercent = AbilityExtensions:GetManaPercent(npcBot) + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -384,6 +452,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_axe.lua b/ability_item_usage_axe.lua index 99b3915..14a4e7a 100644 --- a/ability_item_usage_axe.lua +++ b/ability_item_usage_axe.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.1 NewStructure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -58,6 +60,8 @@ local TalentTree = { return Talents[8] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -71,6 +75,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -97,6 +104,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -121,11 +131,16 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(Radius, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- Check for a channeling enemy for _, npcEnemy in pairs(enemys) do if npcEnemy:IsChanneling() then return BOT_ACTION_DESIRE_HIGH end end + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if HeroHealth <= WeakestEnemy:GetActualIncomingDamage(Damage, DAMAGE_TYPE_MAGICAL) or @@ -135,11 +150,17 @@ Consider[1] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself if (npcBot:WasRecentlyDamagedByAnyHero(2) and #enemys >= 1) or #enemys >= 2 then for _, npcEnemy in pairs(enemys) do return BOT_ACTION_DESIRE_HIGH end end + + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if npcBot:GetMana() >= npcBot:GetMaxMana() * 0.4 + ability:GetManaCost() then if WeakestEnemy ~= nil then @@ -150,6 +171,8 @@ Consider[1] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = fun1:GetTargetIfGood(npcBot) @@ -168,6 +191,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -180,6 +206,10 @@ Consider[2] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -193,6 +223,10 @@ Consider[2] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then for _, npcEnemy in pairs(enemys) do if npcBot:WasRecentlyDamagedByHero(npcEnemy, 2.0) then @@ -202,6 +236,8 @@ Consider[2] = function() end end end + + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if (ManaPercentage > 0.5 or npcBot:GetMana() > ComboMana) then if WeakestEnemy ~= nil then @@ -211,6 +247,8 @@ Consider[2] = function() end end end + + -- If we're farming and can hit 2+ creeps and kill 1+ if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 2 then if CreepHealth <= WeakestCreep:GetActualIncomingDamage(Damage, DAMAGE_TYPE_MAGICAL) and @@ -219,6 +257,7 @@ Consider[2] = function() end end end + -- If we're pushing or defending a lane if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -233,6 +272,8 @@ Consider[2] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = fun1:GetTargetIfGood(npcBot) @@ -246,6 +287,9 @@ Consider[2] = function() end Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -260,6 +304,8 @@ Consider[4] = function() local enemies, enemyIllusions = fun1:GetNearbyHeroes(npcBot, CastRange + 300):Filter(IsWeak):Partition(function(it) return fun1:MayNotBeIllusion(npcBot, it) end) + + -- kill real enemies if fun1:NotRetreating(npcBot) and #enemies == 0 then do local blink = fun1:GetAvailableBlink(npcBot) @@ -296,6 +342,7 @@ Consider[4] = function() end end end + -- kill illusions if #enemies == 0 and fun1:NotRetreating(npcBot) then do local target = enemyIllusions:First() @@ -313,6 +360,7 @@ fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) local callLosingTarget local cullingBladeTarget function AbilityUsageThink() + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then if npcBot:IsCastingAbility() then if npcBot:GetCurrentActiveAbility() == AbilitiesReal[1] then @@ -339,6 +387,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_bane.lua b/ability_item_usage_bane.lua index 913c67a..cabe5d6 100644 --- a/ability_item_usage_bane.lua +++ b/ability_item_usage_bane.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.1 NewStructure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local AbilityExtensions = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -59,6 +61,8 @@ local TalentTree = { return Talents[7] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -72,6 +76,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -109,6 +116,9 @@ local maxMana local manaPercentage Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -121,6 +131,10 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then local npcMostDangerousEnemy = nil @@ -138,6 +152,10 @@ Consider[1] = function() return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself local enemys2 = npcBot:GetNearbyHeroes(500, true, BOT_MODE_NONE) if npcBot:WasRecentlyDamagedByAnyHero(5) then for _, npcEnemy in pairs(enemys2) do @@ -146,6 +164,8 @@ Consider[1] = function() end end end + + -- If we're pushing or defending a lane if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -160,6 +180,8 @@ Consider[1] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -173,6 +195,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -211,6 +236,10 @@ Consider[2] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're seriously retreating if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then if npcBot:WasRecentlyDamagedByAnyHero(2) then do @@ -238,6 +267,7 @@ Consider[2] = function() end end end + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if (manaPercentage > healthPercentage or mana > ComboMana) and abilityLevel >= 2 then do @@ -250,6 +280,7 @@ Consider[2] = function() end end end + -- If we're farming and can hit 2+ creeps and kill 1+ if fun1:IsFarmingOrPushing(npcBot) and #enemies == 0 then if mana > maxMana * 0.7 + manaCost or manaPercentage > healthPercentage + 0.2 then do @@ -262,6 +293,7 @@ Consider[2] = function() end end end + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then do @@ -278,6 +310,9 @@ Consider[2] = function() end Consider[3] = function() local abilityNumber = 3 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -292,6 +327,10 @@ Consider[3] = function() local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 240) local allies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 240, false) do + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- Check for a channeling enemy local target = enemies:First(function(it) return fun1:IsChannelingBreakWorthAbility(it) and CanCast[abilityNumber](it) end) @@ -300,6 +339,7 @@ Consider[3] = function() end end do + -- If we're in a teamfight, use it on the scariest enemy local target = enemies:Filter(function(it) return CanCast[abilityNumber](it) and not fun1:IsOrGoingToBeSeverelyDisabled(it) and #allies <= 1 end):Max(function(it) @@ -309,6 +349,7 @@ Consider[3] = function() return BOT_ACTION_DESIRE_HIGH, target end end + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if fun1:IsRetreating(npcBot) then do local target = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 120):First(function(it) @@ -319,6 +360,7 @@ Consider[3] = function() end end end + -- If we're going after someone if fun1:IsAttackingEnemies(npcBot) then local npcEnemy = fun1:GetTargetIfGood(npcBot) local allys2 = fun1:GetNearbyNonIllusionHeroes(npcBot, 600) @@ -354,6 +396,9 @@ Consider[3] = function() end Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -374,6 +419,10 @@ Consider[4] = function() local duration = ability:GetDuration() local damage = ability:GetAbilityDamage() local castRange = ability:GetCastRange() + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- Check for a channeling enemy for _, npcEnemy in pairs(enemys) do if npcEnemy:IsChanneling() and CanCast[abilityNumber](npcEnemy) and not AbilityExtensions:HasAbilityRetargetModifier(npcEnemy) then @@ -383,6 +432,8 @@ Consider[4] = function() if #enemys2 > 0 then return 0 end + + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) and not enemyDisabled(WeakestEnemy) and #enemys <= 2 then @@ -395,6 +446,8 @@ Consider[4] = function() end end end + + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then local npcMostDangerousEnemy = nil @@ -412,6 +465,9 @@ Consider[4] = function() return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy end end + -------------------------------------- + -- Mode based usage + -------------------------------------- if AbilityExtensions:IsRetreating(npcBot) and #enemys == 1 and not AbilityExtensions:HasAbilityRetargetModifier(enemys[1]) then return BOT_ACTION_DESIRE_HIGH, enemys[1] @@ -428,6 +484,7 @@ Consider[4] = function() end return BOT_ACTION_DESIRE_NONE, 0 end +-- nightmare end Consider[5] = function() local ability = AbilitiesReal[5] if not ability:IsFullyCastable() or ability:IsHidden() then @@ -468,6 +525,8 @@ AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) local drainSnapTarget local fiendsGripTarget function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then if npcBot:IsCastingAbility() then if npcBot:GetCurrentActiveAbility() == AbilitiesReal[2] then @@ -496,6 +555,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_bounty_hunter.lua b/ability_item_usage_bounty_hunter.lua index b0aac5a..28accfb 100644 --- a/ability_item_usage_bounty_hunter.lua +++ b/ability_item_usage_bounty_hunter.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.3 New Structure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -58,6 +60,8 @@ local TalentTree = { return Talents[7] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -71,6 +75,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -93,6 +100,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -106,6 +116,10 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- Check for a channeling enemy for _, npcEnemy in pairs(enemys) do if npcEnemy:IsChanneling() and CanCast[abilityNumber](npcEnemy) then if GetUnitToUnitDistance(npcBot, npcEnemy) < CastRange then @@ -115,6 +129,7 @@ Consider[1] = function() end end end + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -133,6 +148,8 @@ Consider[1] = function() end end end + + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then local trackedEnemy = 0 @@ -149,7 +166,12 @@ Consider[1] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself local enemys2 = npcBot:GetNearbyHeroes(400, true, BOT_MODE_NONE) + -- If we're pushing or defending a lane if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -169,6 +191,8 @@ Consider[1] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -200,6 +224,9 @@ Consider[2] = fun1:ToggleFunctionToAutoCast(npcBot, AbilitiesReal[2], function(i end) Consider[3] = function() local abilityNumber = 3 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -213,11 +240,18 @@ Consider[3] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_MODERATE then if npcBot:WasRecentlyDamagedByAnyHero(2.0) then return BOT_ACTION_DESIRE_HIGH end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = fun1:GetTargetIfGood(npcBot) @@ -235,6 +269,9 @@ end Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -276,6 +313,8 @@ Consider[4] = function() end fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -284,6 +323,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_bristleback.lua b/ability_item_usage_bristleback.lua index 990c443..4bf044e 100644 --- a/ability_item_usage_bristleback.lua +++ b/ability_item_usage_bristleback.lua @@ -1,8 +1,11 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.5d +-- Author: adamqqq Email:adamqqq@163.com +-- Contributor: zmcmcc Email:mengzhang@utexas.edu +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -177,6 +180,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -190,6 +196,10 @@ Consider[2] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(Radius, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -200,6 +210,10 @@ Consider[2] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself if (npcBot:WasRecentlyDamagedByAnyHero(2) and #enemys >= 1) or #enemys >= 2 then for _, npcEnemy in pairs(enemys) do if CanCast[abilityNumber](npcEnemy) then @@ -207,6 +221,8 @@ Consider[2] = function() end end end + + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if (manaPercent > 0.65 or npcBot:GetMana() > ComboMana) then if WeakestEnemy ~= nil then @@ -219,6 +235,8 @@ Consider[2] = function() end end end + + -- If we're farming and can hit 2+ creeps if npcBot:GetActiveMode() == BOT_MODE_FARM or npcBot:GetActiveMode() == BOT_MODE_LANING then if #creeps >= 2 then if WeakestCreep ~= nil then @@ -229,6 +247,8 @@ Consider[2] = function() end end end + + --Last hit if npcBot:GetActiveMode() == BOT_MODE_LANING then if WeakestCreep ~= nil then if (manaPercent > 0.5 or npcBot:GetMana() > ComboMana) and @@ -239,6 +259,9 @@ Consider[2] = function() end end end + + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -250,6 +273,7 @@ Consider[2] = function() end return BOT_ACTION_DESIRE_NONE, 0 end +-- hairball Consider[4] = function() local ability = AbilitiesReal[4] if not ability:IsFullyCastable() or ability:IsHidden() then diff --git a/ability_item_usage_chen.lua b/ability_item_usage_chen.lua index ec36766..40d1236 100644 --- a/ability_item_usage_chen.lua +++ b/ability_item_usage_chen.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.3 New Structure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -105,6 +107,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -117,7 +122,13 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = fun1:GetNearbyCreeps(npcBot, CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself local enemys2 = fun1:GetNearbyCreeps(npcBot, 400, true) + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if (npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH) or #enemys2 > 0 then for _, npcEnemy in pairs(enemys) do @@ -127,6 +138,8 @@ Consider[1] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -158,6 +171,9 @@ end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -172,6 +188,11 @@ Consider[2] = function() local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) local creepsNeutral = npcBot:GetNearbyNeutralCreeps(1600) local StrongestCreep, CreepHealth2 = utility.GetStrongestUnit(creepsNeutral) + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- Find neutral creeps + local holyPersuasionLevelLimit = AbilitiesReal[2]:GetLevel() + 2 local canEnchantAncientCreep = npcBot:GetLevel() <= 15 if ManaPercentage >= 0.3 then @@ -192,6 +213,9 @@ Consider[2] = function() end function ConsiderRecall() local abilityNumber = 3 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -210,6 +234,9 @@ local GetAllAllyHeroes = fun1:EveryManySeconds(2, function() end) Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -249,6 +276,8 @@ Consider[4] = function() return BOT_ACTION_DESIRE_MODERATE end end + + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 and #enemies > 0 then if fun1:Contains(severelyDamagedAllies, npcBot) and #damagedAllies >= 3 or @@ -260,6 +289,8 @@ Consider[4] = function() end fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end diff --git a/ability_item_usage_clinkz.lua b/ability_item_usage_clinkz.lua index 5f6cb9c..a3e67a9 100644 --- a/ability_item_usage_clinkz.lua +++ b/ability_item_usage_clinkz.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.3 New Structure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local AbilityExtensions = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -57,6 +59,8 @@ local TalentTree = { return Talents[7] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -70,6 +74,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local ComboMana local AttackRange local ManaPercentage @@ -102,6 +109,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -114,6 +124,10 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -126,6 +140,11 @@ Consider[1] = function() end end end + + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're farming and can hit 2+ creeps if npcBot:GetActiveMode() == BOT_MODE_FARM then if ManaPercentage > 0.4 or npcBot:GetMana() > ComboMana then local locationAoE = npcBot:FindAoELocation(true, false, npcBot:GetLocation(), CastRange, Radius, 0, 0) @@ -134,6 +153,8 @@ Consider[1] = function() end end end + + -- If we're pushing or defending a lane and can hit 4+ creeps, go for it if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -144,6 +165,8 @@ Consider[1] = function() end end end + + -- If my mana is enough, use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if (ManaPercentage > 0.4 or npcBot:GetMana() > ComboMana) and ability:GetLevel() >= 2 then if WeakestEnemy ~= nil then @@ -153,6 +176,8 @@ Consider[1] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local locationAoE = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), CastRange, Radius, 0, 0) @@ -170,6 +195,9 @@ Consider[1] = function() end Consider[2] = AbilityExtensions:ToggleFunctionToAutoCast(npcBot, AbilitiesReal[2], function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or AbilityExtensions:IsPhysicalOutputDisabled(npcBot) then return 0 @@ -254,12 +282,12 @@ Consider[6] = function() return BOT_ACTION_DESIRE_NONE, 0 end local goodNeutral = { - "npc_dota_neutral_alpha_wolf", - "npc_dota_neutral_centaur_khan", - "npc_dota_neutral_dark_troll_warlord", - "npc_dota_neutral_polar_furbolg_ursa_warrior", - "npc_dota_neutral_satyr_hellcaller", - "npc_dota_neutral_enraged_wildkin", + "npc_dota_neutral_alpha_wolf", -- 头狼 + "npc_dota_neutral_centaur_khan", -- 半人马征服者 + "npc_dota_neutral_dark_troll_warlord", -- 黑暗巨魔召唤法师 + "npc_dota_neutral_polar_furbolg_ursa_warrior", -- 地狱熊怪粉碎者 + "npc_dota_neutral_satyr_hellcaller", -- 萨特苦难使者 + "npc_dota_neutral_enraged_wildkin", -- 枭兽撕裂者 } local function IsGoodNeutralCreeps(npcCreep) local name = npcCreep:GetUnitName() @@ -273,6 +301,9 @@ end Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -285,6 +316,10 @@ Consider[4] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1200, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then local locationAoE = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), AttackRange, 400, 0, 0) @@ -292,6 +327,8 @@ Consider[4] = function() return BOT_ACTION_DESIRE_LOW, locationAoE.targetloc end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -329,6 +366,9 @@ local GetStandardCreepRate = AbilityExtensions:EveryManySeconds(2, function() end) Consider[5] = function() local abilityNumber = 5 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -352,6 +392,8 @@ Consider[5] = function() end AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -360,6 +402,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_doom_bringer.lua b/ability_item_usage_doom_bringer.lua index 43e40bc..bd91d8c 100644 --- a/ability_item_usage_doom_bringer.lua +++ b/ability_item_usage_doom_bringer.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.3 New Structure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -58,6 +60,8 @@ local TalentTree = { return Talents[7] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -78,6 +82,9 @@ function CanCast1(npcEnemy) return npcEnemy:CanBeSeen() and not npcEnemy:IsInvulnerable() end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -183,6 +190,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -207,6 +217,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -220,10 +233,15 @@ Consider[2] = function() local creeps = npcBot:GetNearbyCreeps(Radius + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) local abilityLevel = ability:GetLevel() + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself if npcBot:WasRecentlyDamagedByAnyHero(2) or (npcBot:GetActiveMode() == BOT_MODE_RETREAT and HealthPercentage <= 0.4 + #enemys * 0.05) then return BOT_ACTION_DESIRE_HIGH end + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -237,6 +255,8 @@ Consider[2] = function() end end end + -- If we're farming + if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 3 and ManaPercentage > 0.7 and allyCount < 3 and abilityLevel >= 3 then return BOT_ACTION_DESIRE_LOW @@ -246,6 +266,9 @@ Consider[2] = function() end Consider[3] = function() local abilityNumber = 3 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or fun1:IsPhysicalOutputDisabled(npcBot) then return BOT_ACTION_DESIRE_NONE, 0 @@ -259,6 +282,9 @@ Consider[3] = function() local creeps = npcBot:GetNearbyCreeps(CastRange + 150, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) do + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- local channelingEnemy = A.Linq.First(enemys, function(t) return t:IsChanneling() and CanCast[abilityNumber](t) and GetUnitToUnitDistanceSqr(npcBot, t) <= castWhenNearbyDistanceSqr @@ -267,6 +293,10 @@ Consider[3] = function() return BOT_ACTION_DESIRE_HIGH, channelingEnemy end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're going after someone if fun1:IsAttackingEnemies(npcBot) then do local npcTarget = npcBot:GetTarget() @@ -278,6 +308,7 @@ Consider[3] = function() end end end + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if (HealthPercentage > 0.7 and ManaPercentage > 0.4 or npcBot:GetMana() > ComboMana) then if WeakestEnemy ~= nil then @@ -287,6 +318,8 @@ Consider[3] = function() end end end + + -- If we're farming if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 1 and ManaPercentage > 0.6 or npcBot:GetMana() > ComboMana then return BOT_ACTION_DESIRE_LOW, creeps[1] @@ -532,6 +565,9 @@ Consider[5] = function() end Consider[6] = function() local abilityNumber = 6 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -543,6 +579,10 @@ Consider[6] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 or #allys >= 3 then local npcMostDangerousEnemy = nil @@ -561,6 +601,7 @@ Consider[6] = function() end end do + -- Check for a channeling enemy local channeling = enemys:First(function(t) return fun1:IsChannelingBreakWorthAbility(t, "moderate") and CanCast[6](t) end) @@ -568,6 +609,7 @@ Consider[6] = function() return BOT_ACTION_DESIRE_MODERATE - 0.1, channeling end end + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -580,6 +622,10 @@ Consider[6] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then do @@ -611,6 +657,8 @@ end) fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() RefreshAbilities() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -639,6 +687,7 @@ function AbilityUsageThink() neutralCreeps = npcBot:GetNearbyNeutralCreeps(900) tower = fun1:GetLaningTower(npcBot) cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_ember_spirit.lua b/ability_item_usage_ember_spirit.lua index 930ab16..2cd45e0 100644 --- a/ability_item_usage_ember_spirit.lua +++ b/ability_item_usage_ember_spirit.lua @@ -1,8 +1,6 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- + +-- v1.7 template by AaronSong321 + local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") diff --git a/ability_item_usage_faceless_void.lua b/ability_item_usage_faceless_void.lua index 029080b..4e8e941 100644 --- a/ability_item_usage_faceless_void.lua +++ b/ability_item_usage_faceless_void.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.1 NewStructure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -57,6 +59,8 @@ local TalentTree = { return Talents[7] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -70,6 +74,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -93,6 +100,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or fun1:CannotMove(npcBot) then return BOT_ACTION_DESIRE_NONE, 0 @@ -111,6 +121,8 @@ Consider[1] = function() Timer = DotaTime(), } end + + --try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then local enemys2 = WeakestEnemy:GetNearbyHeroes(900, true, BOT_MODE_NONE) @@ -123,10 +135,16 @@ Consider[1] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we trapped by the trees if trees ~= nil and #trees >= 6 then return BOT_ACTION_DESIRE_HIGH, utility.GetUnitsTowardsLocation(npcBot, GetAncient(GetTeam()), CastRange - 200) + RandomVector(200) end + + -- try to dodge a projectile local projectiles = npcBot:GetIncomingTrackingProjectiles() for _, p in pairs(projectiles) do if GetUnitToLocationDistance(npcBot, p.location) <= 400 and p.is_attack == false and @@ -134,6 +152,8 @@ Consider[1] = function() return BOT_ACTION_DESIRE_HIGH, fun1:GetPointFromLineByDistance(npcBot:GetLocation(), p.location, 450) end end + + -- If we're seriously retreating if fun1:IsRetreating(npcBot) or npcBot.FacelessVoidSkill1.Hp - HealthPercentage >= 0.25 + 0.05 * #enemys then return BOT_ACTION_DESIRE_HIGH, utility.GetUnitsTowardsLocation(npcBot, GetAncient(GetTeam()), CastRange) end @@ -143,6 +163,8 @@ Consider[1] = function() return BOT_ACTION_DESIRE_HIGH + 0.05, locationAoE.targetloc end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -163,6 +185,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -175,6 +200,10 @@ Consider[2] = function() local WeakestAlly, AllyHealth = utility.GetWeakestUnit(allys) local enemys = npcBot:GetNearbyHeroes(Radius, true, BOT_MODE_NONE) local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -187,6 +216,10 @@ Consider[2] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself if npcBot:GetActiveMode() == BOT_MODE_ATTACK then if npcBot:WasRecentlyDamagedByAnyHero(2) or #enemys >= 2 then for _, npcEnemy in pairs(enemys) do @@ -196,6 +229,8 @@ Consider[2] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = fun1:GetTargetIfGood(npcBot) @@ -250,6 +285,9 @@ Consider[4] = function() end Consider[5] = function() local abilityNumber = 5 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -261,6 +299,10 @@ Consider[5] = function() local allys = npcBot:GetNearbyHeroes(1200, false, BOT_MODE_NONE) local enemys = npcBot:GetNearbyHeroes(CastRange + 300, true, BOT_MODE_NONE) local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- Check for a channeling enemy for _, npcEnemy in pairs(enemys) do if npcEnemy:IsChanneling() then local TargetLocation = npcEnemy:GetLocation() @@ -270,6 +312,8 @@ Consider[5] = function() end end end + + --try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -284,6 +328,10 @@ Consider[5] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then local locationAoE = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0) if locationAoE.count >= 3 then @@ -294,6 +342,8 @@ Consider[5] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local locationAoE = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0) @@ -309,6 +359,8 @@ Consider[5] = function() end fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -317,6 +369,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_kunkka.lua b/ability_item_usage_kunkka.lua index 2917181..da6760c 100644 --- a/ability_item_usage_kunkka.lua +++ b/ability_item_usage_kunkka.lua @@ -1,8 +1,11 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.5e +-- Author: adamqqq Email:adamqqq@163.com +-- Contributor: zmcmcc Email:mengzhang@utexas.edu +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -58,6 +61,8 @@ local TalentTree = { return Talents[7] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -71,6 +76,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -110,6 +118,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -123,6 +134,8 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + + -- Check for a channeling enemy for _, npcEnemy in pairs(enemys) do if npcEnemy:IsChanneling() then return BOT_ACTION_DESIRE_HIGH - 0.1, npcEnemy:GetLocation() @@ -131,6 +144,8 @@ Consider[1] = function() if XMarksEnemy() and CanCast[1](xMarkTarget) and DotaTime() - xMarkTime <= 0.8 then return BOT_ACTION_DESIRE_VERYHIGH, xMarkLocation end + + --try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) and WeakestEnemy:HasModifier("modifier_kunkka_x_marks_the_spot") then @@ -141,6 +156,10 @@ Consider[1] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then for _, npcEnemy in pairs(enemys) do if npcBot:WasRecentlyDamagedByHero(npcEnemy, 2.0) then @@ -150,6 +169,8 @@ Consider[1] = function() end end end + + -- If we're farming and can kill 3+ creeps if npcBot:GetActiveMode() == BOT_MODE_FARM then if (ManaPercentage > 0.4 or npcBot:GetMana() > ComboMana) then local locationAoE = npcBot:FindAoELocation(true, false, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0) @@ -158,6 +179,8 @@ Consider[1] = function() end end end + + -- If we're pushing or defending a lane and can hit 4+ creeps if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -168,6 +191,9 @@ Consider[1] = function() end end end + + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local locationAoE = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0) @@ -196,11 +222,15 @@ Consider[3] = function() local allys = npcBot:GetNearbyHeroes(1200, false, BOT_MODE_NONE) local enemys = npcBot:GetNearbyHeroes(CastRange, true, BOT_MODE_NONE) local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) + + -- Check for a channeling enemy for _, enemy in pairs(enemys) do if enemy:IsChanneling() and CanCast[3](enemy) and not enemy:IsSilenced() then return BOT_ACTION_DESIRE_HIGH, enemy end end + + --try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[3](WeakestEnemy) and ManaPercentage > 0.5 then @@ -212,6 +242,8 @@ Consider[3] = function() end end end + + -- If a mode has set a target, and we can kill them, do it local npcTarget = npcBot:GetTarget() if npcTarget ~= nil then if CanCast[3](npcTarget) then @@ -221,6 +253,8 @@ Consider[3] = function() end end end + + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then local npcMostDangerousEnemy = nil @@ -239,6 +273,8 @@ Consider[3] = function() return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcTarget = npcBot:GetTarget() @@ -251,8 +287,13 @@ Consider[3] = function() end return BOT_ACTION_DESIRE_NONE, 0 end + +-- ghost ship Consider[6] = function() local abilityNumber = 6 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -266,6 +307,10 @@ Consider[6] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -280,6 +325,11 @@ Consider[6] = function() end end end + + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're in a teamfight, use it on the scariest enemy local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then local npcMostDangerousEnemy = nil @@ -298,6 +348,8 @@ Consider[6] = function() return BOT_ACTION_DESIRE_LOW, npcMostDangerousEnemy:GetLocation() end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = fun1:GetTargetIfGood(npcBot) @@ -313,6 +365,8 @@ Consider[6] = function() end return BOT_ACTION_DESIRE_NONE, 0 end + +-- torrent storm Consider[4] = function() local ability = AbilitiesReal[4] if not ability:IsFullyCastable() or ability:IsHidden() then @@ -338,6 +392,9 @@ Consider[4] = function() end return 0 end + +-- tidal wave +-- how to use a vector targeted ability? Consider[5] = function() local ability = AbilitiesReal[5] if not ability:IsFullyCastable() or ability:IsHidden() then @@ -354,6 +411,10 @@ Consider[5] = function() local enmeyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) return 0 end + + +-- x_marks_the_target recall +-- name: kunkka_return Consider[7] = function() local abilityNumber = 7 local ability = AbilitiesReal[abilityNumber] @@ -400,6 +461,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_lycan.lua b/ability_item_usage_lycan.lua index 9bdc842..8351d94 100644 --- a/ability_item_usage_lycan.lua +++ b/ability_item_usage_lycan.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.3 New Structure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -57,6 +59,8 @@ local TalentTree = { return Talents[8] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -70,6 +74,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -95,6 +102,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -113,11 +123,17 @@ Consider[1] = function() wolves = wolves + 1 end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if ManaPercentage > 0.6 or npcBot:GetMana() > ComboMana and wolves < 1 then return BOT_ACTION_DESIRE_LOW end end + + -- If we're farming and can kill 3+ creeps with LSA if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -126,6 +142,8 @@ Consider[1] = function() return BOT_ACTION_DESIRE_LOW end end + + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then if npcBot:WasRecentlyDamagedByAnyHero(2.0) and wolves < 1 then return BOT_ACTION_DESIRE_HIGH @@ -146,6 +164,8 @@ Consider[1] = function() end end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -159,6 +179,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -179,8 +202,13 @@ Consider[2] = function() end end end + +-- wolf bite Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() or ability:IsHidden() then return BOT_ACTION_DESIRE_NONE @@ -251,6 +279,9 @@ Consider[4] = function() end Consider[5] = function() local abilityNumber = 5 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -262,11 +293,17 @@ Consider[5] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then if npcBot:WasRecentlyDamagedByAnyHero(2.0) then return BOT_ACTION_DESIRE_HIGH end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = fun1:GetTargetIfGood(npcBot) @@ -276,6 +313,8 @@ Consider[5] = function() end end end + + -- If we're in a teamfight, use it local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(700, false, BOT_MODE_ATTACK) if #tableNearbyAttackingAlliedHeroes >= 2 then local npcEnemy = fun1:GetTargetIfGood(npcBot) @@ -287,6 +326,8 @@ Consider[5] = function() end fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -295,6 +336,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_necrolyte.lua b/ability_item_usage_necrolyte.lua index 6e1a2a5..349e76b 100644 --- a/ability_item_usage_necrolyte.lua +++ b/ability_item_usage_necrolyte.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.3 New Structure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local AbilityExtensions = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -58,6 +60,8 @@ local TalentTree = { return Talents[7] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -71,6 +75,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -111,6 +118,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE @@ -125,6 +135,10 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(Radius, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -137,6 +151,7 @@ Consider[1] = function() end end end + --protect teammate if ManaPercentage > 0.5 or npcBot:GetMana() > ComboMana then for _, npcTarget in pairs(allys) do if npcTarget:GetHealth() / npcTarget:GetMaxHealth() < (0.6 + #enemys * 0.05) then @@ -146,6 +161,10 @@ Consider[1] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself if ManaPercentage > 0.4 or npcBot:GetMana() > ComboMana or (npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH) then if (npcBot:WasRecentlyDamagedByAnyHero(2) and #enemys >= 1) or #enemys >= 2 or HealthPercentage <= 0.4 then @@ -156,6 +175,8 @@ Consider[1] = function() end end end + + -- If we're pushing or defending a lane if npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then @@ -165,6 +186,8 @@ Consider[1] = function() end end end + + -- If my mana is enough,use it at enemy if npcBot:GetActiveMode() == BOT_MODE_LANING then if ManaPercentage > 0.75 then if WeakestEnemy ~= nil and WeakestCreep ~= nil then @@ -174,6 +197,8 @@ Consider[1] = function() end end end + + -- If we're farming and can hit 2+ creeps if npcBot:GetActiveMode() == BOT_MODE_FARM then if #creeps >= 4 then if ManaPercentage > 0.5 or npcBot:GetMana() > ComboMana then @@ -181,6 +206,9 @@ Consider[1] = function() end end end + + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -194,6 +222,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -204,9 +235,16 @@ Consider[2] = function() local allys = npcBot:GetNearbyHeroes(1200, false, BOT_MODE_NONE) local enemys = npcBot:GetNearbyHeroes(Radius, true, BOT_MODE_NONE) local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) + + -------------------------------------- + -- Mode based usage + -------------------------------------- + --protect myself if npcBot:WasRecentlyDamagedByAnyHero(2.0) and #enemys >= 2 and HealthPercentage <= 0.35 + 0.05 * #enemys then return BOT_ACTION_DESIRE_HIGH end + + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then if npcBot:WasRecentlyDamagedByAnyHero(2.0) then return BOT_ACTION_DESIRE_HIGH @@ -276,6 +314,9 @@ Consider[4] = function() end Consider[5] = function() local abilityNumber = 5 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -291,6 +332,10 @@ Consider[5] = function() local allyNumber = AbilityExtensions:GetEnemyHeroNumber(npcBot, AbilityExtensions:Filter(allys, function(t) return AbilityExtensions:IsAttackingEnemies(t) or not t:IsBot() end)) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero do local enemy = enemys:First(A.Hero.IsTeleporting) if enemy and CanCast[abilityNumber](enemy) then @@ -301,6 +346,7 @@ Consider[5] = function() end end end + if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then for i, npcEnemy in pairs(enemys) do if (CanCast[abilityNumber](npcEnemy)) and not npcEnemy:IsMagicImmune() then @@ -322,6 +368,8 @@ Consider[5] = function() end AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -330,6 +378,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_omniknight.lua b/ability_item_usage_omniknight.lua index 0d61c86..ef313a1 100644 --- a/ability_item_usage_omniknight.lua +++ b/ability_item_usage_omniknight.lua @@ -1,8 +1,10 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- +---------------------------------------------------------------------------- +-- Ranked Matchmaking AI v1.1 NewStructure +-- Author: adamqqq Email:adamqqq@163.com +---------------------------------------------------------------------------- +-------------------------------------- +-- General Initialization +-------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local AbilityExtensions = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -57,6 +59,8 @@ local TalentTree = { return Talents[8] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -70,6 +74,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} @@ -177,6 +184,9 @@ end Consider[1] = function() local abilityNumber = 1 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -193,6 +203,10 @@ Consider[1] = function() local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) local creeps = npcBot:GetNearbyCreeps(CastRange + 300, true) local WeakestCreep, CreepHealth = utility.GetWeakestUnit(creeps) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + --Try to kill enemy hero if npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then if WeakestEnemy ~= nil then if CanCast[abilityNumber](WeakestEnemy) then @@ -221,6 +235,9 @@ Consider[1] = function() end end end + -------------------------------------- + -- Mode based usage + -------------------------------------- local enemys3 = npcBot:GetNearbyHeroes(Radius, true, BOT_MODE_NONE) if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then if (npcBot:WasRecentlyDamagedByAnyHero(2.0) and (#enemys3 >= 1 or #enemys == 0) or HealthPercentage <= 0.2) and @@ -228,6 +245,8 @@ Consider[1] = function() return BOT_ACTION_DESIRE_HIGH + 0.08, npcBot end end + + -- If we're going after someone if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local npcEnemy = npcBot:GetTarget() @@ -244,6 +263,9 @@ Consider[1] = function() end Consider[2] = function() local abilityNumber = 2 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -253,6 +275,10 @@ Consider[2] = function() local CastPoint = ability:GetCastPoint() local enemys = npcBot:GetNearbyHeroes(CastRange + 300, true, BOT_MODE_NONE) local allys = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, CastRange + 300, false, BOT_MODE_ATTACK) + -------------------------------------- + -- Global high-priorty usage + -------------------------------------- + -- Protect ally if npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then local weakestAlly, allyHealth = utility.GetWeakestUnit(allys) if weakestAlly ~= nil then @@ -272,6 +298,8 @@ Consider[2] = function() end end end + + -- If we're in a teamfight, use it on the scariest enemy if #allys >= 2 then local npcMostDangerousEnemy = nil local nMostDangerousDamage = 0 @@ -288,12 +316,18 @@ Consider[2] = function() return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy end end + -------------------------------------- + -- Mode based usage + -------------------------------------- + -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH or (#enemys >= 2 and #allys <= 1) then return BOT_ACTION_DESIRE_HIGH, npcBot end return BOT_ACTION_DESIRE_NONE, 0 end + +-- 7.31 move omniknight_hammer_of_purity to ability slot 3 Consider[3] = function() local abilityNumber = 3 local ability = AbilitiesReal[abilityNumber] @@ -341,6 +375,9 @@ end Consider[3] = AbilityExtensions:ToggleFunctionToAutoCast(npcBot, AbilitiesReal[3], Consider[3]) Consider[4] = function() local abilityNumber = 4 + -------------------------------------- + -- Generic Variable Setting + -------------------------------------- local ability = AbilitiesReal[abilityNumber] if not ability:IsFullyCastable() then return BOT_ACTION_DESIRE_NONE, 0 @@ -350,6 +387,8 @@ Consider[4] = function() local allys = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, 1600, false, BOT_MODE_NONE) local enemys = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, 1600) local WeakestEnemy, HeroHealth = utility.GetWeakestUnit(enemys) + + -- If we're in a teamfight, use it on the scariest enemy if npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK then if #allys + #enemys >= 5 then @@ -365,6 +404,8 @@ Consider[4] = function() end AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) function AbilityUsageThink() + + -- Check if we're already using an ability if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then return end @@ -373,6 +414,7 @@ function AbilityUsageThink() ManaPercentage = npcBot:GetMana() / npcBot:GetMaxMana() HealthPercentage = npcBot:GetHealth() / npcBot:GetMaxHealth() cast = ability_item_usage_generic.ConsiderAbility(AbilitiesReal, Consider) + ---------------------------------debug-------------------------------------------- if debugmode == true then ability_item_usage_generic.PrintDebugInfo(AbilitiesReal, cast) end diff --git a/ability_item_usage_puck.lua b/ability_item_usage_puck.lua index a3cde07..7b25c23 100644 --- a/ability_item_usage_puck.lua +++ b/ability_item_usage_puck.lua @@ -1,8 +1,3 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -69,6 +64,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} diff --git a/ability_item_usage_pudge.lua b/ability_item_usage_pudge.lua index ba59d09..8adaa58 100644 --- a/ability_item_usage_pudge.lua +++ b/ability_item_usage_pudge.lua @@ -1,8 +1,6 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- + +-- v1.7 template + local utility = require(GetScriptDirectory() .. "/utility") local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") local AbilityExtensions = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -57,6 +55,8 @@ local TalentTree = { return Talents[8] end, } + +-- check skill build vs current level utility.CheckAbilityBuild(AbilityToLevelUp) function BuybackUsageThink() ability_item_usage_generic.BuybackUsageThink(); @@ -70,6 +70,9 @@ function AbilityLevelUpThink() ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) end +-------------------------------------- +-- Ability Usage Thinking +-------------------------------------- local cast = {} cast.Desire = {} cast.Target = {} diff --git a/mira/ability_item_usage_abaddon.mira b/mira/ability_item_usage_abaddon.mira deleted file mode 100644 index 89bfb3a..0000000 --- a/mira/ability_item_usage_abaddon.mira +++ /dev/null @@ -1,604 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.3 New Structure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local AbilityExtensions = require(GetScriptDirectory().."/util/AbilityAbstraction") -local fun1 = AbilityExtensions -local A = require(GetScriptDirectory().."/util/MiraDota") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[2], - Abilities[3], - Abilities[2], - Abilities[1], - Abilities[2], - Abilities[4], - Abilities[2], - Abilities[1], - Abilities[1], - "talent", - Abilities[1], - Abilities[4], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - "nil", - Abilities[4], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[3] - end, - function() - return Talents[6] - end, - function() - return Talents[8] - end -} --------------------------------------- --- Level Ability and Talent --------------------------------------- - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} - - -local attackRange -local health -local healthPercent -local mana -local manaPercent - -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - - -local function CanCast2( npcEnemy ) - return npcEnemy:CanBeSeen() and not npcEnemy:IsInvulnerable() and not npcEnemy:HasModifier "modifier_abaddon_aphotic_shield" -end - -local CanCast={function(t) - if AbilityExtensions:IsOnSameTeam(npcBot, t) then - return AbilityExtensions:AllyCanCast(t) and not t:HasModifier "modifier_ice_blast" - else - return AbilityExtensions:NormalCanCast(t) - end -end,CanCast2} - -Consider[1]=function() -- TODO: lv 25 AOE mist coil - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local SelfDamage = ability:GetSpecialValueInt("self_damage"); - - - local allys = npcBot:GetNearbyHeroes( CastRange+150, false, BOT_MODE_NONE ); - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, CastRange+150, false) - :Filter(A.Unit.IsNotCreepHero) - - local WeakestAlly,AllyHealth=utility.GetWeakestUnit(allys) - local enemys = npcBot:GetNearbyHeroes(CastRange+150,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL)) - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy; - end - end - end - end - - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect teammate - if(npcBot:GetHealth()/npcBot:GetMaxHealth()>(0.4-#enemys*0.05) or npcBot:HasModifier("modifier_abaddon_aphotic_shield") or npcBot:HasModifier("modifier_abaddon_borrowed_time")) - then - if (WeakestAlly~=nil) - then - if(AllyHealth/WeakestAlly:GetMaxHealth()<0.5) - then - return BOT_ACTION_DESIRE_MODERATE,WeakestAlly - end - end - - for _,npcTarget in pairs( allys ) - do - if(npcTarget:GetHealth()/npcTarget:GetMaxHealth()<(0.5+#enemys*0.05)) - then - if ( CanCast[abilityNumber]( npcTarget ) ) - then - return BOT_ACTION_DESIRE_MODERATE, npcTarget - end - end - end - end - - if npcBot:HasModifier("modifier_abaddon_borrowed_time") then - if WeakestEnemy ~= nil then - return BOT_ACTION_DESIRE_MODERATE, WeakestEnemy - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - if(npcBot:GetHealth()/npcBot:GetMaxHealth()>(0.5-#enemys*0.05) or npcBot:HasModifier("modifier_abaddon_aphotic_shield" )or npcBot:HasModifier("modifier_abaddon_borrowed_time")) - then - local npcEnemy = npcBot:GetTarget(); - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - end - - -- If we're farming - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if ( #creeps >= 2 and npcBot:HasModifier("modifier_abaddon_aphotic_shield")) - then - if(ManaPercentage>0.5) - then - return BOT_ACTION_DESIRE_LOW,WeakestCreep; - end - end - end - - -- If our mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if(ManaPercentage>0.4 and (npcBot:GetHealth()/npcBot:GetMaxHealth()>0.75 or npcBot:HasModifier("modifier_abaddon_aphotic_shield")) and ability:GetLevel()>=2 ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - return BOT_ACTION_DESIRE_LOW,WeakestEnemy; - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - - --- local function MistCoilAuxilliaryCanCast(t) --- if AbilityExtensions:IsOnSameTeam(npcBot, t) then --- return AbilityExtensions:AllyCanCast(t) --- else --- return AbilityExtensions:NormalCanCast(t, true, DAMAGE_TYPE_MAGICAL) --- end --- end - --- local function MistCoilPrimaryCanCast(t) --- if AbilityExtensions:IsOnSameTeam(npcBot, t) then --- return AbilityExtensions:AllyCanCast(t) --- else --- return AbilityExtensions:NormalCanCast(t, true, DAMAGE_TYPE_MAGICAL) and not AbilityExtensions:HasModifier("modifier_antimage_counterspell") --- end --- end - --- local function NormalMistCoil() --- local ability=AbilitiesReal[1] - --- if not ability:IsFullyCastable() then --- return BOT_ACTION_DESIRE_NONE --- end - --- local abilityLevel = ability:GetLevel() --- local castRange = ability:GetCastRange() --- local castPoint = ability:GetCastPoint() --- local manaCost = ability:GetManaCost() --- local enemies = AbilityExtensions:GetNearbyHeroes(npcBot, castRange) --- local realEnemies = AbilityExtensions:Filter(enemies, function(t) return AbilityExtensions:MayNotBeIllusion(npcBot, t) end) --- local friends = AbilityExtensions:GetNearbyHeroes(npcBot, 1200, true) --- local friendCount = AbilityExtensions:GetEnemyHeroNumber(npcBot, friends) --- local targettableFriends = AbilityExtensions:Remove(friends, npcBot) - --- local hasBorrowedTime = npcBot:HasModifier("modifier_abaddon_borrowed_time") --- local hasAphoticShield = npcBot:HasModifier("modifier_abaddon_aphotic_shield") - --- local damage = ability:GetDamage() --- local selfDamage = npcBot:GetActualIncomingDamage(damage * ability:GetSpecialValueInt("self_damage") / 100, DAMAGE_TYPE_PURE) --- local function ChangeDesireBasedOnMyBuff(desire) --- if hasBorrowedTime then --- if healthPercent <= 0.75 then --- desire = desire * 2 --- else --- desire = desire * 1.5 --- end --- else --- if hasAphoticShield and healthPercent >= 0.6 then --- desire = desire * 1.2 --- else --- desire = desire - RemapValClamped(health, selfDamage*1.1, selfDamage*4, 0.8, 0) --- end --- end --- end - --- local function ProtectFriends() --- local protectFriends = AbilityExtensions:Filter(targettableFriends, function(t) return AbilityExtensions:MayNotBeIllusion(t) and MistCoilPrimaryCanCast(t) and AbilityExtensions:GetMaxHealth(t) <= 0.7 and t:GetHealth() <= health * 2 end) --- AbilityExtensions:ForEach(protectFriends, function(t) --- local desire = RemapValClamped(t:GetHealth(), 100, 800, BOT_ACTION_DESIRE_HIGH, BOT_ACTION_DESIRE_VERYLOW) --- desire = ChangeDesireBasedOnMyBuff(desire) --- if AbilityExtensions:IsSeverelyDisabledOrSlowed(t) then --- desire = desire * 1.5 --- end --- coroutine.yield(Clamp(desire, 0, 0.8), t) --- end) --- end - --- if AbilityExtensions:IsAttackingEnemies(npcBot) then --- AbilityExtensions:ForEach(realEnemies, function(t) --- if AbilityExtensions:GetHealthPercent(t) <= 0.6 and MistCoilPrimaryCanCast(t) then --- local actualDamage = t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) --- local desire = RemapValClamped(t:GetHealth(), actualDamage*1.1, actualDamage*8, BOT_ACTION_DESIRE_HIGH, BOT_ACTION_DESIRE_VERYLOW) --- desire = ChangeDesireBasedOnMyBuff(desire) --- coroutine.yield(Clamp(desire, 0, 0.8), t) --- end --- end) --- ProtectFriends() --- elseif AbilityExtensions:IsLaning(npcBot) then --- if friendCount == 1 and health > selfDamage + 0.6 * npcBot:GetMaxHealth() and manaPercent > 0.3 + manaCost then --- local enemyCreeps = AbilityExtensions:GetNearbyAttackableCreeps(npcBot, 900) --- local weakCreeps = AbilityExtensions:Filter(enemyCreeps, function(t) return t:GetHealth() <= t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) end) --- weakCreeps = AbilityExtensions:Filter(weakCreeps, function(t) return t:WasRecentlyDamagedByCreep(1.7) and t:GetAttackRange() >= 450 and GetUnitToLocationDistanceSqr(npcBot, t) > 300^2 end) --- AbilityExtensions:ForEach(weakCreeps, function(t) --- coroutine.yield(BOT_ACTION_DESIRE_MODERATE, t) --- end) --- end --- elseif AbilityExtensions:IsRetreating(npcBot) then --- if not npcBot:WasRecentlyDamagedByAnyHero(0.7) and AbilityExtensions:IsSeverelyDisabledOrSlowed(npcBot) then --- if npcBot:HasModifier("modifier_abaddon_borrowed_time") then --- local attackEnemies = AbilityExtensions:Filter(realEnemies, function(t) return MistCoilPrimaryCanCast(t) and t:GetHealth() <= 800 end) --- AbilityExtensions:ForEach(attackEnemies, function(t) --- return RemapValClamped(t:GetHealth(), 100, 800, BOT_ACTION_DESIRE_VERYHIGH, BOT_ACTION_DESIRE_LOW) --- end) --- end --- end --- else --- ProtectFriends() --- end --- return 0 --- end - --- local function AOEMistCoil() --- local ability=AbilitiesReal[1] - --- if not ability:IsFullyCastable() then --- return BOT_ACTION_DESIRE_NONE --- end - --- local abilityLevel = ability:GetLevel() --- local castRange = ability:GetCastRange() --- local castPoint = ability:GetCastPoint() --- local manaCost = ability:GetManaCost() --- local damage = ability:GetDamage() --- local selfDamage = npcBot:GetActualIncomingDamage(damage * ability:GetSpecialValueInt("self_damage") / 100, DAMAGE_TYPE_PURE) --- local enemies = AbilityExtensions:GetNearbyHeroes(npcBot, castRange) --- local realEnemies = AbilityExtensions:Filter(enemies, function(t) return AbilityExtensions:MayNotBeIllusion(npcBot, t) end) --- local friends = AbilityExtensions:GetNearbyHeroes(npcBot, 1200, true) --- local friendCount = AbilityExtensions:GetEnemyHeroNumber(npcBot, friends) --- local targettableFriends = AbilityExtensions:Remove(friends, npcBot) --- local enemyCreeps = AbilityExtensions:GetNearbyAttackableCreeps(npcBot, 900) --- local friendCreeps = AbilityExtensions:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) --- local weakCreeps = AbilityExtensions:Filter(enemyCreeps, function(t) return t:GetHealth() < t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) end) --- local weakestCreep = utility.GetWeakestUnit(weakCreeps) --- local forbiddenCreeps = AbilityExtensions:Filter(enemyCreeps, function(t) --- return t:GetHealth() > t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) and t:GetHealth() <= t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) + AbilityExtensions:AttackOnceDamage(npcBot, t) * (0.9+#enemyCreeps*0.1) --- end) --- if #friendCreeps == 0 then --- forbiddenCreeps = {} --- end - --- local hasBorrowedTime = npcBot:HasModifier("modifier_abaddon_borrowed_time") --- local hasAphoticShield = npcBot:HasModifier("modifier_abaddon_aphotic_shield") - --- end - --- Consider[1] = function() --- local ability25 = npcBot:GetAbilityByName("special_bonus_unique_abaddon_4") --- if ability25:IsTrained() then --- return NormalMistCoil() --- else --- return AOEMistCoil() --- end --- end - -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, CastRange + 200, false) - :Filter(CanCast[2]) - :Filter { it -> - it:WasRecentlyDamagedByAnyHero(4) or it:WasRecentlyDamagedByTower(2) - } - local WeakestAlly,AllyHealth=utility.GetWeakestUnit(allys) - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --protect teammate,save allys from control - - local function Rate(it) - local rate = 0 - if it == npcBot then - rate += 15 - end - if fun1:IsSeverelyDisabled(it) then - rate += 30 - end - if fun1:GetMovementSpeedPercent(it) <= 0.3 then - rate += 15 - elseif fun1:GetMovementSpeedPercent(it) <= 0.7 then - rate += 8 - end - if fun1:GetHealthPercent(it) <= 0.3 then - rate += 20 - elseif fun1:GetHealthPercent(it) <= 0.7 then - rate += 8 - end - if fun1:DontInterruptAlly(it) then - rate += 10 - end - return rate - end - if local target = allys:Map { it -> - { it, Rate(it) } - }:Filter { it -> - it[2] >= 15 - }:SortByMaxFirst { it -> - it[2] - }:First() then - local t = target[1] - local rate = target[2] - return RemapValClamped(rate, 15, 80, BOT_ACTION_DESIRE_MODERATE - 0.1, BOT_ACTION_DESIRE_VERYHIGH), t - end - - --teamfightUsing - if fun1:IsAttackingEnemies(npcBot) - then - if (WeakestAlly~=nil) - then - if(AllyHealth/WeakestAlly:GetMaxHealth()<0.3) - then - if(CanCast[abilityNumber]( WeakestAlly )) - then - return BOT_ACTION_DESIRE_MODERATE,WeakestAlly - end - end - end - - for _,npcTarget in pairs( allys ) - do - if(npcTarget:GetHealth()/npcTarget:GetMaxHealth()<(0.6+#enemys*0.05+0.2*ManaPercentage) or npcTarget:WasRecentlyDamagedByAnyHero(5.0)) - then - if ( CanCast[abilityNumber]( npcTarget ) ) - then - return BOT_ACTION_DESIRE_MODERATE, npcTarget - end - end - end - end - - -- If we're pushing or defending a lane and can hit 3+ creeps, go for it - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if ( #enemys+#creeps >= 3 ) - then - if (ManaPercentage>0.4) - then - for _,npcTarget in pairs( allys ) - do - if ( CanCast[abilityNumber]( npcTarget ) ) - then - return BOT_ACTION_DESIRE_MODERATE, npcTarget - end - end - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if(ManaPercentage>0.4 and HealthPercentage<=0.66) - then - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcBot )) - then - return BOT_ACTION_DESIRE_MODERATE, npcBot; - end - end - end - end - - -- If my mana is enough,use it - if ( npcBot:GetActiveMode() == BOT_MODE_LANING) - then - if(#enemys>=1 and CanCast[abilityNumber]( npcBot )) - then - if npcBot:GetMana() > npcBot:GetMaxMana() * 0.7 + AbilitiesReal[2]:GetManaCost() - then - npcBot:SetTarget(WeakestEnemy) - return BOT_ACTION_DESIRE_LOW,npcBot; - end - end - end - - -- If we're farming - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if ( #creeps >= 2 and CanCast[abilityNumber]( npcBot )) - then - if(ManaPercentage>0.5) - then - return BOT_ACTION_DESIRE_LOW,npcBot; - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -Consider[4]=function() - - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() or npcBot:HasModifier("modifier_ice_blast") or not npcBot:WasRecentlyDamagedByAnyHero(1.5) then - return BOT_ACTION_DESIRE_NONE - end - - if HealthPercentage <= 0.3 or health <= 370 + npcBot:GetLevel() * 3 then - return BOT_ACTION_DESIRE_HIGH - end - if HealthPercentage <= 0.5 and fun1:IsSeverelyDisabled(npcBot) and not AbilitiesReal[2]:IsFullyCastable() then - return BOT_ACTION_DESIRE_HIGH - end - - return BOT_ACTION_DESIRE_NONE -end - -AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) - -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - attackRange = npcBot:GetAttackRange() - health = npcBot:GetHealth() - healthPercent = AbilityExtensions:GetHealthPercent(npcBot) - mana = npcBot:GetMana() - manaPercent = AbilityExtensions:GetManaPercent(npcBot) - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_arc_warden.mira b/mira/ability_item_usage_arc_warden.mira deleted file mode 100644 index 9a9b9b4..0000000 --- a/mira/ability_item_usage_arc_warden.mira +++ /dev/null @@ -1,562 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.1 NewStructure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -if GetBot():IsInvulnerable() or not GetBot():IsHero() or not string.find(GetBot():GetUnitName(), "hero") or GetBot():IsIllusion() then - return; -end - -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local AbilityExtensions = require(GetScriptDirectory().."/util/AbilityAbstraction") -local A = require(GetScriptDirectory().."/util/MiraDota") - -local debugmode=false -local npcBot = GetBot() -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - - - -local AbilityToLevelUp= -{ - Abilities[3], - Abilities[1], - Abilities[1], - Abilities[2], - Abilities[1], - Abilities[4], - Abilities[1], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - Abilities[4], - Abilities[2], - Abilities[2], - "talent", - Abilities[2], - "nil", - Abilities[4], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[3] - end, - function() - return Talents[6] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -function CanCast1(npcTarget) - if(npcTarget==nil or npcTarget:CanBeSeen()==false) - then - return utility.NCanCast(npcTarget) - end - - local enemys = npcTarget:GetNearbyCreeps(150,false) - local enemys2 = npcTarget:GetNearbyHeroes(150,false, BOT_MODE_NONE) - - if(enemys~=nil and enemys2~=nil and #enemys==0 and #enemys2==0) - then - return utility.NCanCast(npcTarget) - end - - return utility.NCanCast(npcTarget) -end - -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast={CanCast1,utility.NCanCast,utility.NCanCast,utility.UCanCast} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -local health -local maxHealth -local healthPercent -local mana -local maxMana -local manaPercent - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() or npcBot:GetMana() < ability:GetManaCost() or not ability:IsCooldownReady() then - -- tempest double doesn't check ability:IsFullyCastable(), so manual check is required here - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = A.Dota.GetNearbyHeroes(npcBot, CastRange+300, true) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy; - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - local enemys2 = npcBot:GetNearbyHeroes( 400, true, BOT_MODE_NONE ); - --[[ If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( (npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH) or #enemys2>0) - then - for _,npcEnemy in pairs( enemys ) - do - if ( (npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) and CanCast[abilityNumber]( npcEnemy )) or GetUnitToUnitDistance(npcBot,npcEnemy)<400) - then - return BOT_ACTION_DESIRE_HIGH, npcEnemy; - end - end - end]] - - -- If my mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if(HealthPercentage>0.6 and (ManaPercentage>0.6 or npcBot:GetMana()>ComboMana)) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - return BOT_ACTION_DESIRE_LOW,WeakestEnemy; - end - end - end - end - - -- If we're farming and can hit 2+ creeps and kill 1+ - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if ( #creeps >=1 ) - then - if(npcBot:GetMana()>ComboMana*2 and CanCast[abilityNumber](WeakestCreep)) - then - return BOT_ACTION_DESIRE_LOW, WeakestCreep; - end - end - end - - -- If we're pushing or defending a lane - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if ( #enemys>=1) - then - if (ManaPercentage>0.5 or npcBot:GetMana()>ComboMana) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy )and GetUnitToUnitDistance(npcBot,WeakestEnemy)< CastRange + 75*#allys ) - then - return BOT_ACTION_DESIRE_LOW, WeakestEnemy; - end - end - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -Consider[2]=function() - - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() or npcBot:GetMana() < ability:GetManaCost() or not ability:IsCooldownReady() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local Radius = ability:GetAOERadius() - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - local towers = npcBot:GetNearbyTowers(CastRange+300,false) - - -------------------------------------- - -- Mode based usage - -------------------------------------- - - --protect myself - local enemys2 = npcBot:GetNearbyHeroes( 400, true, BOT_MODE_NONE ); - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH or #enemys2>0) - then - for _,npcEnemy in pairs( enemys ) - do - if ( npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) and CanCast[abilityNumber]( npcEnemy ) or GetUnitToUnitDistance(npcBot,npcEnemy)<400) - then - return BOT_ACTION_DESIRE_HIGH, utility.GetUnitsTowardsLocation(npcEnemy,npcBot,Radius); - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK) - then - local locationAoE = npcBot:FindAoELocation( false, true, npcBot:GetLocation(), CastRange, Radius, 0, 0 ); - if ( locationAoE.count >= 2 ) then - return BOT_ACTION_DESIRE_LOW, locationAoE.targetloc; - end - - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) ) - then - return BOT_ACTION_DESIRE_HIGH, utility.GetUnitsTowardsLocation(npcBot,npcEnemy,Radius); - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -Consider[3]=function() - local abilityNumber=3 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() or npcBot:GetMana() < ability:GetManaCost() or not ability:IsCooldownReady() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local Radius = ability:GetAOERadius(); - local CastPoint = ability:GetCastPoint(); - local Delay = ability:GetSpecialValueFloat("activation_delay"); - local searchRadius = ability:GetSpecialValueInt "search_radius" or 375 - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(1600,true,BOT_MODE_NONE) - local vulnerableEnemy = A.Linq.Filter(enemys, A.Hero.MayNotBeIllusion):First(CanCast[abilityNumber]) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(1600,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy:GetExtrapolatedLocation(CastPoint+Delay); - end - end - end - end - - -------------------------------------- - -- Mode based usage - -------------------------------------- - local enemys2 = npcBot:GetNearbyHeroes( 400, true, BOT_MODE_NONE ); - - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if ManaPercentage>0.7 or ManaPercentage >= 0.55 and ability:GetLevel() >= 3 - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - return BOT_ACTION_DESIRE_LOW,utility.GetUnitsTowardsLocation(npcBot,WeakestEnemy,GetUnitToUnitDistance(npcBot,WeakestEnemy)+300) - end - end - end - end - local manaLeft = mana-ability:GetManaCost() - if npcBot:GetActiveMode() == BOT_MODE_LANING then - if manaLeft >= 0.7 * maxMana or manaLeft >= 0.55 * maxMana then - if vulnerableEnemy then - local enemyFriends = vulnerableEnemy:GetNearbyCreeps(searchRadius + vulnerableEnemy+GetBoundingRadius() + 128):Count { t -> - A.Unit.GetHealthPercent(t) >= 0.3 - } - if enemyFriends == 1 then - return BOT_ACTION_DESIRE_LOW, vulnerableEnemy:GetExtrapolatedLocation(CastPoint+Delay) - elif enemyFriends == 0 then - return BOT_ACTION_DESIRE_MODERATE+0.15, vulnerableEnemy:GetExtrapolatedLocation(CastPoint+Delay) - end - end - end - end - - - -- If we're farming and can hit 2+ creeps and kill 1+ - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if #creeps >= 2 and ability:GetLevel() >= 3 - then - if CreepHealth<=WeakestCreep:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) and manaLeft >= 0.75 * maxMana - then - return BOT_ACTION_DESIRE_LOW, WeakestCreep:GetExtrapolatedLocation(CastPoint+Delay); - end - end - end - - -- If we're pushing or defending a lane - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if ( #enemys>=1) - then - if (manaLeft >= 0.65 * maxMana and npcBot:GetMana()>ComboMana and ability:GetLevel()>=4) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy )and GetUnitToUnitDistance(npcBot,WeakestEnemy)< CastRange + 75*#allys ) - then - return BOT_ACTION_DESIRE_LOW, WeakestEnemy:GetExtrapolatedLocation(CastPoint+Delay); - end - end - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint+Delay, 0 ); - if ( locationAoE.count >= 2 ) then - return BOT_ACTION_DESIRE_LOW, locationAoE.targetloc; - end - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy:GetExtrapolatedLocation(CastPoint+Delay); - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -Consider[4]=function() - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() or AbilityExtensions:CannotTeleport(npcBot) or AbilityExtensions:IsTempestDouble(npcBot) then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = 0 - local Damage = 0 - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(800,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(800,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - - -- Stop making a huge bounty for the enemy - if (npcBot:GetHealth() <= 450 or HealthPercentage <= 0.3) and (npcBot:WasRecentlyDamagedByAnyHero(1.5) or AbilityExtensions:CanHardlyMove(npcBot) or AbilityExtensions:CannotTeleport(npcBot)) and not AbilityExtensions:Outnumber(npcBot, allys, enemys) then - return 0 - end - - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1000, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 ) - then - return BOT_ACTION_DESIRE_HIGH - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - local enemys2 = npcBot:GetNearbyHeroes( 400, true, BOT_MODE_NONE ); - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH or #enemys2>0) - then - for _,npcEnemy in pairs( enemys ) - do - if ( npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) and CanCast[abilityNumber]( npcEnemy ) or GetUnitToUnitDistance(npcBot,npcEnemy)<400) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end -AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) - -function AbilityUsageThink() - if npcBot == nil then npcBot = GetBot(); end - - health = npcBot:GetHealth() - maxHealth = npcBot:GetMaxHealth() - healthPercent = AbilityExtensions:GetHealthPercent(npcBot) - mana = npcBot:GetMana() - maxMana = npcBot:GetMaxMana() - manaPercent = AbilityExtensions:GetManaPercent(npcBot) - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_axe.mira b/mira/ability_item_usage_axe.mira deleted file mode 100644 index 083ced5..0000000 --- a/mira/ability_item_usage_axe.mira +++ /dev/null @@ -1,449 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.1 NewStructure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") -local ItemUsage = require(GetScriptDirectory().."/util/ItemUsage-New") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[2], - Abilities[3], - Abilities[3], - Abilities[1], - Abilities[3], - Abilities[4], - Abilities[3], - Abilities[1], - Abilities[1], - "talent", - Abilities[1], - Abilities[4], - Abilities[2], - Abilities[2], - "talent", - Abilities[2], - "nil", - Abilities[4], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[3] - end, - function() - return Talents[6] - end, - function() - return Talents[8] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast = { {t -> fun1:StunCanCast(t, AbilitiesReal[1], true, false, false, false)} - , fun1.NormalCanCastFunction - , utility.NCanCast - , {t -> fun1:NormalCanCast(t, true, DAMAGE_TYPE_PURE, true, true, true)} -} - -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = 0 - local Damage = ability:GetAbilityDamage() - local Radius = ability:GetAOERadius()-50 - local CastPoint = ability:GetCastPoint() - - local blink = fun1:GetAvailableBlink(npcBot) - if(blink~=nil and blink:IsFullyCastable()) - then - CastRange=CastRange+1200 - if(npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), CastRange, Radius, 0, 10000 ) - if ( locationAoE.count >= 2 ) - then - ItemUsage.UseItemOnLocation(npcBot, blink, locationAoE.targetloc) - return 0 - end - end - end - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ) - local enemys = npcBot:GetNearbyHeroes(Radius,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(Radius,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- Check for a channeling enemy - for _,npcEnemy in pairs( enemys ) - do - if ( npcEnemy:IsChanneling() ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or GetUnitToUnitDistance(npcBot,WeakestEnemy) <= Radius-CastPoint* WeakestEnemy:GetCurrentMovementSpeed()) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - if((npcBot:WasRecentlyDamagedByAnyHero(2) and #enemys>=1) or #enemys >=2) - then - for _,npcEnemy in pairs( enemys ) - do - return BOT_ACTION_DESIRE_HIGH - end - end - - -- If my mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if npcBot:GetMana() >= npcBot:GetMaxMana() * 0.4 + ability:GetManaCost() then - if (WeakestEnemy~=nil) - then - if(GetUnitToUnitDistance(npcBot,WeakestEnemy)=300 ) - then - if GetUnitToUnitDistance(npcBot,npcEnemy)<=1200+Radius and blink~=nil then - ItemUsage.UseItemOnLocation(npcBot, blink, npcEnemy:GetExtrapolatedLocation(CastPoint)) - return 0 - end - else - return BOT_ACTION_DESIRE_MODERATE - end - - end - end - - return BOT_ACTION_DESIRE_NONE - -end - -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = ability:GetCastRange() - local Damage = ability:GetAbilityDamage() - local CastPoint = ability:GetCastPoint() - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ) - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if CanCast[abilityNumber]( WeakestEnemy ) then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - npcBot:SetTarget(WeakestEnemy) - return BOT_ACTION_DESIRE_MODERATE,WeakestEnemy - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - for _,npcEnemy in pairs( enemys ) - do - if ( npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy)) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - end - - -- If my mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if((ManaPercentage>0.5 or npcBot:GetMana()>ComboMana)) - then - if (WeakestEnemy~=nil) - then - if CanCast[abilityNumber]( WeakestEnemy ) then - return BOT_ACTION_DESIRE_LOW,WeakestEnemy - end - end - end - end - - -- If we're farming and can hit 2+ creeps and kill 1+ - if npcBot:GetActiveMode() == BOT_MODE_FARM then - if ( #creeps >= 2 ) - then - if(CreepHealth<=WeakestCreep:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana) - then - return BOT_ACTION_DESIRE_LOW, WeakestCreep - end - end - end - - -- If we're pushing or defending a lane - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if ( #enemys>=1) - then - if (ManaPercentage>0.5 or npcBot:GetMana()>ComboMana) - then - if (WeakestEnemy~=nil) - then - if CanCast[abilityNumber]( WeakestEnemy )and GetUnitToUnitDistance(npcBot,WeakestEnemy)< CastRange + 75*#allys then - return BOT_ACTION_DESIRE_LOW, WeakestEnemy - end - end - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = fun1:GetTargetIfGood(npcBot) - - if ( npcEnemy ~= nil ) - then - if CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - - return BOT_ACTION_DESIRE_NONE - -end - -Consider[4]=function() - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = ability:GetCastRange() - local Damage = ability:GetAbilityDamage() - local function IsWeak(t) -> CanCast[4](t) and t:GetHealth() <= Damage - local CastPoint = ability:GetCastPoint() - local enemies, enemyIllusions = fun1:GetNearbyHeroes(npcBot, CastRange + 300):Filter(IsWeak):Partition { it -> - fun1:MayNotBeIllusion(npcBot, it) - } - - -- kill real enemies - if fun1:NotRetreating(npcBot) and #enemies == 0 then - if local blink = fun1:GetAvailableBlink(npcBot) then - if local target = fun1:GetNearbyNonIllusionHeroes(npcBot, CastRange + 1200):First(IsWeak) then - ItemUsage.UseItemOnLocation(npcBot, blink, target:GetLocation()) - return 0 - end - end - end - - if local target = fun1:GetNearbyNonIllusionHeroes(npcBot, CastRange+300):Filter(IsWeak):Min { it -> - GetUnitToUnitDistance(npcBot, it) - } then - local dis = GetUnitToUnitDistance(npcBot, target) - if fun1:NotRetreating(npcBot) then - if local blink = fun1:GetAvailableBlink(npcBot); blink and dis > CastRange + 150 then - ItemUsage.UseItemOnLocation(npcBot, blink, target:GetLocation()) - return 0 - end - return BOT_ACTION_DESIRE_HIGH, target - else - if dis <= CastRange then - return BOT_ACTION_DESIRE_HIGH, target - end - end - end - - -- kill illusions - if #enemies == 0 and fun1:NotRetreating(npcBot) then - if local target = enemyIllusions:First() then - if fun1:GetHealthPercent(npcBot) <= 0.5 and not npcBot:HasModifier "modifier_axe_culling_blade_boost" and target and npcBot:GetMana() > npcBot:GetMaxMana() * 0.4 + ability:GetManaCost() then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - end - - return BOT_ACTION_DESIRE_NONE -end - - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) - -local callLosingTarget -local cullingBladeTarget - -function AbilityUsageThink() - -- Check if we're already using an ability - if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then - if npcBot:IsCastingAbility() then - if npcBot:GetCurrentActiveAbility() == AbilitiesReal[1] then - if not fun1:IsFarmingOrPushing(npcBot) then - local nearbyEnemies = fun1:GetNearbyHeroes(npcBot, AbilitiesReal[1]:GetAOERadius() + 90):Filter(CanCast[1]) - if #nearbyEnemies == 0 then - if callLosingTarget == nil then - callLosingTarget = DotaTime() - elseif DotaTime() - callLosingTarget > 0.15 then - npcBot:Action_ClearActions(true) - end - return - end - end - else - -- if npcBot:GetCurrentActiveAbility() == AbilitiesReal[4] and cullingBladeTarget then - -- if cullingBladeTarget:CanBeSeen() and cullingBladeTarget:GetHealth() > AbilitiesReal[4]:GetSpecialValueInt "kill_threshold" then - -- print(cullingBladeTarget:GetHealth()) - -- npcBot:Action_ClearActions(true) - -- end - -- end - end - end - callLosingTarget = nil - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - local index, target = ability_item_usage_generic.UseAbility(AbilitiesReal,cast) - if index == 4 then - cullingBladeTarget = target - end -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_bane.mira b/mira/ability_item_usage_bane.mira deleted file mode 100644 index 3e11d85..0000000 --- a/mira/ability_item_usage_bane.mira +++ /dev/null @@ -1,621 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.1 NewStructure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local AbilityExtensions = require(GetScriptDirectory().."/util/AbilityAbstraction") -local role = require(GetScriptDirectory() .. "/util/RoleUtility") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[2], - Abilities[3], - Abilities[2], - Abilities[1], - Abilities[2], - Abilities[4], - Abilities[2], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - Abilities[4], - Abilities[1], - Abilities[1], - "talent", - Abilities[1], - "nil", - Abilities[4], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[2] - end, - function() - return Talents[4] - end, - function() - return Talents[6] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} - - -local CanCast = {} -CanCast[1] = function(t) - return AbilityExtensions:NormalCanCast(t, false, DAMAGE_TYPE_MAGICAL, false, true) -end -CanCast[2] = function(t) - return AbilityExtensions:NormalCanCast(t, true, DAMAGE_TYPE_PURE, false, true) and not AbilityExtensions:HasAbilityRetargetModifier(t) and not (t:HasModifier("modifier_item_blade_mail") and AbilityExtensions:IsRetreating(npcBot)) -end -CanCast[3] = {t -> fun1:StunCanCast(t, AbilitiesReal[3], false, true, true, false) and not fun1:DontControlAgain(t)} -CanCast[4] = {t -> fun1:StunCanCast(t, AbilitiesReal[4], true, true, true, false) and not fun1:DontControlAgain(t)} - -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -local health -local maxHealth -local healthPercentage -local mana -local maxMana -local manaPercentage - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1000, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 ) - then - - local npcMostDangerousEnemy = nil; - local nMostDangerousDamage = 0; - - for _,npcEnemy in pairs( enemys ) - do - if ( CanCast[abilityNumber]( npcEnemy )) - then - local Damage2 = npcEnemy:GetEstimatedDamageToTarget( false, npcBot, 3.0, DAMAGE_TYPE_ALL ); - if ( Damage2 > nMostDangerousDamage ) - then - nMostDangerousDamage = Damage2; - npcMostDangerousEnemy = npcEnemy; - end - end - end - - if ( npcMostDangerousEnemy ~= nil ) - then - return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy; - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - local enemys2 = npcBot:GetNearbyHeroes( 500, true, BOT_MODE_NONE ); - if(npcBot:WasRecentlyDamagedByAnyHero(5)) - then - for _,npcEnemy in pairs( enemys2 ) - do - if ( CanCast[abilityNumber]( npcEnemy ) ) - then - return BOT_ACTION_DESIRE_HIGH, npcEnemy - end - end - end - - -- -- If my mana is enough,use it at enemy - -- if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - -- then - -- if((ManaPercentage>0.4 or npcBot:GetMana()>ComboMana)) - -- then - -- if (WeakestEnemy~=nil) - -- then - -- if ( CanCast[abilityNumber]( WeakestEnemy ) and (role.IsCarry(WeakestEnemy:GetUnitName()) or #enemys==1)) - -- then - -- return BOT_ACTION_DESIRE_LOW,WeakestEnemy; - -- end - -- end - -- end - -- end - - -- If we're pushing or defending a lane - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if ( #enemys>=1) - then - if (ManaPercentage>0.5 or npcBot:GetMana()>ComboMana) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy )and GetUnitToUnitDistance(npcBot,WeakestEnemy)< CastRange + 75*#allys ) - then - return BOT_ACTION_DESIRE_LOW, WeakestEnemy; - end - end - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - --- brain sap -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local abilityLevel = ability:GetLevel() - local radius = ability:GetAOERadius()-100 - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local damage = ability:GetAbilityDamage() - local castRange = ability:GetCastRange() - local enemyHeroes = fun1:GetNearbyHeroes(npcBot, castRange + 200, true) - local enemies, enemyIllusions = enemyHeroes:Partition { it -> - fun1:MayNotBeIllusion(npcBot, it) - } - local allies = fun1:GetNearbyNonIllusionHeroes(npcBot, 900, false) - local nearbyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, castRange + 150, true) - - if fun1:NotRetreating(npcBot) then - if local target = enemies:Filter(CanCast[2]):Filter { it -> - it:GetHealth() <= it:GetActualIncomingDamage(damage, DAMAGE_TYPE_PURE) or it:GetHealth() <= it:GetActualIncomingDamage(GetComboDamage(), DAMAGE_TYPE_PURE) and mana > ComboMana - }:Max { it -> it:GetHealth() } then - return BOT_ACTION_DESIRE_HIGH, target - end - end - - if healthPercentage <= 0.3 then - if local target = enemyIllusions:First() then - return BOT_ACTION_DESIRE_HIGH, target - end - end - - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating - if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then - if npcBot:WasRecentlyDamagedByAnyHero(2) then - if local target = enemyIllusions:First() then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - if local target = enemies:First { it -> - CanCast[2](it) and npcBot:WasRecentlyDamagedByHero(it, 2) and GetUnitToUnitDistance(npcBot, it) <= castRange + it:GetBoundingRadius() - } then - return BOT_ACTION_DESIRE_HIGH, target - end - if npcBot:WasRecentlyDamagedByAnyHero(2) then - if local target = nearbyCreeps:First() then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - end - - -- If my mana is enough,use it at enemy - if npcBot:GetActiveMode() == BOT_MODE_LANING then - if (manaPercentage > healthPercentage or mana > ComboMana) and abilityLevel >= 2 then - if local target = enemies:SortByMinFirst { it -> - it:GetHealth() - }:First() then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - end - - -- If we're farming and can hit 2+ creeps and kill 1+ - if fun1:IsFarmingOrPushing(npcBot) and #enemies == 0 then - if mana > maxMana * 0.7 + manaCost or manaPercentage > healthPercentage + 0.2 then - if local target = nearbyCreeps:SortByMinFirst { it -> - it:GetHealth() - }:First() then - return BOT_ACTION_DESIRE_MODERATE - 0.1, target - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - if local target = fun1:GetTargetIfGood(npcBot) then - if CanCast[2](target) and GetUnitToUnitDistance(npcBot, target) < castRange + target:GetBoundingRadius() + 50 * #allies then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - end - - return BOT_ACTION_DESIRE_NONE - -end - -Consider[3]=function() - local abilityNumber = 3 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local abilityLevel = ability:GetLevel() - local radius = ability:GetAOERadius()-100 - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local damage = ability:GetAbilityDamage() - local castRange = ability:GetCastRange() - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 240) - local allies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 240, false) - - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- Check for a channeling enemy - if local target = enemies:First { it -> - fun1:IsChannelingBreakWorthAbility(it) and CanCast[abilityNumber](it) - } then - return BOT_ACTION_DESIRE_HIGH, target - end - - -- If we're in a teamfight, use it on the scariest enemy - if local target = enemies:Filter { it -> - CanCast[abilityNumber](it) and not fun1:IsOrGoingToBeSeverelyDisabled(it) and #allies <= 1 - }:Max { it -> - it:GetEstimatedDamageToTarget(false, npcBot, duration, DAMAGE_TYPE_ALL) or 0 - } then - return BOT_ACTION_DESIRE_HIGH, target - end - - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if fun1:IsRetreating(npcBot) then - if local target = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 120):First { it -> - CanCast[3](it) and not fun1:IsOrGoingToBeSeverelyDisabled(it) - } then - return BOT_ACTION_DESIRE_HIGH, target - end - end - - -- If we're going after someone - if fun1:IsAttackingEnemies(npcBot) then - local npcEnemy = fun1:GetTargetIfGood(npcBot) - local allys2 = fun1:GetNearbyNonIllusionHeroes(npcBot, 600) - local allys3 = fun1:GetNearbyNonIllusionHeroes(npcBot, 1000) - if npcEnemy and #allys2 < #allys3 then - if CanCast[abilityNumber](npcEnemy) and not fun1:IsOrGoingToBeSeverelyDisabled(npcEnemy) and GetUnitToUnitDistance(npcBot, npcEnemy) < castRange + npcEnemy:GetBoundingRadius() then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - - if local target = allies:First { t1 -> - AbilityExtensions:IsOrGoingToBeSeverelyDisabled(t1) and not t1:IsChanneling() and not fun1:DontInterruptAlly(t1) - } then - return BOT_ACTION_DESIRE_MODERATE, target - end - if local target = allies:First { t1 -> - fun1:Any(fun1:GetIncomingDodgeWorthProjectiles(t1)) { - t -> GetUnitToLocationDistance(it, t.location) <= 400 and not t.is_attack and not fun1:DontInterruptAlly(t) - } - } then - return BOT_ACTION_DESIRE_MODERATE, target - end - - return BOT_ACTION_DESIRE_NONE - -end - -Consider[4]=function() - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local enemys2= npcBot:GetNearbyHeroes(CastRange-300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - local abilityLevel = ability:GetLevel() - local radius = ability:GetAOERadius()-100 - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local damage = ability:GetAbilityDamage() - local castRange = ability:GetCastRange() - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- Check for a channeling enemy - for _,npcEnemy in pairs( enemys ) - do - if ( npcEnemy:IsChanneling() and CanCast[abilityNumber]( npcEnemy ) and not AbilityExtensions:HasAbilityRetargetModifier(npcEnemy)) - then - return BOT_ACTION_DESIRE_HIGH, npcEnemy - end - end - - if(#enemys2>0) - then - return 0 - end - - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) and not enemyDisabled(WeakestEnemy) and #enemys <= 2) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy; - end - end - end - end - - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1000, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 ) - then - - local npcMostDangerousEnemy = nil; - local nMostDangerousDamage = 0; - - for _,npcEnemy in pairs( enemys ) - do - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy)) - then - local Damage2 = npcEnemy:GetEstimatedDamageToTarget( false, npcBot, 3.0, DAMAGE_TYPE_ALL ); - if ( Damage2 > nMostDangerousDamage ) - then - nMostDangerousDamage = Damage2; - npcMostDangerousEnemy = npcEnemy; - end - end - end - - if ( npcMostDangerousEnemy ~= nil ) - then - return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy; - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - --[[if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - for _,npcEnemy in pairs( enemys ) - do - if ( npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy)) - then - return BOT_ACTION_DESIRE_HIGH, npcEnemy; - end - end - end - end]] - - if AbilityExtensions:IsRetreating(npcBot) and #enemys == 1 and not AbilityExtensions:HasAbilityRetargetModifier(enemys[1]) then - return BOT_ACTION_DESIRE_HIGH, enemys[1] - end - - if fun1:IsAttackingEnemies(npcBot) then - if local target = AbilityExtensions:GetTargetIfGood(npcBot) then - if CanCast[abilityNumber](target) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - --- nightmare end -Consider[5]=function() - local ability = AbilitiesReal[5] - if not ability:IsFullyCastable() or ability:IsHidden() then - return 0 - end - - local enemies = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, 1200, true, BOT_MODE_NONE) - local nightmaredEnemies = AbilityExtensions:Filter(enemies, function(t) return t:HasModifier("modifier_bane_nightmare") end) - local friends = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, 1200, false, BOT_MODE_NONE) - local nightmaredFriends = AbilityExtensions:Filter(friends, function(t) return t:HasModifier("modifier_bane_nightmare") end) - if #nightmaredEnemies ~= 0 then - if #enemies == 1 and #friends >= 2 and AbilityExtensions:GetModifierRemainingDuration(nightmaredEnemies[1], "modifier_bane_nightmare") <= 4 - or nightmaredEnemies:All { it -> fun1:GetHealthPercent(it) <= 0.3 and fun1:GetModifierRemainingDuration(it, "modifier_bane_nightmare") <= 4 } - and friends:All { it -> fun1:GetHealthPercent(it) >= 0.5 } then - return BOT_ACTION_DESIRE_HIGH - end - end - if #nightmaredFriends ~= 0 then - if AbilityExtensions:All(nightmaredFriends, function(t) - return AbilityExtensions:GetHealthPercent(t) >= 0.3 - end) or AbilityExtensions:All(nightmaredFriends) {t -> #fun1:GetIncomingDodgeWorthProjectiles(t) == 0} and #enemies == 0 then - return BOT_ACTION_DESIRE_HIGH - end - end - return BOT_ACTION_DESIRE_NONE -end - -AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) - -local drainSnapTarget -local fiendsGripTarget - -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - if npcBot:IsCastingAbility() then - if npcBot:GetCurrentActiveAbility() == AbilitiesReal[2] then - if drainSnapTarget and AbilityExtensions:IsGoodTarget(drainSnapTarget) and AbilityExtensions:HasAbilityRetargetModifier(drainSnapTarget) then - npcBot:Action_ClearActions(true) - end - end - if npcBot:GetCurrentActiveAbility() == AbilitiesReal[4] and not npcBot:IsChanneling() then - if fiendsGripTarget and AbilityExtensions:IsGoodTarget(drainSnapTarget) and AbilityExtensions:HasAbilityRetargetModifier(fiendsGripTarget) then - npcBot:Action_ClearActions(true) - end - end - end - return - end - - health = npcBot:GetHealth() - maxHealth = npcBot:GetMaxHealth() - healthPercentage = health / maxHealth - mana = npcBot:GetMana() - maxMana = npcBot:GetMaxMana() - manaPercentage = mana / maxMana - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - local index, target = ability_item_usage_generic.UseAbility(AbilitiesReal,cast) - if index == 2 then - drainSnapTarget = target - elseif index == 4 then - fiendsGripTarget = target - end -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_bounty_hunter.mira b/mira/ability_item_usage_bounty_hunter.mira deleted file mode 100644 index db03865..0000000 --- a/mira/ability_item_usage_bounty_hunter.mira +++ /dev/null @@ -1,397 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.3 New Structure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") -local A = require(GetScriptDirectory().."/util/MiraDota") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[3], - Abilities[2], - Abilities[1], - Abilities[1], - Abilities[1], - Abilities[4], - Abilities[1], - Abilities[3], - Abilities[3], - "talent", - Abilities[2], - Abilities[4], - Abilities[2], - Abilities[2], - "talent", - Abilities[3], - "nil", - Abilities[4], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[3] - end, - function() - return Talents[5] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast={utility.NCanCast,utility.NCanCast,utility.NCanCast,utility.UCanCast} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -Consider[1]=function() --Target Ability Example - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local Radius = ability:GetSpecialValueInt( "bounce_aoe" ); - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(Radius,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- Check for a channeling enemy - for _,npcEnemy in pairs( enemys ) - do - if ( npcEnemy:IsChanneling() and CanCast[abilityNumber]( npcEnemy )) - then - if(GetUnitToUnitDistance(npcBot,npcEnemy)ComboMana)) - then - if(GetUnitToUnitDistance(npcBot,WeakestEnemy)= 2 ) - then - local trackedEnemy=0; - for k,npcEnemy in pairs(enemys) do - if npcEnemy:HasModifier("modifier_bounty_hunter_track") then - trackedEnemy=trackedEnemy+1; - end - end - - if(trackedEnemy>=2) - then - if(creeps[1]~=nil) - then - return BOT_ACTION_DESIRE_HIGH, creeps[1]; - elseif(enemys[1]~=nil) - then - return BOT_ACTION_DESIRE_HIGH, enemys[1]; - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - local enemys2 = npcBot:GetNearbyHeroes( 400, true, BOT_MODE_NONE ); - --[[If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( (npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH) or #enemys2>0) - then - for _,npcEnemy in pairs( enemys ) - do - if ( (npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) and CanCast[abilityNumber]( npcEnemy )) or GetUnitToUnitDistance(npcBot,npcEnemy)<400) - then - if(GetUnitToUnitDistance(npcBot,npcEnemy)=1) - then - if (ManaPercentage>0.5 or npcBot:GetMana()>ComboMana) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(GetUnitToUnitDistance(npcBot,WeakestEnemy) - if local target = npcBot:GetAttackTarget() then - if not target:IsHero() and fun1:GetNearbyLaneCreeps(npcBot, 700, false) then - if target:GetActualIncomingDamage(npcBot:GetAttackDamage(), DAMAGE_TYPE_PHYSICAL) >= target:GetHealth() then - return false - end - end - end - return true -} - -Consider[3]=function() - local abilityNumber=3 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = 0 - local Damage = ability:GetAbilityDamage() - local Radius = ability:GetAOERadius() - local CastPoint = ability:GetCastPoint() - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_MODERATE ) - then - if ( npcBot:WasRecentlyDamagedByAnyHero( 2.0 ) ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = fun1:GetTargetIfGood(npcBot) - if ( npcEnemy ~= nil ) - then - if (GetUnitToUnitDistance(npcBot,npcEnemy)<=2000) - then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - - return BOT_ACTION_DESIRE_NONE -end - -local function HasTrackModifierPenalty(t) - return fun1:GetModifierRemainingDuration(t, "modifier_bounty_hunter_track") <= 5 and 1 or 0.5 -end - - -Consider[4]=function() - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = Clamp(ability:GetCastRange(), 0, 1599) - local realEnemies = fun1:GetNearbyNonIllusionHeroes(npcBot, CastRange):Filter { it -> - fun1:SpellCanCast(it) and it:IsHero() and fun1:MayNotBeIllusion(npcBot, it) - and A.Unit.IsNotCreepHero(it) - }:Map { it -> - { it, it:GetHealth() * HasTrackModifierPenalty(it) } - }:SortByMinFirst { it -> it[2] } - if local t = realEnemies:First() then - local target = t[1] - if fun1:IsFarmingOrPushing(npcBot) or npcBot:GetActiveMode() == BOT_MODE_LANING then - if ManaPercentage >= 0.7 then - -- realEnemies:ForEach { t -> print("bh 1 "..t[1]:GetUnitName())} - return BOT_ACTION_DESIRE_MODERATE, target - end - if fun1:GetHealthPercent(target) <= 0.5 then - -- realEnemies:ForEach { t -> print("bh 2 "..t[1]:GetUnitName())} - return BOT_ACTION_DESIRE_HIGH, target - end - else - return BOT_ACTION_DESIRE_HIGH, target - end - end - if local target = fun1:GetTargetIfGood(npcBot); target and target:GetTeam() ~= npcBot:GetTeam() - and A.Unit.IsNotCreepHero(target) - then - -- print("bh 3 "..target:GetUnitName()) - return BOT_ACTION_DESIRE_HIGH, target - end - - return BOT_ACTION_DESIRE_NONE -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) - -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_bristleback.mira b/mira/ability_item_usage_bristleback.mira deleted file mode 100644 index 682944a..0000000 --- a/mira/ability_item_usage_bristleback.mira +++ /dev/null @@ -1,364 +0,0 @@ - - ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.5d --- Author: adamqqq Email:adamqqq@163.com --- Contributor: zmcmcc Email:mengzhang@utexas.edu ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - - -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents = {} -local Abilities = {} -local AbilitiesReal = {} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[2], - Abilities[3], - Abilities[2], - Abilities[1], - Abilities[2], - Abilities[5], - Abilities[2], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - Abilities[5], - Abilities[1], - Abilities[1], - "talent", - Abilities[1], - "nil", - Abilities[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} -local TalentTree={ - function() - return Talents[2] - end, - function() - return Talents[3] - end, - function() - return Talents[5] - end, - function() - return Talents[7] - end -} - -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) -end - -local cast = { - Desire = {}, - Target = {}, - Type = {} -} -local Consider = {} - -local CanCast = { - fun1.NormalCanCastFunction, - fun1.PhysicalCanCastFunction, - { _ -> true }, - fun1.NormalCanCastFunction, - { _ -> true }, -} - -local attackRange -local health -local maxHealth -local healthPercent -local mana -local maxMana -local manaPercent -local allEnemies -local enemies -local enemyCount -local friends -local friendCount -local enemyCreeps -local friendCreeps -local neutralCreeps -local tower - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - - -Consider[1] = function() - local abilityNumber = 1 - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local castRange = ability:GetCastRange() - - if fun1:HasScepter(npcBot) then - local enemies = npcBot:GetNearbyHeroes(CastRange, true, BOT_MODE_NONE) - enemies = fun1:Filter(enemies, function(t) - local m = t:GetModifierByName("modifier_bristleback_viscous_nasal_goo") - if m ~= -1 and t:GetModifierStackCount(m) >= 6 and t:GetModifierRemainingDuration(m) >= 2.5 then - return false - end - return true - end) - if (fun1:IsAttackingEnemies(npcBot) or fun1:IsRetreating(npcBot)) and npcBot:GetMana() >= 120 then - if #enemies == 0 then - return 0 - end - return #enemies >= 2 and fun1:GetManaPercent(npcBot) >= 0.3 - or #enemies == 1 and fun1:GetManaPercent(npcBot) >= 0.6 - or npcBot:WasRecentlyDamagedByAnyHero(1.5) - end - return 0 - end - - if friends:Count { t -> fun1:CanBeEngaged(t) } >= 2 then - if local target = enemies:Filter(CanCast[1]) - :Max { t -> t:GetEstimatedDamageToTarget(false, npcBot, 3, DAMAGE_TYPE_ALL) } then - return BOT_ACTION_DESIRE_HIGH, target - end - end - if fun1:NotRetreating(npcBot) and not fun1:IsLaning(npcBot) then - if local target = enemies:Max { t -> t:GetHealth() * if fun1:IsSeverelyDisabledOrSlowed(t) { 1.5 } else { 1 } } then - return BOT_ACTION_DESIRE_HIGH, target - end - end - if fun1:IsAttackingEnemies(npcBot) then - if local target = fun1:GetTargetIfGood(npcBot) then - if CanCast[1](target) and GetUnitToUnitDistance(npcBot, target) < castRange then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - end - - return BOT_ACTION_DESIRE_NONE -end - - - -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = 0 - local Damage = ability:GetAbilityDamage() - local Radius = ability:GetAOERadius() - 50 - local CastPoint = ability:GetCastPoint() - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(Radius,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(Radius,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_PHYSICAL) or WeakestEnemy:HasModifier("modifier_bristleback_viscous_nasal_goo" )) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - if((npcBot:WasRecentlyDamagedByAnyHero(2) and #enemys>=1) or #enemys >=2) - then - for _,npcEnemy in pairs( enemys ) - do - if ( CanCast[abilityNumber]( npcEnemy ) ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - - -- If my mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if((manaPercent>0.65 or npcBot:GetMana()>ComboMana)) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(GetUnitToUnitDistance(npcBot,WeakestEnemy)= 2 ) - then - if(WeakestCreep~=nil) - then - if(CreepHealth<=WeakestCreep:GetActualIncomingDamage(Damage,DAMAGE_TYPE_PHYSICAL) and (manaPercent>0.4 or npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_LOW - end - end - end - end - - --Last hit - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if(WeakestCreep~=nil) - then - if((manaPercent>0.5 or npcBot:GetMana()>ComboMana) and GetUnitToUnitDistance(npcBot,WeakestCreep) < Radius) - then - if(CreepHealth<=WeakestCreep:GetActualIncomingDamage(Damage,DAMAGE_TYPE_PHYSICAL)-20) - then - return BOT_ACTION_DESIRE_LOW - end - end - end - end - - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)<=Radius) - then - return BOT_ACTION_DESIRE_MODERATE,npcEnemy - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end --- hairball -Consider[4] = function() - local ability=AbilitiesReal[4] - - if not ability:IsFullyCastable() or ability:IsHidden() then - return BOT_ACTION_DESIRE_NONE - end - - local castRange = ability:GetCastRange() - local radius = ability:GetAOERadius() - 50 - local castPoint = ability:GetCastPoint() - - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, 1599) - local enemyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) - if enemyCount >= 2 then - local info = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), castRange, radius, castPoint, 10000) - if info.count >= enemyCount or info.count >= 3 then - return BOT_ACTION_DESIRE_HIGH, info.targetloc - end - end - if enemyCount == 1 then - return BOT_ACTION_DESIRE_MODERATE, fun1:FindAOELocationAtSingleTarget(npcBot, enemeis[1], castRange, radius, castPoint) - end - if enemyCount == 0 then - if fun1:IsFarmingOrPushing(npcBot) then - local info = npcBot:FindAoELocation(true, false, npcBot:GetLocation(), castRange, radius, castPoint, 10000) - if info.count >= 4 and mana >= 300 then - return BOT_ACTION_DESIRE_HIGH, info.targetloc - end - end - end - return 0 -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - if npcBot:IsChanneling() or npcBot:IsSilenced() then - return - end - ComboMana=GetComboMana() - - attackRange = npcBot:GetAttackRange() - health = npcBot:GetHealth() - maxHealth = npcBot:GetMaxHealth() - healthPercent = fun1:GetHealthPercent(npcBot) - mana = npcBot:GetMana() - maxMana = npcBot:GetMaxMana() - manaPercent = fun1:GetManaPercent(npcBot) - - allEnemies = fun1:GetNearbyHeroes(npcBot, 1200) - enemies = allEnemies:Filter { t -> fun1:MayNotBeIllusion(npcBot, t) } - enemyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) - friends = fun1:GetNearbyNonIllusionHeroes(npcBot, 1500, true) - friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 900) - friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - neutralCreeps = npcBot:GetNearbyNeutralCreeps(900) - tower = fun1:GetLaningTower(npcBot) - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end diff --git a/mira/ability_item_usage_chen.mira b/mira/ability_item_usage_chen.mira deleted file mode 100644 index 319dafc..0000000 --- a/mira/ability_item_usage_chen.mira +++ /dev/null @@ -1,553 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.3 New Structure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - - -local AbilityToLevelUp= -{ - Abilities[1], - Abilities[2], - Abilities[2], - Abilities[1], - Abilities[2], - Abilities[4], - Abilities[2], - Abilities[1], - Abilities[1], - "talent", - Abilities[3], - Abilities[4], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - "nil", - Abilities[4], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[2] - end, - function() - return Talents[3] - end, - function() - return Talents[6] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - - -local attackRange -local healthPercent -local mana -local manaPercent -local enemies -local realEnemies -local friends -local friendCount -local enemyCreeps -local friendCreeps -local neutralCreeps -local tower - -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider = {} -local CanCast = { { - t -> t:GetLevel() <= AbilitiesReal[2]:GetLevel() + 2 -},utility.NCanCast,utility.NCanCast,utility.UCanCast} - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = 0; - local CastPoint = ability:GetCastPoint(); - - local allys = fun1:GetNearbyHeroes(npcBot, 1200, false) - local enemys = fun1:GetNearbyHeroes(npcBot, CastRange+300, true) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = fun1:GetNearbyCreeps(npcBot, CastRange+300, true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - local enemys2 = fun1:GetNearbyCreeps(npcBot, 400, true) - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( (npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH) or #enemys2>0) - then - for _,npcEnemy in pairs( enemys ) - do - if ( (npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) and CanCast[abilityNumber]( npcEnemy )) or GetUnitToUnitDistance(npcBot,npcEnemy)<400) - then - return BOT_ACTION_DESIRE_HIGH, npcEnemy; - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - - -- if npcBot:GetActiveMode() ~= BOT_MODE_LANING - - return BOT_ACTION_DESIRE_NONE, 0; - -end - --- Consider[2]=function() --- local abilityNumber=2 --- -------------------------------------- --- -- Generic Variable Setting --- -------------------------------------- --- local ability=AbilitiesReal[abilityNumber]; - --- if not ability:IsFullyCastable() then --- return BOT_ACTION_DESIRE_NONE, 0; --- end - --- local CastRange = ability:GetCastRange(); --- --local Damage = (ability:GetSpecialValueInt("damage_max")+ability:GetSpecialValueInt("damage_min"))*0.5 --- local Heal = (ability:GetSpecialValueInt("heal_max")+ability:GetSpecialValueInt("heal_min"))*0.5 - --- local HeroHealth=10000 --- local CreepHealth=10000 --- local allys = npcBot:GetNearbyHeroes( CastRange+300, false, BOT_MODE_NONE ); --- local WeakestAlly,AllyHealth=utility.GetWeakestUnit(allys) --- local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) --- local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) --- local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) --- local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) --- -------------------------------------- --- -- Global high-priorty usage --- -------------------------------------- - --- -------------------------------------- --- -- Mode based usage --- -------------------------------------- --- -- If we're seriously retreating --- if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) --- then --- if ( HealthPercentage<=0.5 and npcBot:WasRecentlyDamagedByAnyHero(2.0)) --- then --- if ( CanCast[abilityNumber]( npcBot )) --- then --- return BOT_ACTION_DESIRE_HIGH, npcBot --- end --- end --- end - --- --teamfightUsing --- if( npcBot:GetActiveMode() == BOT_MODE_ROAM or --- npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or --- npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or --- npcBot:GetActiveMode() == BOT_MODE_ATTACK ) --- then --- if (WeakestAlly~=nil) --- then --- if(AllyHealth/WeakestAlly:GetMaxHealth()<0.3+0.2*ManaPercentage) --- then --- return BOT_ACTION_DESIRE_MODERATE,WeakestAlly --- end --- end - --- for _,npcTarget in pairs( allys ) --- do --- local enemys2 = npcTarget:GetNearbyHeroes(600,true,BOT_MODE_NONE) --- local healingFactor=0.2+#enemys2*0.05+0.2*ManaPercentage --- if(enemyDisabled(npcTarget)) --- then --- healingFactor=healingFactor+0.1 --- end - --- if(npcTarget:GetHealth()/npcTarget:GetMaxHealth()=0.3 then - for k,creep in pairs(creepsNeutral) do - if (IsGoodNeutralCreeps(creep) and holyPersuasionLevelLimit >= creep:GetLevel() or (creep:IsAncientCreep() and fun1:HasScepter(npcBot)) ) and CanCast[2](creep) and not creep:WasRecentlyDamagedByAnyHero(1.5) - then - return BOT_ACTION_DESIRE_HIGH, creep; - end - end - end - - local recallDesire, target = ConsiderRecall() - if recallDesire > 0 then - return recallDesire, target - end - - return BOT_ACTION_DESIRE_NONE -end - -function ConsiderRecall() - - local abilityNumber=3 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if ( not ability:IsFullyCastable() ) - then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local allys = fun1:GetNearbyHeroes(npcBot, 1200, false) - local enemys = fun1:GetNearbyHeroes(npcBot, 1600, true) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = fun1:GetNearbyCreeps(npcBot, 1600, true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - local numPlayer = GetTeamPlayers(GetTeam()); - -- for i = 1, #numPlayer - -- do - -- local player = GetTeamMember(i); - -- if player ~= nil and not IsPlayerBot(player:GetPlayerID()) and player:IsAlive() and GetUnitToUnitDistance(npcBot, player) > 1000 then - -- local p = player:GetMostRecentPing(); - -- if p ~= nil and GetUnitToLocationDistance(player, p.location) < 1000 and GameTime() - p.time < 10 then - -- --print("Human pinged to get recalled") - -- return BOT_ACTION_DESIRE_MODERATE, player; - -- end - -- end - -- end - - -- If we're defending a lane - -- if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - -- npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - -- npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - -- npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - -- npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - -- npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - -- then - -- local nearbyTower = npcBot:GetNearbyTowers(1000, false) - -- if nearbyTower[1] ~= nil then - -- local maxDist = 0; - -- local target = nil; - -- for i = 1, #numPlayer - -- do - -- local player = GetTeamMember(i); - -- if player ~= nil and player:IsAlive() and player:GetActiveMode() ~= BOT_MODE_RETREAT then - -- local dist = GetUnitToUnitDistance(nearbyTower[1], player); - -- local health = player:GetHealth()/player:GetMaxHealth(); - -- if IsPlayerBot(player:GetPlayerID()) and dist > maxDist and dist > 2500 and health >= 0.5 then - -- maxDist = dist; - -- target = GetTeamMember(i); - -- end - -- end - -- end - -- if target ~= nil then - -- return BOT_ACTION_DESIRE_MODERATE, target; - -- end - -- end - -- end - - -- if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - -- npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - -- npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT ) - -- then - -- local nearbyTower = npcBot:GetNearbyTowers(1000, true) - -- if nearbyTower[1] ~= nil then - -- local maxDist = 0; - -- local target = nil; - -- for i = 1, #numPlayer - -- do - -- local player = GetTeamMember(i); - -- if player ~= nil and player:IsAlive() and player:GetActiveMode() ~= BOT_MODE_RETREAT then - -- local dist = GetUnitToUnitDistance(nearbyTower[1], player); - -- local health = player:GetHealth()/player:GetMaxHealth(); - -- if IsPlayerBot(player:GetPlayerID()) and dist > maxDist and dist > 2500 and health >= 0.5 then - -- maxDist = dist; - -- target = GetTeamMember(i); - -- end - -- end - -- end - -- if target ~= nil then - -- return BOT_ACTION_DESIRE_MODERATE, target; - -- end - -- end - -- end - - -- -- If we're going after someone - -- if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - -- npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - -- npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - -- npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - -- then - -- local npcTarget = npcBot:GetTarget(); - -- if ( npcTarget ~= nil and npcTarget:IsHero() and GetUnitToUnitDistance( npcTarget, npcBot ) < 1000 ) - -- then - -- local maxDist = 0; - -- local target = nil; - -- for i = 1, #numPlayer - -- do - -- local player = GetTeamMember(i); - -- if player ~= nil and player:IsAlive() and player:GetActiveMode() ~= BOT_MODE_RETREAT then - -- local dist = GetUnitToUnitDistance(player, npcBot); - -- local health = player:GetHealth()/player:GetMaxHealth(); - -- if IsPlayerBot(player:GetPlayerID()) and dist > maxDist and dist > 2500 and health >= 0.5 then - -- maxDist = dist; - -- target = GetTeamMember(i); - -- end - -- end - -- end - -- if target ~= nil then - -- return BOT_ACTION_DESIRE_MODERATE, target; - -- end - -- end - -- end - - return BOT_ACTION_DESIRE_NONE, 0; -end - -local GetAllAllyHeroes = fun1:EveryManySeconds(2, function() - return fun1:GetAllHeores(npcBot, false) -end) - -Consider[4]=function() - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - local healAmount = ability:GetSpecialValueInt("heal_amount") - local function IsSeverelyDamaged(npc) - return (fun1:GetHealthPercent(npc) <= 0.3 or npc:GetHealth() <= 400) and fun1:IsSeverelyDisabled(npc) and npc:WasRecentlyDamagedByAnyHero(0.8) - end - local function IsDamaged(npc) - return npc:GetHealth() <= 400 or fun1:GetHealthDeficit(npc) >= healAmount * 1.3 and npc:GetUnitName() ~= "npc_dota_hero_huskar" and npc:WasRecentlyDamagedByAnyHero(1.2) - end - - local castRange = 1599 - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot) - local allys = GetAllAllyHeroes() - if not fun1:CalledOnThisFrame(allys) then - allys = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange, false) - end - allys = fun1:Filter(allys, function(t) return not t:IsInvulnerable() and not t:HasModifier("modifier_ice_blast") end) - local damagedAllies = fun1:Filter(allys, function(t) return IsDamaged(t) and not IsSeverelyDamaged(t) end) - local severelyDamagedAllies = fun1:Filter(allys, IsSeverelyDamaged) - - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - if npcBot:WasRecentlyDamagedByAnyHero(1.0) and (not IsSeverelyDamaged(npcBot) or #damagedAllies >= 2) then - return BOT_ACTION_DESIRE_HIGH - end - end - - if npcBot:GetActiveMode() == BOT_MODE_LANING then - if #damagedAllies >= 2 and #severelyDamagedAllies >= 1 then - return BOT_ACTION_DESIRE_MODERATE - end - end - - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1000, false, BOT_MODE_ATTACK ); - if #tableNearbyAttackingAlliedHeroes >= 2 and #enemies > 0 then - if fun1:Contains(severelyDamagedAllies, npcBot) and #damagedAllies >= 3 - or #damagedAllies >= 2 and #severelyDamagedAllies >= 1 then - return BOT_ACTION_DESIRE_HIGH - end - end - return 0 -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - -- attackRange = npcBot:GetAttackRange() - -- healthPercent = fun1:GetHealthPercent(npcBot) - -- mana = npcBot:GetMana() - -- manaPercent = fun1:GetManaPercent(npcBot) - - -- enemies = fun1:GetNearbyHeroes(npcBot, 1599) - -- realEnemies = fun1:Filter(enemies, function(t) return fun1:MayNotBeIllusion(npcBot, t) end) - -- friends = fun1:GetNearbyHeroes(npcBot, 1599, true) - -- friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - -- enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 1599) - -- friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - -- neutralCreeps = npcBot:GetNearbyNeutralCreeps(1599) - -- tower = fun1:GetLaningTower(npcBot) - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_clinkz.mira b/mira/ability_item_usage_clinkz.mira deleted file mode 100644 index 18f0b19..0000000 --- a/mira/ability_item_usage_clinkz.mira +++ /dev/null @@ -1,489 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.3 New Structure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local AbilityExtensions = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) -local AbilityToLevelUp= -{ - Abilities[2], - Abilities[1], - Abilities[2], - Abilities[3], - Abilities[2], - Abilities[5], -- lvl 6 - Abilities[2], - Abilities[3], - Abilities[1], - "talent", - Abilities[1], - Abilities[5], -- lvl 12 - Abilities[1], - Abilities[3], - "talent", - Abilities[3], - "nil", - Abilities[5], -- lvl 18 - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[3] - end, - function() - return Talents[6] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local ComboMana; -local AttackRange; -local ManaPercentage; -local HealthPercentage; -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast={utility.NCanCast,{ t -> - AbilityExtensions.PhysicalCanCastFunction(t) or t:IsTower() and not t:HasModifier "modifier_fountain_glyph" -},utility.NCanCast,utility.UCanCast,{ t -> - not t:IsAncientCreep() and not t:IsRoshan() -}} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local Radius = ability:GetAOERadius() - - local allys = npcBot:GetNearbyHeroes(1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy:GetLocation(),"Location" - end - end - end - end - - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're farming and can hit 2+ creeps - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if(ManaPercentage>0.4 or npcBot:GetMana()>ComboMana ) - then - local locationAoE = npcBot:FindAoELocation( true, false, npcBot:GetLocation(), CastRange, Radius, 0, 0 ); - if ( locationAoE.count >= 3 ) - then - return BOT_ACTION_DESIRE_MODERATE-0.03, locationAoE.targetloc,"Location"; - end - end - end - - -- If we're pushing or defending a lane and can hit 4+ creeps, go for it - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if(ManaPercentage>0.4 or npcBot:GetMana()>ComboMana ) - then - local locationAoE = npcBot:FindAoELocation( true, false, npcBot:GetLocation(), CastRange, Radius, 0, 0 ); - if ( locationAoE.count >= 3 ) - then - return BOT_ACTION_DESIRE_MODERATE-0.03, locationAoE.targetloc,"Location"; - end - end - end - - -- If my mana is enough, use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if((ManaPercentage>0.4 or npcBot:GetMana()>ComboMana) and ability:GetLevel()>=2 ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - return BOT_ACTION_DESIRE_LOW,WeakestEnemy:GetLocation(),"Location" - end - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), CastRange, Radius, 0, 0 ); - if ( locationAoE.count >= 2 ) - then - return BOT_ACTION_DESIRE_MODERATE, locationAoE.targetloc,"Location" - end - - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( not enemyDisabled(npcEnemy) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy:GetLocation(),"Location" - end - end - end - - return BOT_ACTION_DESIRE_NONE -end - - -Consider[2] = AbilityExtensions:ToggleFunctionToAutoCast(npcBot, AbilitiesReal[2]) { -> - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() or AbilityExtensions:IsPhysicalOutputDisabled(npcBot) then - return 0 - end - - local CastRange = ability:GetCastRange() - local enemys = npcBot:GetNearbyHeroes(CastRange+100,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - - local function UseAt(target) - if not CanCast[abilityNumber](target) then - return false - end - if target:IsHero() then - if AbilityExtensions:IsAttackingEnemies(npcBot) and npcBot:WasRecentlyDamagedByAnyHero(1) then - return false - end - if GetUnitToUnitDistanceSqr(npcBot, target) <= 190000 then - return false - elseif AbilityExtensions:MustBeIllusion(npcBot, target) then - return AbilityExtensions:GetManaPercent(npcBot) >= 0.8 or AbilityExtensions:GetHealthPercent(target) <= 0.4 - else - return true - end - elseif target:IsBuilding() then - return true - else - return AbilityExtensions:GetManaPercent(npcBot) >= 0.8 - end - - end - - local attackRange = npcBot:GetAttackRange() - if AbilityExtensions:NotRetreating(npcBot) then - if npcBot:GetActiveMode() == BOT_MODE_LANING then - local creeps = npcBot:GetNearbyLaneCreeps(attackRange+120, true) - local allyCreeps = npcBot:GetNearbyLaneCreeps(attackRange+120, false) - if creeps and #creeps > 0 or allyCreeps and #allyCreeps > 0 then - return false - end - end - local target = npcBot:GetAttackTarget() or npcBot:GetTarget() - if target == nil then - if WeakestEnemy ~= nil then - local b = UseAt(WeakestEnemy) - if b then - return BOT_ACTION_DESIRE_MODERATE, WeakestEnemy - else - return false - end - end - else - return UseAt(target) - end - end - return false -} - -Consider[3]=function() - - local abilityNumber=3 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local Radius = ability:GetAOERadius() - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - return BOT_ACTION_DESIRE_MODERATE - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if(GetUnitToUnitDistance(npcBot,npcEnemy)>=1800) - then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -local goodNeutral= -{ - "npc_dota_neutral_alpha_wolf", -- 头狼 - "npc_dota_neutral_centaur_khan", -- 半人马征服者 - "npc_dota_neutral_dark_troll_warlord", -- 黑暗巨魔召唤法师 - "npc_dota_neutral_polar_furbolg_ursa_warrior", -- 地狱熊怪粉碎者 - "npc_dota_neutral_satyr_hellcaller", -- 萨特苦难使者 - "npc_dota_neutral_enraged_wildkin", -- 枭兽撕裂者 -} - -local function IsGoodNeutralCreeps(npcCreep) - local name=npcCreep:GetUnitName(); - for k,creepName in pairs(goodNeutral) do - if(name==creepName) - then - return true; - end - end - return false; -end - -Consider[4]=function() - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local Radius = ability:GetAOERadius() - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 ) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), AttackRange, 400, 0, 0 ); - if ( locationAoE.count >= 2 ) then - return BOT_ACTION_DESIRE_LOW, locationAoE.targetloc; - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if(ManaPercentage>0.4 or npcBot:GetMana()>ComboMana) - then - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 300) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy:GetLocation(); - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -local function RateCreep(creep) - local rate = 0 - rate += creep:GetMaxHealth() * AbilityExtensions:GetTargetHealAmplifyPercent(npcBot) - rate += creep:GetAttackDamage() * 6 - - if creep:IsDominated() then - rate *= 2 - end - if creep:GetTeam() ~= TEAM_NEUTRAL then - rate *= 0.4 - end - if string.match(creep:GetUnitName(), "upgraded_mega") then - rate *= 0.5 - elseif string.match(creep:GetUnitName(), "upgraded") then - rate *= 0.8 - end - return rate -end -local standardCreepRate = 0 -local GetStandardCreepRate = AbilityExtensions:EveryManySeconds(2) { -> - standardCreepRate = AbilityExtensions:MaxV(GetUnitList(UNIT_LIST_ENEMY_CREEPS) or {}, RateCreep) or 0 -} - -Consider[5]=function() - local abilityNumber=5 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = ability:GetCastRange() - - local enemys = npcBot:GetNearbyHeroes(CastRange+300, true, BOT_MODE_NONE) - GetStandardCreepRate() - local creeps = AbilityExtensions:Filter(AbilityExtensions:Concat(npcBot:GetNearbyCreeps(CastRange+300, true), npcBot:GetNearbyNeutralCreeps(CastRange+300)), CanCast[5]) - if local creep = creeps:Max(RateCreep) then - if RateCreep(creep) < standardCreepRate then - return BOT_ACTION_DESIRE_VERYLOW - else - return BOT_ACTION_DESIRE_MODERATE - end - end - - return BOT_ACTION_DESIRE_NONE -end - -AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_doom_bringer.mira b/mira/ability_item_usage_doom_bringer.mira deleted file mode 100644 index 2004ba0..0000000 --- a/mira/ability_item_usage_doom_bringer.mira +++ /dev/null @@ -1,701 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.3 New Structure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") -local A = require(GetScriptDirectory().."/util/MiraDota") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[3], - Abilities[1], - Abilities[3], - Abilities[2], - Abilities[3], - Abilities[6], - Abilities[3], - Abilities[2], - Abilities[2], - "talent", - Abilities[2], - Abilities[6], - Abilities[1], - Abilities[1], - "talent", - Abilities[1], - "nil", - Abilities[6], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[4] - end, - function() - return Talents[5] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - -function CanCast1( npcEnemy ) - if(npcEnemy==nil) - then - return false - end - return npcEnemy:CanBeSeen() and not npcEnemy:IsInvulnerable() -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -local level -local attackRange -local health -local maxHealth -local healthPercent -local mana -local maxMana -local manaPercent -local netWorth - -local allEnemies -local enemies -local enemyCount -local friends -local friendCount -local enemyCreeps -local friendCreeps -local neutralCreeps -local tower - -local CanCast = {function(t) -> not t:IsHero() and not fun1:IsRoshan(t) and t:GetLevel() <= AbilitiesReal[1]:GetLevel()+3 and (not t:IsAncientCreep() or level >= 28), - fun1.NormalCanCastFunction, - fun1.PhysicalCanCastFunction, - fun1.NormalCanCastFunction, - fun1.NormalCanCastFunction, - utility.UCanCast} -local enemyDisabled=utility.enemyDisabled - -local function GetComboMana() - local mana = 0 - local dotaTime = DotaTime()/60 - local estimatedFightTime = if dotaTime <= 20 { - RemapVal(dotaTime, 10, 20, 10, 15) - } elif dotaTime <= 30 { - RemapVal(dotaTime, 20, 30, 15, 30) - } elif dotaTime <= 45 { - RemapVal(dotaTime, 30, 45, 30, 50) - } else { 50 } - - local function GetAbilityMana(ability) - if ability:GetManaCost() == 0 then - return - end - local scorchedEarthReady = ability:IsFullyCastable() - if scorchedEarthReady then - mana += ability:GetManaCost() - end - mana += estimatedFightTime / ability:GetCooldown() * ability:GetManaCost() - end - fun1:ForEach({AbilitiesReal[2], AbilitiesReal[3], AbilitiesReal[6]}) { t -> - GetAbilityMana(t) - } - if dotaTime >= 30 and AbilitiesReal[1]:IsCooldownReady() then - mana += AbilitiesReal[1]:GetManaCost() - end - return mana -end - -local acquiredAbilityPriority = A.Linq.NewTable( - "satyr_trickster_purge", - "mud_golem_hurl_boulder", - "giant_wolf_intimidate", - "granite_golem_granite_aura", - "centaur_khan_war_stomp", - "thunderhide_frenzy" -) -local devourUnitPriority = A.Linq.NewTable( - "npc_dota_neutral_satyr_trickster", - "npc_dota_neutral_mud_golem", - "npc_dota_neutral_giant_wolf", - "npc_dota_neutral_granite_golem", - "npc_dota_neutral_centaur_khan", - "npc_dota_neutral_thunderhide" -) -local function GetAcquiredAbilityUnitPriority(acquiredAbility) - -> if acquiredAbility == nil or acquiredAbility:IsHidden() { -100 } - else { acquiredAbilityPriority:IndexOf(acquiredAbility:GetName()) } --- the priority is higher when the unit is stronger -local function GetUnitPriority(unit) - -> devourUnitPriority:IndexOf(unit:GetUnitName()) - -local function ToggleDevourAutoCast(ability, targetState) - if ability:GetAutoCastState() ~= targetState then - ability:ToggleAutoCast() - return true - end -end - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - if local strongstCreep = utility.GetStrongestUnit(A.Dota.GetNearbyCreeps(npcBot, 800, true):Concat(A.Dota.GetNearbyNeutralCreeps(npcBot, 800)):Filter(CanCast[1])) then - if GetUnitPriority(strongstCreep) > GetAcquiredAbilityUnitPriority(AbilitiesReal[4]) then - if ToggleDevourAutoCast(ability, true) then - return 0 - end - else - if ToggleDevourAutoCast(ability, false) then - return 0 - end - end - return BOT_ACTION_DESIRE_MODERATE, strongstCreep - end - - return BOT_ACTION_DESIRE_NONE - -end - -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local Damage = ability:GetDuration()*ability:GetSpecialValueInt("damage_per_second") - local Radius = ability:GetAOERadius() - - - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, 1200, false) - local allyCount = fun1:GetEnemyHeroNumber(npcBot, allys) - local enemys = npcBot:GetNearbyHeroes(Radius+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(Radius+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - local abilityLevel = ability:GetLevel() - - --try to kill enemy hero - - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - if(npcBot:WasRecentlyDamagedByAnyHero(2) or (npcBot:GetActiveMode() == BOT_MODE_RETREAT and HealthPercentage<=0.4+#enemys*0.05)) - then - return BOT_ACTION_DESIRE_HIGH - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if(ManaPercentage>0.4 or npcBot:GetMana()>ComboMana) - then - if ( npcEnemy ~= nil ) - then - if ( GetUnitToUnitDistance(npcBot,npcEnemy) > 350 or npcEnemy:GetHealth()/npcEnemy:GetMaxHealth() < 0.4) and GetUnitToUnitDistance(npcBot, npcEnemy) < 900 - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - - -- If we're farming - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if #creeps >= 3 and ManaPercentage>0.7 and allyCount < 3 and abilityLevel >= 3 - then - return BOT_ACTION_DESIRE_LOW - end - end - - return BOT_ACTION_DESIRE_NONE - -end - -Consider[3]=function() - local abilityNumber=3 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() or fun1:IsPhysicalOutputDisabled(npcBot) then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local castWhenNearbyDistanceSqr = 320*320 - local Damage = ability:GetAbilityDamage(); - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+150,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+150,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - if local channelingEnemy = A.Linq.First(enemys) { t -> - t:IsChanneling() and CanCast[abilityNumber](t) and GetUnitToUnitDistanceSqr(npcBot, t) <= castWhenNearbyDistanceSqr - } then - return BOT_ACTION_DESIRE_HIGH, channelingEnemy - end - - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're going after someone - if fun1:IsAttackingEnemies(npcBot) then - if local npcTarget = npcBot:GetTarget() then - if CanCast[abilityNumber](npcTarget) and GetUnitToUnitDistanceSqr(npcBot, npcTarget) <= castWhenNearbyDistanceSqr then - return BOT_ACTION_DESIRE_MODERATE, npcTarget - end - end - end - - -- If my mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if((HealthPercentage>0.7 and ManaPercentage>0.4 or npcBot:GetMana()>ComboMana)) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - return BOT_ACTION_DESIRE_LOW,WeakestEnemy; - end - end - end - end - - -- If we're farming - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if ( #creeps >= 1 and ManaPercentage>0.6 or npcBot:GetMana()>ComboMana) - then - return BOT_ACTION_DESIRE_LOW, creeps[1]; - end - end - return BOT_ACTION_DESIRE_NONE, 0; - -end - -local function DoomEmptyAbilityThink(ability) - return 0 -end - -local function centaur_khan_war_stomp(ability) - if not ability:IsFullyCastable() then - return 0 - end - local radius = ability:GetAOERadius() - - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, radius + 90) - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, 800) - if fun1:GetEnemyHeroNumber(npcBot, enemies) >= 2 and (AbilitiesReal[6]:IsFullyCastable() or #ally >= 2) then - return RemapValClamped(mana, 100, ComboMana, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_HIGH) - end - if fun1:NotRetreating(npcBot) then - if local target = fun1:GetTargetIfGood() then - if fun1:NormalCanCast(target) and GetUnitToUnitDistance(npcBot, target) <= radius then - return RemapValClamped(mana, 100, ComboMana, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_HIGH) - end - end - else - if enemies:Any(fun1.NormalCanCastFunction) then - return RemapValClamped(mana, 100, ComboMana, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_HIGH) - end - end - return 0 -end - -local function mud_golem_hurl_boulder(ability) - if not ability:IsFullyCastable() then - return 0 - end - local castRange = ability:GetCastRange() - - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 200) - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, 1000) - - if local target = enemies:Min { t -> t:GetHealth() * if fun1:IsSeverelyDisabled(t) {0.5} else {1} } then - return BOT_ACTION_DESIRE_HIGH, target - end - if fun1:NotRetreating(npcBot) then - if local target = fun1:GetTargetIfGood() then - if fun1:NormalCanCast(target) then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - if local target = fun1:GetTargetIfBad() then - if fun1:NormalCanCast(target) then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - else - if local target = enemies:Min { t -> GetUnitToUnitDistance(npcBot, t) } then - if fun1:NormalCanCast(target) then - return BOT_ACTION_DESIRE_HIGH, target - end - end - end - return 0 -end - -local function satyr_soulstealer_mana_burn(ability) - if not ability:IsFullyCastable() then - return 0 - end - local manaCost = ability:GetManaCost() - local castRange = ability:GetCastRange() - - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 200) - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, 1200) - - if fun1:IsAttackingEnemies(npcBot) then - if mana >= ComboMana + manaCost then - if local target = enemies:Filter(fun1.NormalCanCastFunction) - :Min { t -> t:GetHealth() * if fun1:IsSeverelyDisabledOrSlowed(t) {2} else {1} } - then - return BOT_ACTION_DESIRE_MODERATE-0.1, target - end - end - end - if fun1:IsLaning(npcBot) then - if mana >= 110 then - if local target = enemies:Filter { t -> - if not fun1.NormalCanCastFunction(t) then return false end - if netWorth >= 15000 and not fun1:PhysicalCanCast(t) then return false end - true - } - :Max { t -> - local m = t:GetMana() - local desire = if m <= 40 { BOT_ACTION_DESIRE_LOW } - elif m <= 150 { BOT_ACTION_DESIRE_HIGH } - else { BOT_ACTION_DESIRE_MODERATE - 0.1 } - if t:GetUnitName() == "npc_dota_hero_obsidian_destroyer" then - desire *= 0.1 - end - desire - } then - return BOT_ACTION_DESIRE_MODERATE, target - end - end - end - return 0 -end - -local function satyr_trickster_purge(ability) - if not ability:IsFullyCastable() then - return 0 - end - local castRange = ability:GetCastRange() - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 200) - if mana >= ComboMana + manaCost then - if local enemy = enemies:First { t -> - fun1:HasBasicDispellablePositiveModifier(t) - } then - return BOT_ACTION_DESIRE_HIGH, enemy - end - end - return 0 -end - -local function giant_wolf_intimidate(ability) - if not ability:IsFullyCastable() then - return 0 - end - local aoe = ability:GetAOERadius() - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + 200) - if fun1:IsAttackingEnemies(npcBot) or fun1:IsRetreating(npcBot) then - if mana >= ComboMana + manaCost then - if enemies:Any { t -> - t:GetAttackTarget() and t:GetAttackTarget():IsHero() or t:GetCurrentActiveAbility() and fun1.NormalCanCastFunction(t) - } then - return BOT_ACTION_DESIRE_HIGH - end - end - end - return 0 -end - -local function ogre_bruiser_ogre_smash(ability) - if not ability:IsFullyCastable() then - return 0 - end - local castRange = ability:GetSpecialValueInt "distance" or 200 - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange + ability:GetAOERadius()) - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, 1200) - if local enemy = enemies:First { t -> - fun1.NormalCanCastFunction(t) and (#allys >= 3 and (fun1:GetStunRemainingDuration(t) >= 1.5 or t:IsRooted()) or t:IsChanneling()) - } then - return BOT_ACTION_DESIRE_MODERATE, enemy - end - return 0 -end - -local function enraged_wildkin_tornado(ability) - return 0 -end - - -local function DoomAcquiredAbilityThink(ability) - local abilityName = ability:GetName() - if abilityName == "doom_bringer_empty1" or abilityName == "doom_bringer_empty2" then - return DoomEmptyAbilityThink(ability) - elseif abilityName == "satyr_soulstealer_mana_burn" then - return satyr_soulstealer_mana_burn(ability) - elseif abilityName == "centaur_khan_war_stomp" then - return centaur_khan_war_stomp(ability) - elseif abilityName == "mud_golem_hurl_boulder" then - return mud_golem_hurl_boulder(ability) - elseif abilityName == "enraged_wildkin_tornado" then - return enraged_wildkin_tornado(ability) - elseif abilityName:match("ogre_smash") then - return ogre_bruiser_ogre_smash(ability) - elseif abilityName == "giant_wolf_intimidate" then - return giant_wolf_intimidate(ability) - elseif abilityName == "satyr_trickster_purge" then - return satyr_trickster_purge(ability) - else - return 0 - end -end - -Consider[4] = { -> - DoomAcquiredAbilityThink(AbilitiesReal[4]) -} -Consider[5] = { -> - DoomAcquiredAbilityThink(AbilitiesReal[5]) -} - -Consider[6]=function() - local abilityNumber=6 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local Damage = ability:GetDuration()*ability:GetSpecialValueInt("damage_per_second") - local CastRange = ability:GetCastRange(); - - - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, 1200, false) - local enemys = fun1:GetNearbyNonIllusionHeroes(npcBot, CastRange+300, true) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1000, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 or #allys >=3) - then - - local npcMostDangerousEnemy = nil; - local nMostDangerousDamage = 0; - - for _,npcEnemy in pairs( enemys ) - do - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy)) - then - local Damage2 = npcEnemy:GetEstimatedDamageToTarget( false, npcBot, 3.0, DAMAGE_TYPE_ALL ); - if ( Damage2 > nMostDangerousDamage ) - then - nMostDangerousDamage = Damage2; - npcMostDangerousEnemy = npcEnemy; - end - end - end - - if ( npcMostDangerousEnemy ~= nil ) - then - return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy; - end - end - - -- Check for a channeling enemy - if local channeling = enemys:First { t -> - fun1:IsChannelingBreakWorthAbility(t, "moderate") and CanCast[6](t) - } then - return BOT_ACTION_DESIRE_MODERATE-0.1, channeling - end - - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy; - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - --[[if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - for _,npcEnemy in pairs( enemys ) - do - if ( npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy)) - then - return BOT_ACTION_DESIRE_HIGH, npcEnemy; - end - end - end - end]] - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - if local npcEnemy = fun1:GetTargetIfGood(npcBot) then - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; -end - -local RefreshAbilities = fun1:EveryManySeconds(1) { -> - if local t = npcBot:GetAbilityInSlot(3); t and not t:IsHidden() and not t:IsTalent() and t:GetName() ~= "doom_bringer_doom" then - AbilitiesReal[4] = t - end - if local t = npcBot:GetAbilityInSlot(4); t and not t:IsHidden() and not t:IsTalent() and t:GetName() ~= "doom_bringer_doom" then - AbilitiesReal[5] = t - end -} - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - RefreshAbilities() - - -- Check if we're already using an ability - if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - level = npcBot:GetLevel() - attackRange = npcBot:GetAttackRange() - health = npcBot:GetHealth() - maxHealth = npcBot:GetMaxHealth() - healthPercent = fun1:GetHealthPercent(npcBot) - mana = npcBot:GetMana() - maxMana = npcBot:GetMaxMana() - manaPercent = fun1:GetManaPercent(npcBot) - netWorth = npcBot:GetNetWorth() - - allEnemies = fun1:GetNearbyHeroes(npcBot, 1200) - enemies = allEnemies:Filter { t -> fun1:MayNotBeIllusion(npcBot, t) } - enemyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) - friends = fun1:GetNearbyNonIllusionHeroes(npcBot, 1500, true) - friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 900) - friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - neutralCreeps = npcBot:GetNearbyNeutralCreeps(900) - tower = fun1:GetLaningTower(npcBot) - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_ember_spirit.mira b/mira/ability_item_usage_ember_spirit.mira deleted file mode 100644 index fc13018..0000000 --- a/mira/ability_item_usage_ember_spirit.mira +++ /dev/null @@ -1,590 +0,0 @@ - --- v1.7 template by AaronSong321 -local utility = require(GetScriptDirectory().."/utility") -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -if npcBot:IsIllusion() then - return -end -local AbilityNames, Abilities, Talents = fun1:InitAbility(npcBot) - -local AbilityToLevelUp = -{ - AbilityNames[2], - AbilityNames[3], - AbilityNames[3], - AbilityNames[1], - AbilityNames[3], - AbilityNames[5], - AbilityNames[3], - AbilityNames[2], - AbilityNames[2], - "talent", - AbilityNames[2], - AbilityNames[1], - AbilityNames[1], - AbilityNames[1], - "talent", - AbilityNames[5], - "nil", - AbilityNames[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} -local TalentTree = { - function() - return Talents[1] - end, - function() - return Talents[4] - end, - function() - return Talents[5] - end, - function() - return Talents[8] - end -} -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) -end - -local cast = { - Desire = {}, - Target = {}, - Type = {} -} -local Consider = {} - -local CanCast = { - { t -> fun1:StunCanCast(t, Abilities[1], false, false, true, false) }, - fun1.PhysicalCanCastFunction, - fun1.NormalCanCastFunction, - { -> true }, - { -> true } -} - -local attackRange -local health -local maxHealth -local healthPercent -local mana -local maxMana -local manaPercent -local enemies -local realEnemies -local friends -local friendCount -local enemyCreeps -local friendCreeps -local neutralCreeps -local tower - -local function IsUsingSleightOfFist() - return npcBot:HasModifier "modifier_ember_spirit_sleight_of_fist_in_progress" -end -local function IsUsingRemnant() - return npcBot:HasModifier "modifier_ember_spirit_fire_remnant" -end -local fistCastLocation - -Consider[1] = function() - local ability = Abilities[1] - if not ability:IsFullyCastable() then - return 0 - end - local abilityLevel = ability:GetLevel() - local castRange = ability:GetCastRange() - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local unitCount = ability:GetSpecialValueInt "unit_count" - - local allEnemies = fun1:GetNearbyHeroes(npcBot, castRange) - local enemies = allEnemies:Filter { it -> - fun1:MayNotBeIllusion(npcBot, it) and CanCast[1](it) - } - local enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, castRange) - local neutralCreeps = npcBot:GetNearbyNeutralCreeps(castRange) - local damage = ability:GetSpecialValueInt "total_damage" - local weakCreeps = fun1:Filter(enemyCreeps, function(t) return t:GetHealth() < t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) end) - local forbiddenCreeps = fun1:Filter(enemyCreeps, function(t) - return t:GetHealth() > t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) and t:GetHealth() <= t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) + fun1:AttackOnceDamage(npcBot, t) * (0.9+#enemyCreeps*0.1) - end) - if #friendCreeps == 0 then - forbiddenCreeps = forbiddenCreeps:Filter { it -> false } - end - - local allTargets = allEnemies:Concat(fun1:GetNearbyCreeps(npcBot, castRange, true)):Filter(CanCast[1]) - local targetNumber = #allTargets - if targetNumber <= unitCount then - targetNumber = unitCount - end - - local function ChainExpectancy(targetNumber, unitCount, allUnits) - local t = targetNumber - if targetNumber > unitCount then - t = unitCount - end - return fun1:Aggregate(0, fun1:Range(1, t)) { seed, target -> - seed + fun1:Combination(t, target) * fun1:Combination(allUnits - t, t - target) * target - } / fun1:Combination(unitCount, allUnits) - end - - if fun1:IsFarmingOrPushing(npcBot) then - if mana >= maxMana * 0.6 + manaCost and #enemyCreeps >= 2 then - return BOT_ACTION_DESIRE_LOW - end - end - - if fun1:IsAttackingEnemies(npcBot) then - if #enemies > 0 then - local p = ChainExpectancy(#enemies, unitCount, targetNumber) - if p >= 0.5 and mana >= maxMana * 0.6 + manaCost then - return RemapValClamped(p, 0.5, 1, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_VERYHIGH) - end - if mana >= maxMana * 0.4 + manaCost and p >= 0.8 then - return RemapValClamped(p, 0.5, 1, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_VERYHIGH) - end - end - end - - if fun1:IsRetreating(npcBot) then - if #enemies > 0 then - local p = ChainExpectancy(#enemies, unitCount, targetNumber) - if p >= 0.5 then - return RemapValClamped(p, 0.5, 1, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_VERYHIGH) - end - end - else - if local target = fun1:GetTargetIfGood(npcBot) then - local p = ChainExpectancy(#enemies, unitCount, targetNumber) - if p >= 0.5 then - return RemapValClamped(p, 0.5, 1, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_VERYHIGH) - end - elseif local target = fun1:GetTargetIfBad(npcBot) then - local p = ChainExpectancy(#enemies, unitCount, targetNumber) - if p >= 1 then - return RemapValClamped(p, 0.5, 1, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_VERYHIGH) - end - end - end - - return 0 -end - -Consider[2] = function() - local ability = Abilities[2] - if not ability:IsFullyCastable() or IsUsingRemnant() or IsUsingSleightOfFist() or fun1:CannotMove(npcBot) or ability:GetCurrentCharges() == 0 then - return 0 - end - local abilityLevel = ability:GetLevel() - local castRange = ability:GetCastRange() + 100 - local radius = ability:GetAOERadius() - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local enemies = fun1:GetNearbyHeroes(npcBot, castRange + radius) - local realEnemies = fun1:Filter(enemies, function(t) return fun1:MayNotBeIllusion(npcBot, t) end) - local targettableEnemies = fun1:Filter(enemies, function(t) return fun1:NormalCanCast(t, true, DAMAGE_TYPE_PHYSICAL, true) and not fun1:CannotBeAttacked(t) end) - local friends = fun1:GetNearbyHeroes(npcBot, 1200, true) - local friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - local enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, castRange + radius) - local friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - local neutralCreeps = npcBot:GetNearbyNeutralCreeps(castRange) - local weakestEnemy, enemyHealth = utility.GetWeakestUnit(targettableEnemies) - local creepDamage = npcBot:GetAttackDamage() * (1 + ability:GetSpecialValueInt "creep_damage_penalty" / 100) - local weakCreeps = fun1:Filter(enemyCreeps, function(t) return t:GetHealth() < t:GetActualIncomingDamage(creepDamage, DAMAGE_TYPE_MAGICAL) end) - local weakestCreep = utility.GetWeakestUnit(weakCreeps) - local forbiddenCreeps = fun1:Filter(enemyCreeps, function(t) - return t:GetHealth() > t:GetActualIncomingDamage(creepDamage, DAMAGE_TYPE_MAGICAL) and t:GetHealth() <= t:GetActualIncomingDamage(creepDamage, DAMAGE_TYPE_MAGICAL) + fun1:AttackOnceDamage(npcBot, t) * (0.9+#enemyCreeps*0.1) - end) - if #friendCreeps == 0 then - forbiddenCreeps = {} - end - local damage = npcBot:GetAttackDamage() + ability:GetSpecialValueInt "bonus_hero_damage" - if fun1:GetAvailableItem(npcBot, "item_lesser_crit") then - damage = damage * 1.7 - elseif fun1:GetAvailableItem(npcBot, "item_greater_crit") then - damage = damage * 2.3 - end - local hasBattleFury = fun1:GetAvailableItem(npcBot, "item_bfury") ~= nil - - local projectiles = fun1:GetIncomingDodgeWorthProjectiles(npcBot) or {} - projectiles = fun1:Any(projectiles, function(t) return GetUnitToLocationDistance(npcBot, t.location) <= 200 end) - if projectiles then - local locationAoE = npcBot:FindAoELocation(true, false, npcBot:GetLocation(), castRange+60, radius, 0, 0) - if locationAoE.count >= 2 then - return BOT_ACTION_DESIRE_HIGH, locationAoE.targetloc - end - end - if fun1:IsFarmingOrPushing(npcBot) then - local locationAoE = npcBot:FindAoELocation(true, false, npcBot:GetLocation(), castRange+150, radius, 0, 0) - if hasBattleFury and (locationAoE.count >= 4 and manaPercent >= 0.3 + manaCost or locationAoE.count >= 3 and manaPercent >= 0.6 + manaCost) then - return BOT_ACTION_DESIRE_LOW, locationAoE.targetloc - end - elseif fun1:IsLaning(npcBot) then - if manaPercent >= 0.6 + manaCost and #enemies == 1 and enemies[1]:CanBeSeen() and healthPercent >= 0.8 and abilityLevel >= 3 then - return BOT_ACTION_DESIRE_HIGH, fun1:FindAOELocationAtSingleTarget(npcBot, enemies[1], radius, castRange, castPoint) - end - if manaPercent >= 0.3 and #enemies == 1 and enemies[1]:CanBeSeen() and healthPercent >= 0.75 and abilityLevel >= 4 then - return BOT_ACTION_DESIRE_HIGH, fun1:FindAOELocationAtSingleTarget(npcBot, enemies[1], radius, castRange, castPoint) - end - end - if fun1:NotRetreating(npcBot) then - local findPlace = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), castRange+100, radius, 0, 0) - if findPlace.count >= 3 then - if GetUnitToLocationDistance(npcBot, findPlace.targetloc) <= castRange then - return BOT_ACTION_DESIRE_VERYHIGH, findPlace.targetloc - else - return BOT_ACTION_DESIRE_MODERATE + 0.05, findPlace.targetloc - end - elseif findPlace.count >= 2 then - return BOT_ACTION_DESIRE_MODERATE, findPlace.targetloc - end - - if weakestEnemy ~= nil and enemyHealth ~= -1 then - local damageTaken = weakestEnemy:GetActualIncomingDamage(damage, DAMAGE_TYPE_PHYSICAL) - if enemyHealth <= damageTaken or enemyHealth <= damageTaken * 1.5 and mana > 200 + manaCost then - local targetLocation = fun1:FindAOELocationAtSingleTarget(npcBot, weakestEnemy, radius, castRange, castPoint) - return BOT_ACTION_DESIRE_HIGH, targetLocation - end - end - - local target = npcBot:GetTarget() - if target ~= nil and target:CanBeSeen() and fun1:NormalCanCast(target, true, DAMAGE_TYPE_PHYSICAL) and not fun1:CannotBeAttacked(target) - and (mana >= 200 and target:GetHealth() < target:GetActualIncomingDamage(damage, DAMAGE_TYPE_PHYSICAL) * (0.9 + friendCount*0.1)) then - return BOT_ACTION_DESIRE_HIGH, fun1:FindAOELocationAtSingleTarget(npcBot, target, radius, castRange, castPoint) - end - end - return 0 -end - -Consider[3] = function() - local ability = Abilities[3] - if not ability:IsFullyCastable() or npcBot:HasModifier "modifier_ember_spirit_flame_guard" or npcBot:HasModifier "modifier_shadow_demon_purge_slow" then - return 0 - end - local abilityLevel = ability:GetLevel() - local castRange = ability:GetCastRange() - local radius = ability:GetAOERadius() - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local enemies = fun1:GetNearbyHeroes(npcBot, radius) - local realEnemies = fun1:Filter(enemies, function(t) return fun1:MayNotBeIllusion(npcBot, t) end) - local targettableEnemies = fun1:Filter(realEnemies, function(t) return fun1:NormalCanCast(t) end) - local enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 900) - local friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - local neutralCreeps = npcBot:GetNearbyNeutralCreeps(castRange) - local weakestEnemy, enemyHealth = utility.GetWeakestUnit(targettableEnemies) - local weakCreeps = enemyCreeps - local weakestCreep = utility.GetWeakestUnit(weakCreeps) - local forbiddenCreeps = {} - local manaMaintain = npcBot:GetMaxMana() * 0.6 + manaCost - if fun1:IsFarmingOrPushing(npcBot) then - if #enemyCreeps >= 4 and mana >= manaMaintain and abilityLevel >= 3 then - if not (friendCount >= 3 or npcBot:GetNetWorth() >= 10000 and fun1:GetAvailableItem("item_bfury")) then - return BOT_ACTION_DESIRE_MODERATE - 0.08 - end - end - elseif fun1:IsLaning(npcBot) then - if #enemyCreeps >= 3 and mana >= npcBot:GetMaxMana() * 0.3 + manaCost then - local laneEnemyHero = enemies[1] - if laneEnemyHero ~= nil and GetUnitToUnitDistance(npcBot, laneEnemyHero) <= radius and fun1:GetHealthPercent(laneEnemyHero) <= 0.4 then - return BOT_ACTION_DESIRE_MODERATE - end - if #friendCreeps == 0 and abilityLevel >= 2 then - return BOT_ACTION_DESIRE_MODERATE - end - end - elseif fun1:IsAttackingEnemies(npcBot) then - if abilityLevel <= 1 then - return 0 - end - if IsUsingSleightOfFist() then - local sleightFistMarkedHeroes = fun1:Count(enemies, function(t) return t:HasModifier "modifier_ember_spirit_sleight_of_fist_mark" end) - if sleightFistMarkedHeroes >= 3 then - return BOT_ACTION_DESIRE_HIGH - end - else - if not npcBot:IsMagicImmune() then - local projectiles = fun1:GetIncomingDodgeWorthProjectiles(npcBot) - projectiles = fun1:Any(projectiles, function(t) return GetUnitToLocationDistance(npcBot, t.location) <= 400 end) - if projectiles then - return BOT_ACTION_DESIRE_MODERATE - end - end - if #enemies >= 1 and DotaTime() < 10 * 60 or #realEnemies >= 2 and npcBot:GetNetWorth() / DotaTime() * 60 <= 350 or #realEnemies >= 3 then - return BOT_ACTION_DESIRE_HIGH - end - end - elseif fun1:IsRetreating(npcBot) then - local projectiles = fun1:GetIncomingDodgeWorthProjectiles(npcBot) - projectiles = fun1:Any(projectiles, function(t) return GetUnitToLocationDistance(npcBot, t.location) <= 400 end) - if projectiles and abilityLevel >= 3 then - return BOT_ACTION_DESIRE_HIGH - end - return BOT_ACTION_DESIRE_MODERATE - end - if local target = fun1:GetTargetIfGood(npcBot) then - if CanCast[3](target) and GetUnitToUnitDistance(npcBot, target) < radius + 50 and abilityLevel >= 3 then - return BOT_ACTION_DESIRE_MODERATE - end - end -end - -local activeRemnants -local refreshRemnantToken -local function RefreshActiveRemnants() - activeRemnants = fun1:Filter(GetUnitList(UNIT_LIST_ALLIES), function(t) return t:GetUnitName() == "npc_dota_ember_spirit_remnant" end) -end -local DetectRemnant = fun1:EveryManySeconds(2, RefreshActiveRemnants) -RefreshActiveRemnants() - -Consider[4] = function() - local ability = Abilities[4] - if not ability:IsFullyCastable() or IsUsingSleightOfFist() or IsUsingRemnant() or fun1:CannotMove(npcBot) then - return 0 - end - DetectRemnant() - if #activeRemnants == 0 then - return 0 - end - local abilityLevel = ability:GetLevel() - local radius = ability:GetAOERadius()-100 - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local damage = ability:GetAbilityDamage() - local enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 900) - local friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - local weakCreeps = fun1:Filter(enemyCreeps, function(t) return t:GetHealth() < t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) end) - local weakestCreep = utility.GetWeakestUnit(weakCreeps) - local forbiddenCreeps = fun1:Filter(enemyCreeps, function(t) - return t:GetHealth() > t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) and t:GetHealth() <= t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) + fun1:AttackOnceDamage(npcBot, t) * (0.9+#enemyCreeps*0.1) - end) - if #friendCreeps == 0 then - forbiddenCreeps = {} - end - - if fun1:IsFarmingOrPushing(npcBot) and fun1:GetManaPercent(npcBot) >= 0.9 then - for _, activeRemnant in ipairs(activeRemnants) do - if #weakCreeps >= 3 and #forbiddenCreeps == 0 then - return BOT_ACTION_DESIRE_MODERATE, activeRemnant:GetLocation() - end - end - end - - if healthPercent >= 0.75 and manaPercent >= 0.9 and fun1:GetDistanceFromAncient(npcBot) <= 1000 and DotaTime() <= 15 * 60 then - if fun1:IsLaning(npcBot) then - local laneFront = GetLaneFrontLocation(GetTeam(), npcBot:GetAssignedLane(), 0) - local remnantUnderTower = fun1:Filter(activeRemnants, function(t) return GetUnitToLocationDistance(t, laneFront) <= 1000 end) - if remnantUnderTower[1] then - return BOT_ACTION_DESIRE_MODERATE, remnantUnderTower[1]:GetLocation() - end - elseif fun1:IsFarmingOrPushing(npcBot) then - local remnantUnderTower = fun1:Filter(activeRemnants, function(t) - return GetUnitToUnitDistance(t, npcBot) >= 4000 and #fun1:GetNearbyNonIllusionHeroes(t) == 0 - end) - if remnantUnderTower[1] then - return BOT_ACTION_DESIRE_MODERATE, remnantUnderTower[1]:GetLocation() - end - end - end - if fun1:IsAttackingEnemies(npcBot) then - for _, activeRemnant in ipairs(activeRemnants) do - local enemies = fun1:GetNearbyHeroes(activeRemnant, 1599) - local enemyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) - local friends = fun1:GetNearbyHeroes(activeRemnant, 1200, true) - local friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - local veryNearEnemies = fun1:GetEnemyHeroNumber(npcBot, fun1:GetNearbyHeroes(activeRemnant, 400)) - if friendCount >= enemyCount and veryNearEnemies == 0 then - return BOT_ACTION_DESIRE_MODERATE, activeRemnant:GetLocation() - end - end - end - - if fun1:IsRetreating(npcBot) then - local distanceToFountain = fun1:Filter(activeRemnants, function(t) - local distance = GetUnitToUnitDistance(t, npcBot) - return distance >= npcBot:GetCurrentMovementSpeed() * 2.5 and distance >= 700 and distance > fun1:GetDistanceFromAncient(t) + 600 - end) - distanceToFountain = fun1:Map(distanceToFountain, function(t) return { t, fun1:GetDistanceFromAncient(t) } end) - distanceToFountain = fun1:SortByMinFirst(distanceToFountain, function(t) return t[2] end) - if fun1:Any(distanceToFountain) then - return BOT_ACTION_DESIRE_HIGH, distanceToFountain[1][1]:GetLocation() - end - end - - if fun1:NotRetreating(npcBot) then - for _, activeRemnant in ipairs(activeRemnants) do - local target = fun1:GetTargetIfGood(npcBot) - if target ~= nil and target:CanBeSeen() and fun1:NormalCanCast(target, false) and GetUnitToUnitDistance(activeRemnant, target) <= radius then - if fun1:GetHealthPercent(target) <= 0.7 then - if fun1:Any(activeRemnants, function(t) - local d = GetUnitToUnitDistance(t, target) - return d >= 0.7*radius and d <= 800 and t:IsFacingLocation(target, 30) and t:GetCurrentMovementSpeed() ~= 0 - end) then - return 0.1, activeRemnant:GetLocation() - end - return RemapValClamped(fun1:GetHealthPercent(target), 0, 0.7, 0.9, 0.5), activeRemnant:GetLocation() - end - end - local enemies = fun1:GetNearbyNonIllusionHeroes(activeRemnant) - local realEnemies = fun1:Filter(enemies, function(t) return - fun1:MayNotBeIllusion(npcBot, t) and fun1:NormalCanCast(t, false) - end) - end - end - return 0 -end - -local function ShouldGoToFountainFromLane() - return healthPercent <= 0.25 and not fun1:HasAvailableItem "item_flask" or healthPercent <= 0.4 and manaPercent <= 0.1 -end - -Consider[5] = function() - local ability = Abilities[5] - if not ability:IsFullyCastable() or ability:GetCurrentCharges() == 0 then - return 0 - end - local abilityLevel = ability:GetLevel() - local castRange = ability:GetCastRange() - local radius = ability:GetAOERadius()-100 - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local damage = Abilities[4]:GetAbilityDamage() - local friends = fun1:GetNearbyHeroes(npcBot, 1200, true) - local friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - local enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 900) - local friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - local neutralCreeps = npcBot:GetNearbyNeutralCreeps(castRange) - local weakCreeps = fun1:Filter(enemyCreeps, function(t) return t:GetHealth() < t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) end) - local weakestCreep = utility.GetWeakestUnit(weakCreeps) - local forbiddenCreeps = fun1:Filter(enemyCreeps, function(t) - return t:GetHealth() > t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) and t:GetHealth() <= t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) + fun1:AttackOnceDamage(npcBot, t) * (0.9+#enemyCreeps*0.1) - end) - if #friendCreeps == 0 then - forbiddenCreeps = {} - end - local charge = ability:GetCurrentCharges() - if charge == 0 then - return 0 - end - local remnantSpeed = npcBot:GetCurrentMovementSpeed() * ability:GetSpecialValueInt "speed_multiplier" / 100 - - if fun1:IsFarmingOrPushing(npcBot) and fun1:GetManaPercent(npcBot) >= 0.9 then - local nearbyTowers = npcBot:GetNearbyTowers(1100, true) - if #nearbyTowers == 1 and (nearbyTowers[1] == GetTower(GetTeam(), TOWER_MID_1) or nearbyTowers[1] == GetTower(GetTeam(), TOWER_MID_2)) then - if ShouldGoToFountainFromLane() then - if #activeRemnants == 0 then - return BOT_ACTION_DESIRE_HIGH, nearbyTowers[1]:GetLocation() + RandomVector(200) - else - local enemies = fun1:GetNearbyHeroes(npcBot, 800) - local realEnemies = fun1:Filter(enemies, function(t) return fun1:MayNotBeIllusion(npcBot, t) end) - if #realEnemies == 0 then - fun1:TryUseTp(npcBot) - end - end - end - end - end - - if fun1:IsRetreating(npcBot) then - if IsUsingRemnant() then - return 0 - end - local enemies = fun1:GetNearbyHeroes(npcBot) - if npcBot:WasRecentlyDamagedByAnyHero(1.5) and #enemies ~= 0 then - if #activeRemnants ~= 0 then - return 0 - end - local useRange = castRange - 80 - local nearestEnemy = enemies[1] - local strangeFacing = npcBot:GetFacing() - if nearestEnemy:IsFacingLocation(npcBot:GetLocation(), 20) then - strangeFacing = nearestEnemy:GetFacing() + 75 - end - local extraLocation = npcBot:GetLocation() + Vector(useRange * math.cos(strangeFacing), useRange * math.sin(strangeFacing)) - if npcBot:HasScepter() then - extraLocation = fun1:GetPointFromLineByDistance(npcBot:GetLocation(), fun1:GetAncient(npcBot), useRange) - end - if npcBot:GetCurrentMovementSpeed() >= 285 or npcBot:GetCurrentMovementSpeed() >= 240 and IsUsingSleightOfFist() then - return BOT_ACTION_DESIRE_HIGH, extraLocation - end - end - else - local target = fun1:GetTargetIfGood(npcBot) - if target ~= nil and target:CanBeSeen() and fun1:NormalCanCast(target, false) then - if fun1:GetHealthPercent(target) <= 0.7 then - local remnantNumber = fun1:Count(activeRemnants, function(t) - return GetUnitToUnitDistance(t, target) <= radius - end) - local damageOnce = target:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) - if target:GetHealth() <= (0.9+0.18*friendCount) * damageOnce * remnantNumber + charge then - return BOT_ACTION_DESIRE_HIGH, target:GetExtrapolatedLocation(GetUnitToUnitDistance(target, npcBot) / Clamp((remnantSpeed - target:GetCurrentMovementSpeed()), 100, 1000)) - end - end - end - end - return 0 -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, Abilities) - -function AbilityUsageThink() - if refreshRemnantToken then - RefreshActiveRemnants() - refreshRemnantToken = nil - end - if npcBot:IsChanneling() or npcBot:IsSilenced() then - return - end - attackRange = npcBot:GetAttackRange() - health = npcBot:GetHealth() - maxHealth = npcBot:GetMaxHealth() - healthPercent = fun1:GetHealthPercent(npcBot) - mana = npcBot:GetMana() - maxMana = npcBot:GetMaxMana() - manaPercent = fun1:GetManaPercent(npcBot) - - enemies = fun1:GetNearbyHeroes(npcBot, 1599) - realEnemies = fun1:Filter(enemies, function(t) return fun1:MayNotBeIllusion(npcBot, t) end) - friends = fun1:GetNearbyHeroes(npcBot, 1599, true) - friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 1599) - friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - neutralCreeps = npcBot:GetNearbyNeutralCreeps(1599) - tower = fun1:GetLaningTower(npcBot) - - cast=ability_item_usage_generic.ConsiderAbility(Abilities,Consider) - local abilityIndex, target, castType = ability_item_usage_generic.UseAbility(Abilities,cast) - fun1:RecordAbility(npcBot, abilityIndex, target, castType, Abilities) - if abilityIndex == 5 then - refreshRemnantToken = true - end -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_faceless_void.mira b/mira/ability_item_usage_faceless_void.mira deleted file mode 100644 index cdf6ec9..0000000 --- a/mira/ability_item_usage_faceless_void.mira +++ /dev/null @@ -1,439 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.1 NewStructure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[1], - Abilities[3], - Abilities[1], - Abilities[2], - Abilities[1], - Abilities[5], - Abilities[1], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - Abilities[5], - Abilities[2], - Abilities[2], - "talent", - Abilities[2], - "nil", - Abilities[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[3] - end, - function() - return Talents[6] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast={utility.NCanCast,utility.NCanCast,utility.NCanCast,utility.CanCastNoTarget,utility.UCanCast,} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() or fun1:CannotMove(npcBot) then - return BOT_ACTION_DESIRE_NONE, 0; - end - if fun1:GameNotReallyStarting() then - return 0 - end - - local CastRange = ability:GetSpecialValueInt( "range" ); - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local trees= npcBot:GetNearbyTrees(300) - - if(npcBot.FacelessVoidSkill1==nil or DotaTime()-npcBot.FacelessVoidSkill1.Timer>=2) - then - npcBot.FacelessVoidSkill1={Hp=HealthPercentage,Timer=DotaTime()} - end - - --try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - local enemys2= WeakestEnemy:GetNearbyHeroes(900,true,BOT_MODE_NONE) - if ( CanCast[abilityNumber]( WeakestEnemy ) and #enemys2<=2) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana) - then - return BOT_ACTION_DESIRE_MODERATE,utility.GetUnitsTowardsLocation(npcBot,WeakestEnemy,CastRange+200); - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we trapped by the trees - if(trees~=nil and #trees>=6) - then - return BOT_ACTION_DESIRE_HIGH, utility.GetUnitsTowardsLocation(npcBot,GetAncient(GetTeam()),CastRange-200) + RandomVector(200); - end - - -- try to dodge a projectile - local projectiles = npcBot:GetIncomingTrackingProjectiles() - for _,p in pairs(projectiles) - do - if GetUnitToLocationDistance(npcBot, p.location) <= 400 and p.is_attack == false and not fun1:IgnoreAbilityBlock(p.ability) then - return BOT_ACTION_DESIRE_HIGH, fun1:GetPointFromLineByDistance(npcBot:GetLocation(), p.location, 450) - end - end - - -- If we're seriously retreating - if ( fun1:IsRetreating(npcBot) or npcBot.FacelessVoidSkill1.Hp-HealthPercentage>=0.25+0.05*#enemys) - then - return BOT_ACTION_DESIRE_HIGH, utility.GetUnitsTowardsLocation(npcBot,GetAncient(GetTeam()),CastRange) - end - - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT and ManaPercentage>ComboMana and AbilitiesReal[4]:IsFullyCastable()) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), CastRange+400, 425, 0, 0 ); - if ( locationAoE.count >= 2) - then - return BOT_ACTION_DESIRE_HIGH+0.05, locationAoE.targetloc; - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if(ManaPercentage>0.4 or npcBot:GetMana()>ComboMana) - then - if ( npcEnemy ~= nil ) - then - local enemys2= npcEnemy:GetNearbyHeroes(900,true,BOT_MODE_NONE) - if (enemys2~=nil and #enemys2<=2) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)>CastRange-200 and GetUnitToUnitDistance(npcBot,npcEnemy)<1000) - then - return BOT_ACTION_DESIRE_MODERATE, utility.GetUnitsTowardsLocation(npcBot,npcEnemy,CastRange+200); - end - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = 0 - local Damage = ability:GetAbilityDamage() - local Radius = ability:GetAOERadius() - local CastPoint = ability:GetCastPoint() - - - local allys = npcBot:GetNearbyHeroes(Radius, false, BOT_MODE_NONE ); - local WeakestAlly,AllyHealth=utility.GetWeakestUnit(allys) - local enemys = npcBot:GetNearbyHeroes(Radius,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy )) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - if(npcBot:GetActiveMode() == BOT_MODE_ATTACK) - then - if(npcBot:WasRecentlyDamagedByAnyHero(2) or #enemys >=2) - then - for _,npcEnemy in pairs( enemys ) - do - if ( CanCast[abilityNumber]( npcEnemy ) ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = fun1:GetTargetIfGood(npcBot) - - if ( npcEnemy ~= nil and #enemys==1) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)<=Radius) - then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - - return BOT_ACTION_DESIRE_NONE -end - -local timeWalkLocation -local timeWalkTime -Consider[4] = function() - local abilityNumber = 4 - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() or ability:IsHidden() then - return BOT_ACTION_DESIRE_NONE - end - if not timeWalkLocation or not timeWalkTime then - return 0 - end - - if fun1:IsAttackingEnemies(npcBot) then - if local target = fun1:GetTargetIfGood(npcBot) then - local disHere = GetUnitToUnitDistanceSqr(target, npcBot) - local dis = GetUnitToLocationDistanceSqr(target, timeWalkLocation) - if dis - disHere >= 300000 then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - if fun1:IsRetreating() then - local timeWalkLocationEnemies = fun1:GetEnemyHeroNumber(npcBot, fun1:GetNearbyNonIllusionHeroes(npcBot, 1400):Filter { t -> - GetUnitToLocationDistance(t, timeWalkLocation) <= 350 - }) - local enemies = fun1:GetEnemyHeroNumber(npcBot, fun1:GetNearbyNonIllusionHeroes(npcBot, 350)) - local timeDiff = DotaTime() - timeWalkTime - if timeWalkLocationEnemies < enemies then - if fun1:GetHealthPercent(npcBot) <= 0.15 and timeDiff >= 1 then - return BOT_ACTION_DESIRE_MODERATE - end - if GetUnitToLocationDistanceSqr(npcBot, timeWalkLocation) >= 640000 then - return BOT_ACTION_DESIRE_HIGH - end - end - end - - return 0 -end - -Consider[5]=function() - local abilityNumber=5 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = 0 - local Radius = ability:GetAOERadius()-50; - local CastPoint = ability:GetCastPoint() - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- Check for a channeling enemy - for _,npcEnemy in pairs( enemys ) - do - if ( npcEnemy:IsChanneling() ) - then - local TargetLocation=npcEnemy:GetLocation(); - local Allies = utility.GetAlliesNearLocation(TargetLocation,Radius) - if(#Allies==0) - then - return BOT_ACTION_DESIRE_MODERATE, TargetLocation - end - end - end - - --try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana) - then - local TargetLocation=WeakestEnemy:GetExtrapolatedLocation(CastPoint); - local Allies = utility.GetAlliesNearLocation(TargetLocation,Radius) - if(#Allies==0) - then - return BOT_ACTION_DESIRE_MODERATE-0.1, TargetLocation - end - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0 ); - if ( locationAoE.count >= 3 ) - then - local TargetLocation=locationAoE.targetloc; - local Allies = utility.GetAlliesNearLocation(TargetLocation,Radius) - if(#Allies==0) - then - return BOT_ACTION_DESIRE_LOW-0.1, TargetLocation - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0 ); - if ( locationAoE.count >= 3 ) then - local TargetLocation=locationAoE.targetloc; - local Allies = utility.GetAlliesNearLocation(TargetLocation,Radius) - if(#Allies<=1) - then - return BOT_ACTION_DESIRE_HIGH, TargetLocation - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - local index, target = ability_item_usage_generic.UseAbility(AbilitiesReal,cast) - if index == 1 then - timeWalkLocation = npcBot:GetLocation() - timeWalkTime = DotaTime() - end -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_kunkka.mira b/mira/ability_item_usage_kunkka.mira deleted file mode 100644 index 4e36d2c..0000000 --- a/mira/ability_item_usage_kunkka.mira +++ /dev/null @@ -1,610 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.5e --- Author: adamqqq Email:adamqqq@163.com --- Contributor: zmcmcc Email:mengzhang@utexas.edu ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") -local A = require(GetScriptDirectory().."/util/MiraDota") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[2], - Abilities[1], - Abilities[2], - Abilities[3], - Abilities[2], - Abilities[6], - Abilities[2], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - Abilities[6], - Abilities[1], - Abilities[1], - "talent", - Abilities[1], - "nil", - Abilities[6], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} -local TalentTree={ - function() - return Talents[2] - end, - function() - return Talents[3] - end, - function() - return Talents[6] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast = { - function(t) - return fun1:StunCanCast(t, AbilitiesReal[1], false, false, true, false) - end, - fun1.PhysicalCanCastFunction, - utility.NCanCast, - utility.NCanCast, - utility.NCanCast, - function(t) - return fun1:StunCanCast(t, AbilitiesReal[6], false, false, true, true) - end, -} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -local xMarkTarget -local xMarkTime -local xMarkLocation -local xMarkDuration -local useTorrentAtXMark -local useTorrentAtXMarkTime -local xMarkTargetWasTeleporting - -local function XMarksEnemy() - return A.Dota.IsValidUnit(xMarkTarget) and xMarkTarget:GetTeam() ~= npcBot:GetTeam() -end - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local Radius = ability:GetAOERadius() - local CastPoint = 2 - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - -- Check for a channeling enemy - for _,npcEnemy in pairs( enemys ) - do - if ( npcEnemy:IsChanneling() ) - then - return BOT_ACTION_DESIRE_HIGH-0.1, npcEnemy:GetLocation(); - end - end - - if XMarksEnemy() and CanCast[1](xMarkTarget) and DotaTime()-xMarkTime <= 0.8 then - return BOT_ACTION_DESIRE_VERYHIGH, xMarkLocation - end - - --try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) and WeakestEnemy:HasModifier("modifier_kunkka_x_marks_the_spot")) - then - if WeakestEnemy:GetModifierRemainingDuration( WeakestEnemy:GetModifierByName('modifier_kunkka_x_marks_the_spot') )< 1.6 - then - return BOT_ACTION_DESIRE_HIGH+0.15, WeakestEnemy:GetExtrapolatedLocation(-2.5); - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - for _,npcEnemy in pairs( enemys ) - do - if ( npcBot:WasRecentlyDamagedByHero( npcEnemy, 2.0 ) ) - then - if ( CanCast[abilityNumber]( npcEnemy ) ) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy:GetExtrapolatedLocation(CastPoint+0.5); - end - end - end - end - - -- If we're farming and can kill 3+ creeps - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if((ManaPercentage>0.4 or npcBot:GetMana()>ComboMana)) - then - local locationAoE = npcBot:FindAoELocation( true, false, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0 ); - if ( locationAoE.count >= 3 ) then - return BOT_ACTION_DESIRE_LOW, locationAoE.targetloc; - end - end - end - - -- If we're pushing or defending a lane and can hit 4+ creeps - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if((ManaPercentage>0.4 or npcBot:GetMana()>ComboMana)) - then - local locationAoE = npcBot:FindAoELocation( true, false, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0 ); - if ( locationAoE.count >= 4 ) - then - return BOT_ACTION_DESIRE_LOW, locationAoE.targetloc; - end - end - end - - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local locationAoE = npcBot:FindAoELocation( true, true, npcBot:GetLocation(), CastRange, Radius, CastPoint, 0 ); - if ( locationAoE.count >= 2 ) then - return BOT_ACTION_DESIRE_MODERATE, locationAoE.targetloc; - end - - local npcTarget = npcBot:GetTarget(); - if ( npcTarget ~= nil ) - then - if ( CanCast[abilityNumber]( npcTarget ) and npcTarget:HasModifier("modifier_kunkka_x_marks_the_spot")) - then - if npcTarget:GetModifierRemainingDuration( npcTarget:GetModifierByName('modifier_kunkka_x_marks_the_spot') )< 1.6 - then - return BOT_ACTION_DESIRE_HIGH+0.15, npcTarget:GetExtrapolatedLocation(-2.5); - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; -end - --- Consider[2] = function() --- local ability=AbilitiesReal[3]; - --- if not ability:IsFullyCastable() then --- return 0 --- end - --- local CastRange = ability:GetCastRange(); --- local Damage = ability:GetAbilityDamage(); - --- local HeroHealth=10000 --- local CreepHealth=10000 --- local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); --- local enemys = npcBot:GetNearbyHeroes(CastRange,true,BOT_MODE_NONE) --- local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - --- if npcBot:GetActiveMode() == BOT_MODE_LANING then --- if ability:GetAutoCastState() then --- ability:ToggleAutoCast() --- end - --- end --- Consider[2] = fun1:ToggleFunctionToAutoCast(npcBot, AbilitiesReal[2], Consider[2]) - --- Consider[4] = function() --- return 0 --- end --- Consider[5] = function() --- return 0 --- end - -Consider[3]=function() - - local ability=AbilitiesReal[3]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - - -- Check for a channeling enemy - for _,enemy in pairs( enemys ) - do - if ( enemy:IsChanneling() and CanCast[3]( enemy ) and not enemy:IsSilenced()) - then - return BOT_ACTION_DESIRE_HIGH, enemy - end - end - - --try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[3]( WeakestEnemy ) and ManaPercentage > 0.5) - then - if((HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) or npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy; - end - end - end - end - - -- If a mode has set a target, and we can kill them, do it - local npcTarget = npcBot:GetTarget(); - if ( npcTarget ~= nil ) - then - if(CanCast[3]( npcTarget )) - then - if (GetComboDamage()*(0.85+0.15*#allys) > npcTarget:GetHealth() and GetUnitToUnitDistance( npcTarget, npcBot ) < ( CastRange + 200 ) ) - then - return BOT_ACTION_DESIRE_HIGH, npcTarget; - end - end - end - - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1000, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 ) - then - - local npcMostDangerousEnemy = nil; - local nMostDangerousDamage = 0; - - local tableNearbyEnemyHeroes = npcBot:GetNearbyHeroes( CastRange, true, BOT_MODE_NONE ); - for _,npcEnemy in pairs( tableNearbyEnemyHeroes ) - do - if ( CanCast[3]( npcEnemy ) and not npcEnemy:IsSilenced()) - then - local Damage = npcEnemy:GetEstimatedDamageToTarget( false, npcBot, 3.0, DAMAGE_TYPE_ALL ); - if ( Damage > nMostDangerousDamage ) - then - nMostDangerousDamage = Damage; - npcMostDangerousEnemy = npcEnemy; - end - end - end - - if ( npcMostDangerousEnemy ~= nil ) - then - return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy; - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcTarget = npcBot:GetTarget(); - - if ( npcTarget ~= nil ) - then - if ( CanCast[3]( npcTarget ) and not npcTarget:IsSilenced() and GetUnitToUnitDistance(npcBot,npcTarget)< CastRange) - then - return BOT_ACTION_DESIRE_HIGH, npcTarget; - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0 -end - --- ghost ship -Consider[6]=function() - - local abilityNumber=6 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = 1600; - local Damage = ability:GetAbilityDamage(); - local Radius = ability:GetAOERadius()-300; - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana) - then - if not AbilitiesReal[1]:IsFullyCastable() or WeakestEnemy:GetModifierRemainingDuration( WeakestEnemy:GetModifierByName('modifier_kunkka_x_marks_the_spot') )< 1.2 - then - return BOT_ACTION_DESIRE_HIGH,WeakestEnemy:GetExtrapolatedLocation(-2.9); - end - end - end - end - end - - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're in a teamfight, use it on the scariest enemy - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 1000, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 ) - then - - local npcMostDangerousEnemy = nil; - local nMostDangerousDamage = 0; - - local tableNearbyEnemyHeroes = npcBot:GetNearbyHeroes( CastRange, true, BOT_MODE_NONE ); - for _,npcEnemy in pairs( tableNearbyEnemyHeroes ) - do - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy)) - then - local Damage2 = npcEnemy:GetEstimatedDamageToTarget( false, npcBot, 3.0, DAMAGE_TYPE_ALL ); - if ( Damage2 > nMostDangerousDamage ) - then - nMostDangerousDamage = Damage2; - npcMostDangerousEnemy = npcEnemy; - end - end - end - - if ( npcMostDangerousEnemy ~= nil ) - then - return BOT_ACTION_DESIRE_LOW, npcMostDangerousEnemy:GetLocation(); - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK) - then - local npcEnemy = fun1:GetTargetIfGood(npcBot) - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy )) - then - if not AbilitiesReal[1]:IsFullyCastable() or npcEnemy:GetModifierRemainingDuration( npcEnemy:GetModifierByName('modifier_kunkka_x_marks_the_spot') )< 1.2 - then - return BOT_ACTION_DESIRE_HIGH, npcEnemy:GetExtrapolatedLocation(-2.9); - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; -end - --- torrent storm -Consider[4] = function() - local ability = AbilitiesReal[4] - if not ability:IsFullyCastable() or ability:IsHidden() then - return 0 - end - local abilityLevel = ability:GetLevel() - local castRange = ability:GetCastRange() + 200 - local radius = ability:GetAOERadius() - local enemies = fun1:GetNearbyHeroes(npcBot, castRange + radius) - local realEnemies = fun1:Filter(enemies, function(t) return fun1:MayNotBeIllusion(npcBot, t) end) - local targettableEnemies = fun1:Filter(enemies, function(t) return fun1:NormalCanCast(t, false) and not fun1:CannotBeAttacked(t) end) - local target = npcBot:GetTarget() - - if fun1:GetEnemyHeroNumber(npcBot, enemies) >= 2 then - return RemapValClamped(fun1:GetEnemyHeroNumber(npcBot, enemies), 2, 4, BOT_ACTION_DESIRE_LOW + 0.1, BOT_ACTION_DESIRE_VERYHIGH) - end - if fun1:Contains(targettableEnemies, target) then - return BOT_ACTION_DESIRE_MODERATE - end - return 0 -end - --- tidal wave --- how to use a vector targeted ability? -Consider[5] = function() - local ability = AbilitiesReal[5] - if not ability:IsFullyCastable() or ability:IsHidden() then - return 0 - end - - local abilityLevel = ability:GetLevel() - local radius = ability:GetAOERadius()-100 - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local damage = ability:GetAbilityDamage() - local castRange = ability:GetCastRange() - - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, castRange) - local enmeyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) - return 0 -end - --- this initialisation doesn't work, because ability values cannot be queried before they are learned ---local torrentDelay = AbilitiesReal[1]:GetSpecialValueFloat("delay") ---local xMarksReturnCastPoint = AbilitiesReal[1]:GetCastPoint() - --- x_marks_the_target recall --- name: kunkka_return -Consider[7] = function() - local abilityNumber=7 - local ability=AbilitiesReal[abilityNumber] - if useTorrentAtXMarkTime then - -- print("use torrent time "..useTorrentAtXMarkTime..", should recall at "..(useTorrentAtXMarkTime + AbilitiesReal[1]:GetSpecialValueFloat("delay") - ability:GetCastPoint())) - end - - if not ability:IsFullyCastable() or ability:IsHidden() or xMarkTarget == nil or not xMarkTarget:HasModifier("modifier_kunkka_x_marks_the_spot") then - return 0 - end - if xMarkTarget:IsChanneling() then - if xMarkTarget:HasModifier "modifier_teleporting" then - xMarkTargetWasTeleporting = true - return 0 - end - return BOT_ACTION_DESIRE_VERYHIGH - end - if xMarkTargetWasTeleporting then - xMarkTargetWasTeleporting = nil - return BOT_ACTION_DESIRE_VERYHIGH - end - - if XMarksEnemy() and npcBot:GetActiveMode() ~= BOT_MODE_RETREAT and GetUnitToUnitDistance(npcBot, xMarkTarget) >= 1800 then - return BOT_ACTION_DESIRE_HIGH - end - if XMarksEnemy() and npcBot:GetActiveMode() == BOT_MODE_RETREAT and (GetUnitToUnitDistance(npcBot, xMarkTarget) <= 300 or npcBot:WasRecentlyDamagedByHero(xMarkTarget, 1)) and DotaTime() > 1 + xMarkTime and GetUnitToLocationDistance(xMarkTarget, xMarkLocation) then - return BOT_ACTION_DESIRE_HIGH - end - if XMarksEnemy() and useTorrentAtXMark then - -- print("use torrent time "..useTorrentAtXMarkTime..", should recall at "..(useTorrentAtXMarkTime + AbilitiesReal[1]:GetSpecialValueFloat("delay") - ability:GetCastPoint())) - local timing = useTorrentAtXMarkTime + AbilitiesReal[1]:GetSpecialValueFloat("delay") - ability:GetCastPoint() - if DotaTime() >= timing-0.1 then - return BOT_ACTION_DESIRE_VERYHIGH - end - end -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - if npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - - pcall({-> - if xMarkTarget and (not npcBot:IsAlive() or not xMarkTarget:IsAlive() or not xMarkTarget:HasModifier("modifier_kunkka_x_marks_the_spot")) then - xMarkTarget = nil - xMarkTime = nil - xMarkLocation = nil - useTorrentAtXMark = false - useTorrentAtXMarkTime = nil - end - }) - - local index, target = ability_item_usage_generic.UseAbility(AbilitiesReal, cast) - if index == 3 and target ~= nil then - xMarkTarget = target - xMarkTime = DotaTime()+AbilitiesReal[3]:GetCastPoint() - xMarkLocation = target:GetLocation() - if target:GetTeam() == npcBot:GetTeam() then - xMarkDuration = AbilitiesReal[3]:GetSpecialValueFloat("allied_duration") or 8 - else - xMarkDuration = AbilitiesReal[3]:GetSpecialValueFloat("duration") or 4 - end - elseif index == 1 and xMarkTarget then - useTorrentAtXMark = true - useTorrentAtXMarkTime = DotaTime() + AbilitiesReal[1]:GetCastPoint() - -- print("torrent time after a x mark: "..useTorrentAtXMarkTime) - end -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_lycan.mira b/mira/ability_item_usage_lycan.mira deleted file mode 100644 index e8f9986..0000000 --- a/mira/ability_item_usage_lycan.mira +++ /dev/null @@ -1,381 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.3 New Structure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[3], - Abilities[1], - Abilities[3], - Abilities[1], - Abilities[1], - Abilities[5], - Abilities[1], - Abilities[3], - Abilities[3], - "talent", - Abilities[2], - Abilities[5], - Abilities[2], - Abilities[2], - "talent", - Abilities[2], - "nil", - Abilities[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[2] - end, - function() - return Talents[4] - end, - function() - return Talents[6] - end, - function() - return Talents[8] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast={utility.NCanCast,utility.NCanCast,utility.NCanCast, - { t -> fun1:AllyCanCast(t) and not t:HasModifier "modifier_lycan_wolf_bite_lifesteal"}, - utility.UCanCast -} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -Consider[1]=function() - - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = 500; - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - - local wolves = 0; - local units = GetUnitList(UNIT_LIST_ALLIES); - for _,unit in pairs(units) - do - if string.find(unit:GetUnitName(), "npc_dota_lycan_wolf") then - wolves = wolves + 1; - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If my mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if(ManaPercentage>0.6 or npcBot:GetMana()>ComboMana and wolves < 1 ) then - return BOT_ACTION_DESIRE_LOW; - end - end - - -- If we're farming and can kill 3+ creeps with LSA - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - local locationAoE = npcBot:FindAoELocation( true, false, npcBot:GetLocation(), 600, 300, 0, 0 ); - if ( locationAoE.count >= 3 and npcBot:GetMana()/npcBot:GetMaxMana() > 0.65 and wolves < 1 ) then - return BOT_ACTION_DESIRE_LOW; - end - end - - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - if ( npcBot:WasRecentlyDamagedByAnyHero( 2.0 ) and wolves < 1 ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - - if npcBot:GetActiveMode() == BOT_MODE_FARM - then - local npcTarget = npcBot:GetAttackTarget(); - if npcTarget ~= nil then - return BOT_ACTION_DESIRE_LOW; - end - end - - if ( npcBot:GetActiveMode() == BOT_MODE_ROSHAN ) - then - local npcTarget = npcBot:GetAttackTarget(); - if npcTarget~=nil - then - if string.find(npcTarget:GetUnitName(), "roshan") and GetUnitToUnitDistance(npcBot,npcTarget)< 600 and wolves < 1 then - return BOT_ACTION_DESIRE_LOW; - end - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys and wolves < 1) - then - return BOT_ACTION_DESIRE_MODERATE, npcEnemy - end - end - end - - return BOT_ACTION_DESIRE_NONE; - -end - -Consider[2]=function() - - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local CastPoint = ability:GetCastPoint(); - - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, 1600, false) - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, 1600, true) - local radius = 2000 - - if allys:Any(function(t) return fun1:GetHealthPercent(t) <= 0.5 and t:WasRecentlyDamagedByAnyHero(1.5) end) then - return BOT_ACTION_DESIRE_MODERATE - end - - if npcBot:GetActiveMode() == BOT_MODE_RETREAT and #enemies > 0 then - if ( npcBot:WasRecentlyDamagedByAnyHero( 2.0 )) - then - return BOT_ACTION_DESIRE_HIGH - end - end -end - --- wolf bite -Consider[4]=function() - local abilityNumber=4 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber] - - if not ability:IsFullyCastable() or ability:IsHidden() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = ability:GetCastRange() - local mana = npcBot:GetMana() - local allys = fun1:GetNearbyNonIllusionHeroes(npcBot, CastRange+200, false):Filter(CanCast[4]) - local enemies = fun1:GetNearbyNonIllusionHeroes(npcBot, 1500) - local enemyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) - - if enemyCount > 0 then - local function BiteAllyDesire(ally) - local desire = 0 - local perc = fun1:GetHealthPercent(ally) - desire += RemapValClamped(perc, 0.3, 0.8, 2, 1) - if fun1:IsSeverelyDisabled(ally) then - desire -= 1 - end - local speed = fun1:GetMovementSpeedPercent(ally) - desire += RemapValClamped(speed, 0.2, 0.7, 0.8, 0) - if ally:HasModifier "modifier_ice_blast" or fun1:IsRetreating(ally) then - desire -= 0.5 - end - desire *= Clamp(ally:GetNetWorth() / npcBot:GetNetWorth(), 0.5, 2) - if mana <= 300 and AbilitiesReal[5]:IsFullyCastable() or mana <= 160 then - desire = desire / 2 - end - return desire - end - if local target = allys:Map { t -> { t, BiteAllyDesire(t) } } - :SortByMaxFirst { t -> t[2] } - :First { t -> t[2] >= 0.9 } then - return RemapValClamped(target[2], 0.9, 2, BOT_ACTION_DESIRE_MODERATE, BOT_ACTION_DESIRE_VERYHIGH), target[1] - end - else - if mana >= 350 then - if local target = allys:Filter { t -> - CanCast[4](t) and not t:HasModifier "modifier_ice_blast" and fun1:NotRetreating(t) - } - :Map { t -> - { t, (1-fun1:GetHealthPercent(ally)) * fun1:GetTargetHealAmplifyPercent(ally) } - } - :SortByMaxFirst { t->t[2] } - :First { t->t[2]>= 0.6 } then - return BOT_ACTION_DESIRE_MODERATE, target[1] - end - end - end - return BOT_ACTION_DESIRE_NONE -end - -Consider[5]=function() - - local abilityNumber=5 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local CastPoint = ability:GetCastPoint(); - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - if ( npcBot:WasRecentlyDamagedByAnyHero( 2.0 )) - then - return BOT_ACTION_DESIRE_HIGH - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = fun1:GetTargetIfGood(npcBot) - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< 600 + 75*#allys ) - then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - - -- If we're in a teamfight, use it - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes( 700, false, BOT_MODE_ATTACK ); - if ( #tableNearbyAttackingAlliedHeroes >= 2 ) - then - local npcEnemy = fun1:GetTargetIfGood(npcBot) - - if GetUnitToUnitDistance(npcBot, npcEnemy) <= 600 then - return BOT_ACTION_DESIRE_HIGH-0.1 - end - end - - return BOT_ACTION_DESIRE_NONE; - -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_necrolyte.mira b/mira/ability_item_usage_necrolyte.mira deleted file mode 100644 index e04836c..0000000 --- a/mira/ability_item_usage_necrolyte.mira +++ /dev/null @@ -1,433 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.3 New Structure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local AbilityExtensions = require(GetScriptDirectory().."/util/AbilityAbstraction") -local A = require(GetScriptDirectory().."/util/MiraDota") - - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[1], - Abilities[3], - Abilities[1], - Abilities[2], - Abilities[1], - Abilities[5], - Abilities[1], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - Abilities[5], - Abilities[2], - Abilities[2], - "talent", - Abilities[2], - "nil", - Abilities[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} -local TalentTree={ - function() - return Talents[1] - end, - function() - return Talents[4] - end, - function() - return Talents[6] - end, - function() - return Talents[7] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast={function(t) - if AbilityExtensions:IsOnSameTeam(npcBot, t) then - return AbilityExtensions:AllyCanCast(t) and not t:HasModifier "modifier_ice_blast" - else - return AbilityExtensions:NormalCanCast(t) - end -end,utility.NCanCast,utility.NCanCast,{ t -> - if AbilityExtensions:IsOnSameTeam(npcBot, t) { - AbilityExtensions:AllyCanCast(t) - } else { - AbilityExtensions:NormalCanCast(t) - } - },function(t) - -> AbilityExtensions:NormalCanCast(t) and not AbilityExtensions:HasAnyModifier(t, AbilityExtensions.CannotKillModifiers) -} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE - end - - local CastRange = 0 - local Damage = ability:GetAbilityDamage() - local Radius = ability:GetAOERadius() - local CastPoint = ability:GetCastPoint() - - - local allys = npcBot:GetNearbyHeroes(Radius, false, BOT_MODE_NONE ); - local WeakestAlly,AllyHealth=utility.GetWeakestUnit(allys) - local enemys = npcBot:GetNearbyHeroes(Radius,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(Radius,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy )) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - - --protect teammate - if(ManaPercentage>0.5 or npcBot:GetMana()>ComboMana) - then - for _,npcTarget in pairs( allys ) - do - if(npcTarget:GetHealth()/npcTarget:GetMaxHealth()<(0.6+#enemys*0.05)) - then - if ( CanCast[abilityNumber]( npcTarget ) ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - if(ManaPercentage>0.4 or npcBot:GetMana()>ComboMana or (npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH) ) - then - if((npcBot:WasRecentlyDamagedByAnyHero(2) and #enemys>=1) or #enemys >=2 or HealthPercentage<=0.4) - then - for _,npcEnemy in pairs( enemys ) - do - if ( CanCast[abilityNumber]( npcEnemy ) ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - - -- If we're pushing or defending a lane - if ( npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT ) - then - if ( #enemys+#creeps>=5) - then - if (ManaPercentage>0.6 or npcBot:GetMana()>ComboMana * 1.5) - then - return BOT_ACTION_DESIRE_MODERATE, WeakestEnemy; - end - end - end - - -- If my mana is enough,use it at enemy - if ( npcBot:GetActiveMode() == BOT_MODE_LANING ) - then - if(ManaPercentage>0.75) - then - if (WeakestEnemy~=nil and WeakestCreep ~=nil ) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - return BOT_ACTION_DESIRE_LOW - end - end - end - end - - -- If we're farming and can hit 2+ creeps - if ( npcBot:GetActiveMode() == BOT_MODE_FARM ) - then - if ( #creeps >= 4 ) - then - if(ManaPercentage>0.5 or npcBot:GetMana()>ComboMana) - then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)<=Radius) - then - return BOT_ACTION_DESIRE_MODERATE - end - end - end - - return BOT_ACTION_DESIRE_NONE - - -end - -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = 0 - local Damage = 0 - local Radius = 750 - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - local enemys = npcBot:GetNearbyHeroes(Radius,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - - -------------------------------------- - -- Mode based usage - -------------------------------------- - --protect myself - if(npcBot:WasRecentlyDamagedByAnyHero(2.0) and #enemys>=2 and HealthPercentage<=0.35+0.05*#enemys) - then - return BOT_ACTION_DESIRE_HIGH - end - - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - if ( npcBot:WasRecentlyDamagedByAnyHero( 2.0 ) ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - return BOT_ACTION_DESIRE_NONE -end - -Consider[4] = function() - local ability = AbilitiesReal[4] - if not ability:IsFullyCastable() or ability:IsHidden() then - return 0 - end - - local castRange = ability:GetRange() - - local enemies = AbilityExtensions:GetPureHeroes(npcBot, castRange+200) - local allys = AbilityExtensions:GetPureHeroes(npcBot, castRange+200, false) - local strongestEnemy = enemies:Filter(CanCast[4]):Max { t -> t:GetNetWorth() } - - if AbilityExtensions:IsAttackingEnemies(npcBot) then - local target = AbilityExtensions:GetTargetIfGood(npcBot) - if target and AbilityExtensions:GetHealthPercent(target) <= 0.55 and AbilityExtensions:GetHealthPercent(target) >= 0.4 and target:GetHealth() > 600 and target:GetHealth() < (enemies:MaxV { t -> t:GetHealth() } or npcBot:GetHealth()) / 4 and AbilityExtensions:NormalCanCast(target) then - return BOT_ACTION_DESIRE_HIGH, target - end - - local fEnemy = enemies:Filter(CanCast[4]):First(function(t) return AbilityExtensions:DontInterruptAlly(t) end) - if fEnemy then - return BOT_ACTION_DESIRE_HIGH, fEnemy - end - if #enemies > 1 and #allys > 1 then - if AbilitiesReal[1]:IsFullyCastable() and #enemies > 1 + #allys then - return BOT_ACTION_DESIRE_MODERATE, strongestEnemy - else - return BOT_ACTION_DESIRE_VERYLOW, strongestEnemy - end - elseif #enemies > 1 and #allys == 1 then - if AbilitiesReal[1]:IsFullyCastable() then - return BOT_ACTION_DESIRE_HIGH, strongestEnemy - else - return BOT_ACTION_DESIRE_LOW, strongestEnemy - end - end - - if local weakestAlly = allys:Filter { t -> - CanCast[4](t) and not AbilityExtensions:DontInterruptAlly(t) and (AbilityExtensions:GetHealthPercent(t) < 0.3 and t:WasRecentlyDamagedByAnyHero(1.2) or AbilityExtensions:IsSeverelyDisabled(t)) and AbilityExtensions:NotBlasted(t) - }:SortByMinFirst { t -> AbilityExtensions:GetHealthPercent(t) } then - return BOT_ACTION_DESIRE_MODERATE, weakestAlly - end - end - - - if AbilityExtensions:IsRetreating(npcBot) then - if strongestEnemy then - return BOT_ACTION_DESIRE_HIGH, true - end - end - - return 0 -end - -Consider[5]=function() - - local abilityNumber=5 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local DamagePercent = ability:GetSpecialValueFloat("damage_per_health") - - - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ) - local enemys = AbilityExtensions:GetPureHeroes(npcBot, CastRange+300):Filter(A.Unit.IsNotCreepHero) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local maxHealth = (AbilityExtensions:GetNearbyHeroes(npcBot):MaxV { t -> - t:GetHealth() - } or npcBot:GetHealth()) / 3 - local allyNumber = AbilityExtensions:GetEnemyHeroNumber(npcBot, AbilityExtensions:Filter(allys) { t -> - AbilityExtensions:IsAttackingEnemies(t) or not t:IsBot() - }) - - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if local enemy = enemys:First(A.Hero.IsTeleporting); enemy and CanCast[abilityNumber](enemy) then - local k = (1-enemy:GetMagicResist()) * d * (1 + 0.08 * allyNumber) - local maxHealthPercentToKill = k / (1 + k) - if AbilityExtensions:GetHealthPercent(enemy) <= maxHealthPercentToKill then - return BOT_ACTION_DESIRE_HIGH, enemy - end - end - - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - for i,npcEnemy in pairs(enemys) - do - if ( CanCast[abilityNumber]( npcEnemy ) ) and not npcEnemy:IsMagicImmune() - then - local Damage=(npcEnemy:GetMaxHealth()-npcEnemy:GetHealth())*DamagePercent* (1+allyNumber*0.06) - local n1 = npcEnemy:GetHealth() - local n2 = npcEnemy:GetActualIncomingDamage(Damage, DAMAGE_TYPE_MAGICAL) - - if npcEnemy:GetHealth()<=npcEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) - and (npcEnemy:GetHealth() >= (ability:GetLevel()*100+300) and npcEnemy:GetHealth() > maxHealth - and AbilityExtensions:GetHealthPercent(npcEnemy) >= 0.25) - then - return BOT_ACTION_DESIRE_HIGH,npcEnemy - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0 -end -AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) - -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_omniknight.mira b/mira/ability_item_usage_omniknight.mira deleted file mode 100644 index c804cb2..0000000 --- a/mira/ability_item_usage_omniknight.mira +++ /dev/null @@ -1,491 +0,0 @@ ----------------------------------------------------------------------------- --- Ranked Matchmaking AI v1.1 NewStructure --- Author: adamqqq Email:adamqqq@163.com ----------------------------------------------------------------------------- --------------------------------------- --- General Initialization --------------------------------------- -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local AbilityExtensions = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[1], - Abilities[2], - Abilities[1], - Abilities[3], - Abilities[1], - Abilities[5], - Abilities[1], - Abilities[2], - Abilities[2], - "talent", - Abilities[2], - Abilities[5], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - "nil", - Abilities[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[2] - end, - function() - return Talents[4] - end, - function() - return Talents[6] - end, - function() - return Talents[8] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast={utility.NCanCast,utility.NCanCast,AbilityExtensions.PhysicalCanCastFunction,utility.NCanCast,utility.UCanCast} -local enemyDisabled=utility.enemyDisabled - -function GetComboDamage() - return ability_item_usage_generic.GetComboDamage(AbilitiesReal) -end - -function GetComboMana() - return ability_item_usage_generic.GetComboMana(AbilitiesReal) -end - -function GetAbilityTarget(npcTarget) - - -- if(npcTarget:GetTeam()~=npcBot:GetTeam()) - -- then - local Radius=AbilitiesReal[1]:GetAOERadius() - local tableNearbyEnemyHeroes = npcTarget:GetNearbyHeroes( Radius, true, BOT_MODE_NONE ); - local tableNearbyEnemyCreeps = npcTarget:GetNearbyCreeps( Radius, true ); - if(tableNearbyEnemyCreeps~=nil) - then - for _,c in pairs(tableNearbyEnemyCreeps) - do - if GetUnitToUnitDistance(c, npcTarget) < Radius and CanCast[1]( c ) - then - return BOT_ACTION_DESIRE_HIGH, c; - end - end - end - if(tableNearbyEnemyHeroes~=nil) - then - for _,h in pairs(tableNearbyEnemyHeroes) - do - if GetUnitToUnitDistance(h, npcTarget) < Radius and CanCast[1]( h ) - then - return BOT_ACTION_DESIRE_HIGH, h; - end - end - end - return 0,0 - --end - --return 0,0 -end - -function ComputeFactor(UnitGroup) - local HighestFactor=0 - local TempTarget - local Radius=AbilitiesReal[1]:GetAOERadius() - for _,npcTarget in pairs( UnitGroup ) - do - if ( CanCast[1]( npcTarget ) ) - then - local enemys2 = npcTarget:GetNearbyHeroes(Radius,true,BOT_MODE_NONE) - if(enemys2==nil) then enemys2={} end - local healingFactor=0.3+#enemys2*0.1+0.2*ManaPercentage-npcTarget:GetHealth()/npcTarget:GetMaxHealth() - if(enemyDisabled(npcTarget)) - then - healingFactor=healingFactor+0.1 - end - if(healingFactor>HighestFactor) - then - HighestFactor=healingFactor - TempTarget=npcTarget - end - end - end - if(TempTarget~=nil) - then - --npcBot:ActionImmediate_Chat("omniknight.purify.Factor="..HighestFactor.." Target:"..TempTarget:GetUnitName(),true) - end - return HighestFactor,TempTarget - -end - -function GetTargetFactor() - local allys = npcBot:GetNearbyHeroes( 1200, false, BOT_MODE_NONE ); - return ComputeFactor(allys) -end - -function GetTargetFactor2() - local Radius=AbilitiesReal[1]:GetAOERadius() - local allycreeps = npcBot:GetNearbyCreeps(Radius+300,false) - for i,creep in pairs(allycreeps) - do - local allycreeps2 = npcBot:GetNearbyCreeps(Radius,true) - if(#allycreeps2<3) - then - table.remove(allycreeps,i) - end - end - - local HighestFactor,TempTarget=GetTargetFactor() - local HighestFactor2,TempTarget2=ComputeFactor(allycreeps) - if(HighestFactor2>HighestFactor) - then - return HighestFactor2,TempTarget2 - else - return HighestFactor,TempTarget - end -end - -local function HealRate(t) - local healthDeficit = AbilityExtensions:GetHealthDeficit(t) - if healthDeficit <= 400 then - return 0 - end - local rate = Clamp(healthDeficit, 400, 1000) - rate -= Clamp(t:GetHealthRegen(), 10, 50) * 16 - if t:WasRecentlyDamagedByAnyHero(1.5) then - rate += 200 - end - rate *= AbilityExtensions:GetTargetHealAmplifyPercent(t) - return rate -end - - -Consider[1]=function() - local abilityNumber=1 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local CastPoint = ability:GetCastPoint(); - local Radius = ability:GetAOERadius(); - - local allys = AbilityExtensions:GetPureHeroes(npcBot, 1200, false) - allys = AbilityExtensions:Filter(npcBot, function(t) return not t:HasModifier("modifier_ice_blast") end) - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - local creeps = npcBot:GetNearbyCreeps(CastRange+300,true) - local WeakestCreep,CreepHealth=utility.GetWeakestUnit(creeps) - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - --Try to kill enemy hero - if(npcBot:GetActiveMode() ~= BOT_MODE_RETREAT ) - then - if (WeakestEnemy~=nil) - then - if ( CanCast[abilityNumber]( WeakestEnemy ) ) - then - if(HeroHealth<=WeakestEnemy:GetActualIncomingDamage(Damage,DAMAGE_TYPE_MAGICAL) or (HeroHealth<=WeakestEnemy:GetActualIncomingDamage(GetComboDamage(),DAMAGE_TYPE_MAGICAL) and npcBot:GetMana()>ComboMana)) - then - local desire,target=GetAbilityTarget(WeakestEnemy) - if(desire>0) - then - return desire,target - end - end - end - end - end - - if AbilityExtensions:NotRetreating(npcBot) then - if npcBot:GetMana() >= ComboMana and ability:GetLevel() >= 4 then - if local ally = AbilityExtensions:GetPureHeroes(npcBot, CastRange+150, false):Max(HealRate) then - local rate = HealRate(ally) - if rate >= 100 then - return BOT_ACTION_DESIRE_HIGH, ally - end - end - end - end - - -------------------------------------- - -- Mode based usage - -------------------------------------- - local enemys3 = npcBot:GetNearbyHeroes( Radius, true, BOT_MODE_NONE ) - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH ) - then - if ( npcBot:WasRecentlyDamagedByAnyHero( 2.0 ) and (#enemys3>=1 or #enemys==0) or HealthPercentage<=0.2) and not npcBot:HasModifier("modifier_ice_blast") - then - return BOT_ACTION_DESIRE_HIGH+0.08,npcBot; - end - end - - -- If we're going after someone - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - local npcEnemy = npcBot:GetTarget(); - - if ( npcEnemy ~= nil ) - then - if ( CanCast[abilityNumber]( npcEnemy ) and GetUnitToUnitDistance(npcBot,npcEnemy)< CastRange + 75*#allys) - then - local desire,target=GetAbilityTarget(npcEnemy) - if(desire>0) - then - return desire-0.02,target - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - -Consider[2]=function() - local abilityNumber=2 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange(); - local Damage = ability:GetAbilityDamage(); - local CastPoint = ability:GetCastPoint(); - - local enemys = npcBot:GetNearbyHeroes(CastRange+300,true,BOT_MODE_NONE) - local allys = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, CastRange+300, false, BOT_MODE_ATTACK ); - -------------------------------------- - -- Global high-priorty usage - -------------------------------------- - -- Protect ally - if (npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or npcBot:GetActiveMode() == BOT_MODE_ATTACK) then - local weakestAlly, allyHealth = utility.GetWeakestUnit(allys) - if (weakestAlly ~= nil) then - local allyNeaybyEnemys = weakestAlly:GetNearbyHeroes(CastRange, true, BOT_MODE_NONE) - if - (allyHealth / weakestAlly:GetMaxHealth() < 0.4 + 0.4 * ManaPercentage + #allyNeaybyEnemys * 0.05 or - #allyNeaybyEnemys >= 2) - then - return BOT_ACTION_DESIRE_MODERATE, weakestAlly - end - end - - for _, npcTarget in pairs(allys) do - local allyNeaybyEnemys = npcTarget:GetNearbyHeroes(CastRange, true, BOT_MODE_NONE) - if - (npcTarget:GetHealth() / npcTarget:GetMaxHealth() < (0.6 + #enemys * 0.05 + 0.2 * ManaPercentage) or - npcTarget:WasRecentlyDamagedByAnyHero(5.0) or - #allyNeaybyEnemys >= 2) - then - if (CanCast[abilityNumber](npcTarget)) then - return BOT_ACTION_DESIRE_MODERATE, npcTarget - end - end - end - end - - -- If we're in a teamfight, use it on the scariest enemy - if ( #allys >= 2 ) - then - - local npcMostDangerousEnemy = nil; - local nMostDangerousDamage = 0; - - for _,npcEnemy in pairs( allys ) - do - if ( CanCast[abilityNumber]( npcEnemy ) and not enemyDisabled(npcEnemy)) - then - local Damage2 = npcEnemy:GetOffensivePower() - if ( Damage2 > nMostDangerousDamage ) - then - nMostDangerousDamage = Damage2; - npcMostDangerousEnemy = npcEnemy; - end - end - end - - if ( npcMostDangerousEnemy ~= nil ) - then - return BOT_ACTION_DESIRE_HIGH, npcMostDangerousEnemy; - end - end - -------------------------------------- - -- Mode based usage - -------------------------------------- - -- If we're seriously retreating, see if we can land a stun on someone who's damaged us recently - if ( npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH or (#enemys>=2 and #allys<=1) ) - then - return BOT_ACTION_DESIRE_HIGH, npcBot; - end - - return BOT_ACTION_DESIRE_NONE, 0; - -end - --- 7.31 move omniknight_hammer_of_purity to ability slot 3 -Consider[3] = function() - local abilityNumber = 3 - local ability = AbilitiesReal[abilityNumber] - if not ability:IsFullyCastable() or AbilityExtensions:IsPhysicalOutputDisabled(npcBot) then - return 0 - end - - local CastRange = ability:GetCastRange() - local enemys = npcBot:GetNearbyHeroes(CastRange+100,true,BOT_MODE_NONE) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - - local function UseAt(target) - if not CanCast[abilityNumber](target) then - return false - end - if target:IsHero() then - if AbilityExtensions:MustBeIllusion(npcBot, target) then - return AbilityExtensions:GetManaPercent(npcBot) >= 0.8 or AbilityExtensions:GetHealthPercent(target) <= 0.4 - else - return AbilityExtensions:GetManaPercent(npcBot) >= 0.4 or AbilityExtensions:GetManaPercent(npcBot) >= 0.2 - end - elseif target:IsBuilding() then - return false - else - return AbilityExtensions:GetManaPercent(npcBot) >= 0.8 - end - - end - - if AbilityExtensions:NotRetreating(npcBot) then - local target = npcBot:GetAttackTarget() - if target == nil then - if WeakestEnemy ~= nil then - local b = UseAt(WeakestEnemy) - if b then - return BOT_ACTION_DESIRE_HIGH, WeakestEnemy - else - return false - end - end - else - return UseAt(target) - end - end - return false -end -Consider[3] = AbilityExtensions:ToggleFunctionToAutoCast(npcBot, AbilitiesReal[3], Consider[3]) - -Consider[5]=function() - - local abilityNumber=5 - -------------------------------------- - -- Generic Variable Setting - -------------------------------------- - local ability=AbilitiesReal[abilityNumber]; - - if not ability:IsFullyCastable() then - return BOT_ACTION_DESIRE_NONE, 0; - end - - local CastRange = ability:GetCastRange() - local Damage = 0 - - local allys = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, 1600, false, BOT_MODE_NONE) - local enemys = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, 1600) - local WeakestEnemy,HeroHealth=utility.GetWeakestUnit(enemys) - - -- If we're in a teamfight, use it on the scariest enemy - if ( npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK ) - then - if ( #allys+#enemys >= 5 ) - then - for i,npcTarget in pairs(allys) - do - if(npcTarget:GetActiveMode()== BOT_MODE_RETREAT or npcTarget:GetHealth()/npcTarget:GetMaxHealth()<=0.7 ) - then - return BOT_ACTION_DESIRE_HIGH - end - end - end - end - - return BOT_ACTION_DESIRE_NONE, 0; -end - -AbilityExtensions:AutoModifyConsiderFunction(npcBot, Consider, AbilitiesReal) -function AbilityUsageThink() - - -- Check if we're already using an ability - if ( npcBot:IsUsingAbility() or npcBot:IsChanneling() or npcBot:IsSilenced() ) - then - return - end - - ComboMana=GetComboMana() - AttackRange=npcBot:GetAttackRange() - ManaPercentage=npcBot:GetMana()/npcBot:GetMaxMana() - HealthPercentage=npcBot:GetHealth()/npcBot:GetMaxHealth() - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ---------------------------------debug-------------------------------------------- - if(debugmode==true) - then - ability_item_usage_generic.PrintDebugInfo(AbilitiesReal,cast) - end - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end \ No newline at end of file diff --git a/mira/ability_item_usage_puck.mira b/mira/ability_item_usage_puck.mira deleted file mode 100644 index 5ecb8cb..0000000 --- a/mira/ability_item_usage_puck.mira +++ /dev/null @@ -1,218 +0,0 @@ -local utility = require(GetScriptDirectory().."/utility") -local ability_item_usage_generic = local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -if npcBot:IsIllusion() then - return -end -local AbilityNames, Abilities, Talents = fun1:InitAbility() - -local AbilityToLevelUp = { - AbilityNames[1], - AbilityNames[3], - AbilityNames[1], - AbilityNames[2], - AbilityNames[1], - AbilityNames[5], - AbilityNames[1], - AbilityNames[3], - AbilityNames[2], - "talent", - AbilityNames[2], - AbilityNames[5], - AbilityNames[2], - AbilityNames[3], - "talent", - AbilityNames[3], - "nil", - AbilityNames[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree = { - function() return Talents[2] end, - function() return Talents[3] end, - function() return Talents[6] end, - function() return Talents[8] end, -} - -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp, TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast= {} cast.Desire= {} cast.Target= {} cast.Type= {} -local CanCast = {} -CanCast[1] = fun1.NormalCanCastFunction -CanCast[2] = fun1.NormalCanCastFunction -CanCast[3] = { t -> not fun1:IsInvulnerable(t) or not fun1:ShouldNotBeAttacked(t) } -CanCast[4] = { -> true } -CanCast[5] = fun1.NormalCanCastFunction - -local level -local attackRange -local health -local maxHealth -local healthPercent -local mana -local maxMana -local manaPercent -local netWorth -local allEnemies -local enemies -local enemyCount -local friends -local friendCount -local enemyCreeps -local friendCreeps -local neutralCreeps -local tower - -local illusoryOrbCastLocation -local illusoryOrbMaxTravelDistance -local illusoryOrbRemainingTime -local isPhaseShifting - -local Consider = {} - -local function GetIllusoryOrb() - return fun1:First(GetLinearProjectiles()) { t -> t.ability and t.ability:GetName() == "puck_illusory_orb" and t.caster == npcBot } -end -local illusoryOrb = GetIllusoryOrb() - -Consider[1] = function() - local ability = Abilities[1] - if not ability:IsFullyCastable() then - return 0 - end - local abilityLevel = ability:GetLevel() - local castRange = ability:GetCastRange() - local castPoint = ability:GetCastPoint() - local manaCost = ability:GetManaCost() - local duration = ability:GetDuration() - local damage = ability:GetDamage() - local forbiddenCreeps = fun1:Filter(enemyCreeps, function(t) - return t:GetHealth() > t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) and (t:GetHealth() <= t:GetActualIncomingDamage(damage, DAMAGE_TYPE_MAGICAL) + fun1:AttackOnceDamage(npcBot, t) * (0.9+#enemyCreeps*0.1) or GetUnitToUnitDistance(tower, t) <= 700) - end) - if #friendCreeps == 0 then - forbiddenCreeps = {} - end - - if fun1:NotRetreating(npcBot) then - if local target = fun1:GetTargetIfGood(npcBot) then - coroutine.yield(BOT_ACTION_DESIRE_HIGH, target:GetLocation()) - end - if local target = fun1:GetTargetIfBad(npcBot) then - if mana >= 650 then - coroutine.yield(BOT_ACTION_DESIRE_MODERATE, target:GetLocation()) - end - end - end - if fun1:IsFarmingOrPushing(npcBot) then - if #enemyCreeps > 3 and #forbiddenCreeps == 0 and mana > 0.6 * maxMana + manaCost then - coroutine.yield(BOT_ACTION_DESIRE_MODERATE, enemyCreeps[2]:GetLocation()) - end - elif fun1:IsRetreating(npcBot) then - coroutine.yield(BOT_ACTION_DESIRE_HIGH, fun1:GetAncientLocation(npcBot)) - end - return 0 -end - -local phaseShiftStartTime -local phaseShiftRemainingTime -local phaseShiftReasons = {} - -Consider[3] = function() - local ability = Abilities[3] - if not ability:IsFullyCastable() then - return 0 - end - - if fun1:HasSeverelyDisableProjectiles(npcBot) then - table.insert(phaseShiftReasons, "projectiles") - return BOT_ACTION_DESIRE_HIGH - end - - return 0 -end - -fun1:AutoModifyConsiderFunction(npcBot, Consider, Abilities) - -function AbilityUsageThink() - isPhaseShifting = npcBot:HasModifier "modifier_puck_phase_shift" - if phaseShiftRemainingTime then - phaseShiftRemainingTime -= fun1:GetDeltaTime() - end - if npcBot:IsUsingAbility() or npcBot:IsSilenced() then - return - end - if npcBot:IsChanneling() then - if isPhaseShifting then - local reason = phaseShiftReasons.reason - if reason == "projectiles" then - if #npcBot:GetIncomingTrackingProjectiles() == 0 then - npcBot:Action_ClearActions(false) - return - end - end - else - phaseShiftReasons = {} - end - end - - level = npcBot:GetLevel() - attackRange = npcBot:GetAttackRange() - health = npcBot:GetHealth() - maxHealth = npcBot:GetMaxHealth() - healthPercent = fun1:GetHealthPercent(npcBot) - mana = npcBot:GetMana() - maxMana = npcBot:GetMaxMana() - manaPercent = fun1:GetManaPercent(npcBot) - netWorth = npcBot:GetNetWorth() - - allEnemies = fun1:GetNearbyHeroes(npcBot, 1200) - enemies = allEnemies:Filter { t -> fun1:MayNotBeIllusion(npcBot, t) } - enemyCount = fun1:GetEnemyHeroNumber(npcBot, enemies) - friends = fun1:GetNearbyNonIllusionHeroes(npcBot, 1500, true) - friendCount = fun1:GetEnemyHeroNumber(npcBot, friends) - enemyCreeps = fun1:GetNearbyAttackableCreeps(npcBot, 900) - friendCreeps = fun1:GetNearbyAttackableCreeps(npcBot, npcBot:GetAttackRange()+150, false) - neutralCreeps = npcBot:GetNearbyNeutralCreeps(900) - tower = fun1:GetLaningTower(npcBot) - - - cast=ability_item_usage_generic.ConsiderAbility(Abilities,Consider) - local abilityIndex, target, castType = ability_item_usage_generic.UseAbility(Abilities,cast) - if abilityIndex == 1 then - illusoryOrbCastLocation = npcBot:GetLocation() - illusoryOrbMaxTravelDistance = Abilities[1]:GetSpecialValueInt("max_distance") - 50 - illusoryOrbRemainingTime = illusoryOrbMaxTravelDistance / Abilities[1]:GetSpecialValueInt "orb_speed" - elseif abilityIndex == 3 then - phaseShiftStartTime = DotaTime() - phaseShiftRemainingTime = Abilities[3]:GetSpecialValueFloat "duration" - 0.08 - end -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end diff --git a/mira/ability_item_usage_pudge.mira b/mira/ability_item_usage_pudge.mira deleted file mode 100644 index f3b957d..0000000 --- a/mira/ability_item_usage_pudge.mira +++ /dev/null @@ -1,261 +0,0 @@ - --- v1.7 template -local utility = require( GetScriptDirectory().."/utility" ) -local ability_item_usage_generic = require(GetScriptDirectory() .. "/ability_item_usage_generic") -local AbilityExtensions = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local debugmode=false -local npcBot = GetBot() -if npcBot:IsIllusion() then return end -local Talents ={} -local Abilities ={} -local AbilitiesReal ={} - -ability_item_usage_generic.InitAbility(Abilities,AbilitiesReal,Talents) - -local AbilityToLevelUp= -{ - Abilities[2], - Abilities[1], - Abilities[1], - Abilities[2], - Abilities[1], - Abilities[5], - Abilities[1], - Abilities[3], - Abilities[2], - "talent", - Abilities[2], - Abilities[5], - Abilities[3], - Abilities[3], - "talent", - Abilities[3], - "nil", - Abilities[5], - "nil", - "talent", - "nil", - "nil", - "nil", - "nil", - "talent", -} - -local TalentTree={ - function() - return Talents[2] - end, - function() - return Talents[3] - end, - function() - return Talents[5] - end, - function() - return Talents[8] - end -} - --- check skill build vs current level -utility.CheckAbilityBuild(AbilityToLevelUp) - -function BuybackUsageThink() - ability_item_usage_generic.BuybackUsageThink(); -end - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink(); -end - -function AbilityLevelUpThink() - ability_item_usage_generic.AbilityLevelUpThink2(AbilityToLevelUp,TalentTree) -end - --------------------------------------- --- Ability Usage Thinking --------------------------------------- -local cast={} cast.Desire={} cast.Target={} cast.Type={} -local Consider ={} -local CanCast = { { t -> - AbilityExtensions:NormalCanCast(t, false, DAMAGE_TYPE_PURE, true, false) - }, - AbilityExtensions.NormalCanCastFunction, - utility.NCanCast, - utility.CanCastNoTarget, - { t -> - AbilityExtensions:NormalCanCast(t, false, DAMAGE_TYPE_MAGICAL, true, true) and not AbilityExtensions:HasAbilityRetargetModifier(t) - } -} - -Consider[1] = function() - local ability = AbilitiesReal[1] - if not ability:IsFullyCastable() or npcBot:IsChanneling() then - return 0 - end - local castPoint = ability:GetCastPoint() - local range = ability:GetSpecialValueInt("hook_distance") - local searchRadius = ability:GetSpecialValueInt("hook_width") - local hookSpeed = ability:GetSpecialValueFloat("hook_speed") - local allNearbyUnits = AbilityExtensions:GetNearbyAllUnits(npcBot, range):Remove(npcBot) - - local function NotBlockedByAnyUnit(line, target, distance) -> - AbilityExtensions:Remove(allNearbyUnits, target):All { t -> - local closeEnough = AbilityExtensions:GetPointToLineDistance(t:GetLocation(), line) <= searchRadius + target:GetBoundingRadius() - -- if closeEnough then - -- print("want to hook "..target:GetUnitName()..", blocked by "..t:GetUnitName()) - -- end - local mayHook = closeEnough and distance > GetUnitToUnitDistance(npcBot, t) - return not mayHook or t:IsInvulnerable() - } - - local function T(target) - if not CanCast[1](target) then return false end - local point = target:GetExtrapolatedLocation(GetUnitToUnitDistance(npcBot, target) / hookSpeed + castPoint) - local distance = GetUnitToLocationDistance(npcBot, point) - local line = AbilityExtensions:GetLine(npcBot:GetLocation(), point) - local result = GetUnitToLocationDistance(npcBot, point) <= range and NotBlockedByAnyUnit(line, target, distance) - return result - end - - if AbilityExtensions:IsAttackingEnemies(npcBot) then - local enemies = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, range, true, BOT_MODE_NONE) - enemies = AbilityExtensions:SortByMaxFirst(enemies, function(t) return GetUnitToUnitDistance(npcBot, t) end) - enemies = AbilityExtensions:Filter(enemies, T) - if #enemies ~= 0 then - return BOT_MODE_DESIRE_HIGH, enemies[1]:GetExtrapolatedLocation(GetUnitToUnitDistance(npcBot, enemies[1]) / hookSpeed) - end - - if local ally = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, range, false, BOT_MODE_NONE) - :Filter(allies) { t -> t:IsStunned() or t:IsRooted() } - :First(allies, T) then - return BOT_MODE_DESIRE_HIGH, ally:GetExtrapolatedLocation(GetUnitToUnitDistance(npcBot, enemies[1]) / hookSpeed) - end - end - - if AbilityExtensions:IsAttackingEnemies(npcBot) then - if local atos = AbilityExtensions:GetAvailableItem(npcBot, "item_rod_of_atos") or AbilityExtensions:GetAvailableItem(npcBot, "item_gungir") then - if local t = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, range):First { t -> - not AbilityExtensions:CannotMove(t) and T(t) and AbilityExtensions:NormalCanCast(t) - } then - if atos:GetName() == "item_rod_of_atos" then - ItemUsage.UseItemOnEntity(npcBot, atos, t) - else - ItemUsage.UseItemOnLocation(npcBot, atos, t:GetLocation()) - end - return 0 - end - end - - if local target = AbilityExtensions:GetTargetIfGood(npcBot) then - if T(target) then - return BOT_ACTION_DESIRE_HIGH, target:GetExtrapolatedLocation(GetUnitToUnitDistance(npcBot, target) / hookSpeed + castPoint) - end - end - if local enemy = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, range):First { t -> - (AbilityExtensions:CannotMove(t) or AbilityExtensions:GetMovementSpeedPercent(t) <= 0.3) and T(t) - } then - return BOT_ACTION_DESIRE_HIGH, enemy:GetExtrapolatedLocation(GetUnitToUnitDistance(npcBot, enemy) / hookSpeed + castPoint) - end - end - - return 0 -end - -Consider[2] = function() - local ability = AbilitiesReal[2] - local radius = ability:GetAOERadius() - if not ability:IsFullyCastable() then - return 0 - end - if AbilityExtensions:IsAttackingEnemies(npcBot) or AbilityExtensions:IsRetreating(npcBot) then - if local nearbyEnemies = AbilityExtensions:GetNearbyHeroes(npcBot, radius, true); nearbyEnemies:Any(CanCast[2]) then - return true - end - end - if local target = npcBot:GetTarget(); target and GetUnitToUnitDistance(target, npcBot) <= radius and CanCast[2](target) then - if not AbilityExtensions:IsHero(target) or AbilityExtensions:MustBeIllusion(npcBot, target) then - if npcBot:GetHealth() <= 270 or AbilityExtensions:GetHealthPercent(npcBot) <= 0.3 and npcBot:WasRecentlyDamagedByHero(target, 1.5) then - return false - end - end - return true - end - - return false -end -Consider[2] = AbilityExtensions:ToggleFunctionToAction(npcBot, Consider[2], AbilitiesReal[2]) - -local swallowingSomething -local swallowTimer -Consider[4] = function() - local ability = AbilitiesReal[4] - if not ability:IsFullyCastable() or npcBot:IsChanneling() then - return 0 - end - swallowingSomething = npcBot:HasModifier("modifier_pudge_swallow") or npcBot:HasModifier("modifier_pudge_swallow_effect") or npcBot:HasModifier("modifier_pudge_swallow_hide") - if swallowingSomething then - if swallowTimer ~= nil then - if DotaTime() >= swallowTimer + 3 then - return BOT_MODE_DESIRE_VERYHIGH - end - else - swallowTimer = DotaTime() - end - end - return 0 -end - -Consider[5] = function() - local ability = AbilitiesReal[5] - if not ability:IsFullyCastable() or npcBot:IsChanneling() then - return nil - end - local range = ability:GetCastRange() + 100 - local hookedEnemy = AbilityExtensions:First(AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, range, true, BOT_MODE_NONE)) { t -> - t:IsHero() and AbilityExtensions:MayNotBeIllusion(npcBot, t) and t:HasModifier("modifier_pudge_meat_hook") - } - if hookedEnemy then - return BOT_MODE_DESIRE_VERYHIGH, hookedEnemy - end - - if local target = AbilityExtensions:GetTargetIfGood(npcBot); target and CanCast[5](target) and GetUnitToUnitDistance(npcBot, target) <= range then - return BOT_MODE_DESIRE_HIGH, target - end - local nearbyEnemies = AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, 900, true, BOT_MODE_NONE) - if AbilityExtensions:IsAttackingEnemies(npcBot) then - if local u = utility.GetWeakestUnit(nearbyEnemies); u and CanCast[5](u) then - return BOT_MODE_DESIRE_HIGH, u - end - end - if AbilityExtensions:IsRetreating(npcBot) and #nearbyEnemies == 1 then - if local loneEnemy = nearbyEnemies[1]; loneEnemy and not AbilityExtensions:HasAbilityRetargetModifier(loneEnemy) and CanCast[5](loneEnemy) then - return BOT_MODE_DESIRE_MODERATE, loneEnemy - end - end - - -- if has shard - -- local function CanCast5AtFriend(friend) - -- return not AbilityExtensions:IsInvulnerable(friend) and not AbilityExtensions:CannotBeTargetted() - -- end - -- local nearbyAllies = AbilityExtensions:Filter(AbilityExtensions:GetNearbyNonIllusionHeroes(npcBot, range+200, false, BOT_MODE_NONE), function(t) return AbilityExtensions:CanHardlyMove(t) end) - -- nearbyAllies = AbilityExtensions:SortByMinFirst(nearbyAllies, function(t) return t:GetHealth() end) - -- if #nearbyAllies ~= 0 and CanCast5AtFriend(nearbyAllies[1]) then - -- return BOT_MODE_DESIRE_MODERATE, nearbyAllies[1] - -- end - return 0 -end - - -function CourierUsageThink() - ability_item_usage_generic.CourierUsageThink() -end - -function AbilityUsageThink() - if npcBot:IsUsingAbility() or npcBot:IsSilenced() then - return - end - - cast=ability_item_usage_generic.ConsiderAbility(AbilitiesReal,Consider) - ability_item_usage_generic.UseAbility(AbilitiesReal,cast) -end diff --git a/mira/mode_item_generic.mira b/mira/mode_item_generic.mira deleted file mode 100644 index dd75a72..0000000 --- a/mira/mode_item_generic.mira +++ /dev/null @@ -1,22 +0,0 @@ -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local bot = GetBot() - -local function PrintCarriedItems(bot) - print(bot:GetUnitName().." has items:") - for i = 0, 8 do - if local item = bot:GetItemInSlot(i) then - print(i.." "..item:GetName()) - end - end -end - -function OnStart() - bot = GetBot() - -- PrintCarriedItems(bot) -end - -function OnEnd() - -- PrintCarriedItems(bot) -end - diff --git a/mode_item_generic.lua b/mode_item_generic.lua index 94281bd..9a8a04a 100644 --- a/mode_item_generic.lua +++ b/mode_item_generic.lua @@ -1,8 +1,3 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") local bot = GetBot() local function PrintCarriedItems(bot) diff --git a/util/AbilityAbstraction.lua b/util/AbilityAbstraction.lua index 7e6e846..3932825 100644 --- a/util/AbilityAbstraction.lua +++ b/util/AbilityAbstraction.lua @@ -1,10 +1,8 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local M = {} local binlib = require(GetScriptDirectory() .. "/util/BinDecHex") + +-- LINQ functions + local magicTable = {} local function GiveLinqFunctions(t) setmetatable(t, magicTable) @@ -618,6 +616,9 @@ local function AddLinqFunctionsToMetatable(mt) end AddLinqFunctionsToMetatable(magicTable) + +-- bot mode behaviour + local Trim = function(v, left, right) if right >= left then if v > right then @@ -676,6 +677,10 @@ M.HasEnoughManaToUseAttackAttachedAbility = function(self, npcBot, ability) return percent >= 0.4 and npcBot:GetMana() >= 300 and npcBot:GetManaRegen() >= npcBot:GetAttackSpeed() / 100 * ability:GetManaCost() * 0.75 end + +-- function generator + +-- turn a function that returns true, false, nil to a function that decides whether to toggle the ability or not M.ToggleFunctionToAction = function(self, npcBot, oldConsider, ability) local name = ability:GetName() return function() @@ -714,6 +719,9 @@ M.PreventAbilityAtIllusion = function(self, npcBot, oldConsiderFunction, ability end M.PreventEnemyTargetAbilityUsageAtAbilityBlock = function(self, npcBot, oldConsiderFunction, ability) local newConsider = function() + -- TODO: do we consider the base cooldown or the modified cooldown + -- (arcane rune, octarine orb)? Will you crack a sphere's spell block + -- with an ultimate ability when you're on arcane rune? local desire, target, targetTypeString = oldConsiderFunction() if desire == 0 or target == nil or target == 0 or self:IsVector(target) or targetTypeString == "Location" then return desire, target, targetTypeString @@ -833,6 +841,8 @@ function M:InitAbility(npcBot) return abilityNames, abilities, talents end +-- ability information + local keysBeforeAbilityInformation = M:Keys(M) M.UndisjointableProjectiles = { "alchemist_berser_potion", @@ -1091,6 +1101,8 @@ M.timeSensitivePositiveModifiers = { "modifier_medusa_stone_gaze", "modifier_monkey_king_fur_army_soldier_in_position", } +-- sorted by importance, used by dispell abilities + M.basicDispellablePositiveModifiers = { "modifier_omniknight_guardian_angle", "modifier_ember_spirit_flame_guard", @@ -1145,6 +1157,8 @@ M.unbreakableChannelAbilities = { "item_trusty_shovel", "item_fallen_sky", } +-- items cannot be break by silence + M.lowPriorityChannelAbilities = { "windrunner_powershot", "ability_capture", @@ -1189,7 +1203,7 @@ M.hexModifiers = { "modifier_shadow_shaman_voodoo", "modifier_sheepstick_debuff", "modifier_item_princes_knife_hex", - "modifier_hexxed", + "modifier_hexxed", -- dazzle_poison_touch aghanim's shard "modifier_item_unstable_wand_critter", } M.silenceModifiers = { @@ -1271,9 +1285,10 @@ M.knockbackModifiers = { "modifier_force_boots_active", } M.blindModifiers = { "modifier_item_black_powder_bag_blind" } +-- TODO: how to record the caster of these abilities M.noTrueSightRootAbilityAssociation = { dark_willow_branble_maze = "modifier_dark_willow_bramble_maze", - item_diffusal_blade = "modifier_rooted", + item_diffusal_blade = "modifier_rooted", -- most people don't know diffusal blade apply root on non-hero units } M.conditionalTrueSightRootAbilityAssociation = { dark_troll_warlord_ensnare = "modifier_dark_troll_warlord_ensnare", @@ -1317,6 +1332,10 @@ abilityInformationKeys:ForEach(function(t) M[k .. "Abilities"] = a M[k .. "Modifiers"] = b end) + + +-- enums + function M:ToIntItemPurchaseResult(i) return (function() if i == PURCHASE_ITEM_SUCCESS then @@ -1372,6 +1391,8 @@ function M:ToIntBotMode(i) return "UNKNOWN_BOT_MODE_ENUM" end +-- unit function + function M:IsRoshan(npcTarget) return npcTarget ~= nil and npcTarget:IsAlive() and string.find(npcTarget:GetUnitName(), "roshan") end @@ -1418,6 +1439,7 @@ M.GetIncomingDodgeWorthProjectiles = function(self, npc) if t.is_attack then return false end + -- caster can be nil if t.caster then if npc:GetTeam() == t.caster:GetTeam() then return false @@ -1550,6 +1572,8 @@ function M:GetLifeSteal(npc) if self:GetAvailableItem(npc, "item_paladin_sword") then amp = amp + 0.14 end + + -- lifesteal amplifications for i = 1, npc:NumModifiers() do local modifierName = npc:GetModifierName(i) if modifierName == "modifier_item_spirit_vessel_damage" then @@ -1964,6 +1988,8 @@ function M:HasUnobstructedMovement(npc) return #activeFlyingModifiers ~= 0 end +-- item function + M.GetAvailableItem = function(self, npc, itemName) for _, i in ipairs(self:Range(0, 5):Concat({ 16 })) do local item = npc:GetItemInSlot(i) @@ -2257,7 +2283,7 @@ function M:IsDuelCaster(npc) self:GetModifierRemainingDuration(_npc, "modifier_legion_commander_duel") + 1 >= ability:GetCooldown() end - if not npc then + if not npc then --dont know why _npc can be null return false end local npcBot = GetBot() @@ -2526,6 +2552,8 @@ function M:GetLaningTower(npc) end end +-- debug functions + M.DebugTable = function(self, tb) local msg = "{ " local DebugRec @@ -2581,6 +2609,8 @@ function M:PrintMode(npc) print("bot " .. npc:GetUnitName() .. " in mode " .. npc:GetActiveMode() .. ", desire = " .. npc:GetActiveModeDesire()) end +-- ability function + function M:NormalCanCast(target, isPureDamageWithoutDisable, damageType, pierceMagicImmune, targetMustBeSeen, mustBeTargettable) damageType = damageType or DAMAGE_TYPE_MAGICAL @@ -2794,6 +2824,9 @@ M.ExecuteAbilityLevelUp = function(self, npcBot) npcBot:ActionImmediate_LevelAbility(abilityName) abilityTable.justLevelUpAbility = true end + +-- geometry + M.IsVector = function(self, object) return type(object) == "userdata" and type(object.x) == "number" and type(object.y) == "number" and type(object.z) == "number" @@ -2826,6 +2859,8 @@ M.commonBoudingRadius = 100 M.GetPointToPointDistance = function(self, a, b) return ((a.x - b.x) ^ 2 + (a.y - b.y) ^ 2) ^ 0.5 end + +-- Get the location on the line determined by startPoint and endPoint, with distance from startPoint to the target location M.GetPointFromLineByDistance = function(self, startPoint, endPoint, distance) local distanceTo = self:GetPointToPointDistance(startPoint, endPoint) local divide = (endPoint - startPoint) / distanceTo * distance @@ -2972,6 +3007,40 @@ M.PURCHASE_ITEM_INSUFFICIENT_GOLD = 63 M.PURCHASE_ITEM_NOT_AT_SECRET_SHOP = 62 M.PURCHASE_ITEM_NOT_AT_HOME_SHOP = 67 M.PURCHASE_ITEM_SUCCESS = -1 + +-- specified ability is not actually an ability (2) +-- invalid order(3) unrecognised order name +-- invalid order(40) order not allowed for illusions +-- unit is dead (20) +-- target tree is not active (43) +-- ability is still in cooldown (15) +-- cannot cast ability on tree (34) +-- cannot cast ability on target +-- target is unselectable +-- order requires a physical item target, but specified target is not a physical item (9) +-- item cannot be used from stash (37) +-- does not have enough mana to cast ability (14) +-- item is still in cooldown (61) +-- can't cast attack ability on target, target is attack immune (32) +-- order invalid for units with attack ability DOTA_UNIT_CAP_NO_ATTACK (41) +-- can't cast on target, ability cannot target enemies (30) +-- can't cast on target, ability cannot target creeps (56) +-- unit can't perform command, unit has commands restricted (74) +-- hero does not have enough ability points to upgrade ability (13) +-- ability is hidden (60) +-- can't cast on target, ability cannot target teammates (29) +-- cannot attack or cast on target, target is unselectable (36) +-- unit cannot cast, unit is silenced (24) +-- cannot cast ability on NPC (19), unit is dead +-- unit cannot manipulate items (39) +-- target cannot be seen by the unit's team (26) +-- unit does not have moevement capability and target is out of attack range (46) + + +-- runtime errors: +--- Bad key for entity "npc_dota_creep_neutral": Out of range parsed value for field "teamnumber" (-1)! + + M.IgnoreDamageModifiers = { "modifier_abaddon_borrowed_time", "modifier_item_aeon_disk_buff", @@ -3061,7 +3130,7 @@ M.GetIllusionBattlePower = function(self, npc) if self:Contains(inventory, "item_greater_crit") then t = t + 0.08 end - if npc:HasModifier "modifier_special_bonus_mana_break" then + if npc:HasModifier "modifier_special_bonus_mana_break" then -- mirana talent[5] t = t + 0.04 end return t @@ -3145,6 +3214,7 @@ M.GetHeroGroupBattlePower = function(self, npcBot, heroes, isEnemy) local name = enemy:GetUnitName() if not self:Contains(readNames, name) then table.insert(readNames, name) + -- TODO: enemyNetWorthMap[name] should not be null if enemyNetWorthMap[name] then netWorth = netWorth + enemyNetWorthMap[name] end @@ -3170,6 +3240,9 @@ M.HasScepter = function(self, npc) npc:HasModifier "modifier_item_ultimate_scepter" or npc:HasModifier "modifier_item_ultimate_scepter_consumed_alchemist" end + +-- ability record + local locationAOEAbilities = { cone = { "lina_dragon_slave" }, circle = { "lina_light_strike_array" }, @@ -3210,6 +3283,8 @@ local function FloatEqual(a, b) return math.abs(a - b) < 0.000001 end +-- tick + function M:GetFrameNumber() return frameNumber end @@ -3357,6 +3432,8 @@ function M:GameNotReallyStarting() return false end +-- coroutine + function M:ResumeUntilReturn(func) local g = NewTable() local thread = coroutine.create(func) @@ -3399,6 +3476,9 @@ function M:StopCoroutine(thread) self:Remove_Modify(coroutineRegistry, thread) end +-- get data from ability +-- for example, to get value aoe_radius, use ability.aoe_radius rather than ability:GetSpecialValueInt + local function GetDataFromAbility(ability, valueName) local a = ability:GetSpecialValueInt(valueName) return a == 0 and ability:GetSpecialValueFloat(valueName) or a diff --git a/util/AbilityAbstraction.mira b/util/AbilityAbstraction.mira deleted file mode 100644 index d556d89..0000000 --- a/util/AbilityAbstraction.mira +++ /dev/null @@ -1,3560 +0,0 @@ -local M = {} - -local binlib = require(GetScriptDirectory().."/util/BinDecHex") - --- LINQ functions - -local magicTable = {} -local function GiveLinqFunctions(t) - setmetatable(t, magicTable) -end - -local function NewTable() - local a = {} - GiveLinqFunctions(a, magicTable) - return a -end -magicTable.__index = magicTable - -function M:NewTable() - return NewTable() -end - -M.Range = function(self, min, max, step) - if step == nil then step = 1 end - local g = NewTable() - for i = min, max, step do - table.insert(g, i) - end - return g -end - -M.Contains = function(self, tb, value, equals) - equals = equals or {==} - for _, v in ipairs(tb) do - if equals(v, value) then - return true - end - end - return false -end - -M.ContainsKey = function(self, tb, key, equals) - equals = equals or {==} - for k, _ in pairs(tb) do - if equals(key, k) then - return true - end - end - return false -end - -function M:Keys(tb) - local g = NewTable() - for k, _ in pairs(tb) do - table.insert(g, k) - end - return g -end - -M.Filter = function(self, tb, filter) - local g = NewTable() - for k, v in ipairs(tb) do - if filter(v, k) then - table.insert(g, v) - end - end - return g -end -M.FilterNot = function(self, tb, filter) - local g = NewTable() - for k, v in ipairs(tb) do - if not filter(v, k) then - table.insert(g, v) - end - end - return g -end - -M.Count = function(self, tb, filter) - local g = 0 - for k, v in ipairs(tb) do - if filter == nil or filter(v, k) then - g = g + 1 - end - end - return g -end - -function M:NonEmpty(self, tb) - return self:Filter(tb, function(t) - return t ~= nil and #t ~= 0 - end) -end - -M.Map = function(self, tb, transform) - local g = NewTable() - for k, v in ipairs(tb) do - g[k] = transform(v) - end - return g -end - -function M:MapDic(tb, transform) - local g = NewTable() - for k, v in pairs(tb) do - g[k] = transform(k, v) - end - return g -end - -M.ForEach = function(self, tb, action) - for k, v in ipairs(tb) do - action(v, k) - end -end -function M:ForEachDic(tb, action) - for k, v in pairs(tb) do - action(v, k) - end -end - -M.Any = function(self, tb, filter) - for k, v in ipairs(tb) do - if filter == nil or filter(v, k) then - return true - end - end - return false -end - -M.All = function(self, tb, filter) - for k, v in ipairs(tb) do - if not filter(v, k) then - return false - end - end - return true -end - -M.Aggregate = function(self, seed, tb, aggregate) - for k, v in ipairs(tb) do - seed = aggregate(seed, v, k) - end - return seed -end - -M.ShallowCopy = function(self, tb) - local g = NewTable() - for k, v in pairs(tb) do - g[k] = v - end - return g -end - -M.First = function(self, tb, filter) - if filter == nil then - filter = { _ -> true } - end - for k, v in ipairs(tb) do - if filter == nil or filter(v, k) then - return v - end - end -end - -M.Skip = function(self, tb, number) - local g = NewTable() - local i = 0 - for _, v in ipairs(tb) do - i = i + 1 - if i > number then - table.insert(g, v) - end - end - return g -end - -M.Take = function(self, tb, number) - local g = NewTable() - local i = 0 - for _, v in ipairs(tb) do - i = i + 1 - if i <= number then - table.insert(g, v) - else - break - end - end - return g -end - -local function deepCopy(self, tb) - local copiedTables = NewTable() - local g = NewTable() - table.insert(copiedTables, tb) - for k, v in pairs(tb) do - if type(v) ~= "table" then - g[k] = v - else - if self:Contains(copiedTables, v) then - return {} - end - g[k] = deepCopy(self, v) - end - end - return g -end -M.DeepCopy = deepCopy - -M.Concat = function(self, a, ...) - local g = NewTable() - local rec - rec = function(b, ...) - if b == nil then - return - end - for _, v in ipairs(b) do - table.insert(g, v) - end - rec(...) - end - rec(a, ...) - return g -end - -M.Remove = function(self, a, b) - local g = self:ShallowCopy(a) - for k,v in pairs(a) do - if v == b then - g[k] = nil - end - end - return g -end -M.RemoveAll = function(self, a, b) - local g = NewTable() - for _,v in pairs(a) do - if not self:Contains(b, v) then - table.insert(g, v) - end - end - return g -end - -M.Prepend = function(self, a, b) - return self:Concat(b, a) -end - -M.GroupBy = function(self, collection, keySelector, elementSelector, resultSelector, comparer) - comparer = comparer or { == } - resultSelector = resultSelector or function(key, value) return value end - elementSelector = elementSelector or self.IdentityFunction - local keys = NewTable() - local values = NewTable() - for _, k in ipairs(collection) do - local keyFound = false - for readKeyIndex, readKey in ipairs(keys) do - if comparer(readKey, keySelector(k)) then - keyFound = true - table.insert(values[readKeyIndex], elementSelector(k)) - break - end - end - if not keyFound then - table.insert(keys, keySelector(k)) - local v = NewTable() - table.insert(v, elementSelector(k)) - table.insert(values, v) - end - end - return self:Map2(keys, values, resultSelector) -end - -M.Partition = function(self, tb, filter) - local a = NewTable() - local b = NewTable() - for k, v in pairs(tb) do - if filter(v, k) then - table.insert(a, v) - else - table.insert(b, v) - end - end - return a, b -end - -M.Distinct = function(self, tb, equals) - equals = equals or {==} - local g = NewTable() - for _, v in pairs(tb) do - if not self:Contains(g, v, equals) then - table.insert(g, v) - end - end - return g -end - -M.Reverse = function(self, tb) - local g = NewTable() - for i = #tb, 1, -1 do - table.insert(g, tb[i]) - end - return g -end - -M.Last = function(self, tb, filter) - return self:First(self:Reverse(tb), filter) -end - -function M:Identity(t) return t end -M.IdentityFunction = function(t) return t end - -function M:Max(tb, map) - if #tb == 0 then - return nil - end - map = map or self.IdentityFunction - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m > maxm then - maxm = m - maxv = tb[i] - end - end - return maxv -end - -function M:MaxV(tb, map) - if #tb == 0 then - return nil - end - map = map or self.IdentityFunction - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m > maxm then - maxm = m - maxv = tb[i] - end - end - return maxm -end - -function M:Min(tb, map) - if #tb == 0 then - return nil - end - map = map or self.IdentityFunction - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m < maxm then - maxm = m - maxv = tb[i] - end - end - return maxv -end - -function M:MinV(tb, map) - if #tb == 0 then - return nil - end - map = map or self.IdentityFunction - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m < maxm then - maxm = m - maxv = tb[i] - end - end - return maxm -end - -M.Repeat = function(self, element, count) - local g = NewTable() - for i = 1, count do - table.insert(g, element) - end - return g -end - -M.Select = M.Map -M.SelectMany = function(self, tb, map, filter) - local g = NewTable() - for _, source in ipairs(tb) do - local collection = map(source) - for index, value in ipairs(collection) do - if filter == nil or filter(value, index) then - table.insert(g, value) - end - end - end - return g -end - -M.Where = M.Filter - -M.SkipLast = function(self, tb, number) - return self:Skip(self:Reverse(tb), number) -end - -M.Replace = function(self, tb, filter, map) - local g = NewTable() - for k, v in ipairs(tb) do - if filter(v, k) then - table.insert(g, map(v, k)) - else - table.insert(g, v) - end - end - return g -end - -M.IndexOf = function(self, tb, filter) - local g = NewTable() - for k, v in ipairs(tb) do - if type(filter) == "function" then - if filter(v, k) then - return k - end - elseif filter ~= nil then - if v == filter then - return k - end - end - end - return -1 -end - -M.Zip2 = function(self, tb1, tb2, map) - if map == nil then - map = function(a, b) - return {a, b} - end - end - local g = NewTable() - for i = 1, #tb1 do - table.insert(g, map(tb1[i], tb2[i])) - end - return g -end - -M.ForEach2 = function(self, tb1, tb2, func) - for i = 1, #tb1 do - func(tb1[i], tb2[i]) - end -end - -M.Map2 = function(self, tb1, tb2, map) - local g = NewTable() - for i = 1, #tb1 do - table.insert(g, map(tb1[i], tb2[i], i)) - end - return g -end - -M.Filter2 = function(self, tb1, tb2, filter, map) - if map == nil then - map = function(a,b,c) return {a,b,c} end - end - local g = NewTable() - for i = 1, #tb1 do - if filter(tb1[i], tb2[i], i) then - table.insert(map(tb1[i], tb2[i], i)) - end - end - return g -end - -M.SlowSort = function(self, tb, sort) - local g = self:ShallowCopy(tb) - local len = #g - if sort ~= nil then - for i = 1, len-1 do - for j = i+1, len do - if sort(g[i], g[j]) > 0 then - g[i], g[j] = g[j], g[i] - end - end - end - else - for i = 1, len-1 do - for j = i+1, len do - if g[i] > g[j] then - g[i], g[j] = g[j], g[i] - end - end - end - end - return g -end - -M.MergeSort = function(self, tb, sort) - if sort == nil then - sort = function(a, b) return a-b end - end - local function Merge(a, b) - local g = NewTable() - local aLen = #a - local bLen = #b - local i = 1 - local j = 1 - while i <= aLen and j <= bLen do - if sort(a[i], b[j]) > 0 then - table.insert(g, b[j]) - j = j+1 - else - table.insert(g, a[i]) - i = i+1 - end - end - if i <= aLen then - for _ = i, aLen do - table.insert(g, a[i]) - end - end - if j <= bLen then - for _ = j, bLen do - table.insert(g, b[j]) - end - end - return g - end - local function SortRec(tab) - local tableLength = #tab - if tableLength == 1 then - return tab - end - local left = SortRec(self:Take(tab, tableLength/2)) - local right = SortRec(self:Skip(tab, tableLength/2)) - local merge = Merge(left, right) - return merge - end - return SortRec(tb) -end - -M.Sort = M.SlowSort -M.SortByMaxFirst = function(self, tb, map) - map = map or M.IdentityFunction - return self:Sort(tb, function(a, b) - return map(b) - map(a) - end) -end -M.SortByMinFirst = function(self, tb, map) - map = map or M.IdentityFunction - return self:Sort(tb, function(a, b) - return map(a) - map(b) - end) -end - -function M:Remove_Modify(tb, item) - local filter = item - if type(item) ~= "function" then - filter = function(t) return t == item end - end - local i = 1 - local d = #tb - while i <= d do - if filter(tb[i]) then - table.remove(tb, i) - d = d - 1 - else - i = i + 1 - end - end -end - -function M:InsertAfter_Modify(tb, item, after) - if after == nil then - table.insert(tb, item) - else - for index, value in ipairs(tb) do - if after == value then - table.insert(tb, index, item) - return - end - end - table.insert(tb, item) - end -end - -function M:Unpack(tb) - local index = #tb - local function rec(...) - if index >= 1 then - index = index - 1 - return rec(tb[index + 1], ...) - else - return ... - end - end - return rec() -end - -function M:UnpackIfTable(p) - if type(p) == "table" then - return self:Unpack(p) - else - return p - end -end - -function M:Also(tb, block) - block(tb) - return tb -end - -function M:Let(tb, block) - return block(tb) -end - - --- function M:ClampGroup(tb, min, max) --- local vmin = math.min(tb) --- local vmax = math.max(tb) --- return self:Map(tb, function(t) return RemapVal(t, vmin, vmax, min, max) end) --- end - -local function AddLinqFunctionsToMetatable(mt) - for k, v in pairs(M) do - mt[k] = function(...) - return v(M, ...) - end - end - for functionName, func in pairs(table) do - mt[functionName] = func - end -end - -AddLinqFunctionsToMetatable(magicTable) - --- bot mode behaviour - -local Trim = function(v, left, right) - if right >= left then - if v > right then - return right - elseif v < left then - return left - else - return v - end - else - if v > left then - return left - elseif v < right then - return right - else - return v - end - end -end - -M.TrimDesire = function(self, desire) - return Trim(desire, 0, 1) -end - -M.GetAbilityImportance = function(self, cooldown) - return Trim(cooldown/120, 0, 1) -end - -M.IsFarmingOrPushing = function(self, npcBot) - local mode = npcBot:GetActiveMode() - return mode==BOT_MODE_FARM or mode==BOT_MODE_PUSH_TOWER_BOT or mode==BOT_MODE_PUSH_TOWER_MID or mode==BOT_MODE_PUSH_TOWER_TOP or mode == BOT_MODE_DEFEND_TOWER_BOT or mode==BOT_MODE_DEFEND_TOWER_MID or mode==BOT_MODE_DEFEND_TOWER_TOP -end - -M.IsLaning = function(self, npcBot) - local mode = npcBot:GetActiveMode() - return mode == BOT_MODE_LANING -end - -M.IsAttackingEnemies = function(self, npcBot) - local mode = npcBot:GetActiveMode() - return mode == BOT_MODE_ROAM or mode == BOT_MODE_TEAM_ROAM or mode == BOT_MODE_ATTACK or mode == BOT_MODE_DEFEND_ALLY -end - -function M:CanBeEngaged(npcBot) - return self:IsAttackingEnemies(npcBot) or self:IsFarmingOrPushing(npcBot) or self:IsLaning(npcBot) or not npcBot:IsBot() -end - -M.IsRetreating = function(self, npcBot) - return npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_ACTION_DESIRE_MODERATE -end -M.NotRetreating = function(self, npcBot) - return not self:IsRetreating(npcBot) -end - -M.HasEnoughManaToUseAttackAttachedAbility = function(self, npcBot, ability) - local percent = self:GetManaPercent(npcBot) - if percent >= 0.8 and npcBot:GetMana() >= 650 then - return true - end - return percent >= 0.4 and npcBot:GetMana() >= 300 and npcBot:GetManaRegen() >= npcBot:GetAttackSpeed() / 100 * ability:GetManaCost() * 0.75 -end - --- function generator - --- turn a function that returns true, false, nil to a function that decides whether to toggle the ability or not -M.ToggleFunctionToAction = function(self, npcBot, oldConsider, ability) - local name = ability:GetName() - return function() - local value, target, castType = oldConsider() - if type(value) == "number" then - return value, target, castType - end - if value ~= ability:GetToggleState() and ability:IsFullyCastable() and not ability:IsHidden() then - npcBot:Action_UseAbility(ability) - end - end -end - -M.ToggleFunctionToAutoCast = function(self, npcBot, ability, oldToggle) - return function() - local value, target, castType = oldToggle() - if type(value) == "number" then - return value, target, castType - end - if ability:IsFullyCastable() and value ~= ability:GetAutoCastState() and not ability:IsHidden() then - ability:ToggleAutoCast() - end - return 0 - end -end - -M.PreventAbilityAtIllusion = function(self, npcBot, oldConsiderFunction, ability) - return function() - local desire, target, targetTypeString = oldConsiderFunction() - if desire == 0 or target == nil or target == 0 or self:IsVector(target) or targetTypeString == "Location" then - return desire, target, targetTypeString - end - if self:MustBeIllusion(npcBot, target) then - return 0 - end - return desire, target, targetTypeString - end -end - -M.PreventEnemyTargetAbilityUsageAtAbilityBlock = function(self, npcBot, oldConsiderFunction, ability) - local newConsider = function() - -- TODO: do we consider the base cooldown or the modified cooldown (arcane rune, octarine orb)? Will you crack a sphere's spell block with an ultimate ability when you're on arcane rune? - local desire, target, targetTypeString = oldConsiderFunction() - if desire == 0 or target == nil or target == 0 or self:IsVector(target) or targetTypeString == "Location" then - return desire, target, targetTypeString - end - local oldDesire = desire - if npcBot:GetTeam() ~= target:GetTeam() then -- some ability can cast to both allies and enemies (abbadon_mist_coil, etc) - local cooldown = ability:GetCooldown() - local abilityImportance = self:GetAbilityImportance(cooldown) - - if target:HasModifier "modifier_antimage_counterspell" then - return 0 - end - if target:HasModifier "modifier_item_sphere" or target:HasModifier "modifier_roshan_spell_block" or target:HasModifier "modifier_special_bonus_spell_block" then -- qop lv 25 - if cooldown >= 30 then - desire = desire - abilityImportance - elseif cooldown <= 20 then - desire = desire + abilityImportance - end - end - if target:HasModifier "modifier_item_sphere_target" then - if cooldown >= 60 then - desire = 0 - elseif cooldown >= 30 then - desire = desire - abilityImportance + 0.1 - elseif cooldown <= 20 then - desire = desire + abilityImportance - if abilityImportance > 0.1 then - desire = desire - 0.1 - end - end - end - if target:HasModifier "modifier_item_lotus_orb_active" then - if npcBot:GetActiveMode() == BOT_MODE_RETREAT then - desire = 0 - else - desire = desire - abilityImportance/2 - end - end - if target:HasModifier "modifier_mirror_shield_delay" then - desire = desire - abilityImportance*1.5 - end - - desire = self:TrimDesire(desire) - end - return desire, target, targetTypeString - end - return newConsider -end - -M.GetUsedAbilityInfo = function(self, ability, abilityInfoTable, considerTarget) - abilityInfoTable.lastUsedTime = DotaTime() - abilityInfoTable.lastUsedCharge = ability:GetCurrentCharges() - abilityInfoTable.lastUsedTarget = considerTarget - abilityInfoTable.lastUsedRemainingCooldown = ability:GetCooldownTimeRemaining() -end - -M.AddCooldownToChargeAbility = function(self, oldConsider, ability, abilityInfoTable, additionalCooldown) - return function() - if abilityInfoTable.lastUsedTime == nil then - abilityInfoTable.lastUsedTime = DotaTime() - end - if not (ability:GetCurrentCharges() > 0 and ability:IsFullyCastable()) then - return 0 - end - if DotaTime() <= abilityInfoTable.lastUsedTime + additionalCooldown and abilityInfoTable.lastUsedCharge >= ability:GetCurrentCharges() and abilityInfoTable.lastUsedRemainingCooldown <= ability:GetCooldownTimeRemaining() then - return 0 - end - return oldConsider() - end -end - -local function CaptureOutpost() - return 0 -end - -local function UnderlordFly() - return 0 -end - -M.AutoModifyConsiderFunction = function(self, npcBot, considers, abilitiesReal) - for index, ability in pairs(abilitiesReal) do - if ability:GetName() == "ability_capture" then - considers[index] = CaptureOutpost - elseif ability:GetName() == "abyssal_underlord_portal_warp" then - considers[index] = UnderlordFly - elseif not binlib.Test(ability:GetBehavior(), ABILITY_BEHAVIOR_PASSIVE) and considers[index] == nil then - print("Missing consider function "..ability:GetName()) - elseif binlib.Test(ability:GetTargetTeam(), ABILITY_TARGET_TEAM_ENEMY) and binlib.Test(ability:GetTargetType(), binlib.Or(ABILITY_TARGET_TYPE_HERO, ABILITY_TARGET_TYPE_CREEP, ABILITY_TARGET_TYPE_BUILDING)) and binlib.Test(ability:GetBehavior(), ABILITY_BEHAVIOR_UNIT_TARGET) then - considers[index] = self.PreventAbilityAtIllusion(self, npcBot, considers[index], ability) - if not self:IgnoreAbilityBlock(ability) then - considers[index] = self.PreventEnemyTargetAbilityUsageAtAbilityBlock(self, npcBot, considers[index], ability) - end - end - end - npcBot.abilityRecords = {} -end - -function M:InitAbility(npcBot) - local abilities = NewTable() - local abilityNames = NewTable() - local talents = NewTable() - for i = 0, 23 do - local ability = npcBot:GetAbilityInSlot(i) - if (ability ~= nil) then - if (ability:GetName() ~= "generic_hidden") then - if (ability:IsTalent() == true) then - table.insert(talents, ability:GetName()) - else - table.insert(abilityNames, ability:GetName()) - table.insert(abilities, ability) - end - end - end - end - npcBot.abilityInited = true - return abilityNames, abilities, talents -end - --- ability information - -local keysBeforeAbilityInformation = M:Keys(M) - -M.UndisjointableProjectiles = { - "alchemist_berser_potion", - "alchemist_unstable_concoction_throw", - "arc_warden_spark_wraith", - "grimstroke_phantoms_embrace", - "earthshaker_echoslam", - "gyrocopter_homing_missile", - "beastmaster_hawk_dive", - "huskar_life_break", - "lich_chain_frost", - "medusa_cold_blooded", - "medusa_mystic_snake", - "mirana_starstorm", - "necrolyte_death_pulse", - "necrolyte_death_seeker", - "oracle_fortunes_end", - "queenofpain_scream_of_pain", - "skywrath_mage_arcane_bolt", - "snapfire_firesnap_cookie", - "spectre_spectral_dagger", - "tiny_toss", - "tusk_snowball", - "witch_doctor_paralyzing_cask", -} - -M.targetTrackingStunAbilities = { - "alchemist_berser_potion", - "alchemist_unstable_concoction_throw", - "chaos_knight_chaos_bolt", - "dragon_knight_dragon_tail", - "gyrocopter_homing_missile", - "morphling_adaptive_strike_str", - "mud_golem_hurl_boulder", - "skeleton_king_hellfire_blast", - "sven_storm_hammer", - "vengefulspirit_magic_missile", - "windrunner_shackleshot", -} - -M.targetNonTrackingStunAbilities = { - "bane_fiends_grip", - "beastmaster_primal_roar", - "dark_willow_cursed_crown", - "enigma_malefice", - "invoker_cold_snap", - "item_abyssal_blade", - "lich_sinister_gaze", - "luna_lucent_beam", - "necrolyte_reapers_scythe", - "ogre_magi_fireblast", - "ogre_magi_unrefined_fireblast", - "pudge_dismember", - "rubick_telekinesis", - "shadow_shaman_shackles", - "storm_spirit_electric_vortex", -} - -M.targetStunAbilities = M:Concat(M.targetTrackingStunAbilities, M.targetNonTrackingStunAbilities) - -M.locationStunAbilities = { - "axe_berserkers_call", - "centaur_hoof_stomp", - "dark_seer_vacuum", - "dark_willow_cursed_crown", - "dawnbreaker_fire_wreath", - "dawnbreaker_solar_guardian", - "earthshaker_fissure", - "earthshaker_enchant_totem", - "earthshaker_echoslam", - "enigma_black_hole", - "faceless_void_chronosphere", - "jakiro_ice_path", - "keeper_of_the_light_will_o_wisp", - "kunkka_ghostship", - "kunkka_torrent", - "kunkka_torrent_storm", - "lina_light_strike_array", - "magnataur_skewer", - "magnataur_horn_toss", - "magnataur_reverse_polarity", - "monkey_king_boundless_strike", - "phoenix_supernova", - "puck_dream_coil", - "sand_king_burrowstrike", - "slardar_slithereen_crush", - "tidehunter_ravage", -} - -M.targetTrackingDisableAbilities = { - "gleipnir_eternal_chains", - "naga_siren_ensnare", - "riki_sleeping_dart", - "viper_viper_strike", -} - -M.targetNonTrackingDisableAbilities = { - "bloodseeker_rupture", - "doom_bringer_doom", - "ember_spirit_searing_chains", - "grimstroke_ink_creature", - "grimstroke_soul_chain", - "item_sheepstick", - "lion_vex", - "shadow_demon_purge", - "shadow_shaman_voodoo", -} - -M.targetDisableAbilities = M:Concat(M.targetNonTrackingStunAbilities, M.targetTrackingDisableAbilities) - -M.locationDisableAbilities = { - "dark_willow_bramble_maze", - "death_prophet_silence", - "disruptor_kinetic_field", - "disruptor_static_storm", - "drow_ranger_wave_of_silence", - "elder_titan_echo_stomp", - "invoker_deafening_wave", - "treant_overgrowth", -} - -M.targetTrackingHeavyDamageAbilities = { - "item_ethereal_blade", - "lich_chain_frost", - "lion_finger_of_death", - "morphling_adaptive_strike_agi", - "sniper_assassinate", -} - -M.targetNonTrackingHeavyDamageAbilities = { - "antimage_mana_void", - "item_dagon", - "lina_laguna_blade", - "pugna_life_drain", - "tinker_laser", - "zuus_lightning_bolt", -} - -M.targetHeavyDamageAbilities = M:Concat(M.targetTrackingHeavyDamageAbilities, M.targetNonTrackingHeavyDamageAbilities) - -M.locationHeavyDamageAbilities = { - "ancient_apparition_ice_blast", - "antimage_mana_void", - "disruptor_static_storm", - "invoker_chaos_meteor", - "invoker_sun_strike", - "jakiro_macropyre", - "kunkka_ghostship", - "nevermore_requiem_of_souls", - "obsidian_destroyer_sanitys_eclipse", - "phoenix_sun_ray", - "puck_dream_coil", - "pugna_nether_blast", - "queenofpain_sonic_wave", - "sand_king_epicenter", - "skywrath_mage_mystic_flare", - "venomancer_poison_nova", -} - -M.heavyDamageAbilities = M:Concat(M.targetTrackingHeavyDamageAbilities, M.locationHeavyDamageAbilities) - -M.dodgeWorthAbilities = M:Concat(M.targetStunAbilities, M.locationStunAbilities, M.heavyDamageAbilities) - -M.invisibleModifiers = { - "modifier_bounty_hunter_wind_walk", - "modifier_clinkz_wind_walk", - "modifier_dark_willow_shadow_realm_buff", - "modifier_item_glimmer_cape_glimmer", - "modifier_invoker_ghost_walk_self", - "modifier_nyx_assassin_vendetta", - "modifier_item_phase_boots_active", - "modifier_item_shadow_amulet_fade", - "modifier_item_invisibility_edge_windwalk", - "modifier_shadow_fiend_requiem_thinker", - "modifier_item_silver_edge_windwalk", - "modifier_windrunner_wind_walk", - "modifier_storm_wind_walk", - "modifier_templar_assassin_meld", - "modifier_visage_silent_as_the_grave", - "modifier_weaver_shukuchi", - "modified_invisible", - "modifier_rune_invis", - "modifier_nyx_assassin_burrow", - "modifier_oracle_false_promise_invis", -} - -M.truesightModifiers = { - "modifier_item_dustofappearance", - "modifier_bounty_hunter_track", - "modifier_slardar_amplify_damage", - "modifier_truesight", -} - -M.phaseModifiers = { - "modifier_bounty_hunter_wind_walk", - "modifier_clinkz_wind_walk", - "modifier_dark_willow_shadow_realm_buff", - "modifier_faceless_void_chronosphere_selfbuff", - "modifier_item_glimmer_cape_glimmer", - "modifier_invoker_ghost_walk_self", - "modifier_nyx_assassin_vendetta", - "modifier_item_phase_boots_active", - "modifier_item_shadow_amulet_fade", - "modifier_item_invisibility_edge_windwalk", - "modifier_shadow_fiend_requiem_thinker", - "modifier_item_silver_edge_windwalk", - "modifier_slardar_sprint", - "modifier_storm_wind_walk", - "modifier_templar_assassin_meld", - "modifier_weaver_shukuchi", -} - -M.phaseUnits = { - "npc_dota_brewmaster_fire_1", - "npc_dota_brewmaster_fire_2", - "npc_dota_brewmaster_fire_3", - "npc_dota_broodmother_web", - "npc_dota_courier", - "npc_dota_phoenix_sun", - "npc_dota_juggernaut_healing_ward", - "npc_dota_techies_land_mine", - "npc_dota_techies_stasis_trap", - "npc_dota_techies_remote_mine", - "npc_dota_weaver_swarm", -} - -M.unobstructedMovementModifiers = { - "modifier_batrider_firefly", - "modifier_broodmother_spin_web", - "modifier_centaur_stampede", - "modifier_dragon_knight_dragon_form", - "modifier_item_giants_ring_giants_foot", - "modifier_lich_sinister_gaze", - "modifier_legion_commander_duel", - "modifier_nyx_assassin_vendetta", - "modifier_spectre_spectral_dagger_path_phased", - "modifier_item_spider_legs_active", - "modifier_visage_silent_as_the_grave", -} - -M.flyingModifiers = { - "modifier_rattletrap_jetpack", - "modifier_night_stalker_darkness", - "modifier_winter_wyvern_arctic_burn_flight", -} - -M.flyingUnits = { - "npc_dota_visage_familiar1", - "npc_dota_visage_familiar2", - "npc_dota_visage_familiar3", - "npc_dota_flying_courier", - "npc_dota_beastmaster_hawk", -} - -M.positiveForceMovementModifiers = { - "modifier_faceless_void_time_walk", - "modifier_huskar_life_break_charge", - "modifier_magnataur_skewer_movement", - "modifier_monkey_king_bounce", - "modifier_monkey_king_bounce_leap", - "modifier_monkey_king_tree_dance_activity", - "modifier_monkey_king_bounce_perch", - "modifier_monkey_king_right_click_jump_activity", - "modifier_pangolier_swashbuckle", - "modifier_pangolier_swashbuckle_attack", - "modifier_pangolier_swashbuckle_stunned", - "modiifer_pangolier_shield_crash_jump", - "modifier_pangolier_rollup", - "modifier_lone_druid_true_form_transform", - "modifier_snapfire_firesnap_cookie", - "modifier_snapfire_gobble_up", - "modifier_sand_king_burrowstrike", - "modifier_techies_suicide_leap", -} - -M.timeSensitivePositiveModifiers = { - "modifier_item_black_king_bar", - "modifier_faceless_void_chronosphere_selfbuff", - "modifier_medusa_stone_gaze", - "modifier_monkey_king_fur_army_soldier_in_position", -} --- sorted by importance, used by dispell abilities - -M.basicDispellablePositiveModifiers = { - "modifier_omniknight_guardian_angle", - "modifier_ember_spirit_flame_guard", - "modifier_legion_commander_press_the_attack", - "modifier_windrunner_windrun", - "modifier_lich_frost_shield", - "modifier_oracle_purifying_flames", - "modifier_ogre_magi_bloodlust", - "modifier_treant_living_armor", - "modifier_mirana_leap_buff", - "modifier_necrolyte_death_seeker", - "modifier_necrolyte_sadist_active", - "modifier_pugna_decrepify", - "modifier_item_ethereal_blade_ethereal", - "modifier_ghost_state", - "modifier_abaddon_frostmourne_buff", - "modifier_item_mjollnir_static", - "modifier_visage_silent_as_the_grave", - "modifier_spirit_breaker_bulldoze", - "modifier_item_spider_legs_active", - "modifier_item_bullwhip_buff", - "modifier_haste_rune_haste", - "modifier_double_damage_rune", - "modifier_arcane_rune", -- not sure what the names are -} - -M.basicDispellWorthPositiveModifiers = { - "modifier_omniknight_guardian_angle", - "modifier_ember_spirit_flame_guard", - "modifier_legion_commander_press_the_attack", - "modifier_windrunner_windrun", - "modifier_lich_frost_shield", - "modifier_oracle_purifying_flames", - "modifier_ogre_magi_bloodlust", - "modifier_treant_living_armor", - "modifier_mirana_leap_buff", - "modifier_necrolyte_death_seeker", - "modifier_necrolyte_sadist_active", - "modifier_pugna_decrepify", - "modifier_item_ethereal_blade_ethereal", - "modifier_ghost_state", -} - -M.basicDispellWorthNegativeModifiers = { - "modifier_abaddon_frostmourne_debuff_bonus", -} - -M.basicDispellableNegativeModifiers = { - "modifier_abaddon_frostmourne_debuff", - "modifier_abaddon_frostmourne_debuff_bonus", -} - -M.unbreakableChannelAbilities = { - "puck_phase_shift", - "lone_druid_true_form", - "phoenix_supernova", - "lycan_shapeshift", - "item_trusty_shovel", - "item_fallen_sky", -} --- items cannot be break by silence - -M.lowPriorityChannelAbilities = { - "windrunner_powershot", - "ability_capture", - "tinker_keen_conveyance", - "tinker_rearm", - "lion_mana_drain", -} - -M.moderatePriorityChannelAbilities = { - "keeper_of_the_light_illuminate", - "pugna_life_drain", - "hoodwink_hunters_boomerang", - "drow_ranger_multishot", - "clinkz_piercing_arrow", -} - -M.nonIllusionModifiers = {} - -M.valubleNeutrals = { - "npc_dota_neutral_alpha_wolf", - "npc_dota_neutral_centaur_khan", - "npc_dota_neutral_polar_furbolg_ursa_warrior", - "npc_dota_neutral_dark_troll_warlord", - "npc_dota_neutral_mud_golem", - "npc_dota_neutral_satyr_hellcaller", -} - -M.valubleAncientNeutrals = { - "npc_dota_neutral_black_dragon", - "npc_dota_neutral_rock_golem", - "npc_dota_neutral_big_thunder_lizard", -} - -M.hypnosisModifiers = { - "modifier_lich_sinister_gaze", - "modifier_void_spirit_aether_remnant_pull", - "modifier_keeper_of_the_light_will_o_wisp", -} - -M.fearModifiers = { - "modifier_dark_willow_debuff_fear", - "modifier_lone_druid_savage_roar", - "modifier_shadow_fiend_requiem_fear", - "modifier_terrorblade_fear", -} - -M.hexModifiers = { - "modifier_lion_voodoo", - "modifier_shadow_shaman_voodoo", - "modifier_sheepstick_debuff", - "modifier_item_princes_knife_hex", - "modifier_hexxed", -- dazzle_poison_touch aghanim's shard - "modifier_item_unstable_wand_critter", -} - -M.silenceModifiers = { - "modifier_abaddon_frostmourne_debuff_bonus", - "modifier_silence", - "modifier_bloodthorn_debuff", - "modifier_disruptor_static_storm", - "modifier_doom_bringer_doom", - "modifier_drow_ranger_wave_of_silence", - "modifier_earth_spirit_geomagnetic_grip_debuff", - "modifier_enigma_black_hole_pull", - "modifier_grimstroke_ink_creature_debuff", - "modifier_legion_commander_duel", - "modifier_item_mask_of_madness_berserk", - "modifier_night_stalker_crippling_fear", - "modifier_orchid_malevolence_debuff", - "modifier_riki_smoke_screen", - "modifier_silencer_global_silence", - "modifier_silencer_last_word", - "modifier_skywrath_mage_ancient_seal", - "modifier_item_book_of_shadows", -} - -M.timedSilenceModifiers = { - "modifier_abaddon_frostmourne_debuff_bonus", - "modifier_silence", - "modifier_bloodthorn_debuff", - "modifier_doom_bringer_doom", - "modifier_drow_ranger_wave_of_silence", - "modifier_earth_spirit_geomagnetic_grip_debuff", - "modifier_grimstroke_ink_creature_debuff", - "modifier_legion_commander_duel", - "modifier_item_mask_of_madness_berserk", - "modifier_orchid_malevolence_debuff", - "modifier_silencer_global_silence", - "modifier_silencer_last_word", - "modifier_skywrath_mage_ancient_seal", - "modifier_item_book_of_shadows", -} - -M.magicImmuneModifiers = { - "modifier_item_black_king_bar", - "modifier_life_stealer_rage", - "modifier_juggernaut_blade_fury", - "modifier_minotaur_horn_immune", - "modifier_elder_titan_echo_stomp_magic_immune", - "modifier_huskar_life_break_charge", - "modifier_legion_commander_press_the_attack_immunity", - "modifier_lion_mana_drain_immunity", -} - -M.disarmModifiers = { - "modifier_haskar_inner_fire_disarm", - "modifier_item_book_of_shadows", - "modifier_heavens_halberd_debuff", -} - -M.stunModifiers = { - "" -} - -M.muteModifiers = { - "modifier_tusk_snowball", - "modifier_doom_bringer_doom", - "modifier_disruptor_static_storm_mute", - "modifier_item_book_of_shadows", - "modifier_item_nullifier_mute" -} - -M.breakModifiers = { - -- "modifier_doom_bringer_doom",--only breaks with scepter - "modifier_hoodwink_sharpshooter", - "modifier_phantom_assassin_fan_of_knives", - -- "modifier_shadow_demon_purge_slow",--only break with scepter - "modifier_silver_edge_debuff", - -- "modifier_spirit_breaker_greaterbash_break",--only break with shard - "modifier_viper_nethertoxin", -} - -M.knockbackModifiers = { - "modifier_huskar_inner_fire_knockback", - "modifier_pudge_meat_hook", - "modifier_snapfire_firesnap_cookie_pre_hop", - "modifier_snapfire_firesnap_cookie_short_hop", - "modifier_knockback", - "modifier_drowranger_wave_of_silence_knockback", - "modifier_item_forcestaff_active", - "modifier_item_hurricane_pike_active", - "modifier_item_pogostick_active", - "modifier_item_psychic_headband_active", - "modifier_force_boots_active", -} - -M.blindModifiers = { - "modifier_item_black_powder_bag_blind", -} --- TODO: how to record the caster of these abilities - -M.noTrueSightRootAbilityAssociation = { - dark_willow_branble_maze = "modifier_dark_willow_bramble_maze", - item_diffusal_blade = "modifier_rooted", -- most people don't know diffusal blade apply root on non-hero units -} - -M.conditionalTrueSightRootAbilityAssociation = { - dark_troll_warlord_ensnare = "modifier_dark_troll_warlord_ensnare", - ember_spirit_searing_chains = "modifier_ember_spirit_searing_chains", - oracle_fortunes_end = "modifier_oracle_fortunes_end_purge", - item_rod_of_atos = "modifier_rod_of_atos_debuff", - item_gungir = "modifier_gungir_debuff", -} - -M.permanentTrueSightRootAbilityAssociation = { - broodmother_silken_bola = "modifier_broodmother_silken_bola", - crystal_maiden_frostbite = "modfifier_crystal_maiden_frostbite", - meepo_earthbind = "modifier_meepo_earthbind", - naga_siren_ensnare = "modifier_naga_siren_ensnare", - spirit_bear_entangling_claws = "modifier_lone_druid_spirit_bear_entangle_effect", - techies_stasis_trap = "modifier_techies_stasis_trap_stunned", - treant_overgrowth = "modifier_treant_overgrowth", - troll_warlord_berserkers_rage = "modifier_troll_warlord_berserkers_rage_ensnare", - abyssal_underlord_pit_of_malice = "modifier_abyssal_underlord_pit_of_malice_ensare", -} - -M.rootAbilityAssociation = M:Concat(M.noTrueSightRootAbilityAssociation, M.conditionalTrueSightRootAbilityAssociation, M.permanentTrueSightRootAbilityAssociation) - -local keysAfterAbilityInformation = M:Keys(M) -local abilityInformationKeys = keysAfterAbilityInformation:RemoveAll(keysBeforeAbilityInformation) -abilityInformationKeys:ForEach(function(t) setmetatable(M[t], magicTable) end) -abilityInformationKeys = abilityInformationKeys:Filter(function(t) return t:match "AbilityAssociation" end) - -local function ExtendAssociation(association) - return association:MapDic(function(key, value) return key end), association:Map(function(key, value) return value end):Distinct() -end -abilityInformationKeys:ForEach(function(t) - local a, b = ExtendAssociation(M[t]) - local k = t:sub(1, #t-#"AbilityAssociation") - M[k.."Abilities"] = a - M[k.."Modifiers"] = b -end) - - --- enums - -function M:ToIntItemPurchaseResult(i) - return if i == PURCHASE_ITEM_SUCCESS { "PURCHASE_ITEM_SUCCESS" } - elif i == PURCHASE_ITEM_OUT_OF_STOCK { "PURCHASE_ITEM_OUT_OF_STOCK" } - elif i == PURCHASE_ITEM_DISALLOWED_ITEM { "PURCHASE_ITEM_DISALLOWED_ITEM" } - elif i == PURCHASE_ITEM_INSUFFICIENT_GOLD { "PURCHASE_ITEM_INSUFFICIENT_GOLD" } - elif i == PURCHASE_ITEM_NOT_AT_HOME_SHOP { "PURCHASE_ITEM_NOT_AT_HOME_SHOP" } - elif i == PURCHASE_ITEM_NOT_AT_SECRET_SHOP { "PURCHASE_ITEM_NOT_AT_SECRET_SHOP" } - elif i == PURCHASE_ITEM_INVALID_ITEM_NAME { "PURCHASE_ITEM_INVALID_ITEM_NAME"} - else { "UNKNOWN_ITEM_PURCHASE_RESULT_ENUM" } -end - -M.botModeEnum = { - BOT_MODE_NONE = BOT_MODE_NONE, - BOT_MODE_LANING = BOT_MODE_LANING, - BOT_MODE_ATTACK = BOT_MODE_ATTACK, - BOT_MODE_ROAM = BOT_MODE_ROAM, - BOT_MODE_RETREAT = BOT_MODE_RETREAT, - BOT_MODE_SECRET_SHOP = BOT_MODE_SECRET_SHOP, - BOT_MODE_SIDE_SHOP = BOT_MODE_SIDE_SHOP, - BOT_MODE_PUSH_TOWER_TOP = BOT_MODE_PUSH_TOWER_TOP, - BOT_MODE_PUSH_TOWER_MID = BOT_MODE_PUSH_TOWER_MID, - BOT_MODE_PUSH_TOWER_BOT = BOT_MODE_PUSH_TOWER_BOT, - BOT_MODE_DEFEND_TOWER_TOP = BOT_MODE_DEFEND_TOWER_TOP, - BOT_MODE_DEFEND_TOWER_MID = BOT_MODE_DEFEND_TOWER_MID, - BOT_MODE_DEFEND_TOWER_BOT = BOT_MODE_DEFEND_TOWER_BOT, - BOT_MODE_ASSEMBLE = BOT_MODE_ASSEMBLE, - BOT_MODE_TEAM_ROAM = BOT_MODE_TEAM_ROAM, - BOT_MODE_FARM = BOT_MODE_FARM, - BOT_MODE_DEFEND_ALLY = BOT_MODE_DEFEND_ALLY, - BOT_MODE_EVASIVE_MANEUVERS = BOT_MODE_EVASIVE_MANEUVERS, - BOT_MODE_ROSHAN = BOT_MODE_ROSHAN, - BOT_MODE_ITEM = BOT_MODE_ITEM, - BOT_MODE_WARD = BOT_MODE_WARD, -} -GiveLinqFunctions(M.botModeEnum) -function M:ToIntBotMode(i) - for k, v in pairs(botModeEnum) do - if v == i then - return k - end - end - return "UNKNOWN_BOT_MODE_ENUM" -end - --- unit function - -function M:IsRoshan(npcTarget) - return npcTarget ~= nil and npcTarget:IsAlive() and string.find(npcTarget:GetUnitName(), "roshan") -end - -function M:IsHero(t) - return t:IsHero() -end - -function M:IsTempestDouble(npc) - return npc:HasModifier "modifier_arc_warden_tempest_double" -end - -function M:IsLoneDruidBear(npc) - return string.match(npc:GetUnitName(), "npc_dota_lone_druid_bear") -end - -function M:IsVisageFamiliar(npc) - return string.match(npc:GetUnitName(), "npc_dota_visage_familiar") -end - -function M:IsBrewmasterPrimalSplit(npc) - local unitName = npc:GetUnitName() - return string.match(unitName, "npc_dota_brewmaster_") -end - -function M:IsHeroLevelUnit(npc) - if self:IsBrewmasterPrimalSplit(npc) then return true end - local name = npc:GetUnitName() - if name == "npc_dota_phoenix_sun" then return true end - if string.sub(name, 1, #"npc_dota_lone_druid_bear") == "npc_dota_lone_druid_bear" then return true end - return false -end - -M.GetIncomingDodgeWorthProjectiles = function(self, npc) - local health = npc:GetHealth() - local projectiles = npc:GetIncomingTrackingProjectiles() - projectiles = self:Filter(projectiles, function(t) - if t.is_attack then - return false - end - -- caster can be nil - if t.caster then - if npc:GetTeam() == t.caster:GetTeam() then - return false - end - else - if GetTeamForPlayer(t.playerid) == npc:GetTeam() then - return false - end - end - - local ability = t.ability - if ability then - local abilityName = ability:GetName() - if self:Contains(self.UndisjointableProjectiles, abilityName) then - return false - end - if self:Contains(self.targetTrackingStunAbilities, abilityName) or self:Contains(self.targetTrackingDisableAbilities, abilityName) or self:Contains(self.targetTrackingHeavyDamageAbilities, abilityName) or npc:GetHealth() <= npc:GetActualIncomingDamage(ability:GetAbilityDamage(), ability:GetDamageType()) then - return true - end - return false - end - return true - end) - return projectiles -end - -function M:StackManipulators(amplifications, reductions) - return self:Aggregate(1, reductions) { - agg, factor -> agg * (1 - factor) - } - self:Aggregate(1, amplifications) { - agg, factor -> agg * (1 - factor) - } -end - -M.GetTargetHealAmplifyPercent = function(self, npc) - local amps = {} - local reds = {} - for i = 1, npc:NumModifiers() do - local modifierName = npc:GetModifierName(i) - if modifierName == "modifier_item_spirit_vessel_damage" then - table.insert(reds, 0.45) - end - if modifierName == "modifier_holy_blessing" then - table.insert(amps, 0.35) - end - if modifierName == "modifier_necrolyte_sadist_active" then - table.insert(amps, 0.75) - end - if npc:HasModifier "modifier_bane_enfeeble_effect" then - table.insert(reds, 0.6) - end - if npc:HasModifier "modifier_drow_ranger_frost_arrows_slow" then - local t = npc:GetModifierByName "modifier_drow_ranger_frost_arrows_hypothermia" - if t ~= -1 then - table.insert(reds, npc:GetModifierStackCount(t) * 0.1) - end - end - if npc:HasModifier "modifier_item_skadi_slow" then - table.insert(reds, 0.4) - end - if npc:HasModifier "modifier_item_shivas_guard_aura" then - table.insert(reds, 0.25) - end - if npc:HasModifier "modifier_treant_natures_guise" then - table.insert(amps, 0.4) - end - end - - if self:GetAvailableItem(npc, "item_paladin_sword") then - table.insert(amps, 0.14) - end - local amp = 1 + self:StackManipulators(amps, reds) - if npc:HasModifier("modifier_oracle_false_promise") then - amp *= 2 - end - if npc:HasModifier("modifier_ice_blast") then - amp *= 0 - end - return amp -end - -function M:GetLifeSteal(npc) - local amp = 0 - local amps = {} - local reds = {} - if npc:HasModifier "modifier_item_vladmir_aura" then - amp += 0.15 - end - table.insert(amps, if self:GetAvailableItem(npc, "item_satanic") { 0.25 } - elif self:GetAvailableItem(npc, "item_mask_of_madness") { 0.2 } - elif self:GetAvailableItem(npc, "item_paladin_sword") { 0.16 } - elif self:GetAvailableItem(npc, "item_morbid_mask") { 0.15 } - elif self:GetAvailableItem(npc, "item_possessed_mask") { 0.05 } - else { 0 }) - if npc:HasModifier "modifier_item_satanic_unholy" then - amp += 1.75 - end - if npc:HasModifier "modifier_troll_warlord_battle_trance" then - amp += Clamp(math.floor(npc:GetLevel()/6), 1, 3) * 0.2 + 0.2 - end - local talentLifestealValue = {10,15,18,20,25,30,35,40,100} - self:ForEach(talentLifestealValue) { value -> - if local abi = npc:GetAbilityByName("special_bonus_unique_lifesteal_"..value) then - if abi:IsActivated() then - amp += 0.15 - end - end - } - if self:GetAvailableItem(npc, "item_paladin_sword") then - amp += 0.14 - end - - -- lifesteal amplifications - for i = 1, npc:NumModifiers() do - local modifierName = npc:GetModifierName(i) - if modifierName == "modifier_item_spirit_vessel_damage" then - table.insert(reds, 0.45) - end - if modifierName == "modifier_bane_enfeeble_effect" then - table.insert(reds, 0.6) - end - if modifierName == "modifier_drow_ranger_frost_arrows_slow" then - table.insert(reds, npc:GetModifierStackCount(i) * 0.1) - end - if modifierName == "modifier_skeleton_king_vampiric_aura" then - amp += 0.34 - end - if modifierName == "modifier_item_skadi_slow" then - table.insert(reds, 0.4) - end - if modifierName == "modifier_item_shivas_guard_aura" then - table.insert(reds, 0.25) - end - if modifierName == "modifier_treant_natures_guise" then - table.insert(amps, 0.4) - end - if modifierName == "modifier_broodmother_insatiable_hunger" then - local abi = npc:GetAbilityByName "broodmother_insatiable_hunger" - if abi then - amp += abi:GetSpecialValueFloat "lifesteal_pct" - end - end - if modifierName == "modifier_lycan_wolf_bite_lifesteal" then - amp += 0.3 - end - end - if local abi = npc:GetAbilityByName "chaos_knight_chaos_strike" then - if abi:GetLevel() >= 1 then - amp += abi:GetSpecialValueFloat("lifesteal") * abi:GetSpecialValueFloat("chance") * (abi:GetSpecialValueFloat("crit_min") + abi:GetSpecialValueFloat("crit_max")) / 2 - end - end - if local abi = npc:GetAbilityByName "legion_commander_moment_of_courage" then - if abi:GetLevel() >= 1 then - amp += abi:GetSpecialValueFloat("hp_leech_percent") - end - end - if local abi = npc:GetAbilityByName "lone_druid_spirit_link" then - if abi:GetLevel() >= 1 then - amp += abi:GetSpecialValueFloat("lifesteal_percent") - end - end - - if self:GetAvailableItem(npc, "item_kaya_and_sange") or self:GetAvailableItem(npc, "item_sange_and_yasha") then - table.insert(amps, 0.22) - elif self:GetAvailableItem(npc, "item_sange") or self:GetAvailableItem(npc, "item_heavens_halberd") then - table.insert(amps, 0.2) - end - amp *= self:StackManipulators(amps, reds) - if npc:HasModifier "modifier_oracle_false_promise" then - amp *= 2 - end - if npc:HasModifier"modifier_ice_blast" then - amp *= 0 - end - return amp -end - -M.IsChannelingItem = function(self, npc) - return npc:HasModifier "modifier_item_meteor_hammer" or npc:HasModifier "modifier_teleporting" or npc:HasModifier "modifier_boots_of_travel_incoming" -end - -M.IsChannelingAbility = function(self, npc) - return npc:IsChanneling() and not self:IsChannelingItem(npc) -end - -function M:IsChannelingBreakWorthAbility(npc, level) - if not npc:IsChanneling() then - return false - end - local ability = npc:GetCurrentActiveAbility() - if ability == nil then - if npc:HasModifier "modifier_teleporting" then - return true - end - end - local name = ability:GetName() - if self:Contains(self.unbreakableChannelAbilities, name) then - return false - end - if level == nil or level == "low" then - if self:Contains(self.lowPriorityChannelAbilities, name) then - return false - end - elseif level == "moderate" then - if self:Contains(self.moderatePriorityChannelAbilities, name) or self:Contains(self.lowPriorityChannelAbilities, name) then - return false - end - end - return true -end - -M.RadiantPlayerId = GetTeamPlayers(TEAM_RADIANT) -M.DirePlayerId = GetTeamPlayers(TEAM_DIRE) - -M.GetTeamPlayers = function(self, team) - if team == TEAM_RADIANT then - return self.RadiantPlayerId - else - return self.DirePlayerId - end -end - -M.GetEnemyTeamMemberNames = function(self, npcBot) - local enemies = self:GetEnemyHeroUnique(npcBot, GetUnitList(UNIT_LIST_ENEMY_HEROES)) - return self:Map(enemies, function(t) return t:GetUnitName() end) -end - -M.enemyVisibleIllusionModifiers = { - "modifier_illusion", - -- "modifier_phantom_lancer_doppelwalk_illusion", - -- "modifier_phantom_lancer_juxtapose_illusion", - "modifier_terrorblade_conjureimage", - "modifier_grimstroke_scepter_buff", - "modifier_arc_warden_tempest_double", - "modifier_skeleton_king_reincarnation_active", - "modifier_vengefulspirit_hybrid_special", -} - --- function M:GetOtherTeam() --- return if GetTeam() == TEAM_RADIANT { TEAM_DIRE } else { TEAM_RADIANT } --- end - --- function M:GetEnemyHeroNames() --- if self.enemyHeroNames == nil then --- self.enemyHeroNames = self:NewTable() --- self:ForEach(GetTeamPlayers(self:GetOtherTeam())) { t -> --- table.insert(self.enemyHeroNames, GetSelectedHeroName(t)) --- } --- end --- return M.enemyHeroNames --- end - -M.MustBeIllusion = function(self, npcBot, target) - if target.GetTeam and npcBot:GetTeam() == target:GetTeam() then - return target:IsIllusion() - end - -- if self:HasAnyModifier(target, self.enemyVisibleIllusionModifiers) or not self:GetEnemyHeroNames():Contains(target:GetUnitName()) then - -- return true - -- end - if target.markedAsIllusion then - return true - end - if target.markedAsRealHero then - return false - end - if not IsHeroAlive(target:GetPlayerID()) then - return true - end - return false -end -M.MayNotBeIllusion = function(self, npcBot, target) return not self:MustBeIllusion(npcBot, target) end - -function M:IsOnSameTeam(a, b) - return a:GetTeam() == b:GetTeam() -end - -function M:IsNonIllusionHero(npcBot, target) - return self:MayNotBeIllusion(npcBot, target) and self:IsHero(target) -end - -function M:HasNonIllusionModifier(npc) - return self:HasAnyModifier(npc, self.nonIllusionModifiers) -end - -function M:CanIllusionUseAbility(npc) - local name = npc:GetUnitName() - local ability = npc:GetCurrentActiveAbility() - if ability == nil then - return false - end - if name == "npc_dota_hero_bane" and self:HasScepter(npc) and ability:GetName() == "bane_fiends_grip" then - return true - end -end - -M.DetectIllusion = function(self, npcBot) - local nearbyEnemies = self:GetNearbyNonIllusionHeroes(npcBot, 1599) - nearbyEnemies = self:Filter(nearbyEnemies, function(t) return string.match(t:GetUnitName(), "npc_dota_hero") end) - local nearbyEnemyGroups = self:GroupBy(nearbyEnemies, function(t) return t:GetUnitName() end) - nearbyEnemyGroups = self:Filter(nearbyEnemyGroups, function(t) return #t > 1 end) - self:ForEach(nearbyEnemyGroups, function(nearbyEnemyGroup) - local castingEnemies = self:Filter(nearbyEnemyGroup, function(t) - return (t:IsUsingAbility() or t:IsChanneling() or self:HasNonIllusionModifier(t) or t.markedAsRealHero) and not t.markedAsIllusion - end) - local castingEnemy = castingEnemies[1] - if castingEnemy and not self:CanIllusionUseAbility(castingEnemy) then - castingEnemy.markedAsRealHero = true - castingEnemies = self:Remove(nearbyEnemyGroup, castingEnemy) - self:ForEach(castingEnemies, function(t) - t.markedAsIllusion = true - end) - end - end) -end - -M.GetNearbyHeroes = function(self, npcBot, range, getEnemy, botModeMask) - range = range or 1200 - if getEnemy == nil then - getEnemy = true - end - botModeMask = botModeMask or BOT_MODE_NONE - local heroes = npcBot:GetNearbyHeroes(range, getEnemy, botModeMask) or {} - GiveLinqFunctions(heroes) - return heroes -end - -function M:GetUnitList(unitListKind) - local units = GetUnitList(unitListKind) or {} - GiveLinqFunctions(units) - return units -end - -function M:GetAllHeores(npcBot, getEnemy) - if getEnemy == nil then - getEnemy = true - end - if getEnemy then - return self:GetEnemyHeroUnique(npcBot, GetUnitList(UNIT_LIST_ENEMY_HEROES)):Filter { it -> - self:MayNotBeIllusion(npcBot, it) - } - else - return self:Filter(GetUnitList(UNIT_LIST_ALLIED_HEROES)) { it -> - self:MayNotBeIllusion(npcBot, it) - } - end -end - -function M:GetNearbyCreeps(npcBot, range, getEnemy) - if getEnemy == nil then - getEnemy = true - end - local t = npcBot:GetNearbyCreeps(range, getEnemy) or {} - GiveLinqFunctions(t) - return t -end -function M:GetNearbyLaneCreeps(npcBot, range, getEnemy) - if getEnemy == nil then - getEnemy = true - end - local t = npcBot:GetNearbyLaneCreeps(range, getEnemy) or {} - GiveLinqFunctions(t) - return t -end - -M.GetNearbyNonIllusionHeroes = function(self, npcBot, range, getEnemy, botModeMask) - range = range or 1200 - if getEnemy == nil then - getEnemy = true - end - botModeMask = botModeMask or BOT_MODE_NONE - local heroes = npcBot:GetNearbyHeroes(range, getEnemy, botModeMask) or {} - return self:Filter(heroes, function(t) return self:MayNotBeIllusion(npcBot, t) end) -end - -function M:GetPureHeroes(npcBot, range, getEnemy) - range = range or 1600 - if getEnemy == nil then - getEnemy = true - end - return self:GetNearbyNonIllusionHeroes(npcBot, range, getEnemy):Filter { t -> - self:MayNotBeIllusion(npcBot, t) and not self:IsHeroLevelUnit(t) - } -end - -function M:AttackOnceDamage(npcBot, target) - return target:GetActualIncomingDamage(npcBot:GetAttackDamage() - npcBot:GetBaseDamageVariance()/2, DAMAGE_TYPE_PHYSICAL) -end - -function M:GetNearbyAttackableCreeps(npcBot, range, getEnemy) - if getEnemy == nil then - getEnemy = true - end - local creeps = npcBot:GetNearbyCreeps(range, getEnemy) - if getEnemy then - creeps = self:Filter(creeps, function(t) return t:HasModifier "modifier_fountain_glyph" end) - end - GiveLinqFunctions(creeps) - return creeps -end - -M.GetNearbyAllUnits = function(self, npcBot, range) - local h1 = npcBot:GetNearbyHeroes(range, true, BOT_MODE_NONE) - local h2 = self:Remove(npcBot:GetNearbyHeroes(range, false, BOT_MODE_NONE), npcBot) - local h3 = npcBot:GetNearbyCreeps(range, true) - local h4 = npcBot:GetNearbyCreeps(range, false) - return self:Concat(h1, h2, h3, h4) -end - -function M:GetNearbyEnemyUnits(npc, range) - local h1 = npc:GetNearbyHeroes(range, true, BOT_MODE_NONE) - local h3 = npc:GetNearbyCreeps(range, true) - return self:Concat(h1, h3) -end - - -M.GetEnemyHeroUnique = function(self, npcBot, enemies) - local p = self:Filter(enemies, function(t) self:MayNotBeIllusion(npcBot, t) end) - local g = NewTable() - local readNames = NewTable() - for _, enemy in pairs(p) do - local name = enemy:GetUnitName() - if not self:Contains(readNames, name) then - table.insert(readNames, name) - table.insert(g, enemy) - end - end - return g -end - -M.GetMovementSpeedPercent = function(self, npc) - return npc:GetCurrentMovementSpeed() / npc:GetBaseMovementSpeed() -end -M.CanHardlyMove = function(self, npc) - return npc:IsStunned() or npc:IsRooted() or npc:GetCurrentMovementSpeed() <= 150 -end - -M.GetModifierRemainingDuration = function(self, npc, modifierName) -> - if local mod = npc:GetModifierByName(modifierName); mod ~= -1 { - return npc:GetModifierRemainingDuration(mod) - } - else { 0 } - -M.imprisonmentModifier = { - "modifier_item_cyclone", - "modifier_item_wind_waker", - "modifier_shadow_demon_disruption", - "modifier_obsidian_destroyer_astral_imprisonment_prison", - "modifier_brewmaster_storm_cyclone", - "modifier_invoker_tornado", - --"modifier_x_marks_the_target", -} -M.GetImprisonmentRemainingDuration = function(self, npc) - return self:First(self:Map(self.imprisonmentModifier, function(t) return self:GetModifierRemainingDuration(npc, t) end), function(t) return t ~= 0 end) or 0 -end - -function M:GetMagicImmuneRemainingDuration(npc) - local remainingTime = self:Map(self.magicImmuneModifiers, function(t) return { t, self:GetModifierRemainingDuration(npc, t)} end) - remainingTime = self:SortByMaxFirst(remainingTime, function(t) return t[2] end) - remainingTime = remainingTime[1] - return remainingTime and remainingTime[2] or 0 -end - -function M:GetSilenceRemainingDuration(npc) - local silenceModifierRemainings = self:Map(self.timedSilenceModifiers, function(t) - return self:GetModifierRemainingDuration(npc, t) - end) - if npc:HasModifier "modifier_disruptor_static_storm" then - table.insert(silenceModifierRemainings, 1, 6) - end - if npc:HasModifier "modifier_enigma_black_hole_pull" or npc:HasModifier "modifier_riki_smoke_screen" then - table.insert(silenceModifierRemainings, 1, 4) - end - silenceModifierRemainings = #silenceModifierRemainings ~= 0 and math.max(self:Unpack(silenceModifierRemainings)) or 0 - return silenceModifierRemainings -end - -function M:GetStunRemainingDuration(npc) - return self:DontControlAgain(npc) and 1 or 0 -end - -M.GetEnemyHeroNumber = function(self, npcBot, enemies) - return #self:GetEnemyHeroUnique(npcBot, enemies) -end - -function M:HasPhasedMovement(npc) - return self:HasAnyModifier(npc, self.phaseModifiers) or self:Contains(self.phaseUnits, npc:GetUnitName()) -end - -function M:HasUnobstructedMovement(npc) - if self:HasAnyModifier(npc, self.flyingModifiers) or self:Contains(self.flyingUnits, npc:GetUnitName()) then - if string.match(npc:GetUnitName(), "npc_dota_visage_familiar") then - return npc:HasModifier "modifier_rooted" - end - return true - end - local activeFlyingModifiers = self:Filter(self.unobstructedMovementModifiers, function(t) return npc:HasModifier(t) end) - if #activeFlyingModifiers ~= 0 then - local dragonKnightDragonForm = self:IndexOf(activeFlyingModifiers, "modifier_dragon_knight_dragon_form") - if dragonKnightDragonForm ~= -1 then - local ability = npc:GetAbilityByName "dragon_knight_elder_dragon_form" - if ability == nil or not (ability:GetLevel() == 4) then - table.remove(activeFlyingModifiers, dragonKnightDragonForm) - end - end - local stampede = self:IndexOf(activeFlyingModifiers, "modifier_centaur_stampede") - if stampede ~= -1 then - local ability = npc:GetAbilityByName "modifier_centaur_stampede" - if ability == nil or not self:hasScepter(npc) then - table.remove(activeFlyingModifiers, stampede) - end - end - end - return #activeFlyingModifiers ~= 0 -end - --- item function - -M.GetAvailableItem = function(self, npc, itemName) - for _, i in ipairs(self:Range(0, 5):Concat({16})) do - local item = npc:GetItemInSlot(i) - if item and item:GetName() == itemName and item:IsFullyCastable() then - return item - end - end -end - -local radianceAncientLocation = Vector(-7200,-6666) -local direAncientLocation = Vector(7137,6548) - -M.GetAncientLocation = function(self, npc) - if npc:GetTeam() == TEAM_RADIANT then - return radianceAncientLocation - else - return direAncientLocation - end -end - -M.GetDistanceFromAncient = function(self, npc) - local fountain = self:GetAncientLocation(npc) - return GetUnitToLocationDistance(npc, fountain) -end - -M.TryUseTp = function(self, npc) - local item = npc:GetItemInSlot(15) - if item ~= nil and item:IsFullyCastable() and self:CanMove(npc) then - local distanceFromFountain - if npc:GetTeam() == TEAM_RADIANT then - distanceFromFountain = radianceAncientLocation + Vector(400, 400) - else - distanceFromFountain = direAncientLocation + Vector(-400, -400) - end - npc:Action_UseAbilityOnLocation(item, distanceFromFountain) - return true - end -end - -M.GetAvailableBlink = function(self, npc) - local blinks = { - "item_blink", - "item_overwhelming_blink", - "item_swift_blink", - "item_arcane_blink", - } - return self:Aggregate(nil, blinks, function(a, blinkName) - return a or self:GetAvailableItem(npc, blinkName) - end) -end - -function M:GetAvailableTravelBoots(npc) - local travelBoots = { - "item_travel_boots", - "item_travel_boots_2", - } - return self:Aggregate(nil, travelBoots, function(seed, t) - return seed or self:GetAvailableItem(npc, t) - end) -end - -M.GetEmptyInventorySlots = function(self, npc) - local g = 0 - for i = 0, 5 do - if npc:GetItemInSlot(i) == nil then - g = g+1 - end - end - return g -end - -M.GetEmptyItemSlots = function(self, npc) - local g = 0 - for i = 0, 8 do - if npc:GetItemInSlot(i) == nil then - g = g+1 - end - end - return g -end - -M.GetEmptyBackpackSlots = function(self, npc) - local g = 0 - for i = 6, 8do - if npc:GetItemInSlot(i) == nil then - g = g+1 - end - end - return g -end - -M.SwapItemToBackpack = function(self, npc, itemIndex) - for i = 6, 8 do - if npc:GetItemInSlot(i) == nil then - npc:ActionImmediate_SwapItems(itemIndex, i) - return true - end - end - return false -end - -M.GetCarriedItems = function(self, npc) - local g = NewTable() - for i = 0, 8 do - local item = npc:GetItemInSlot(i) - if item ~= nil then - item.slotIndex = i - table.insert(g, item) - end - end - return g -end - -M.GetInventoryItems = function(self, npc) - local g = NewTable() - for i = 0, 5 do - local item = npc:GetItemInSlot(i) - if item ~= nil then - item.slotIndex = i - table.insert(g, item) - end - end - return g -end - -M.GetInventoryItemNames = function(self, npc) - local g = NewTable() - for i = 0, 5 do - local item = npc:GetItemInSlot(i) - if item ~= nil then - item.slotIndex = i - table.insert(g, item:GetName()) - end - end - return g -end - -M.GetStashItems = function(self, npc) - local g = NewTable() - for i = 9, 14 do - local item = npc:GetItemInSlot(i) - if item ~= nil then - item.slotIndex = i - table.insert(g, item) - end - end - return g -end - -function M:GetCourierItems(courier) - local g = NewTable() - for i = 0, 8 do - local item = courier:GetItemInSlot(i) - if item then - table.insert(g, item) - end - end - return g -end - -function M:GetMyCourier(npcBot) - if npcBot.courierIDNew == nil then - self:FindCourier(npcBot) - end - return GetCourier(npcBot.courierIDNew or 0) -end - -function M:FindCourier(npcBot) - for i = 0,4 do - local courier = GetCourier(i) - if courier ~= nil then - if courier:GetPlayerID() == npcBot:GetPlayerID() then - npcBot.courierIDNew = i - end - end - end -end - -M.GetAllBoughtItems = function(self, npcBot) - local g = NewTable() - for i = 0, 16 do - local item = npcBot:GetItemInSlot(i) - if item then - table.insert(g, item) - end - end - if not self:GameNotReallyStarting() then - g = self:Concat(g, self:GetCourierItems(self:GetMyCourier(npcBot))) - end - return g -end - -M.IsBoots = function(self, item) - if type(item) ~= "string" then - item = item:GetName() - end - return string.match(item, "boots") or item == "item_guardian_greaves" or item == "item_power_treads" -end - -M.SwapCheapestItemToBackpack = function(self, npc) - local cheapestItem = self:First(self:Sort(self:Filter(self:GetInventoryItems(npc), function(t) - local itemName = t:GetName() - return not self:IsBoots(t) and not string.match(itemName, "ward") and not itemName == "item_gem" and not itemName == "item_dust" - end), function(a, b) return GetItemCost(a:GetName()) - GetItemCost(b:GetName()) end)) - if cheapestItem == nil then - return false - end - return self:SwapItemToBackpack(npc, cheapestItem.slotIndex) -end - -M.SuitableForSilence = function(self, npc, target) - return self:MayNotBeIllusion(npc, target) and not target:IsMagicImmune() and not self:IsInvulnerable(target) -end - -M.GetHeroFullName = function(self, s) - return "npc_dota_hero_"..s -end -M.GetHeroShortName = function(self, s) - return string.sub(s, 15) -end - -M.IsMeleeHero = function(self, npc) - local range = npc:GetAttackRange() - local name = npc:GetUnitName() - return range <= 210 or name == self:GetHeroFullName "tiny" or name == self:GetHeroFullName "doom_bringer" or name == self:GetHeroFullName "pudge" -end - -function M:HasAnyModifier(npc, modifierGroup) - return self:First(modifierGroup, function(t) return npc:HasModifier(t) end) -end - -M.AttackPassiveAbilities = { - "doom_bringer_infernal_blade", - "drow_ranger_frost_arrows", - "clinkz_fire_arrows", - "viper_poison_attack", - "obsidian_destroyer_arcane_orb", -} -M.OtherIgnoreAbilityBlockAbilities = { - "batrider_flaming_lasso", - "gyrocopter_homing_missile", - "axe_culling_blade", -} -M.IgnoreAbilityBlockAbilities = { - "dark_seer_ion_shell", - "grimstroke_soulbind", - "rubick_spell_steal", - "spectre_spectral_dagger", - "morphling_morph", - "urn_of_shadows_soul_release", - "spirit_vessel_soul_release", - "medallion_of_courage_valor", - "solar_crest_armor_shine", -} - -M.IgnoreAbilityBlock = function(self, ability) - local abilityName = ability:GetName() - return self:Contains(self.AttackPassiveAbilities, abilityName) or self:Contains(self.IgnoreAbilityBlockAbilities, abilityName) or self:Contains(self.OtherIgnoreAbilityBlockAbilities, abilityName) -end - -M.AbilityRetargetModifiers = { - "modifier_antimage_counterspell", - "modifier_item_lotus_orb_active", - "modifier_nyx_assassin_spiked_carapace", - -- "modifier_item_blade_mail", -} -M.HasAbilityRetargetModifier = function(self, npc) - return self:HasAnyModifier(npc, self.AbilityRetargetModifiers) -end - -function M:DarkPactRemainingTime(npc) - if npc:HasModifier "modifier_slark_dark_pact" then - return self:GetModifierRemainingDuration(npc, "modifier_slark_dark_pact") + 1 - else - return self:GetModifierRemainingDuration(npc, "modifier_slark_dark_pact_pulses") - end -end - -M.CanMove = function(self, npc) - return not npc:IsStunned() and not npc:IsRooted() and not self:IsNightmared(npc) and not self:IsTaunted(npc) -end - -function M:CannotMove(npc) - return -- npc:IsStunned() or self:IsNightmared(npc) or --actually still able to cast abilities or move while stunned or nightmared, but makes no dfference - npc:IsRooted() or self:IsTaunted(npc)or self:IsHypnosed(npc) or self:IsFeared(npc) -end - -function M:CannotTeleport(npc) - return npc:IsRooted() or self:IsTaunted(npc)or self:IsHypnosed(npc) or self:IsFeared(npc) -end - -function M:IsNightmared(npc) - return npc:HasModifier "modifier_bane_nightmare" or npc:HasModifier "modifier_riki_poison_dart_debuff" -end - -function M:IsTaunted(npc) - return npc:HasModifier "modifier_axe_berserkers_call" or npc:HasModifier "modifier_legion_commander_duel" -end - -function M:DontControlAgain(npc) - return npc:IsStunned() or self:IsNightmared(npc) or self:IsTaunted(npc) or self:IsHypnosed(npc) -end - -function M:IsDuelCaster(npc) - local function IsTaunting(_npc) - local ability = _npc:GetAbilityByName "modifier_legion_commander_duel" - return ability and ability:GetCooldownTimeRemaining() + self:GetModifierRemainingDuration(_npc, "modifier_legion_commander_duel") + 1 >= ability:GetCooldown() - end - if not npc then --dont know why _npc can be null - return false - end - local npcBot = GetBot() - if npcBot:GetTeam() == npc:GetTeam() then - return IsTaunting(npc) - else - local players = self:Map(self:Range(0, 4), GetTeamMember) - local tauntingPlayer = self:First(players, function(t) - return IsTaunting(t) and t:GetAttackTarget() == npc - end) - return tauntingPlayer and not IsTaunting(tauntingPlayer) - end -end - -function M:IsMuted(npc) - return self:HasAnyModifier(npc, self.muteModifiers) -end - -function M:IsHypnosed(npc) - return self:HasAnyModifier(npc, self.hypnosisModifiers) -end - -function M:IsFeared(npc) - return self:HasAnyModifier(npc, self.fearModifiers) -end - -M.IsSeverelyDisabled = function(self, npc) - return npc:IsStunned() or npc:IsHexed() or npc:IsRooted() or self:IsFeared(npc) or self:IsHypnosed(npc) - or self:IsNightmared(npc) - or npc:HasModifier "modifier_legion_commander_duel" and not self:IsDuelCaster(npc) or npc:HasModifier "modifier_axe_berserkers_call" - or npc:HasModifier "modifier_shadow_demon_purge_slow" - or npc:HasModifier "modifier_doom_bringer_doom" -end - -M.IsSeverelyDisabledOrSlowed = function(self, npc) - return self:IsSeverelyDisabled(npc) or self:GetMovementSpeedPercent(npc) <= 0.35 -end - -M.HasSeverelyDisableProjectiles = function(self, npc) - local projectiles = self:GetIncomingDodgeWorthProjectiles(npc) - return self:Any(projectiles, function(t) - return self:Contains(self.targetTrackingStunAbilities, t.ability:GetName()) - end) -end - -M.IsOrGoingToBeSeverelyDisabled = function(self, npc) - return self:IsSeverelyDisabled(npc) or self:HasSeverelyDisableProjectiles(npc) -end - -M.etherealModifiers = { - "modifier_ghost_state", - "modifier_item_ethereal_blade_ethereal", - "modifier_necrolyte_death_seeker", - "modifier_necrolyte_sadist_active", - "modifier_pugna_decrepify", -} -M.IsEthereal = function(self, npc) - return self:HasAnyModifier(npc, self.etherealModifiers) -end - -function M:NotBlasted(self, npc) - return not npc:HasModifier "modifier_ice_blast" -end - -function M:NearbyBatteryAssault(npc) - return self:GetNearbyNonIllusionHeroes(npc, 275 + npc:GetBoundingRadius()):Any { - t -> t:HasModifier "modifier_rattletrap_battery_assault" - } -end - -M.CannotBeTargetted = function(self, npc) - return self:HasAnyModifier(npc, self.CannotBeTargettedModifiers) -end - -M.CanBeTargettedFunction = function(npc) return not M:CanBeTargetted(npc) end - -M.CannotBeAttacked = function(self, npc) - return self:IsEthereal(npc) or self:IsInvulnerable(npc) or self:CannotBeTargetted(npc) -end - -M.CanBeAttackedFunction = function(npc) return not M:CanBeAttacked(npc) end - -M.IsInvulnerable = function(self, npc) - return npc:IsInvulnerable() or self:Any(self.IgnoreDamageModifiers, function(t) return npc:HasModifier(t) end) -end - -M.invisibilityItems = { - "item_shadow_amulet", - "item_invis_sword", - "item_silver_edge", - "item_glimmer_cape", - "item_trickster_cloak", -} -M.invisibilityHeroes = { - riki = 6, - clinkz = 4, - bounty_hunter = 1, - phantom_assassin = 2, - weaver = 1, - windrunner = 20, - nyx_assassin = 6, - mirana = 6, -} - -function M:HasInvisibility(npc) - if npc:HasInvisibility(true) then return true end - if self:GetCarriedItems(npc):Any { t -> - self:Contains(self.invisibilityItems, t:GetName()) - } then - return true - end - local heroName = self:GetHeroShortName(npc:GetUnitName()) - if local requiredLevel = self.invisibilityHeroes[heroName] then - return npc:GetLevel() >= requiredLevel - end - if heroName == "brewmaster" and self:HasScepter(npc) then - return true - end - return false -end - -M.MayNotBeSeen = function(self, npc) - if not npc:IsInvisible() or npc:HasModifier "modifier_item_dustofappearance" or npc:HasModifier "modifier_bounty_hunter_track" or npc:HasModifier "modifier_slardar_amplify_damage" or npc:HasModifier "modifier_truesight" then - return false - end - if self:HasAnyModifier(npc, self.permanentTrueSightRootModifiers) then - return false - end - local enemies = self:GetNearbyHeroes(npc) - return self:All(enemies, function(t) - if self:GetAvailableItem(t, "item_gem") then - return false - end - if t:GetAttackTarget() == npc then - return false - end - if t:IsUsingAbility() then - local ability = t:GetCurrentActiveAbility() - if binlib.Test(ability:GetBehavior(), ABILITY_BEHAVIOR_UNIT_TARGET) and t:IsFacingLocation(npc:GetLocation(), 10) then - return false - end - end - return true - end) and not self:Any(npc:GetNearbyCreeps(1000, true), function(t) - return t:GetUnitName() == "npc_dota_necronomicon_warrior_3" - end) -end - -M.ShouldNotBeAttacked = function(self, npc) - return self:CannotBeAttacked(npc) or self:Any(self.IgnoreDamageModifiers, function(t) return npc:HasModifier(t) end) or self:Any(self.IgnorePhysicalDamageModifiers, function(t) return npc:HasModifier(t) end) -end - -M.PhysicalCanCastFunction = function(npc) - return not M:IsInvulnerable(npc) and not M:ShouldNotBeAttacked(npc) and not npc:IsMagicImmune() -end - -M.IsPhysicalOutputDisabled = function(self, npc) - return npc:IsDisarmed() or npc:IsBlind() and not self:GetAvailableItem(npc, "item_monkey_king_bar") or self:IsEthereal(npc) -end - -M.GetHealthPercent = function(self, npc) - return npc:GetHealth() / npc:GetMaxHealth() -end - -function M:GetPhysicalHealth(t) - return t:GetHealth() * (1+0.06*t:GetArmor()) / (1 - t:GetEvasion()) -end - -function M:GetBuildingPhysicalHealth(t) - local h = self:GetPhysicalHealth(t) - if t:HasModifier "modifier_fountain_glyph" then - h = h + self:GetModifierRemainingDuration(t, "modifier_fountain_glyph") * 200 - end - return h -end - -M.GetManaPercent = function(self, npc) - return npc:GetMana() / npc:GetMaxMana() -end - -M.GetHealthDeficit = function(self, npc) - return npc:GetMaxHealth() - npc:GetHealth() -end - -function M:GetManaDeficit(npc) - return npc:GetMaxMana() - npc:GetMana() -end - -function M:IsGoodTarget(npc, target) - return target:IsHero() and target:IsAlive() and self:MayNotBeIllusion(npc, target) and not self:IsHeroLevelUnit(target) -end -function M:GetTargetIfGood(npc) - local target = npc:GetTarget() - if target and self:IsGoodTarget(npc, target) then - return target - end -end - -function M:GetTargetIfBad(npc) - local target = npc:GetTarget() - if target and not self:IsGoodTarget(npc, target) then - return target - end -end - -function M:IndexOfBasicDispellablePositiveModifier(npc) - return self:Aggregate(nil, self.basicDispellWorthPositiveModifiers, function(seed, modifier, index) - if seed then - return seed - end - local b = npc:HasModifier(modifier) - if b then - return index - else - return nil - end - end) or -1 -end - -function M:HasBasicDispellablePositiveModifier(npc) - return self:Any(self.basicDispellWorthPositiveModifiers, function(t) return t:HasModifier(t) end) -end - -function M:DontInterruptAlly(npc) - return self:HasAnyModifier(npc, self.positiveForceMovementModifiers) or self:HasAnyModifier(npc, self.timeSensitivePositiveModifiers) or self:IsDuelCaster(npc) or npc:IsChanneling() -end - -M.MidLaneTowers = { TOWER_MID_1, TOWER_MID_2, TOWER_MID_3 } -M.BotLaneTowers = { TOWER_BOT_1, TOWER_BOT_2, TOWER_BOT_3 } -M.TopLaneTowers = { TOWER_TOP_1, TOWER_TOP_2, TOWER_TOP_3 } - -function M:GetLaningTower(npc) - local team = npc:GetTeam() - local lane = npc:GetAssignedLane() - local function ToTower(t) return GetTower(team, t) end - local function TowerExists(t) return t:GetHealth() > 0 end - if lane == LANE_BOT then - local a = self:Map(self.BotLaneTowers, ToTower) - return self:First(a, TowerExists) - elseif lane == LANE_MID then - return self:First(self:Map(self.MidLaneTowers, ToTower), TowerExists) - elseif lane == LANE_TOP then - return self:First(self:Map(self.TopLaneTowers, ToTower), TowerExists) - end -end - --- debug functions - -M.DebugTable = function(self, tb) - local msg = "{ " - local DebugRec - DebugRec = function(tc) - for k,v in pairs(tc) do - if type(v) == "number" or type(v) == "string" then - msg = msg..k.." = "..v..", " - elseif type(v) == "boolean" then - msg = msg..k.." = "..tostring(v)..", " - elseif type(v) == "table" then - msg = msg..k.." = ".."{ " - DebugRec(v) - msg = msg.."}, " - end - end - end - DebugRec(tb) - msg = msg.." }" - print(msg) -end - -M.DebugLongTable = function(self, tb) - for k,v in pairs(tb) do - if type(v) == "table" then - print(tostring(k).." = ") - self:DebugTable(v) - else - print(tostring(k).." = "..tostring(v)) - end - end -end - -M.DebugArray = function(self, tb) - for k,v in ipairs(tb) do - if type(v) == "table" then - self:DebugTable(v) - else - print(v) - end - end -end - -M.PrintAbilities = function(self, npcBot) - local abilityNames = "{\n" - for i = 0,23 do - local ability = npcBot:GetAbilityInSlot(i) - if ability ~= nil and ability:GetName() ~= "generic_hidden" then - abilityNames = abilityNames.."\t\""..ability:GetName().."\",\n" - end - end - abilityNames = abilityNames.."}" - print(npcBot:GetUnitName()) - print(abilityNames) -end - -function M:PrintMode(npc) - print("bot "..npc:GetUnitName().." in mode "..npc:GetActiveMode()..", desire = "..npc:GetActiveModeDesire()) -end - --- ability function - -function M:NormalCanCast(target, isPureDamageWithoutDisable, damageType, pierceMagicImmune, targetMustBeSeen, mustBeTargettable) - damageType = damageType or DAMAGE_TYPE_MAGICAL - if pierceMagicImmune == nil then - if damageType == DAMAGE_TYPE_MAGICAL then - pierceMagicImmune = false - else - pierceMagicImmune = true - end - end - if isPureDamageWithoutDisable == nil then - isPureDamageWithoutDisable = true - end - if self:IsInvulnerable(target) then - return false - end - if mustBeTargettable == nil then - mustBeTargettable = true - end - if mustBeTargettable and self:CannotBeTargetted(target) then - return false - end - if not pierceMagicImmune and target:IsMagicImmune() then - return false - end - if targetMustBeSeen and not target:CanBeSeen() then - return false - end - if isPureDamageWithoutDisable and (damageType == DAMAGE_TYPE_PHYSICAL and self:ShouldNotBeAttacked(target) or damageType == DAMAGE_TYPE_MAGICAL and (target:IsMagicImmune() or self:Contains(self.IgnoreMagicalDamageModifiers, function(t) target:HasModifier(t) end))) then - return false - end - return true -end - -M.NormalCanCastFunction = function(target) return M:NormalCanCast(target) end - -function M:SpellCanCast(target, pierceMagicImmune, targetMustBeSeen, mustBeTargettable) - if targetMustBeSeen == nil then - targetMustBeSeen = true - end - if mustBeTargettable == nil then - mustBeTargettable = true - end - if target:IsInvulnerable() then - return false - end - if mustBeTargettable and self:CannotBeTargetted(target) then - return false - end - if not pierceMagicImmune and target:IsMagicImmune() then - return false - end - return true -end - -M.SpellCanCastFunction = function(target) return M:SpellCanCast(target) end - -function M:StunCanCast(target, ability, pierceMagicImmune, targetCast, dispellable, considerDamage) - if dispellable == nil then - dispellable = true - end - if considerDamage == nil then - considierDamage = true - end - if not pierceMagicImmune and target:IsMagicImmune() then - return false - end - if targetCast and self:HasAbilityRetargetModifier(target) then - return false - end - if target:IsInvulnerable() then - return false - end - -- if considerDamage and target:GetHealth() <= target:GetActualIncomingDamage(ability:GetDamage(), ability:GetDamageType()) then - -- return true - -- end - if dispellable and self:DarkPactRemainingTime(target) > ability:GetCastPoint() then - return false - end - return true -end - -function M:AllyCanCast(target, pierceMagicImmune) - if pierceMagicImmune == nil then - pierceMagicImmune = true - end - if not pierceMagicImmune and target:IsMagicImmune() then - return false - end - return not target:IsInvulnerable() and not self:CannotBeTargetted(target) -end - -M.AllyCanCastFunction = function(target) return M:AllyCanCast(target) end - -function M:NeutralCanCast(target) - -end - -function M:EnemyAllyCanCast(target, isPureDamageWithoutDisable, damageType, pierceMagicImmune, targetMustBeSeen) - if self:IsOnSameTeam(target, GetBot()) then - return self:NormalCanCast(target, isPureDamageWithoutDisable, damageType, pierceMagicImmune, targetMustBeSeen) - else - return self:AllyCanCast(target, pierceMagicImmune, targetMustBeSeen) - end -end - -M.SpecialBonusAttributes = "special_bonus_attributes" -M.TalentNamePrefix = "special_bonus_" -M.IncorrectAbilityName = "incorrect_name" - -M.IsTalent = function(self, ability) - if ability == nil then - return false - end - if type(ability) ~= "string" then - ability = ability:GetName() - end - return ability ~= "special_bonus_attributes" and #ability >= #self.TalentNamePrefix and string.sub(ability, 1, #self.TalentNamePrefix) == self.TalentNamePrefix -end - -M.GetAbilities = function(self, npcBot) - local g = NewTable() - for i = 0,25 do - local ability = npcBot:GetAbilityInSlot(i) - if ability ~= nil and ability:GetName() ~= "generic_hidden" then - table.insert(g, ability) - end - end - return g -end - -M.GetAbilityNames = function(self, npcBot) - return self:Map(self:GetAbilities(npcBot), function(t) return t:GetName() end) -end - -M.GetTalents = function(self, npcBot) - return self:Filter(self:GetAbilities(npcBot), function(t) return self:IsTalent(t) end) -end - -M.GetAbilityLevelUpIndex = function(self, npcBot) - return npcBot:GetLevel() - npcBot:GetAbilityPoints() + 1 + npcBot.abilityTable.incorrectAbilityLevelUpNumber -end - -M.FillInAbilities = function(self, npcBot, abilityTable) - local abilities = self:GetAbilityNames(npcBot) - if #abilityTable == 19 then - table.insert(abilityTable, 17, self.SpecialBonusAttributes) - table.insert(abilityTable, 19, self.SpecialBonusAttributes) - table.insert(abilityTable, 21, self.SpecialBonusAttributes) - table.insert(abilityTable, 22, self.SpecialBonusAttributes) - table.insert(abilityTable, 23, self.SpecialBonusAttributes) - table.insert(abilityTable, 24, self.SpecialBonusAttributes) - end - if #abilityTable == 25 then - table.insert(abilityTable, 26, self.SpecialBonusAttributes) - end - for i = 1, 26 do - if abilityTable[i] == "nil" then - abilityTable[i] = self.SpecialBonusAttributes - end - if not self:Contains(abilities, abilityTable[i]) and abilityTable[i] ~= "talent" then - print("Bot script "..npcBot:GetUnitName().." contains incorrect ability name: "..abilityTable[i]) - abilityTable[i] = self.IncorrectAbilityName - end - end - if #abilityTable == 30 then - npcBot.abilityTable = abilityTable - abilityTable.incorrectAbilityLevelUpNumber = self:Count(abilityTable, function(ability, index) - return index < npcBot:GetLevel() - npcBot:GetAbilityPoints() + 1 and (ability == nil or not ability:CanAbilityBeUpgraded() or ability:GetName() == self.IncorrectAbilityName) - end) - return - end - - local talents = self:Map(self:GetTalents(npcBot), function(t) return t:GetName() end) - local levelUpTalents = self:Filter(abilityTable, function(t) return self:IsTalent(t) end) - local g = self:Concat(abilityTable, self:RemoveAll(talents, levelUpTalents)) - g.incorrectAbilityLevelUpNumber = self:Count(g, function(ability, index) - return index < npcBot:GetLevel() - npcBot:GetAbilityPoints() + 1 and (ability == nil or not ability:CanAbilityBeUpgraded() or ability:GetName() == self.IncorrectAbilityName) - end) - npcBot.abilityTable = g -end - -M.ExecuteAbilityLevelUp = function(self, npcBot) - local abilityTable = npcBot.abilityTable - if abilityTable.justLevelUpAbility then - if abilityTable.abilityPoints == npcBot:GetAbilityPoints() then - abilityTable.incorrectAbilityLevelUpNumber = abilityTable.incorrectAbilityLevelUpNumber + 1 - end - abilityTable.justLevelUpAbility = false - end - abilityTable.abilityPoints = npcBot:GetAbilityPoints() - if npcBot:GetAbilityPoints() < 1 + abilityTable.incorrectAbilityLevelUpNumber or GetGameState() ~= GAME_STATE_PRE_GAME and GetGameState() ~= GAME_STATE_GAME_IN_PROGRESS then - return - end - local abilityName = abilityTable[self:GetAbilityLevelUpIndex(npcBot)] - if abilityName == self.IncorrectAbilityName or abilityName == self.SpecialBonusAttributes then - abilityTable.incorrectAbilityLevelUpNumber = abilityTable.incorrectAbilityLevelUpNumber + 1 - end - npcBot:ActionImmediate_LevelAbility(abilityName) - abilityTable.justLevelUpAbility = true -end - --- geometry - -M.IsVector = function(self, object) - return type(object)=="userdata" and type(object.x)=="number" and type(object.y)=="number" and type(object.z)=="number" -end -M.ToStringVector = function(self, object) - return string.format("(%d,%d,%d)",object.x,object.y,object.z) -end - -M.GetLine = function(self, a, b) - if a.x == b.x then - return { a = 1, b = 0, c = -a.x } - end - local k = (a.y-b.y)/(a.x-b.x) - local bb = a.y-k*a.x - return { a = k, b = -1, c = bb } -end - -M.GetPointToLineDistance = function(self, point, line) - local up = math.abs(line.a*point.x+line.b*point.y+line.c) - local down = math.sqrt(line.a*line.a+line.b*line.b) - return up/down -end - -M.commonBoudingRadius = 100 - -M.GetPointToPointDistance = function(self, a, b) - return ((a.x-b.x)^2+(a.y-b.y)^2)^0.5 -end - --- Get the location on the line determined by startPoint and endPoint, with distance from startPoint to the target location -M.GetPointFromLineByDistance = function(self, startPoint, endPoint, distance) - local distanceTo = self:GetPointToPointDistance(startPoint, endPoint) - local divide = (endPoint - startPoint) / distanceTo * distance - return startPoint + divide -end - -M.GetCos = function(self, b, c, a) - return (b^2+c*2-a*2)/2/b/c -end -M.GetLocationToLocationDistance = function(self, a, b) - return ((a.x-b.x)^2+(a.y-b.y)^2)^0.5 -end - -function M:GetDegree(loc1, loc2) - local y = loc2.y-loc1.y - local x = loc2.x-loc1.x - return math.atan2(y, x) * 180 / math.pi -end - -function M:MultiplyBetween(down, up) - local result = 1 - local g = down - while g <= up do - result *= g - ++g - end - return result -end - -function M:Combination(down, up) - return self:MultiplyBetween(down - up + 1, down) / self:MultiplyBetween(1, up) -end -function M:Arrange(down, up) - return self:MultiplyBetween(down - up + 1, down) -end - -function M:FindAoELocation(npcBot, target, ability, hero, maxHealth) - if hero == nil then - hero = true - end - if maxHealth == nil then - maxHealth = 10000 - end - return npcBot:FindAoELocation(true, hero, npcBot:GetLocation(), ability:GetCastRange(), ability:GetAOERadius(), ability:GetCastPoint(), maxHealth) -end - -function M:FindAOELocationAtSingleTarget(npcBot, target, radius, castRange, castPoint) - local targetLoc = target:GetLocation() - local npcLoc = npcBot:GetLocation() - local targetMove = target:GetCurrentMovementSpeed() * castPoint - local ntDis = self:GetLocationToLocationDistance(targetLoc, npcLoc) - target:GetBoundingRadius() - if ntDis >= targetMove + radius then - local centre = if target:IsFacingLocation(npcLoc, 180) { ntDis - targetMove } else { ntDis + targetMove } - return self:GetPointFromLineByDistance(npcLoc, targetLoc, centre) - end - return self:GetPointFromLineByDistance(npcLoc, targetLoc, ntDis + targetMove + target:GetBoundingRadius()) -end --- Find the location to use a aoe at a single target with the least distance the hero needs to walk before casting ---M.FindAOELocationAtSingleTarget = function(self, npcBot, target, radius, castRange, castPoint) --- if self:CanMove(target) then --- radius = radius * 0.8 --- end --- local g --- GeneratePath(npcBot:GetLocation(), target:GetLocation(), {}, function(distance, waypoints) --- if waypoints == 0 then --- waypoints = { npcBot:GetLocation(), target:GetLocation() } --- end --- for i = 1, #waypoints-1 do --- local waypoint1 = waypoints[i] --- local waypoint2 = waypoints[i+1] --- local dis1 = GetUnitToLocationDistance(target, waypoint1) --- local dis2 = GetUnitToLocationDistance(target, waypoint2) --- if dis1 > dis2 then --- if radius >= dis1 then --- g = waypoint1 --- return --- elseif radius >= dis2 then --- local waypointDis = self:GetLocationToLocationDistance(waypoint1, waypoint2) --- local cosine = self:GetCos(dis2, waypointDis, dis1) --- local walkDis = dis1*cosine - (dis1^2-radius*2)^0.5 --- local targetLocation = self:GetPointFromLineByDistance(waypoint1, waypoint2, walkDis) --- g = targetLocation --- return --- end --- else --- if radius >= dis1 then --- g = waypoint1 --- return --- end --- end --- end --- g = waypoints[#waypoints] --- end) --- return g ---end --- M.FindAOELocationAtSingleTarget = function(self, npcBot, target, radius, castRange, castPoint) --- radius = radius - 80 --- local distance = GetUnitToUnitDistance(npcBot, target) --- if distance < radius + castRange then --- return self:GetPointFromLineByDistance(npcBot:GetLocation(), target:GetLocation(), castRange) --- else --- return self:GetPointFromLineByDistance(target:GetLocation(), npcBot:GetLocation(), radius) --- end --- end - -M.MinValue = function(self, coefficients, min, max) - max = max or 10000 - min = min or -10000 - local function Differential(coefficients) - local g = {} - for index, coefficient in pairs(coefficients) do - g[index-1] = coefficient*index - end - return g - end - local function Y(coefficients, x) - local g = 0 - for index, coefficient in pairs(coefficients) do - g = g + coefficient * x ^ index - end - return g - end - - local differential = Differential(coefficients) - if differential[1] ~= nil and differential[1] ~= 0 then - local zeroPoint = -differential[0]/differential[1] - if Y(coefficients, zeroPoint+0.1)>0 then - if zeroPoint > max then - return Y(coefficients, max) - elseif zeroPoint < min then - return Y(coefficients, min) - else - return Y(coefficients, zeroPoint) - end - else - if zeroPoint > max then - return Y(coefficients, min) - elseif zeroPoint < min then - return Y(coefficients, max) - else - local val1 = Y(coefficients, min) - local val2 = Y(coefficients, min) - return math.min(val1, val2) - end - end - else - return Y(coefficients, min) - end -end - -M.MaxValue = function(self, coefficients, min, max) - local g = {} - for index, coefficient in coefficients do - g[index] = -coefficient - end - return self:MinValue(g, -max, -min) -end - -M.GetCollapseInfo = function(self, obj1, obj2, timeLimit) - local x1 = obj1.location.x-obj2.location.x - local x2 = obj1.velocity.x-obj2.velocity.x - local coefficient0 = x1^2 - local coefficient1 = 2*x1*x2 - local coefficient3 = x2^2 - x1 = obj1.location.y-obj2.location.y - x2 = obj2.velocity.y-obj2.velocity.y - coefficient0 = coefficient0 -end - -M.PreventHealAtHealSuppressTarget = function(self, npcBot, oldConsiderFunction, ability) - return function() - local desire, target, targetTypeString = oldConsiderFunction() - if desire == 0 or target == nil or target == 0 or targetTypeString == "Location" then - return desire, target, targetTypeString - end - if npcBot:GetTeam() == target:GetTeam() then - desire = desire * self:GetTargetHealAmplifyPercent(target) - end - desire = self:TrimDesire(desire) - return desire, target, targetTypeString - end -end - -M.PURCHASE_ITEM_OUT_OF_STOCK=82 -M.PURCHASE_ITEM_INVALID_ITEM_NAME=33 -M.PURCHASE_ITEM_DISALLOWED_ITEM=78 -M.PURCHASE_ITEM_INSUFFICIENT_GOLD=63 -M.PURCHASE_ITEM_NOT_AT_SECRET_SHOP=62 -M.PURCHASE_ITEM_NOT_AT_HOME_SHOP=67 -M.PURCHASE_ITEM_SUCCESS=-1 - --- specified ability is not actually an ability (2) --- invalid order(3) unrecognised order name --- invalid order(40) order not allowed for illusions --- unit is dead (20) --- target tree is not active (43) --- ability is still in cooldown (15) --- cannot cast ability on tree (34) --- cannot cast ability on target --- target is unselectable --- order requires a physical item target, but specified target is not a physical item (9) --- item cannot be used from stash (37) --- does not have enough mana to cast ability (14) --- item is still in cooldown (61) --- can't cast attack ability on target, target is attack immune (32) --- order invalid for units with attack ability DOTA_UNIT_CAP_NO_ATTACK (41) --- can't cast on target, ability cannot target enemies (30) --- can't cast on target, ability cannot target creeps (56) --- unit can't perform command, unit has commands restricted (74) --- hero does not have enough ability points to upgrade ability (13) --- ability is hidden (60) --- can't cast on target, ability cannot target teammates (29) --- cannot attack or cast on target, target is unselectable (36) --- unit cannot cast, unit is silenced (24) --- cannot cast ability on NPC (19), unit is dead --- unit cannot manipulate items (39) --- target cannot be seen by the unit's team (26) --- unit does not have moevement capability and target is out of attack range (46) - - --- runtime errors: ---- Bad key for entity "npc_dota_creep_neutral": Out of range parsed value for field "teamnumber" (-1)! - - -M.IgnoreDamageModifiers = { - "modifier_abaddon_borrowed_time", - "modifier_item_aeon_disk_buff", - "modifier_winter_wyvern_winters_curse", - "modifier_winter_wyvern_winters_curse_aura", - "modifier_skeleton_king_reincarnation_scepter_active", - "modifier_fountain_glyph", -} - -M.CannotKillModifiers = { - "modifier_dazzle_shadow_grave", - "modifier_troll_warlord_battle_trance", -} - -M.CannotBeTargettedModifiers = { - "modifier_slark_shadow_dance", - "modifier_item_book_of_shadows", - "modifier_dark_willow_shadow_realm_buff", -} - -M.IgnorePhysicalDamageModifiers = { - "modifier_winter_wyvern_cold_embrace", - "modifier_omniknight_guardian_angle", -} - -M.IgnoreMagicalDamageModifiers = { - "modifier_oracle_fates_edict", -} - -M.LastForAtLeastSeconds = function(self, predicate, time, infoTable) - if infoTable.lastTrueTime == nil then - infoTable.lastTrueTime = DotaTime() - end - if predicate() then - if DotaTime() - infoTable.lastTrueTime >= time then - return true - else - return false - end - else - infoTable.lastTrueTime = nil - return false - end -end - -M.GoodIllusionHero = { - "antimage","spectre","terrorblade","naga_siren", -} -M.ModerateIllusionHero = { - "abaddon","axe","chaos_knight","arc_warden","juggernaut","luna","medusa","morphling","phantom_lancer","sniper","wraith_king","phantom_assassin", -} - -M.GetIllusionBattlePower = function(self, npc) - local name = self:GetHeroShortName(npc:GetUnitName()) - if npc:HasModifier "modifier_arc_warden_tempest_double" or npc:HasModifier "modifier_skeleton_king_reincarnation_active" then - return 0.8 - end - if npc:HasModifier "modifier_vengefulspirit_hybrid_special" then - return 1.05 - end - local t = 0.1 - if self:Contains(self.GoodIllusionHero, name) then - t = 0.4 - elseif self:Contains(self.ModerateIllusionHero, name) then - t = 0.25 - elseif not self:IsMeleeHero(npc) then - t = t + npc:GetAttackRange() / 2000 - end - local inventory = self:Map(self:GetInventoryItems(npc)) { t -> t:GetName() } - if self:Contains(inventory, "item_radiance") then - t = t+0.07 - end - if self:Contains(inventory, "item_diffusal_blade") then - t = t+0.05 - end - if self:Contains(inventory, "item_lesser_crit") then - t = t+0.04 - end - if self:Contains(inventory, "item_greater_crit") then - t = t+0.08 - end - if npc:HasModifier "modifier_special_bonus_mana_break" then-- mirana talent[5] - t = t+0.04 - end - return t -end - -M.GetNetWorth = function(self, npc, isEnemy) - if isEnemy then - local itemCost = self:Map(self:GetInventoryItems(npc), function(t) return GetItemCost(t:GetName()) end) - return self:Aggregate(0, itemCost, function(a, b) return a+b end) - else - return npc:GetNetWorth() - end -end - -function M:GetBattlePower(npc) - local power = 0 - local name = npc:GetUnitName() - if string.match(name, "npc_dota_hero") then - power = npc:GetNetWorth() + npc:GetLevel() * 1000 - if npc:GetLevel() >= 25 then - power += 1000 - end - if npc:GetLevel() >= 30 then - power += 600 - end - if name:match("lone_druid") then - power *= 0.25 - end - elseif string.match(name, "npc_dota_lone_druid_bear") then - local heroLevel = GetHeroLevel(npc:GetPlayerID()) - power = name[#"npc_dota_lone_druid_bear"+2]*2000-1000 - + heroLevel * 310 - + npc:GetNetWorth()*0.75 - end - if npc:HasModifier "modifier_item_assault_positive" and not npc:HasModifier "modifier_item_assault_positive_aura" then - power = power + 1500 - end - local items = self:GetInventoryItemNames(npc) - if npc:HasModifier "modifier_item_pipe_aura" and not self:Contains(items, "item_pipe") then - power = power + 400 - end - if npc:HasModifier "modifier_item_vladmir_aura" and not self:Contains(items, "item_vladmir") then - power = power + 300 - end - if npc:HasModifier "modifier_item_guardian_greaves_aura" and not self:Contains(items, "item_guardian_greaves") then - power = power + 1000 - elseif npc:HasModifier "modifier_item_mekansm_aura" and not self:Contains(items, "item_mekansm") then - power = power + 500 - end - if npc:IsIllusion() then - power *= self:GetIllusionBattlePower(npc) - end - return power -end - -M.GetHeroGroupBattlePower = function(self, npcBot, heroes, isEnemy) - local function A(tb) - local battlePowerMap = self:Map(tb, function(t) return { t:GetUnitName(), self:GetBattlePower(t) } end) - battlePowerMap = self:SortByMaxFirst(battlePowerMap, function(t) return t[2] end) - battlePowerMap = self:Map(battlePowerMap, function(t, index) return t[2] * (1.15-0.15*index) end) - local g = NewTable() - for _, v in ipairs(battlePowerMap) do - g[v[1]] = v[2] - end - return g - end - local enemyNetWorthMap = A(self:GetEnemyHeroUnique(npcBot, heroes)) - local netWorth = 0 - local readNames = NewTable() - for _, enemy in pairs(heroes) do - local name = enemy:GetUnitName() - if not self:Contains(readNames, name) then - table.insert(readNames, name) - -- TODO: enemyNetWorthMap[name] should not be null - if enemyNetWorthMap[name] then - netWorth = netWorth + enemyNetWorthMap[name] - end - else - if enemyNetWorthMap[name] then - netWorth = netWorth + enemyNetWorthMap[name] * self:GetIllusionBattlePower(enemy) - end - end - end - return netWorth -end - -M.Outnumber = function(self, npcBot, friends, enemies) - return self:GetHeroGroupBattlePower(npcBot, friends, false) >= self:GetHeroGroupBattlePower(npcBot, enemies, true) * 1.8 -end - - -M.CannotBeKilledNormally = function(self, target) - return target:IsInvulnerable() or self:Any(self.IgnoreDamageModifiers, function(t) target:HasModifier(t) end) or target:HasModifier "modifier_dazzle_shallow_grave" -end - -M.HasScepter = function(self, npc) - return npc:HasScepter() or npc:HasModifier "modifier_wisp_tether_scepter" or npc:HasModifier "modifier_item_ultimate_scepter" or npc:HasModifier "modifier_item_ultimate_scepter_consumed_alchemist" -end - --- ability record - -local locationAOEAbilities = { - cone = { - "lina_dragon_slave", - }, - circle = { - "lina_light_strike_array", - }, - isoscelesTrapezoid = { - "kunkka_tidebringer", - }, -} - -function M:RecordAbility(npc, index, target, castType, abilities) - local abilityRecords = npc.abilityRecords - if index ~= nil then - abilityRecords[index] = {} - if castType == "Location" then - abilityRecords[index].location = target - elseif castType == "Target" then - abilityRecords[index].target = target - elseif castType == "Tree" then - abilityRecords[index].targetTree = target - elseif self:IsVector(target) then - abilityRecords[index].location = target - elseif target ~= nil then - abilityRecords[index].target = target - end - abilityRecords.usingAbilityIndex = index - abilityRecords[index].beginCastTime = DotaTime() - return - end - if not npc:IsUsingAbility() and not npc:IsChanneling() then - if abilityRecords.usingAbilityIndex ~= nil and not abilities[abilityRecords.usingAbilityIndex]:IsCooldownReady() then - abilityRecords.lastUsedAbilityIndex = abilityRecords.usingAbilityIndex - abilityRecords.usingAbilityIndex = nil - abilityRecords.lastUsedAbilityTime = DotaTime() - end - end -end - -local frameNumber = 0 -local dotaTimer -local deltaTime = 0 -local function FloatEqual(a, b) - return math.abs(a-b)<0.000001 -end - --- tick - -function M:GetFrameNumber() - return frameNumber -end - -function M:GetDeltaTime() - return deltaTime -end - -function M:EveryManyFrames(count, times) - times = times or 1 - return frameNumber % count < times -end - -local defaultReturn = NewTable() -local everySecondsCallRegistry = NewTable() - -function M:EveryManySeconds(second, oldFunction) - local functionName = tostring(oldFunction) - local callTable = {} - everySecondsCallRegistry[functionName] = callTable - callTable.lastCallTime = DotaTime() + RandomFloat(0, second) - callTable.interval = second - callTable.startup = true - return function(...) - local callTable = everySecondsCallRegistry[tostring(oldFunction)] - if callTable.startup then - callTable.startup = nil - return oldFunction(...) - elif callTable.lastCallTime <= DotaTime() - callTable.interval then - callTable.lastCallTime = DotaTime() - return oldFunction(...) - else - return defaultReturn - end - end -end - -local singleForTeamRegistry = NewTable() - -function M:SingleForTeam(oldFunction) - local functionName = tostring(oldFunction) - return function(...) - if singleForTeamRegistry[functionName] ~= frameNumber then - singleForTeamRegistry[functionName] = frameNumber - return oldFunction(...) - else - return defaultReturn - end - end -end - -local groupAnnounceTimes1 = 0 -function M:AnnounceGroups1(npcBot) - if groupAnnounceTimes1 == 0 then - npcBot:ActionImmediate_Chat("Thanks for choosing RMM AI. Join our new discord group at https://discord.gg/Agd632pvhA to put suggestions or devloping issues!", true) - groupAnnounceTimes1 = 1 - end -end -local groupAnnounceTimes2 = 0 -function M:AnnounceGroups2(npcBot) - if groupAnnounceTimes2 == 0 then - npcBot:ActionImmediate_Chat("Or join QQ group at 946823144!", true) - groupAnnounceTimes2 = 1 - end -end - -function M:CalledOnThisFrame(functionInvocationResult) - return functionInvocationResult ~= defaultReturn -end - -local slowFunctionRegistries = NewTable() -local coroutineRegistry = NewTable() -local coroutineExempt = NewTable() - -function M:TickFromDota() - local time = DotaTime() - local function ResumeCoroutine(thread) - local coroutineResult = { coroutine.resume(thread, deltaTime) } - if not coroutineResult[1] then - table.remove(coroutineResult, 1) - print("error in coroutine:") - self:DebugLongTable(coroutineResult) - end - end - if dotaTimer == nil then - dotaTimer = time - return - end - deltaTime = time - dotaTimer - if not FloatEqual(time, dotaTimer) then - frameNumber = frameNumber + 1 - self:ForEach(slowFunctionRegistries, function(t) t(deltaTime) end) - local threadIndex = 1 - while threadIndex <= #coroutineRegistry do - local t = coroutineRegistry[threadIndex] - local exemptIndex - local exempt - self:ForEach(coroutineExempt, function(exemptPair, index) - if exemptPair[1] == t then - if exemptPair[2] == frameNumber then - exempt = true - end - exemptIndex = index - end - end) - if exemptIndex then - table.remove(coroutineExempt, exemptIndex) - end - if not exempt then - if coroutine.status(t) == "suspended" then - ResumeCoroutine(t) - threadIndex = threadIndex + 1 - elseif coroutine.status(t) == "dead" then - table.remove(coroutineRegistry, threadIndex) - else - threadIndex = threadIndex + 1 - end - end - end - dotaTimer = time - end -end - -function M:RegisterSlowFunction(oldFunction, calledWhenHowManyFrames, frameOffset, defaultReturn) - return function(...) - if frameNumber % calledWhenHowManyFrames == frameOffset then - return oldFunction(...) - else - return self:UnpackIfTable(defaultReturn) - end - end -end - -function M:GameNotReallyStarting() - local gameMode = GetGameMode() - if gameMode == GAMEMODE_AP then - return DotaTime() <= -75 - elif gameMode == GAMEMODE_ALL_DRAFT or gameMode == GAMEMODE_RD then - return DotaTime() <= -52 - elif gameMode == GAMEMODE_SD then - return DotaTime() <= -35 - end - return false -end - --- coroutine - -function M:ResumeUntilReturn(func) - local g = NewTable() - local thread = coroutine.create(func) - while true do - local values = { coroutine.resume(thread) } - if values[1] then - table.remove(values, 1) - table.insert(g, values) - else - table.remove(values, 1) - print("error in coroutine:") - self:DebugLongTable(values) - break - end - end - return g -end - -function M:StartCoroutine(func) - local newCoroutine = coroutine.create(func) - table.insert(coroutineRegistry, newCoroutine) - table.insert(coroutineExempt, {newCoroutine, frameNumber}) - return newCoroutine -end - -function M:WaitForSeconds(seconds) - local t = seconds - while t > 0 do - t = t - coroutine.yield() - end -end - -function M:StopCoroutine(thread) - self:Remove_Modify(coroutineExempt, function(t) return t[1] == thread end) - self:Remove_Modify(coroutineRegistry, thread) -end - --- get data from ability --- for example, to get value aoe_radius, use ability.aoe_radius rather than ability:GetSpecialValueInt - -local function GetDataFromAbility(ability, valueName) - local a = ability:GetSpecialValueInt(valueName) - return a==0 and ability:GetSpecialValueFloat(valueName) or a -end - -local function Append__Index(tb, __index) - local m = getmetatable(tb) - if m == nil then - m = {} - setmetatable(tb, m) - end - local oldIndex = m.__index - if oldIndex == nil then - m.__index = __index - elseif type(oldIndex) == "function" then - m.__index = function(ability, i) - local oldResult = { oldIndex(ability, i) } - if oldResult[1] == nil then - return __index(ability, i) - else - return M.Unpack(oldResult) - end - end - elseif type(oldIndex) == "table" then - if oldIndex == m then - m.__index = function(g, h) - local newResult = { __index(g, h) } - if newResult[1] == nil then - return oldIndex[h] - else - return M.Unpack(newResult) - end - end - else - Append__Index(oldIndex, __index) - end - end -end -Append__Index(CDOTABaseAbility_BotScript, GetDataFromAbility) - -function M:pcall(func, ...) - local result = { func(...) } - if result[1] then - table.remove(result, 1) - return self:Unpack(result) - else - self:DebugPause() - end -end - --- M.debug = true -function M:DebugPause() - if self.debug then - DebugPause() - end -end - -return M diff --git a/util/CommonBehaviours.lua b/util/CommonBehaviours.lua index a6b5817..7f0fd39 100644 --- a/util/CommonBehaviours.lua +++ b/util/CommonBehaviours.lua @@ -1,8 +1,3 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") local A = require(GetScriptDirectory() .. "/util/MiraDota") local M = {} diff --git a/util/CommonBehaviours.mira b/util/CommonBehaviours.mira deleted file mode 100644 index 64f716c..0000000 --- a/util/CommonBehaviours.mira +++ /dev/null @@ -1,90 +0,0 @@ - -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") -local A = require(GetScriptDirectory().."/util/MiraDota") -local M = {} -local avoidCurseList = fun1:NewTable() - - -local bot -local AvoidWintersCurse = fun1:EveryManySeconds(0.3) { -> - local l = bot._commonBehaviours_alt - if local cursedOne = fun1:GetNearbyHeroes(bot, 800, false):First { t -> t:HasModifier "modifier_winter_wyvern_winters_curse_aura" } then - if not bot:IsMagicImmune() and not l.avoidCurseList:Contains(cursedOne) then - table.insert(l.avoidCurseList, cursedOne) - local location = cursedOne:GetLocation() - -- location.z = 525 + bot:GetBoundingRadius() - -- local zone = AddAvoidanceZone(location) - -- print("add zone "..tostring(zone)) - -- fun1:StartCoroutine { deltaTime -> - -- -- fun1:WaitForSeconds(cursedOne:GetModifierRemainingDuration "modifier_winter_wyvern_winters_curse_aura") - -- while cursedOne:HasModifier "modifier_winter_wyvern_winters_curse_aura" do - -- -- DebugDrawCircle(cursedOne:GetLocation(), 525+fun1.commonBoudingRadius, 255, 0, 0) - -- coroutine.yield() - -- end - -- RemoveAvoidanceZone(zone) - -- l.avoidCurseList:Remove_Modify(cursedOne) - -- } - end - end -} - -local AvoidFirestorm = fun1:EveryManySeconds(1) {-> - local l = bot._commonBehaviours_alt - fun1:GetNearbyHeroes(bot, 800, false):Concat(fun1:GetNearbyCreeps(bot, 800, false)):All { - t -> t:HasModifier "modifier_abyssal_underlord_firestorm_burn" - }:ForEach { t -> - if not l.avoidFirestorm:Contains(t) then - local location t:GetLocation() - location.z = 500 + bot:GetBoundingRadius() - local zone = AddAvoidanceZone(location) - fun1:StartCoroutine {-> - while t:HasModifier "modifier_winter_wyvern_winters_curse_aura" do - -- DebugDrawCircle(t:GetLocation(), 500+fun1.commonBoudingRadius, 60, 183, 0) - coroutine.yield() - end - RemoveAvoidanceZone(zone) - l.avoidFirestorm:Remove_Modify(t) - } - end - } -} - -local Init = function() - if bot._commonBehaviours_alt == nil then - bot._commonBehaviours_alt = { - avoidCurseList = fun1:NewTable(), - avoidFirestorm = fun1:NewTable(), - } - end -end - -local pushModes = A.Linq.NewTable(BOT_MODE_PUSH_TOWER_BOT, BOT_MODE_PUSH_TOWER_MID, BOT_MODE_PUSH_TOWER_TOP) -local function IsPushingMode(mode) - return pushModes:Contains(mode) -end - -local NoNearbyEnemiesWhenLaning = function() - if bot:GetActiveMode() == BOT_MODE_LANING or IsPushingMode(bot:GetActiveMode()) and A.Dota.GetNearbyHeroes(bot, 1600):Count() == 0 then - if bot.noNearbyEnemiesWhenLaningTime == nil then - bot.noNearbyEnemiesWhenLaningTime = DotaTime() - end - if bot.noNearbyEnemiesWhenLaningTime - DotaTime() > 3 then - bot.pushWhenNoEnemies = true - end - else - bot.pushWhenNoEnemies = nil - end -end - -local Think = function() - AvoidWintersCurse() - NoNearbyEnemiesWhenLaning() -end - -function M.Think() - bot = GetBot() - Init() - Think() -end - -return M diff --git a/util/ItemUsage-New.lua b/util/ItemUsage-New.lua index 0ec527f..a53a1f5 100644 --- a/util/ItemUsage-New.lua +++ b/util/ItemUsage-New.lua @@ -1,8 +1,3 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local M = {} local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") local BotsInit = require("game/botsinit") @@ -83,6 +78,10 @@ local function IsStuck(npcBot) return false end +-- +-- TP usage +-- + local myTeam = GetTeam() local opTeam = GetOpposingTeam() local function GetLaningTPLocation(nLane) @@ -223,20 +222,28 @@ local function ShouldTP() end return false, nil end +-- old functions end + + +-- use functions to use items for debugging issues function M.UseItemNoTarget(npc, item) + -- print(npc:GetUnitName()..": use "..item:GetName()) npc:Action_UseAbility(item) end function M.UseItemOnEntity(npc, item, entity) + -- print(npc:GetUnitName()..": use "..item:GetName().." on entity "..entity:GetUnitName()) npc:Action_UseAbilityOnEntity(item, entity) end function M.UseItemOnLocation(npc, item, loc) + -- print(npc:GetUnitName()..": use "..item:GetName().." on location "..tostring(loc)) npc:Action_UseAbilityOnLocation(item, loc) end function M.UseItemOnTree(npc, item, tree) + -- print(npc:GetUnitName()..": use "..item:GetName().." on tree "..tostring(tree)) npc:Action_UseAbilityOnTree(item, tree) end diff --git a/util/ItemUsage-New.mira b/util/ItemUsage-New.mira deleted file mode 100644 index b1672e1..0000000 --- a/util/ItemUsage-New.mira +++ /dev/null @@ -1,1051 +0,0 @@ -local M = {} - -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") -local BotsInit = require("game/botsinit") -local role = require(GetScriptDirectory() .. "/util/RoleUtility") -local A = require(GetScriptDirectory().."/util/MiraDota") - -local function IsItemAvailable(item_name) - return fun1:GetAvailableItem(GetBot(), item_name) -end - -local function GetItemIfNotImplemented(itemName) - if local item = IsItemAvailable(itemName) then - if local itemTable = GetBot().itemUsage then - if local f = itemTable[itemName] then - f() - end - end - return item - end -end - -local function GetItemCount(unit, item_name) - local count = 0 - for i = 0, 8 do - local item = unit:GetItemInSlot(i) - if item ~= nil and item:GetName() == item_name then - count = count + 1 - end - end - return count -end - -local function GetItemCharges(unit, item_name) - local count = 0 - for i = 0, 8 do - local item = unit:GetItemInSlot(i) - if item ~= nil and item:GetName() == item_name then - count = count + item:GetCurrentCharges() - end - end - return count -end - -local function CanSwitchPTStat(pt) - local npcBot = GetBot() - if npcBot:GetPrimaryAttribute() == ATTRIBUTE_STRENGTH and pt:GetPowerTreadsStat() ~= ATTRIBUTE_STRENGTH then - return true - elseif npcBot:GetPrimaryAttribute() == ATTRIBUTE_AGILITY and pt:GetPowerTreadsStat() ~= ATTRIBUTE_INTELLECT then - return true - elseif npcBot:GetPrimaryAttribute() == ATTRIBUTE_INTELLECT and pt:GetPowerTreadsStat() ~= ATTRIBUTE_AGILITY then - return true - end - return false -end - -local function IsStuck(npcBot) - if npcBot.stuckLoc ~= nil and npcBot.stuckTime ~= nil then - local attackTarget = npcBot:GetAttackTarget(); - local EAd = GetUnitToUnitDistance(npcBot, GetAncient(GetOpposingTeam())); - local TAd = GetUnitToUnitDistance(npcBot, GetAncient(GetTeam())); - local Et = npcBot:GetNearbyTowers(450, true); - local At = npcBot:GetNearbyTowers(450, false); - if npcBot:GetCurrentActionType() == BOT_ACTION_TYPE_MOVE_TO and attackTarget == nil and EAd > 2200 and TAd > 2200 and #Et == 0 and #At == 0 - and DotaTime() > npcBot.stuckTime + 5.0 and GetUnitToLocationDistance(npcBot, npcBot.stuckLoc) < 25 - then - print(npcBot:GetUnitName().." is stuck") - return true; - end - end - return false -end - --- --- TP usage --- - -local myTeam = GetTeam() -local opTeam = GetOpposingTeam() - -local function GetLaningTPLocation(nLane) - local teamT1Top = GetTower(myTeam, TOWER_TOP_1) - local teamT1Mid = GetTower(myTeam, TOWER_MID_1) - local teamT1Bot = GetTower(myTeam, TOWER_BOT_1) - if nLane == LANE_TOP and teamT1Top~=nil then - return teamT1Top:GetLocation() - elseif nLane == LANE_MID and teamT1Mid~=nil then - return teamT1Mid:GetLocation() - elseif nLane == LANE_BOT and teamT1Bot~=nil then - return teamT1Bot:GetLocation() - end - return Vector(0.000000, 0.000000, 0.000000); -end - -local function GetDefendTPLocation(nLane) - return GetLaneFrontLocation(opTeam, nLane, -1600) -end - -local function GetPushTPLocation(nLane) - return GetLaneFrontLocation(myTeam, nLane, 0) -end - -local idlt = 0 -local idlm = 0 -local idlb = 0 -local function printDefendLaneDesire() - local npcBot = GetBot() - - local md = npcBot:GetActiveMode() - local mdd = npcBot:GetActiveModeDesire() - local dlt = GetDefendLaneDesire(LANE_TOP) - local dlm = GetDefendLaneDesire(LANE_MID) - local dlb = GetDefendLaneDesire(LANE_BOT) - if npcBot:GetPlayerID() == 2 then - if idlt ~= dlt then - idlt = dlt - print("DefendLaneDesire TOP: " .. tostring(dlt)) - elseif idlm ~= dlm then - idlm = dlm - print("DefendLaneDesire MID: " .. tostring(dlm)) - elseif idlb ~= dlb then - idlb = dlb - print("DefendLaneDesire TOP: " .. tostring(dlb)) - end - if md == BOT_MODE_DEFEND_TOWER_TOP then - print("Def Tower Des TOP: " .. tostring(mdd)) - elseif md == BOT_MODE_DEFEND_TOWER_MID then - print("Def Tower Des MID: " .. tostring(mdd)) - elseif md == BOT_MODE_DEFEND_TOWER_BOT then - print("Def Tower Des npcBot: " .. tostring(mdd)) - end - end -end - -local tpThreshold = 4500 - -local function ShouldTP() - local npcBot = GetBot() - local tpLoc = nil - local mode = npcBot:GetActiveMode() - local modDesire = npcBot:GetActiveModeDesire() - local botLoc = npcBot:GetLocation() - local enemies = npcBot:GetNearbyHeroes(1600, true, BOT_MODE_NONE) - if mode == BOT_MODE_LANING and #enemies == 0 then - local assignedLane = npcBot:GetAssignedLane() - if assignedLane == LANE_TOP then - local botAmount = GetAmountAlongLane(LANE_TOP, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_TOP, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetLaningTPLocation(LANE_TOP) - end - elseif assignedLane == LANE_MID then - local botAmount = GetAmountAlongLane(LANE_MID, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_MID, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetLaningTPLocation(LANE_MID) - end - elseif assignedLane == LANE_BOT then - local botAmount = GetAmountAlongLane(LANE_BOT, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_BOT, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetLaningTPLocation(LANE_BOT) - end - end - elseif mode == BOT_MODE_DEFEND_TOWER_TOP and modDesire >= BOT_MODE_DESIRE_MODERATE and #enemies == 0 then - local botAmount = GetAmountAlongLane(LANE_TOP, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_TOP, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetDefendTPLocation(LANE_TOP) - end - elseif mode == BOT_MODE_DEFEND_TOWER_MID and modDesire >= BOT_MODE_DESIRE_MODERATE and #enemies == 0 then - local botAmount = GetAmountAlongLane(LANE_MID, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_MID, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetDefendTPLocation(LANE_MID) - end - elseif mode == BOT_MODE_DEFEND_TOWER_BOT and modDesire >= BOT_MODE_DESIRE_MODERATE and #enemies == 0 then - local botAmount = GetAmountAlongLane(LANE_BOT, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_BOT, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetDefendTPLocation(LANE_BOT) - end - elseif mode == BOT_MODE_PUSH_TOWER_TOP and modDesire >= BOT_MODE_DESIRE_MODERATE and #enemies == 0 then - local botAmount = GetAmountAlongLane(LANE_TOP, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_TOP, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetPushTPLocation(LANE_TOP) - end - elseif mode == BOT_MODE_PUSH_TOWER_MID and modDesire >= BOT_MODE_DESIRE_MODERATE and #enemies == 0 then - local botAmount = GetAmountAlongLane(LANE_MID, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_MID, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetPushTPLocation(LANE_MID) - end - elseif mode == BOT_MODE_PUSH_TOWER_BOT and modDesire >= BOT_MODE_DESIRE_MODERATE and #enemies == 0 then - local botAmount = GetAmountAlongLane(LANE_BOT, botLoc) - local laneFront = GetLaneFrontAmount(myTeam, LANE_BOT, false) - if botAmount.distance > tpThreshold or botAmount.amount < laneFront / 5 then - tpLoc = GetPushTPLocation(LANE_BOT) - end - elseif - mode == BOT_MODE_DEFEND_ALLY and modDesire >= BOT_MODE_DESIRE_MODERATE and - role.CanBeSupport(npcBot:GetUnitName()) == true and - #enemies == 0 - then - local target = npcBot:GetTarget() - if target ~= nil and target:IsHero() then - local nearbyTower = target:GetNearbyTowers(1300, true) - if nearbyTower ~= nil and #nearbyTower > 0 and npcBot:GetMana() > 0.25 * npcBot:GetMaxMana() then - tpLoc = nearbyTower[1]:GetLocation() - end - end - elseif mode == BOT_MODE_RETREAT then - tpLoc = nil - elseif IsStuck(npcBot) and #enemies == 0 then - npcBot:ActionImmediate_Chat("I'm using tp while stuck.", true) - tpLoc = GetAncient(GetTeam()):GetLocation() - end - if tpLoc ~= nil then - return true, tpLoc - end - return false, nil -end --- old functions end - - --- use functions to use items for debugging issues - -function M.UseItemNoTarget(npc, item) - -- print(npc:GetUnitName()..": use "..item:GetName()) - npc:Action_UseAbility(item) -end -function M.UseItemOnEntity(npc, item, entity) - -- print(npc:GetUnitName()..": use "..item:GetName().." on entity "..entity:GetUnitName()) - npc:Action_UseAbilityOnEntity(item, entity) -end -function M.UseItemOnLocation(npc, item, loc) - -- print(npc:GetUnitName()..": use "..item:GetName().." on location "..tostring(loc)) - npc:Action_UseAbilityOnLocation(item, loc) -end -function M.UseItemOnTree(npc, item, tree) - -- print(npc:GetUnitName()..": use "..item:GetName().." on tree "..tostring(tree)) - npc:Action_UseAbilityOnTree(item, tree) -end - -local CannotFade = function(t) - if t:HasModifier"modifier_item_dustofappearance" or t:HasModifier "modifier_truesight" or t:HasModifier"modifier_bounty_hunter_track" or t:HasModifier"modifier_slardar_amplify_damage" then - return true - end - return false -end - -local DontUseItemIfBreakInvisibility = function(t) - return t:IsInvisible() and (not CannotFade(t) or not t:UsingItemBreaksInvisibility()) -end - -local giveTime = -90 -function M.ItemUsageThink() - local npcBot = GetBot() - if npcBot:IsChanneling() or npcBot:IsUsingAbility() or DontUseItemIfBreakInvisibility(npcBot) or npcBot:IsMuted() then - return - end - local notBlasted = not npcBot:HasModifier("modifier_ice_blast") - local tableNearbyEnemyHeroes = fun1:GetNearbyNonIllusionHeroes(npcBot, 800) - local nearByTowers = npcBot:GetNearbyTowers(1000, true) - - local npcTarget = npcBot:GetTarget() - local nearbyAllies = fun1:GetNearbyNonIllusionHeroes(npcBot, 900, false) - local mode = npcBot:GetActiveMode() - local healthPercent = fun1:GetHealthPercent(npcBot) - local manaPercent = fun1:GetManaPercent(npcBot) - - local tps = npcBot:GetItemInSlot(15) - if tps ~= nil and tps:IsFullyCastable() then - local tpLoc - local shouldTP - shouldTP, tpLoc = ShouldTP() - if shouldTP then - M.UseItemOnLocation(npcBot, tps, tpLoc) - return - end - end - - local function GetWantedPowerTreadsAttribute() - if mode == BOT_MODE_RETREAT and npcBot:WasRecentlyDamagedByAnyHero(3) then - return ATTRIBUTE_STRENGTH - elseif fun1:IsAttackingEnemies(npcBot) then - local name = npcBot:GetUnitName() - name = fun1:GetHeroShortName(name) - if fun1:Contains({"obsidian_destroyer","silencer","huskar","drow_ranger"}, name) then - return npcBot:GetPrimaryAttribute() - else - return ATTRIBUTE_AGILITY - end - elseif mode == BOT_MODE_LANING then - return npcBot:GetPrimaryAttribute() - else - -- return npcBot:GetPrimaryAttribute() - return npcBot:GetPrimaryAttribute() - end - end - local function UsePowerTreads(treads) - if math.floor(DotaTime()) / 4 ~= 0 then - return - end - if npcBot:IsInvisible() and npcBot:UsingItemBreaksInvisibility() then - if npcBot:HasModifier("modifier_item_dustofappearance") then - M.UseItemNoTarget(npcBot, treads) - return true - end - return - end - if GetWantedPowerTreadsAttribute() ~= treads:GetPowerTreadsStat() then - M.UseItemNoTarget(npcBot, treads) - return true - end - end - - local pt = GetItemIfNotImplemented("item_power_treads") - if pt ~= nil and pt:IsFullyCastable() and notBlasted then - if UsePowerTreads(pt) then - return - end - end - - local its = GetItemIfNotImplemented("item_tango_single") - local tango - if its ~= nil then - tango = its - elseif itg ~= nil then - tango = itg - end - - if tango ~= nil and tango:IsFullyCastable() and npcBot:DistanceFromFountain() > 1000 then - if DotaTime() > 0 and not npcBot:HasModifier("modifier_tango_heal") then - local trees = npcBot:GetNearbyTrees(1000) - if - trees[1] ~= nil and healthPercent < 0.7 and - (IsLocationVisible(GetTreeLocation(trees[1])) or IsLocationPassable(GetTreeLocation(trees[1]))) and - #tableNearbyEnemyHeroes == 0 and - #nearByTowers == 0 - then - M.UseItemOnTree(npcBot, tango, trees[1]) - return - end - end - end - - local ifl = GetItemIfNotImplemented("item_flask") - if ifl ~= nil and ifl:IsFullyCastable() and npcBot:DistanceFromFountain() > 1000 then - local tableNearbyEnemyHeroes2 = #npcBot:GetNearbyHeroes(750, true, BOT_MODE_NONE) ~= 0 - if DotaTime() > 0 then - if healthPercent < 0.35 and not npcBot:WasRecentlyDamagedByAnyHero(1.5) then - M.UseItemOnEntity(npcBot, ifl, npcBot) - return - end - if local weakestAlly = nearbyAllies:Filter { it -> - fun1:GetHealthPercent(it) < 0.25 and not it:WasRecentlyDamagedByAnyHero(1.5) and it:GetActiveMode() ~= BOT_MODE_RETREAT - and (tableNearbyEnemyHeroes2 or it:HasModifier "modifier_templar_assassin_reflection_absorb" - or fun1:HasAnyModifier(it, fun1.IgnoreDamageModifiers)) - }:SortByMinFirst { it -> it:GetHealth() } - :First() then - M.UseItemOnEntity(npcBot, weakestAlly, npcBot) - return - end - end - end - - local icl = GetItemIfNotImplemented("item_clarity") - if icl ~= nil and icl:IsFullyCastable() and npcBot:DistanceFromFountain() > 1000 then - local tableNearbyEnemyHeroes2 = #npcBot:GetNearbyHeroes(650, true, BOT_MODE_NONE) ~= 0 - if DotaTime() > 0 then - if (manaPercent) < 0.35 then - M.UseItemOnEntity(npcBot, icl, npcBot) - return - end - if local weakestAlly = nearbyAllies:Filter { it -> - fun1:GetManaPercent(it) < 0.4 and not it:WasRecentlyDamagedByAnyHero(3) and it:GetActiveMode() ~= BOT_MODE_RETREAT - and (tableNearbyEnemyHeroes2 or it:HasModifier "modifier_templar_assassin_reflection_absorb" - or fun1:HasAnyModifier(it, fun1.IgnoreDamageModifiers)) - }:SortByMinFirst { it -> it:GetMana() } - :First() then - M.UseItemOnEntity(npcBot, weakestAlly, npcBot) - return - end - end - end - - local itemQuellingBlade = GetItemIfNotImplemented("item_quelling_blade") or GetItemIfNotImplemented("item_bfury") - if itemQuellingBlade ~= nil and itemQuellingBlade:IsFullyCastable() then - local trees = npcBot:GetNearbyTrees(250) - if #trees >= 6 and fun1:Contains(npcBot:GetNearbyHeroes(900, true, BOT_MODE_NONE), function(t) return t:GetUnitName() == "npc_dota_hero_furion" end) then - M.UseItemOnTree(npcBot, itemQuellingBlade, trees[1]) - return - end - end - - local msh = GetItemIfNotImplemented("item_moon_shard") - if msh ~= nil and msh:IsFullyCastable() then - if not npcBot:HasModifier("modifier_item_moon_shard_consumed") then - print("use Moon") - M.UseItemOnEntity(npcBot, msh, npcBot) - return - end - end - - local mg=GetItemIfNotImplemented("item_enchanted_mango") - if mg~=nil and mg:IsFullyCastable() then - if npcBot:GetMana() < 100 - then - M.UseItemNoTarget(npcBot, mg) - return - end - end - - local tok = GetItemIfNotImplemented("item_tome_of_knowledge") - if tok ~= nil and tok:IsFullyCastable() then - M.UseItemNoTarget(npcBot, tok) - return - end - - local ff = GetItemIfNotImplemented("item_faerie_fire") - if ff ~= nil and ff:IsFullyCastable() and notBlasted then - if - npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH and - healthPercent < 0.15 and npcBot:WasRecentlyDamagedByAnyHero(3) - then - M.UseItemNoTarget(npcBot, ff) - return - end - end - - local noDust = not fun1:GetNearbyNonIllusionHeroes(npcBot, 1100):Any {t-> - fun1:GetCarriedItems(t):Any { t -> t:GetName()=="item_dust" or t:GetName() == "item_gem" } - } - local shadowAmulet = GetItemIfNotImplemented("item_shadow_amulet") - if shadowAmulet and shadowAmulet:IsFullyCastable() then - if local ally = fun1:GetNearbyNonIllusionHeroes(npcBot, shadowAmulet:GetCastRange()+200, false):First { - t -> t:IsChanneling() and not CannotFade(t) - } then - M.UseItemOnEntity(npcBot, shadowAmulet, ally) - end - end - - - local sr = GetItemIfNotImplemented("item_soul_ring") - if sr ~= nil and sr:IsFullyCastable() and notBlasted then - if npcBot:GetActiveMode() == BOT_MODE_LANING and fun1:IsFarmingOrPushing(npcBot) then - if healthPercent > 0.7 and manaPercent < 0.4 then - M.UseItemNoTarget(npcBot, sr) - return - end - end - end - - local bst = GetItemIfNotImplemented("item_bloodstone") - if bst ~= nil and bst:IsFullyCastable() and notBlasted then - if - npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH and - healthPercent < 0.3 - then - M.UseItemOnLocation(npcBot, bst, npcBot:GetLocation()) - return - end - end - - local pb = GetItemIfNotImplemented("item_phase_boots") - if pb ~= nil and pb:IsFullyCastable() then - if - (npcBot:GetActiveMode() == BOT_MODE_ATTACK or npcBot:GetActiveMode() == BOT_MODE_RETREAT or - npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_GANK or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY) and not fun1:IsSeverelyDisabled(npcBot) - then - M.UseItemNoTarget(npcBot, pb) - return - end - end - - local bt = GetItemIfNotImplemented("item_bloodthorn") - if bt ~= nil and bt:IsFullyCastable() then - if - (npcBot:GetActiveMode() == BOT_MODE_ATTACK or npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_GANK or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY) - then - if - (npcTarget ~= nil and npcTarget:IsHero() and fun1:NormalCanCast(npcTarget) and - GetUnitToUnitDistance(npcTarget, npcBot) < 900) - then - M.UseItemOnEntity(npcBot, bt, npcTarget) - return - end - end - end - - --[[ - local IsUsingArmlet = npcBot:HasModifier("modifier_item_armlet_unholy_health") - local itemArmlet = GetItemIfNotImplemented("item_armlet") - if itemArmlet then - if npcBot.armlet_lastOpenTime == nil and IsUsingArmlet then - npcBot.armlet_lastOpenTime = DotaTime() - return - end - if not IsUsingArmlet then - npcBot.armlet_lastOpenTime = nil - return - end - end - - if itemArmlet and itemArmlet:IsFullyCastable() and notBlasted then - if fun1:IsFarmingOrPushing(npcBot) then - local target = npcBot:GetAttackTarget() - if target and target:IsAlive() and (fun1:GetHealthPercent(npcBot) >= 0.45 or npcBot:GetHealth() <= 400 or npcBot:GetUnitName() == "npc_bot_hero_huskar" and npcBot:GetLevel() >= 7) then - if not IsUsingArmlet then - M.UseItemNoTarget(npcBot, itemArmlet) - npcBot.armlet_lastOpenTime = DotaTime() - return - else - if npcBot:GetHealth() <= 250 and not npcBot:WasRecentlyDamagedByAnyHero(0.8) then - M.UseItemNoTarget(npcBot, itemArmlet) - npcBot.armlet_lastOpenTime = nil - end - end - else - if IsUsingArmlet then - M.UseItemNoTarget(npcBot, itemArmlet) - npcBot.armlet_lastOpenTime = nil - return - end - end - elseif fun1:IsAttackingEnemies(npcBot) or fun1:IsRetreating(npcBot) then - if not IsUsingArmlet then - if #npcBot:GetNearbyHeroes(1000, true, BOT_MODE_NONE) > 0 or npcBot:WasRecentlyDamagedByAnyHero(1.5) then - M.UseItemNoTarget(npcBot, itemArmlet) - npcBot.armlet_lastOpenTime = DotaTime() - return - end - else - if npcBot:GetHealth() <= 300 then - local projectiles = fun1:FilterNot(npcBot:GetIncomingTrackingProjectiles(), function(t) return fun1:IsOnSameTeam(t, npcBot) end) - if (#projectiles == 0 or fun1:CannotBeKilledNormally(npcBot)) and DotaTime() - npcBot.armlet_lastOpenTime >= 1 then - M.UseItemNoTarget(npcBot, itemArmlet) - npcBot.armlet_lastOpenTime = DotaTime() - return - end - end - end - else - if IsUsingArmlet then - M.UseItemNoTarget(npcBot, itemArmlet) - npcBot.armlet_lastOpenTime = nil - return - end - end - end]] - - local sc = GetItemIfNotImplemented("item_solar_crest") or GetItemIfNotImplemented("item_medallion_of_courage") - if sc ~= nil and sc:IsFullyCastable() then - if npcBot:GetActiveMode() == BOT_MODE_ROSHAN then - local target = npcBot:GetTarget() - if fun1:IsRoshan(target) then - M.UseItemOnEntity(npcBot, sc, target) - return - end - end - - if local ally = nearbyAllies:Filter(fun1.PhysicalCanCastFunction) - :Filter { t -> - not t:HasModifier("modifier_item_medallion_of_courage_armor_addition") and not t:HasModifier("modifier_item_solar_crest_armor_addition") - } - :First { t -> - fun1:IsSeverelyDisabledOrSlowed(t) - } then - M.UseItemOnEntity(npcBot, sc, ally) - return - end - - if - (npcBot:GetActiveMode() == BOT_MODE_ATTACK or npcBot:GetActiveMode() == BOT_MODE_ROAM or - npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_GANK or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY) - then - if npcTarget ~= nil and npcTarget:IsHero() and GetUnitToUnitDistance(npcTarget, npcBot) < 900 and not npcTarget:HasModifier("modifier_item_medallion_of_courage_armor_addition") and not npcTarget:HasModifier("modifier_item_medallion_of_courage_armor_reduction") then - M.UseItemOnEntity(npcBot, sc, npcTarget) - return - end - end - - if local ally = nearbyAllies:Filter { it -> - (fun1:GetHealthPercent(it) < 0.35 and #tableNearbyEnemyHeroes > 0 or fun1:IsSeverelyDisabled(it)) and fun1:AllyCanCast(it) - } then - M.UseItemOnEntity(npcBot, sc, Ally) - return - end - end - - local se = GetItemIfNotImplemented("item_silver_edge") or IsItemAvailable "item_invis_sword" - if se ~= nil and se:IsFullyCastable() then - if - npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH and - tableNearbyEnemyHeroes ~= nil and - #tableNearbyEnemyHeroes > 0 - then - M.UseItemNoTarget(npcBot, se) - return - end - if - (npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_GANK) - then - if npcTarget and fun1:MayNotBeIllusion(npcBot, npcTarget) and npcTarget:IsHero() and GetUnitToUnitDistance(npcTarget, npcBot) > 1000 and GetUnitToUnitDistance(npcTarget, npcBot) < 2500 then - M.UseItemNoTarget(npcBot, se) - return - end - end - end - - local hood = GetItemIfNotImplemented("item_hood_of_defiance") or GetItemIfNotImplemented("item_pipe") - if hood ~= nil and hood:IsFullyCastable() and healthPercent < 0.8 then - if tableNearbyEnemyHeroes ~= nil and #tableNearbyEnemyHeroes > 0 then - M.UseItemNoTarget(npcBot, hood) - return - end - end - - local lotus = GetItemIfNotImplemented("item_lotus_orb") - if lotus ~= nil and lotus:IsFullyCastable() then - if - (healthPercent < 0.45 and tableNearbyEnemyHeroes ~= nil and - #tableNearbyEnemyHeroes > 0) or - npcBot:IsSilenced() or - (tableNearbyEnemyHeroes ~= nil and #tableNearbyEnemyHeroes >= 3 and - healthPercent < 0.75) - then - M.UseItemOnEntity(npcBot, lotus, npcBot) - return - end - end - - if lotus ~= nil and lotus:IsFullyCastable() then - local Allies = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_NONE) - for _, Ally in pairs(Allies) do - if - (Ally:GetHealth() / Ally:GetMaxHealth() < 0.35 and tableNearbyEnemyHeroes ~= nil and - #tableNearbyEnemyHeroes > 0) or fun1:IsOrGoingToBeSeverelyDisabled(Ally) - then - M.UseItemOnEntity(npcBot, lotus, Ally) - return - end - end - end - - local hurricanpike = GetItemIfNotImplemented("item_hurricane_pike") - if hurricanpike ~= nil and hurricanpike:IsFullyCastable() then - if npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_HIGH then - for _, npcEnemy in pairs(tableNearbyEnemyHeroes) do - if GetUnitToUnitDistance(npcEnemy, npcBot) < 400 and fun1:NormalCanCast(npcEnemy) then - M.UseItemOnEntity(npcBot, hurricanpike, npcEnemy) - return - end - end - if npcBot:IsFacingLocation(GetAncient(GetTeam()):GetLocation(), 10) and npcBot:DistanceFromFountain() > 0 then - M.UseItemOnEntity(npcBot, hurricanpike, npcBot) - return - end - end - end - - local ghost = GetItemIfNotImplemented("item_ghost") - if ghost and ghost:IsFullyCastable() then - if npcBot:GetActiveMode() == BOT_MODE_ATTACK or npcBot:GetActiveMode() == BOT_MODE_RETREAT then - if npcBot:WasRecentlyDamagedByAnyHero(2.0) and npcBot:GetHealth()/npcBot:GetMaxHealth() <= 0.6 then - M.UseItemNoTarget(npcBot, ghost) - return - end - end - end - - local itemEtherealBlade = GetItemIfNotImplemented("item_ethereal_blade") - if itemEtherealBlade and itemEtherealBlade:IsFullyCastable() then - if npcTarget ~= nil and fun1:NormalCanCast(npcTarget) then - M.UseItemOnEntity(npcBot, itemEtherealBlade, npcBot) - return - end - end - - local itemDagon = fun1:Aggregate(GetItemIfNotImplemented("item_dagon"), fun1:Range(2, 5), function(seed, dagonLevelIndex) - return seed or GetItemIfNotImplemented("item_dagon_"..dagonLevelIndex) - end) - if itemDagon and itemDagon:IsFullyCastable() then - if npcTarget ~= nil and fun1:NormalCanCast(npcTarget) then - M.UseItemOnEntity(npcBot, itemDagon, npcBot) - return - end - end - - local glimmer = GetItemIfNotImplemented("item_glimmer_cape") - if glimmer and glimmer:IsFullyCastable() then - if - (healthPercent < 0.45 and - (tableNearbyEnemyHeroes ~= nil and #tableNearbyEnemyHeroes > 0)) or - (tableNearbyEnemyHeroes ~= nil and #tableNearbyEnemyHeroes >= 3 and - healthPercent < 0.65) - then - M.UseItemOnEntity(npcBot, glimmer, npcBot) - return - end - end - - local hod = GetItemIfNotImplemented("item_helm_of_the_overlord") or GetItemIfNotImplemented("item_helm_of_the_dominator") - if hod ~= nil and hod:IsFullyCastable() then - local maxHP = 0 - local NCreep = nil - local tableNearbyCreeps = npcBot:GetNearbyCreeps(1000, true) - if #tableNearbyCreeps >= 2 then - for _, creeps in pairs(tableNearbyCreeps) do - local CreepHP = creeps:GetHealth() - if - CreepHP > maxHP and (creeps:GetHealth() / creeps:GetMaxHealth()) > .75 and - not creeps:IsAncientCreep() - then - NCreep = creeps - maxHP = CreepHP - end - end - end - if NCreep ~= nil then - M.UseItemOnEntity(npcBot, hod, NCreep) - return - end - end - - if glimer ~= nil and glimer:IsFullyCastable() then - local Allies = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_NONE) - for _, Ally in pairs(Allies) do - if - (Ally:GetHealth() / Ally:GetMaxHealth() < 0.35 and tableNearbyEnemyHeroes ~= nil and - #tableNearbyEnemyHeroes > 0 and - fun1:NormalCanCast(Ally)) or - (fun1:IsOrGoingToBeSeverelyDisabled(Ally) and fun1:NormalCanCast(Ally)) - then - M.UseItemOnEntity(npcBot, glimer, Ally) - return - end - end - end - - local satanic = GetItemIfNotImplemented("item_satanic") - if satanic ~= nil and satanic:IsFullyCastable() and notBlasted then - if - healthPercent < 0.50 and tableNearbyEnemyHeroes ~= nil and - #tableNearbyEnemyHeroes > 0 and - npcBot:GetActiveMode() == BOT_MODE_ATTACK - then - M.UseItemNoTarget(npcBot, satanic) - return - end - end - - local function NotSuitableForGuardianGreaves(t) - return fun1:AllyCanCast(t) and not t:HasModifier("modifier_ice_blast") and not t:HasModifier("modifier_item_mekansm_noheal") and not t:HasModifier("modifier_item_guardian_greaves_noheal") - end - - local mekansm = GetItemIfNotImplemented("item_mekansm") - if mekansm and mekansm:IsFullyCastable() then - local enemies = fun1:GetEnemyHeroNumber(npcBot, fun1:GetNearbyNonIllusionHeroes(npcBot)) - local function MekansmRate(t) - local rate = 1 - if fun1:GetHealthPercent(t) < 0.35 or t:GetHealth() <= 360 then - rate += 0.6 - end - if t:HasModifier "modifier_abaddon_borrowed_time" then - rate -= 0.5 - end - if (t:GetHealthRegen() > 50 or fun1:GetLifeSteal(t) >= 0.15) then - rate *= if enemies >= 1 { 0.5 } else {0.9} - end - rate *= fun1:GetTargetHealAmplifyPercent(t) - return rate - end - - local radius = mekansm:GetAOERadius() - local allAllys = fun1:GetPureHeroes(npcBot, 1450, false) - local allys = fun1:GetPureHeroes(npcBot, radius, false):Filter(NotSuitableForGuardianGreaves):Filter { t -> - t:GetHealth() < t:GetMaxHealth() - 450 - } - local rate = fun1:Aggregate(0, allys:Map(MekansmRate), { + }) - if rate >= 2.6 and rate >= #allys * 1.1 then - M.UseItemNoTarget(npcBot, mekansm) - return - end - - if fun1:IsRetreating(npcBot) and MekansmRate(npcBot) >= 1.6 then - M.UseItemNoTarget(npcBot, mekansm) - return - end - end - - local ggr = GetItemIfNotImplemented("item_guardian_greaves") - if ggr ~= nil and ggr:IsFullyCastable() then - local allys = npcBot:GetNearbyHeroes(900, false, BOT_MODE_NONE) - allys = fun1:Filter(allys, NotSuitableForGuardianGreaves) - local factor = 0 - - for k, v in pairs(allys) do - local allyFactor = (2 - v:GetMana() / v:GetMaxMana() - v:GetHealth() / v:GetMaxHealth()) * 0.5 - factor = factor + allyFactor - end - - if factor / #allys > 0.5 - 0.2 * math.log(#allys) / math.log(6) then - M.UseItemNoTarget(npcBot, ggr) - return - end - end - - local stick = GetItemIfNotImplemented("item_magic_stick") - if stick ~= nil and stick:IsFullyCastable() and stick:GetCurrentCharges() > 0 and notBlasted then - if DotaTime() > 0 then - local tableNearbyEnemyHeroes = npcBot:GetNearbyHeroes(500, true, BOT_MODE_NONE) - if - ((healthPercent < 0.4 or manaPercent < 0.2) and - #tableNearbyEnemyHeroes >= 1 and - GetItemCharges(npcBot, "item_magic_stick") >= 1) or - ((healthPercent < 0.7 and manaPercent < 0.7) and - GetItemCharges(npcBot, "item_magic_stick") >= 7) - then - M.UseItemNoTarget(npcBot, stick) - return - end - end - end - - local wand = GetItemIfNotImplemented("item_magic_wand") - if wand ~= nil and wand:IsFullyCastable() and wand:GetCurrentCharges() > 0 and notBlasted then - if DotaTime() > 0 then - local tableNearbyEnemyHeroes = npcBot:GetNearbyHeroes(500, true, BOT_MODE_NONE) - if - ((healthPercent < 0.4 or manaPercent < 0.2) and - #tableNearbyEnemyHeroes >= 1 and - GetItemCharges(npcBot, "item_magic_wand") >= 1) or - ((healthPercent < 0.7 and manaPercent < 0.7) and - GetItemCharges(npcBot, "item_magic_wand") >= 12) - then - M.UseItemNoTarget(npcBot, wand) - return - end - end - end - - local holyLocket = GetItemIfNotImplemented("item_holy_locket") - if holyLocket ~= nil and holyLocket:IsFullyCastable() and notBlasted then - if DotaTime() > 0 then - local tableNearbyEnemyHeroes = npcBot:GetNearbyHeroes(500, true, BOT_MODE_NONE) - if - ((healthPercent < 0.4 or manaPercent < 0.2) and - #tableNearbyEnemyHeroes >= 1 and - GetItemCharges(npcBot, "item_holy_locket") >= 1) or - ((healthPercent < 0.7 and manaPercent < 0.7) and - GetItemCharges(npcBot, "item_holy_locket") >= 12) - then - M.UseItemOnEntity(npcBot, wand, npcBot) - return - end - end - end - - local bottle = GetItemIfNotImplemented("item_bottle") - if bottle ~= nil and bottle:IsFullyCastable() and notBlasted then - local tableNearbyEnemyHeroes = npcBot:GetNearbyHeroes(650, true, BOT_MODE_NONE) - if GetItemCharges(npcBot, "item_bottle") > 0 and not npcBot:HasModifier("modifier_bottle_regeneration") then - if - ((healthPercent < 0.65 and manaPercent < 0.45) or - healthPercent < 0.4 or - manaPercent < 0.2) and - #tableNearbyEnemyHeroes == 0 - then - M.UseItemOnEntity(npcBot, bottle, npcBot) - return - end - end - end - - local cyclone = GetItemIfNotImplemented("item_cyclone") or GetItemIfNotImplemented("item_wind_waker") - if cyclone ~= nil and cyclone:IsFullyCastable() then - if - npcTarget ~= nil and (npcTarget:IsChanneling() and not fun1:IsOrGoingToBeSeverelyDisabled(npcTarget) or fun1:CannotBeKilledNormally(npcTarget)) and - fun1:NormalCanCast(npcTarget) and - GetUnitToUnitDistance(npcBot, npcTarget) < 775 - then - M.UseItemOnEntity(npcBot, cyclone, npcTarget) - return - end - end - - local metham = GetItemIfNotImplemented("item_meteor_hammer") - if metham ~= nil and metham:IsFullyCastable() then - local tableNearbyAttackingAlliedHeroes = npcBot:GetNearbyHeroes(1000, false, BOT_MODE_ATTACK) - if - (npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT) - then - local towers = npcBot:GetNearbyTowers(800, true) - if #towers > 0 and towers[1] ~= nil and towers[1]:IsInvulnerable() == false then - M.UseItemOnLocation(npcBot, metham, towers[1]:GetLocation()) - return - end - elseif #tableNearbyAttackingAlliedHeroes >= 2 then - local locationAoE = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), 600, 300, 0, 0) - if locationAoE.count >= 2 then - M.UseItemOnLocation(npcBot, metham, locationAoE.targetloc) - return - end - elseif - (npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK) - then - if - npcTarget ~= nil and npcTarget:IsHero() and fun1:NormalCanCast(npcTarget) and - GetUnitToUnitDistance(npcBot, npcTarget) < 800 and - fun1:IsOrGoingToBeSeverelyDisabled(true, npcTarget) == true - then - M.UseItemOnLocation(npcBot, metham, npcTarget:GetLocation()) - return - end - end - end - - local sv = GetItemIfNotImplemented("item_spirit_vessel") - if sv ~= nil and sv:IsFullyCastable() and sv:GetCurrentCharges() > 0 then - if local enemy = fun1:GetPureHeroes(npcBot, sv:GetCastRange() + 200):Filter { t->fun1:NormalCanCast(t) }:First { - t -> t:GetHealthRegen() >= 55 - } then - M.UseItemOnEntity(npcBot, sv, enemy) - end - - if - (npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK) - then - if - npcTarget ~= nil and npcTarget:IsHero() and fun1:MayNotBeIllusion(npcBot, npcTarget) and fun1:NormalCanCast(npcTarget) and - GetUnitToUnitDistance(npcBot, npcTarget) < 900 and - npcTarget:HasModifier("modifier_item_spirit_vessel_damage") == false and - npcTarget:GetHealth() / npcTarget:GetMaxHealth() < 0.65 and - not npcTarget:HasModifier("modifier_ice_blast") - then - M.UseItemOnEntity(npcBot, sv, npcTarget) - return - end - else - local Allies = npcBot:GetNearbyHeroes(1150, false, BOT_MODE_NONE) - for _, Ally in pairs(Allies) do - if - not Ally:IsIllusion() and Ally:HasModifier("modifier_item_spirit_vessel_heal") == false and fun1:NormalCanCast(Ally) and - Ally:GetHealth() / Ally:GetMaxHealth() < 0.35 and - #tableNearbyEnemyHeroes == 0 and - Ally:WasRecentlyDamagedByAnyHero(2.5) == false and - not Ally:HasModifier("modifier_ice_blast") - then - M.UseItemOnEntity(npcBot, sv, Ally) - return - end - end - end - end - - local nullifier = GetItemIfNotImplemented("item_nullifier") - if nullifier ~= nil and nullifier:IsFullyCastable() then - if - (npcBot:GetActiveMode() == BOT_MODE_ROAM or npcBot:GetActiveMode() == BOT_MODE_TEAM_ROAM or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY or - npcBot:GetActiveMode() == BOT_MODE_ATTACK) - then - if - npcTarget ~= nil and npcTarget:IsHero() and fun1:NormalCanCast(npcTarget) and - GetUnitToUnitDistance(npcBot, npcTarget) < 800 and - npcTarget:HasModifier("modifier_item_nullifier_mute") == false - then - M.UseItemOnEntity(npcBot, nullifier, npcTarget) - return - end - end - end - - -- test code -- - - -- local wards=GetItemIfNotImplemented("item_ward_dispenser") - - -- if(wards~=nil) - -- then - -- local sentry=wards:GetSecondaryCharges() - -- local observer= wards:GetCurrentCharges() - -- local state=wards:GetToggleState() - -- print(npcBot:GetUnitName().."2nd Charge:"..sentry.." 1st Charge"..observer) - - -- if(state==true) - -- then - -- npcBot:Action_UseAbilityOnEntity(wards,npcBot) - -- print("state true") - -- else - -- npcBot:Action_UseAbilityOnEntity(wards,npcBot) - -- print("state false") - -- end - - -- end - - local WardList = GetUnitList(UNIT_LIST_ALLIED_WARDS) - local HaveWard = false - - for _, ward in pairs(WardList) do - if GetUnitToUnitDistance(ward, npcBot) <= 1500 then - HaveWard = true - end - end - - local sentry = GetItemIfNotImplemented("item_ward_sentry") - if sentry ~= nil and sentry:IsFullyCastable() and sentry:IsCooldownReady() then - local NearbyTowers = npcBot:GetNearbyTowers(1600, true) - local NearbyTowers2 = npcBot:GetNearbyTowers(800, true) - local NearbyTowers3 = npcBot:GetNearbyTowers(800, false) - - if HaveWard == false then - if npcBot:GetActiveMode() == BOT_MODE_ATTACK then - M.UseItemOnLocation(npcBot, sentry, npcBot:GetLocation()) - end - - if - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP or npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT and #NearbyTowers2 == 0 and #NearbyTowers > 0 - then - M.UseItemOnLocation(npcBot, sentry, npcBot:GetXUnitsInBehind(300)) - end - - if - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or - npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT and #NearbyTowers3 == 0 - then - M.UseItemOnLocation(npcBot, sentry, npcBot:GetXUnitsInFront(300)) - end - end - end -end - -return M diff --git a/util/MiraDota.lua b/util/MiraDota.lua index d70c59f..7d6cf0b 100644 --- a/util/MiraDota.lua +++ b/util/MiraDota.lua @@ -1,8 +1,3 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") local M = {} local Linq = {} @@ -1280,7 +1275,7 @@ function ItemFun.GetAvailableItem(npc, itemName, isNeutral) return item end end - if isNeutral then + if isNeutral then -- although we can test if the item is neutral through ItemFun.IsNeutralItem, the parameter is passed explicitly for performance issue local item = npc:GetItemInSlot(16) if item and item:IsFullyCastable() then return item @@ -1817,6 +1812,7 @@ local function ConsiderAvailableItem(item, bot, itemUsageAuxiliaryInfo) local itemFunc = bot.ItemUsage and bot.ItemUsage[name] or ItemUseDefaultImpl[name] if itemFunc == nil then GameLoop.EveryManySeconds(5, "NotifyUnimplementedItem " .. name, function() + -- print("Item not implemented: "..name) end) return 0 else diff --git a/util/MiraDota.mira b/util/MiraDota.mira deleted file mode 100644 index 22ba70d..0000000 --- a/util/MiraDota.mira +++ /dev/null @@ -1,2192 +0,0 @@ -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local M = {} - -local Linq = {} -local Debug = {} -local DotaExt = {} -local AbilInfo = {} -local ItemUseDefaultImpl = {} -local Push = {} -local Abil = {} -local Math = {} -local Hero = {} -local UnitFun = {} -local Building = {} - - - - -local magicTable = {} - -function Linq.Give(t) - setmetatable(t, magicTable) -end -magicTable.__index = magicTable - -function Linq.NewTable(...) - local a = { ... } - Linq.Give(a, magicTable) - return a -end - -function Linq.Aggregate(tb, seed, aggregate) - for k, v in ipairs(tb) do - seed = aggregate(seed, v, k) - end - return seed -end - -function Linq.All(tb, filter) - for k, v in ipairs(tb) do - if not filter(v, k) then - return false - end - end - return true -end - -function Linq.Any(tb, filter) - for k, v in ipairs(tb) do - if filter == nil or filter(v, k) then - return true - end - end - return false -end - -function Linq.Append(tb, item) - local g = Linq.ShallowCopy(tb) - table.insert(g, item) - return g -end - -function Linq.Average(tb) - local i = 0 - local sum = 0 - for _, v in ipairs(tb) do - i = i + 1 - sum = sum + v - end - return sum / i -end - -function Linq.Concat(a, b) - local g = Linq.NewTable() - for _, v in ipairs(a) do - table.insert(g, v) - end - for _, v in ipairs(b) do - table.insert(g, v) - end - return g -end - -function Linq.Contains(tb, value, equals) - equals = equals or { == } - for _, v in ipairs(tb) do - if equals(v, value) then - return true - end - end - return false -end - -function Linq.ContainsKey(tb, key, equals) - equals = equals or { == } - for k, _ in pairs(tb) do - if equals(key, k) then - return true - end - end - return false -end - -function Linq.Count(tb, filter) - local g = 0 - for k, v in ipairs(tb) do - if filter == nil or filter(v, k) then - g = g + 1 - end - end - return g -end - -function Linq.DeepCopy(tb) - local copiedTables = Linq.NewTable() - local g = Linq.NewTable() - table.insert(copiedTables, tb) - for k, v in pairs(tb) do - if type(v) ~= "table" then - g[k] = v - else - if Linq.Contains(copiedTables, v) then - return {} - end - g[k] = Linq.DeepCopy(v) - end - end - return g -end - -function Linq.Distinct(tb, equals) - equals = equals or { == } - local g = Linq.NewTable() - for _, v in pairs(tb) do - if not Linq.Contains(g, v, equals) then - table.insert(g, v) - end - end - return g -end - -function Linq.Except(tb, tb2, equals) - local g = Linq.NewTable() - for _, v in ipairs(tb) do - if not Linq.Contains(tb2, v, equals) then - table.insert(g, v) - end - end - return g -end - -function Linq.Filter(tb, filter) - local g = Linq.NewTable() - for k, v in ipairs(tb) do - if filter(v, k) then - table.insert(g, v) - end - end - return g -end - -function Linq.Filter2(tb1, tb2, filter, map) - map = map or { a, b, c -> { a, b } } - local g = Linq.NewTable() - for i = 1, #tb1 do - if filter(tb1[i], tb2[i], i) then - table.insert(map(tb1[i], tb2[i], i)) - end - end - return g -end - -function Linq.FilterNot(tb, filter) - local g = Linq.NewTable() - for k, v in ipairs(tb) do - if not filter(v, k) then - table.insert(g, v) - end - end - return g -end - -function Linq.First(tb, filter) - filter = filter or { -> true } - for k, v in ipairs(tb) do - if filter == nil or filter(v, k) then - return v - end - end -end - -function Linq.ForEach2(tb1, tb2, func) - for i = 1, #tb1 do - func(tb1[i], tb2[i]) - end -end - -function Linq.ForEach(tb, action) - for k, v in ipairs(tb) do - action(v, k) - end -end - -function Linq.ForEachDic(tb, action) - for k, v in pairs(tb) do - action(v, k) - end -end - -function Linq.GroupBy(collection, keySelector, elementSelector, resultSelector, comparer) - comparer = comparer or { == } - resultSelector = resultSelector or { key, value -> value } - elementSelector = elementSelector or Linq.Identity - local keys = Linq.NewTable() - local values = Linq.NewTable() - for _, k in ipairs(collection) do - local keyFound = false - for readKeyIndex, readKey in ipairs(keys) do - if comparer(readKey, keySelector(k)) then - keyFound = true - table.insert(values[readKeyIndex], elementSelector(k)) - break - - end - end - if not keyFound then - table.insert(keys, keySelector(k)) - local v = Linq.NewTable() - table.insert(v, elementSelector(k)) - table.insert(values, v) - end - end - return Linq.Map2(keys, values, resultSelector) -end - -function Linq.GroupJoin(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer) - comparer = comparer or { == } - resultSelector = resultSelector or { key, values -> { key, values } } - innerKeySelector = innerKeySelector or Linq.Identity - outerKeySelector = outerKeySelector or Linq.Identity - local t = NewTable() - for k, v in ipairs(outer) do - local key = outerKeySelector(v, k) - local m = Linq.Filter(inner, function(v, k) - return comparer(innerKeySelector(v, k), key) - end) - table.insert(t, resultSelector { key, m }) - end - return t -end - -Linq.Identity = { t -> t } - -function Linq.InsertAfter_Modify(tb, item, after) - if after == nil then - table.insert(tb, item) - else - for index, value in ipairs(tb) do - if after == value then - table.insert(tb, index, item) - return - end - end - table.insert(tb, item) - end -end - -function Linq.Intersect(tb, tb2, equals) - local g = Linq.NewTable() - for _, v in tb do - if Linq.Contains(tb2, v, equals) then - table.insert(g, v) - end - end - return g -end - -function Linq.Join(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer) - comparer = comparer or { == } - resultSelector = resultSelector or { o, i -> { o, i } } - innerKeySelector = innerKeySelector or Linq.Identity - outerKeySelector = outerKeySelector or Linq.Identity - local g = NewTable() - for k, v in ipairs(outer) do - local key = outerKeySelector(v, k) - Linq.Filter(inner, function(v, k) - return comparer(innerKeySelector(v, k), key) - end):Map(function(v2) - return resultSelector(v, v2) - end):ForEach(function(t) - return table.insert(g, t) - end) - end - return g -end - -function Linq.Keys(tb) - local g = Linq.NewTable() - for k, _ in pairs(tb) do - table.insert(g, k) - end - return g -end - -function Linq.Last(tb, filter) - return Linq.First(Linq.Reverse(tb), filter) -end - -function Linq.Map(tb, transform) - local g = Linq.NewTable() - for k, v in ipairs(tb) do - g[k] = transform(v) - end - return g -end - -function Linq.MapDic(tb, transform) - local g = Linq.NewTable() - for k, v in pairs(tb) do - g[k] = transform(k, v) - end - return g -end - -function Linq.Max(tb, map) - if #tb == 0 then - return nil - end - map = map or Linq.Identity - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m > maxm then - maxm = m - maxv = tb[i] - end - end - return maxm -end - -function Linq.MaxKey(tb, map) - if #tb == 0 then - return nil - end - map = map or Linq.Identity - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m > maxm then - maxm = m - maxv = tb[i] - end - end - return maxv -end - -function Linq.Min(tb, map) - if #tb == 0 then - return nil - end - map = map or Linq.Identity - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m < maxm then - maxm = m - maxv = tb[i] - end - end - return maxm -end - -function Linq.MinKey(tb, map) - if #tb == 0 then - return nil - end - map = map or Linq.Identity - local maxv, maxm = tb[1], map(tb[1]) - for i = 2, #tb do - local m = map(tb[i]) - if m < maxm then - maxm = m - maxv = tb[i] - end - end - return maxv -end - -function Linq.NonEmpty(tb) - return Linq.Filter(tb, function(t) - return t ~= nil and #t ~= 0 - end) -end - -function Linq.IndexOf(tb, filter) - local g = Linq.NewTable() - for k, v in ipairs(tb) do - if type(filter) == "function" then - if filter(v, k) then - return k - end - elseif filter ~= nil then - if v == filter then - return k - end - end - end - return -1 -end - -function Linq.Map2(tb1, tb2, map) - local g = Linq.NewTable() - for i = 1, #tb1 do - table.insert(g, map(tb1[i], tb2[i], i)) - end - return g -end - -function Linq.MergeSort(tb, sort) - sort = sort or { - } - local function Merge(a, b) - local g = Linq.NewTable() - local aLen = #a - local bLen = #b - local i = 1 - local j = 1 - while i <= aLen and j <= bLen do - if sort(a[i], b[j]) > 0 then - table.insert(g, b[j]) - j = j + 1 - else - table.insert(g, a[i]) - i = i + 1 - end - end - if i <= aLen then - for _ = i, aLen do - table.insert(g, a[i]) - end - end - if j <= bLen then - for _ = j, bLen do - table.insert(g, b[j]) - end - end - return g - end - local function SortRec(tab) - local tableLength = #tab - if tableLength == 1 then - return tab - end - local left = SortRec(Linq.Take(tab, tableLength / 2)) - local right = SortRec(Linq.Skip(tab, tableLength / 2)) - local merge = Merge(left, right) - return merge - end - return SortRec(tb) -end - -function Linq.OrderBy(tb, map) - map = map or Linq.Identity - return Linq.Sort(tb) { a, b -> return map(a) - map(b) } -end - -function Linq.OrderByDescending(tb, map) - map = map or Linq.Identity - return Linq.Sort(tb) { a, b -> return map(b) - map(a) } -end - -function Linq.Partition(tb, filter) - local a = Linq.NewTable() - local b = Linq.NewTable() - for k, v in pairs(tb) do - if filter(v, k) then - table.insert(a, v) - else - table.insert(b, v) - end - end - return a, b -end - -function Linq.Prepend(a, b) - return Linq.Concat(b, a) -end - -function Linq.Range(min, max, step) - step = step or 1 - local g = Linq.NewTable() - for i = min, max, step do - table.insert(g, i) - end - return g -end - -function Linq.Remove(a, b) - local g = Linq.ShallowCopy(a) - for k, v in pairs(a) do - if v == b then - g[k] = nil - end - end - return g -end - -function Linq.RemoveAll(a, b) - local g = Linq.NewTable() - for _, v in pairs(a) do - if not Linq.Contains(b, v) then - table.insert(g, v) - end - end - return g -end - -function Linq.Remove_Modify(tb, item) - local filter = item - if type(item) ~= "function" then - filter = { t -> t == item } - end - local i = 1 - local d = #tb - while i <= d do - if filter(tb[i]) then - table.remove(tb, i) - d = d - 1 - else - i = i + 1 - end - end -end - -function Linq.Repeat(element, count) - local g = Linq.NewTable() - for i = 1, count do - table.insert(g, element) - end - return g -end - -function Linq.Replace(tb, filter, map) - local g = Linq.NewTable() - for k, v in ipairs(tb) do - if filter(v, k) then - table.insert(g, map(v, k)) - else - table.insert(g, v) - end - end - return g -end - -function Linq.Reverse(tb) - local g = Linq.NewTable() - for i = #tb, 1, -1 do - table.insert(g, tb[i]) - end - return g -end - -function Linq.ShallowCopy(tb) - local g = Linq.NewTable() - for k, v in pairs(tb) do - g[k] = v - end - return g -end - -function Linq.SlowSort(tb, sort) - local g = Linq.ShallowCopy(tb) - local len = #g - if sort ~= nil then - for i = 1, len - 1 do - for j = i + 1, len do - if sort(g[i], g[j]) > 0 then - g[i], g[j] = g[j], g[i] - end - end - end - else - for i = 1, len - 1 do - for j = i + 1, len do - if g[i] > g[j] then - g[i], g[j] = g[j], g[i] - end - end - end - end - return g -end -Linq.Sort = Linq.SlowSort - -function Linq.SelectMany(tb, map, filter) - local g = Linq.NewTable() - for _, source in ipairs(tb) do - local collection = map(source) - for index, value in ipairs(collection) do - if filter == nil or filter(value, index) then - table.insert(g, value) - end - end - end - return g -end - -function Linq.Skip(tb, number) - local g = Linq.NewTable() - local i = 0 - for _, v in ipairs(tb) do - i = i + 1 - if i > number then - table.insert(g, v) - end - end - return g -end - -function Linq.SkipLast(tb, number) - return Linq.Skip(Linq.Reverse(tb), number) -end - -function Linq.SkipWhile(tb, filter) - local g = Linq.NewTable() - local failure - for k, v in ipairs(tb) do - if failure then - table.insert(tb, v) - else - if not filter(v, k) then - table.insert(tb, v) - failure = true - end - end - end - return g -end - -function Linq.Take(tb, number) - local g = Linq.NewTable() - local i = 0 - for _, v in ipairs(tb) do - i = i + 1 - if i <= number then - table.insert(g, v) - else - break - end - end - return g -end - -function Linq.TakeWhile(tb, filter) - local g = Linq.NewTable() - for k, v in ipairs(tb) do - if filter(v, k) then - table.insert(g, v) - else - break - - end - end - return g -end - -function Linq.Zip2(tb1, tb2, map) - map = map or { a, b -> { a, b } } - local g = Linq.NewTable() - for i = 1, #tb1 do - table.insert(g, map(tb1[i], tb2[i])) - end - return g -end - -local function AddLinqfunctionsToMetatable(mt) - for functionName, func in pairs(table) do - mt[functionName] = func - end - for k, v in pairs(Linq) do - mt[k] = v - end -end - -AddLinqfunctionsToMetatable(magicTable) - - - - - - - -function Debug.DebugTable(tb) - local msg = "{ " - local DebugRec - DebugRec = function(tc) - for k,v in pairs(tc) do - if type(v) == "number" or type(v) == "string" then - msg = msg..k.." = "..v..", " - elseif type(v) == "boolean" then - msg = msg..k.." = "..tostring(v)..", " - elseif type(v) == "table" then - msg = msg..k.." = ".."{ " - DebugRec(v) - msg = msg.."}, " - end - end - end - DebugRec(tb) - msg = msg.." }" - print(msg) -end - -function Debug.DebugLongTable(tb) - if type(tb) ~= "table" then - print(tostring(tb)) - return - end - for k,v in pairs(tb) do - if type(v) == "table" then - print(tostring(k).." = ") - Debug.DebugTable(v) - else - print(tostring(k).." = "..tostring(v)) - end - end -end - - - - - -local AttributeTypeEnum = { - ATTRIBUTE_INVALID = ATTRIBUTE_INVALID, - ATTRIBUTE_STRENGTH = ATTRIBUTE_STRENGTH, - ATTRIBUTE_AGILITY = ATTRIBUTE_AGILITY, - ATTRIBUTE_INTELLECT = ATTRIBUTE_INTELLECT, -} -function DotaExt.AttributeTypeToString(i) - for k, v in pairs(AttributeTypeEnum) do - if v == i then - return k - end - end - return "unknown attribute type" -end - -function DotaExt.GetNearbyHeroes(bot, range, getEnemy, botMode) - botMode = botMode or BOT_MODE_NONE - getEnemy = getEnemy or true - local range1 = (function() - if range > 1600 then - return 1600 - else - return range - end - end)() - local units = bot:GetNearbyHeroes(range1, getEnemy, botMode) - Linq.Give(units) - return units -end - -function DotaExt.GetNearbyLaneCreeps(bot, range, getEnemy) - getEnemy = getEnemy or true - local range1 = (function() - if range > 1600 then - return 1600 - else - return range - end - end)() - local units = bot:GetNearbyLaneCreeps(range1, getEnemy) - Linq.Give(units) - return units -end - -function DotaExt.GetNearbyNeutralCreeps(bot, range) - local range1 = (function() - if range > 1600 then - return 1600 - else - return range - end - end)() - local units = bot:GetNearbyNeutralCreeps(range1) - Linq.Give(units) - return units -end - -local botModeEnum = { - BOT_MODE_NONE = BOT_MODE_NONE, - BOT_MODE_LANING = BOT_MODE_LANING, - BOT_MODE_ATTACK = BOT_MODE_ATTACK, - BOT_MODE_ROAM = BOT_MODE_ROAM, - BOT_MODE_RETREAT = BOT_MODE_RETREAT, - BOT_MODE_SECRET_SHOP = BOT_MODE_SECRET_SHOP, - BOT_MODE_SIDE_SHOP = BOT_MODE_SIDE_SHOP, - BOT_MODE_PUSH_TOWER_TOP = BOT_MODE_PUSH_TOWER_TOP, - BOT_MODE_PUSH_TOWER_MID = BOT_MODE_PUSH_TOWER_MID, - BOT_MODE_PUSH_TOWER_BOT = BOT_MODE_PUSH_TOWER_BOT, - BOT_MODE_DEFEND_TOWER_TOP = BOT_MODE_DEFEND_TOWER_TOP, - BOT_MODE_DEFEND_TOWER_MID = BOT_MODE_DEFEND_TOWER_MID, - BOT_MODE_DEFEND_TOWER_BOT = BOT_MODE_DEFEND_TOWER_BOT, - BOT_MODE_ASSEMBLE = BOT_MODE_ASSEMBLE, - BOT_MODE_TEAM_ROAM = BOT_MODE_TEAM_ROAM, - BOT_MODE_FARM = BOT_MODE_FARM, - BOT_MODE_DEFEND_ALLY = BOT_MODE_DEFEND_ALLY, - BOT_MODE_EVASIVE_MANEUVERS = BOT_MODE_EVASIVE_MANEUVERS, - BOT_MODE_ROSHAN = BOT_MODE_ROSHAN, - BOT_MODE_ITEM = BOT_MODE_ITEM, - BOT_MODE_WARD = BOT_MODE_WARD, -} -function DotaExt.BotModeToString(mode) - for k, v in pairs(botModeEnum) do - if mode == v then - return k - end - end - return "unknown bot mode "..mode -end - -DotaExt.towerNames = Linq.NewTable(TOWER_TOP_1, TOWER_TOP_2, TOWER_TOP_3, TOWER_MID_1, TOWER_MID_2, TOWER_MID_3, TOWER_BOT_1, TOWER_BOT_2, TOWER_BOT_3, TOWER_BASE_1, TOWER_BASE_2) -DotaExt.barracksNames = Linq.NewTable(BARRACKS_TOP_MELEE, BARRACKS_TOP_RANGED, BARRACKS_MID_MELEE, BARRACKS_MID_RANGED, BARRACKS_BOT_MELEE, BARRACKS_BOT_RANGED) -DotaExt.shrineNames = Linq.NewTable(SHRINE_BASE_1, SHRINE_BASE_2, SHRINE_BASE_3, SHRINE_BASE_4, SHRINE_BASE_5) - -function DotaExt.IsValidUnit(v) - return v and not v:IsNull() and v:IsAlive() -end - -function DotaExt.GetAllBuildings(team) - return DotaExt.towerNames:Map { t -> GetTower(team, t) } - :Concat( - DotaExt.barracksNames:Map { t -> GetBarracks(team, t) } - ) - :Concat( - DotaExt.shrineNames:Map { t -> GetShrine(team, t) } - ) - :Concat { GetAncient(team) } - :Filter { t -> DotaExt.IsValidUnit(t) and not t:IsInvulnerable() } -end - -function DotaExt.GetPureHeroes(npcBot, range, getEnemy) - range = range or 1600 - if getEnemy == nil then - getEnemy = true - end - return Linq.Filter(DotaExt.GetNearbyHeroes(npcBot, range, getEnemy)) { t -> - Hero.MayNotBeIllusion(npcBot, t) and not UnitFun.IsHeroLevelUnit(t) - } -end - -function DotaExt.EmptyFun() -> nil -function DotaExt.EmptyDesireFun() -> BOT_ACTION_DESIRE_NONE - -function DotaExt.GetNearbyCreeps(npc, range, getEnemy) - local r = npc:GetNearbyCreeps(range, getEnemy) - Linq.Give(r) - return r -end - -function DotaExt.GetNearbyNeutralCreeps(npc, range) - local r = npc:GetNearbyNeutralCreeps(range) - Linq.Give(r) - return r -end - - - - - - - - -AbilInfo.invisibleModifiers = Linq.NewTable( - "modifier_bounty_hunter_wind_walk", - "modifier_clinkz_wind_walk", - "modifier_dark_willow_shadow_realm_buff", - "modifier_item_glimmer_cape_glimmer", - "modifier_invoker_ghost_walk_self", - "modifier_nyx_assassin_vendetta", - "modifier_item_phase_boots_active", - "modifier_item_shadow_amulet_fade", - "modifier_item_invisibility_edge_windwalk", - "modifier_shadow_fiend_requiem_thinker", - "modifier_item_silver_edge_windwalk", - "modifier_windrunner_wind_walk", - "modifier_storm_wind_walk", - "modifier_templar_assassin_meld", - "modifier_visage_silent_as_the_grave", - "modifier_weaver_shukuchi", - "modified_invisible", - "modifier_rune_invis", - "modifier_nyx_assassin_burrow", - "modifier_oracle_false_promise_invis" -) - -AbilInfo.truesightModifiers = Linq.NewTable( - "modifier_item_dustofappearance", - "modifier_bounty_hunter_track", - "modifier_slardar_amplify_damage", - "modifier_truesight" -) - -function AbilInfo.HasAnyModifier(bot, modifiers) - return modifiers:Any { t -> - bot:HasModifier(t) - } -end - - - - - -local frameNumber = 0 -local dotaTimer -local deltaTime = 0 - -local function FloatEqual(a, b) - return math.abs(a - b) < 0.000001 -end - -local GameLoop = {} - -function GameLoop.GetFrameNumber() - return frameNumber -end - -function GameLoop.GetDeltaTime() - return deltaTime -end - -function GameLoop.EveryManyFrames(count, times) - times = times or 1 - return frameNumber % count < times -end - -local defaultReturn = Linq.NewTable() -local everySecondsCallRegistry = Linq.NewTable() - -function GameLoop.EveryManySeconds(second, registerName, oldFunction, ...) - if everySecondsCallRegistry[registerName] == nil then - local callTable = {} - callTable.lastCallTime = DotaTime() + RandomFloat(0, second) - second - callTable.interval = second - everySecondsCallRegistry[registerName] = callTable - end - local callTable = everySecondsCallRegistry[registerName] - if callTable.lastCallTime <= DotaTime() - callTable.interval then - callTable.lastCallTime = DotaTime() - return oldFunction(...) - else - return defaultReturn - end -end - -local singleForTeamRegistry = Linq.NewTable() -function GameLoop.SingleForTeam(oldFunction) - local functionName = tostring(oldFunction) - return function(...) - if singleForTeamRegistry[functionName] ~= frameNumber then - singleForTeamRegistry[functionName] = frameNumber - return oldFunction(...) - else - return defaultReturn - end - end -end - -function GameLoop.CalledOnThisFrame(functionInvocationResult) - return functionInvocationResult ~= defaultReturn -end - -function GameLoop.AiTicking() - return DotaTime() >= -75 -end - -local coroutineRegistry = Linq.NewTable() -local coroutineExempt = Linq.NewTable() - -function GameLoop.TickFromDota() - if not GameLoop.AiTicking() then - return - end - local time = DotaTime() - local function ResumeCoroutine(thread) - local coroutineResult = { coroutine.resume(thread, deltaTime) } - if not coroutineResult[1] then - print("error in coroutine:") - table.remove(coroutineResult, 1) - Debug.DebugLongTable(coroutineResult) - end - end - if dotaTimer == nil then - dotaTimer = time - return - end - deltaTime = time - dotaTimer - if not FloatEqual(time, dotaTimer) then - frameNumber = frameNumber + 1 - local threadIndex = 1 - while threadIndex <= #coroutineRegistry do - local t = coroutineRegistry[threadIndex] - local exemptIndex - local exempt - coroutineExempt:ForEach(function(exemptPair, index) - if exemptPair[1] == t then - if exemptPair[2] == frameNumber then - exempt = true - end - exemptIndex = index - end - end) - if exemptIndex then - table.remove(coroutineExempt, exemptIndex) - end - if not exempt then - if coroutine.status(t) == "suspended" then - ResumeCoroutine(t) - threadIndex = threadIndex + 1 - elseif coroutine.status(t) == "dead" then - table.remove(coroutineRegistry, threadIndex) - else - threadIndex = threadIndex + 1 - end - end - end - dotaTimer = time - end -end - -function GameLoop.ResumeUntilReturn(func) - local g = NewTable() - local thread = coroutine.create(func) - while true do - local values = { coroutine.resume(thread) } - if values[1] then - table.remove(values, 1) - table.insert(g, values) - else - print("error in coroutine:") - table.remove(values, 1) - Debug.DebugLongTable(values) - break - end - end - return g -end - -function GameLoop.StartCoroutine(func) - local newCoroutine = coroutine.create(func) - table.insert(coroutineRegistry, newCoroutine) - table.insert(coroutineExempt, { - newCoroutine, - frameNumber, - }) - return newCoroutine -end - -function GameLoop.WaitForSeconds(seconds) - local t = seconds - while t > 0 do - t = t - coroutine.yield() - end -end - -function GameLoop.StopCoroutine(thread) - GameLoop.Remove_Modify(coroutineExempt, function(t) - return t[1] == thread - end) - GameLoop.Remove_Modify(coroutineRegistry, thread) -end - - - - - -function Abil.UseAbilityOnEntity(bot, abil, entity, motive, queueType) - if Abil.print then - local printContent = bot:GetUnitName().." use "..abil:GetName().." on entity "..entity:GetUnitName() - if motive then - printContent = printContent..", motive = "..tostring(motive) - end - print(motive) - end - if queueType == "queue" then - bot:ActionQueue_UseAbilityOnEntity(abil, entity) - elif queueType == "push" then - bot:ActionPush_UseAbilityOnEntity(abil, entity) - else - bot:Action_UseAbilityOnEntity(abil, entity) - end -end -function Abil.UseAbility(bot, abil, motive, queueType) - if Abil.print then - local printContent = bot:GetUnitName().." use "..abil:GetName() - if motive then - printContent = printContent..", motive = "..tostring(motive) - end - print(motive) - end - if queueType == "queue" then - bot:ActionQueue_UseAbility(abil) - elif queueType == "push" then - bot:ActionPush_UseAbility(abil) - else - bot:Action_UseAbility(abil) - end -end -function Abil.UseAbilityOnLocation(bot, abil, location, motive, queueType) - if Abil.print then - local printContent = bot:GetUnitName().." use "..abil:GetName().." on location "..fun1:ToStringVector(location) - if motive then - printContent = printContent..", motive = "..tostring(motive) - end - print(motive) - end - if queueType == "queue" then - bot:ActionQueue_UseAbilityOnLocation(abil, location) - elif queueType == "push" then - bot:ActionPush_UseAbilityOnLocation(abil, location) - else - bot:Action_UseAbilityOnLocation(abil, location) - end -end -function Abil.UseAbilityOnTree(bot, abil, tree, motive, queueType) - if Abil.print then - local printContent = bot:GetUnitName().." use "..abil:GetName().." on tree "..tree - if motive then - printContent = printContent..", motive = "..tostring(motive) - end - print(motive) - end - if queueType == "queue" then - bot:ActionQueue_UseAbilityOnTree(abil, tree) - elif queueType == "push" then - bot:ActionPush_UseAbilityOnTree(abil, tree) - else - bot:Action_UseAbilityOnTree(abil, tree) - end -end - - - - - - -function UnitFun.IsFarmingOrPushing(npcBot) - local mode = npcBot:GetActiveMode() - return mode == BOT_MODE_FARM or mode == BOT_MODE_PUSH_TOWER_BOT or mode == BOT_MODE_PUSH_TOWER_MID or mode == BOT_MODE_PUSH_TOWER_TOP or mode == BOT_MODE_DEFEND_TOWER_BOT or mode == BOT_MODE_DEFEND_TOWER_MID or mode == BOT_MODE_DEFEND_TOWER_TOP -end - -function UnitFun.IsLaning(npcBot) - local mode = npcBot:GetActiveMode() - return mode == BOT_MODE_LANING -end - -function UnitFun.IsAttackingEnemies(npcBot) - local mode = npcBot:GetActiveMode() - return mode == BOT_MODE_ROAM or mode == BOT_MODE_TEAM_ROAM or mode == BOT_MODE_ATTACK or mode == BOT_MODE_DEFEND_ALLY -end - -function UnitFun.IsRetreating(npcBot) - return npcBot:GetActiveMode() == BOT_MODE_RETREAT and npcBot:GetActiveModeDesire() >= BOT_MODE_DESIRE_MODERATE -end - -function UnitFun.NotRetreating(npcBot) - return not UnitFun.IsRetreating(npcBot) -end - -local heroNamePrefixLen = #"npc_dota_hero_" -function UnitFun.GetHeroShortName(name) - return string.sub(name, heroNamePrefixLen + 1) -end - -function UnitFun.IsTempestDouble(npc) - return npc:HasModifier "modifier_arc_warden_tempest_double" -end - -function UnitFun.IsLoneDruidBear(npc) - return string.match(npc:GetUnitName(), "npc_dota_lone_druid_bear") -end - -function UnitFun.IsVisageFamiliar(npc) - return string.match(npc:GetUnitName(), "npc_dota_visage_familiar") -end - -function UnitFun.IsBrewmasterPrimalSplit(npc) - local unitName = npc:GetUnitName() - return string.match(unitName, "npc_dota_brewmaster_") -end - -function UnitFun.IsHeroLevelUnit(npc) - if UnitFun.IsBrewmasterPrimalSplit(npc) then return true end - local name = npc:GetUnitName() - if name == "npc_dota_phoenix_sun" then return true end - if string.match(npc:GetUnitName(), "npc_dota_lone_druid_bear") then - return true - end - return false -end - -local canUseItemIllusionModifiers = Linq.NewTable( - "modifier_arc_warden_tempest_double", - "modifier_skeleton_king_reincarnation_active", - "modifier_vengefulspirit_hybrid_special" -) - -function UnitFun.CanBuyItem(npc) - if UnitFun.IsHeroLevelUnit(npc) or UnitFun.IsTempestDouble(npc) then - return false - end - if npc:IsIllusion() then - return false - end - return true -end - -function UnitFun.CanUseItem(npc) - if UnitFun.IsBrewmasterPrimalSplit(npc) then return false end - if string.match(npc:GetUnitName(), "npc_dota_lone_druid_bear") then - return true - end - if name == "npc_dota_phoenix_sun" then - return false - end - if npc:IsIllusion() and not AbilInfo.HasAnyModifier(npc, canUseItemIllusionModifiers) then - return false - end - return true -end - -function UnitFun.IsGoodTarget(npc, target) - return target:IsHero() and Hero.MayNotBeIllusion(npc, target) and not UnitFun.IsHeroLevelUnit(target) -end - -function UnitFun.GetHeroTarget(npc) - if local t = npc:GetTarget(); t and UnitFun.IsGoodTarget(npc, t) then - return t - end -end - -function UnitFun.IsHero(npc) -> npc:IsHero() and not UnitFun.IsCreepHero(npc) -function UnitFun.IsCreepHero(npc) -> UnitFun.IsLoneDruidBear(npc) or UnitFun.IsVisageFamiliar(npc) -function UnitFun.IsNotCreepHero(npc) -> not UnitFun.IsCreepHero(npc) - - - - - - - -function Building.CanBeAttacked(buillding, npc) - if not building:IsAlive() or building:HasModifier "modifier_foutain_glyph" then - return false - end - npc = npc or GetBot() - if buidling:HasModifier "modifier_backdoor_protection_active" then - if local target = building:GetAttackTarget() then - if not target:IsHero() or target:IsIllusion() then - return true - end - end - return DotaExt.GetNearbyHeroes(npc, 1500, false):Filter(Hero.MayNotBeIllusion) - :Count { it -> - it:GetAttackTarget() == building - } * 80 >= building:GetHealth() - end - return true -end - - - - - - - - - -local ItemFun = {} - -function ItemFun.GetAvailableItem(npc, itemName, isNeutral) - if npc:IsMuted() then - return nil - end - if (itemName) == "item_tpscroll" then - local item = npc:GetItemInSlot(15) - if item and item:IsFullyCastable() then - return item - end - end - if isNeutral then -- although we can test if the item is neutral through ItemFun.IsNeutralItem, the parameter is passed explicitly for performance issue - local item = npc:GetItemInSlot(16) - if item and item:IsFullyCastable() then - return item - end - end - for _, i in ipairs(Linq.Range(0, 5):Concat { 16 }) do - local item = npc:GetItemInSlot(i) - if item and item:GetName() == itemName and item:IsFullyCastable() then - return item - end - end -end - -function ItemFun.GetAvailableTp(npc) - if local teleportation = npc:GetAbilityByName("furion_teleportation") then - if not npc:IsSilenced() and teleportation:IsFullyCastable() and teleportation:GetLevel() >= 2 then - return teleportation - end - end - if local keenConveyance = npc:GetAbilityByName("tinker_keen_conveyance") then - if keenConveyance:IsTrained() then - return keenConveyance - end - end - return ItemFun.GetAvailableItem(npc, "item_tpscroll") -end - -function ItemFun.CanUseAvailableTp(npc, tp) - local rearm = npc:GetAbilityByName "tinker_rearm" - if tp:GetName() == "tinker_keen_conveyance" then - if tp:IsFullyCastable() then - return true - end - if not tp:IsCooldownReady() and not npc:HasModifier "modifier_rejuvenation_aura_buff" and rearm and rearm:IsTrained() then - return true - end - end - if tp:GetName() == "furion_teleportation" then - return not npc:IsSilenced() and tp:IsFullyCastable() - end - return not npc:IsMuted() and tp:IsFullyCastable() -end - -function ItemFun.UseAvailableTp(npc, tp, location) - if tp:GetName() == "tinker_keen_conveyance" then - if tp:IsFullyCastable() then - ItemFun.UseAbilityOnLocation(npc, tp, location) - end - local rearm = npc:GetAbilityByName "tinker_rearm" - if not tp:IsCooldownReady() and not npc:HasModifier "modifier_rejuvenation_aura_buff" and rearm and rearm:IsTrained() then - while npc:IsSilenced() or not rearm:IsFullyCastable() do - coroutine.yield() - end - Abil.UseAbility(npc, rearm) - coroutine.yield() - while npc:IsChanneling() do - coroutine.yield() - end - Abil.UseAbilityOnLocation(npc, tp, location) - return true - end - return false - end - if tp:GetName() == "furion_teleportation" then - Abil.UseAbilityOnLocation(npc, tp, location) - return true - end - ItemFun.UseItemOnLocation(npc, tp, location) -end - - -function ItemFun.GetAvailableBlink(npc) - local blinks = { - "item_blink", - "item_overwhelming_blink", - "item_swift_blink", - "item_arcane_blink", - } - return Linq.Aggregate(blinks, nil, function(a, blinkName) - return a or ItemFun.GetAvailableItem(npc, blinkName) - end) -end - -function ItemFun.GetAvailableTravelBoots(npc) - local travelBoots = { - "item_travel_boots", - "item_travel_boots_2", - } - return Linq.Aggregate(travelBoots, nil, function(seed, t) - return seed or ItemFun.GetAvailableItem(npc, t) - end) -end - -function ItemFun.GetEmptyInventorySlots(npc) - local g = 0 - for i = 0, 5 do - if npc:GetItemInSlot(i) == nil then - g = g + 1 - end - end - return g -end - -function ItemFun.GetEmptyItemSlots(npc) - local g = 0 - for i = 0, 8 do - if npc:GetItemInSlot(i) == nil then - g = g + 1 - end - end - return g -end - -function ItemFun.GetEmptyBackpackSlots(npc) - local g = 0 - for i = 6, 8 do - if npc:GetItemInSlot(i) == nil then - g = g + 1 - end - end - return g -end - -function ItemFun.SwapItemToBackpack(npc, itemIndex) - for i = 6, 8 do - if npc:GetItemInSlot(i) == nil then - npc:ActionImmediate_SwapItems(itemIndex, i) - return true - end - end - return false -end - -function ItemFun.GetCarriedItems(npc) - local g = Linq.NewTable() - for i = 0, 8 do - local item = npc:GetItemInSlot(i) - if item then - table.insert(g, item) - end - end - return g -end - -function ItemFun.GetCarriedItemsWithIndex(npc) - local g = Linq.NewTable() - for i = 0, 8 do - local item = npc:GetItemInSlot(i) - if item then - table.insert(g, { - i, - item, - }) - end - end - return g -end - -function ItemFun.GetInventoryItems(npc) - local g = Linq.NewTable() - for i = 0, 5 do - local item = npc:GetItemInSlot(i) - if item then - table.insert(g, item) - end - end - return g -end - -function ItemFun.GetInventoryItemNames(npc) - local g = Linq.NewTable() - for i = 0, 5 do - local item = npc:GetItemInSlot(i) - if item then - table.insert(g, item:GetName()) - end - end - return g -end - -function ItemFun.GetStashItems(npc) - local g = Linq.NewTable() - for i = 9, 14 do - local item = npc:GetItemInSlot(i) - if item then - item.slotIndex = i - table.insert(g, item) - end - end - return g -end - -function ItemFun.GetAllBoughtItems(npcBot) - local g = Linq.NewTable() - for i = 0, 16 do - local item = npcBot:GetItemInSlot(i) - if item then - table.insert(g, item) - end - end - return g -end - -function ItemFun.IsBoots(item) - if type(item) ~= "string" then - item = item:GetName() - end - return string.match(item, "boots") or item == "item_guardian_greaves" or item == "item_power_treads" -end - -ItemFun.InventoryOnlyItems = Linq.NewTable("item_gem", "item_rapier", "item_bloodstone", "item_aegis") -ItemFun.PurchasedConsumables = Linq.NewTable('item_clarity', 'item_tango', 'item_flask', 'item_faerie_fire', 'item_enchanted_mango', 'item_infused_raindrop') -ItemFun.NeutralItems = Linq.NewTable() -ItemFun.NeutralItems.T1 = Linq.NewTable("item_arcane_ring", "item_broom_handle", "item_chipped_vest", "item_fairys_trinket", "item_keen_optic", "item_ocean_heart", "item_pig_hole", "item_possessed_mask", "item_trusty_shovel", "item_tumblers_toy") -ItemFun.NeutralItems.T2 = Linq.NewTable("item_brigands_blade", "item_bullwhip", "item_dragon_scale", "item_essence_ring", "item_fae_grenade", "item_grove_bow", "item_nether_shawl", "item_philosophers_stome", "item_pupils_gift", "item_quicksilver_amulet", "item_ring_of_aquila", "item_vambrace") -ItemFun.NeutralItems.T3 = Linq.NewTable("item_blast_rig", "item_ceremonial_robe", "item_cloak_of_flames", "item_elven_tunic", "item_enchanted_quiver", "item_mind_breaker", "item_paladin_sword", "item_psychic_headband", "item_quickening_charm", "item_spider_legs", "item_titan_silver") -ItemFun.NeutralItems.T4 = Linq.NewTable("item_ascetics_cap", "item_flicker", "item_ninja_gear", "item_penta_edged_sword", "item_spell_prism", "item_stormcrafter", "item_telescope", "item_the_leveller", "item_timeless_relic", "item_trickster_cloak", "item_witchblade") -ItemFun.NeutralItems.T5 = Linq.NewTable("item_apex", "item_arcanists_armor", "item_book_of_shadows", "item_book_of_the_dead", "item_ex_machina", "item_fallen_sky", "item_force_boots", "item_giants_ring", "item_mirror_shield", "item_pirate_hat", "item_seer_stone", "item_stygian_desolator") - -function ItemFun.IsNeutralItem(name) - return Linq.Range(1, 5):Map { t -> - ItemFun.NeutralItems["T"..t] - }:Any { t -> - t:Contains(name) - } -end - -function ItemFun.CannotBePutIntoBackpack(item) - if type(item) ~= "string" then - item = item:GetName() - end - return ItemFun.InventoryOnlyItems:Contains(item) -end - -local function RateItem(item) - local name = item:GetName() - local rate = if name == "item_gem" { 4000 } - elif name == "item_dust" { 1800+200*item:GetCurrentCharges() } - elif ItemFun.PurchasedConsumables:Contains(name) { - local rate1 = GetItemCost(name) * item:GetCurrentCharges() - if name == "item_tango" then rate1 = rate1 / 3 - elseif name == "item_infused_raindrop" then rate1 = rate1 / 6 - end - rate1 - } - elif name == "item_rapier" { 14000 } - elif string.match(name, "recipe_") { 0 } - else { GetItemCost(name) } - return rate -end - -function ItemFun.SwapUsefulOnes(bot) - local items = ItemFun.GetCarriedItemsWithIndex(bot):Map { t -> - { - inventIndex = t[1], - item = t[2], - rate = RateItem(t[2]) - } - }:OrderByDescending { t -> - if bot:GetActiveMode() == BOT_MODE_WARD and (t.item:GetName() == "item_ward_observer" or t.item:GetName() == "item_ward_dispenser") then return 10000 end - if ItemFun.InventoryOnlyItems:Contains(t.item:GetName()) { 20000 } elif ItemFun.IsNeutralItem(t) { 0 } else { t.rate } - } - items:ForEach { t, index -> - t.correctIndex = index - 1 - } - local backpackItemsInInventory = items:Filter { t -> - bot:GetItemSlotType(t.inventIndex) == ITEM_SLOT_TYPE_MAIN and bot:GetItemSlotType(t.correctIndex) == ITEM_SLOT_TYPE_BACKPACK - } - local inventoryItemsInBackpack = items:Filter { t -> - bot:GetItemSlotType(t.inventIndex) == ITEM_SLOT_TYPE_BACKPACK and bot:GetItemSlotType(t.correctIndex) == ITEM_SLOT_TYPE_MAIN - } - Linq.ForEach2(backpackItemsInInventory, inventoryItemsInBackpack) { a, b -> - -- print(bot:GetUnitName().." swap "..a.item:GetName().." at index "..a.inventIndex.." with "..b.item:GetName().." index "..b.inventIndex) - -- bot:ActionImmediate_SwapItems(a.inventIndex, b.inventIndex) - -- b.item.cooldownFromBackpack = 6 - } -end - -ItemFun.defaultAbilityFunctions = Linq.NewTable("CanAbilityBeUpgraded", "GetAbilityDamage", "GetAOERadius", "GetAutoCastState", "GetBehavior", "GetCaster", "GetCastPoint", "GetCastRange", "GetChannelledManaCostPerSecond", "GetChannelTime", "GetDuration", "GetCooldown", "GetCooldownTimeRemaining", "GetCurrentCharges", "GetDamageType", "GetEstimatedDamageToTarget", "GetHeroLevelRequiredToUpgrade", "GetInitialCharges", "GetLevel", "GetManaCost", "GetMaxLevel", "GetName", "GetSecondaryCharges", "GetSpecialValueFloat", "GetSpecialValueInt", "GetTargetFlags", "GetTargetTeam", "GetTargetType", "GetToggleState", "IsActivated", "IsAttributeBonus", "IsChanneling", "IsCooldownReady", "IsFullyCastable", "IsHidden", "IsInAbilityPhase", "IsItem", "IsNull", "IsOwnersManaEnough", "IsPassive", "IsStealable", "IsStolen", "IsTalent", "IsToggle", "IsTrained", "IsUltimate", "ProcsMagicStick", "ToggleAutoCast") -ItemFun.defaultItemExtraFunctions = Linq.NewTable("CanBeDisassembled", "IsCombineLocked", "GetPowerTreadsStat") -ItemFun.defaultItemFunctions = ItemFun.defaultAbilityFunctions:Concat(ItemFun.defaultItemExtraFunctions) - -function ItemFun.UseItemNoTarget(npc, item, cause) - if ItemFun.print then - local s = npc:GetUnitName()..": use "..item:GetName() - if cause then s = s.." because of "..cause end - print(s) - end - npc:Action_UseAbility(item) -end -function ItemFun.UseItemOnEntity(npc, item, entity, cause) - if ItemFun.print then - local s = npc:GetUnitName()..": use "..item:GetName().." on entity "..entity:GetUnitName() - if cause then - s = s.." because of "..cause - end - print(s) - end - npc:Action_UseAbilityOnEntity(item, entity) -end -function ItemFun.UseItemOnLocation(npc, item, loc, cause) - if ItemFun.print then - local s = npc:GetUnitName()..": use "..item:GetName().." on location "..fun1:ToStringVector(loc) - if cause then - s = s.." because of "..cause - end - print(s) - end - npc:Action_UseAbilityOnLocation(item, loc) -end -function ItemFun.UseItemOnTree(npc, item, tree, cause) - if ItemFun.print then - local s = npc:GetUnitName()..": use "..item:GetName().." on tree "..tostring(tree) - if cause then - s = s.." because of "..cause - end - print(s) - end - npc:Action_UseAbilityOnTree(item, tree) -end - -function ItemFun.FadeWouldMakeNoSense(t) - if t:HasModifier"modifier_item_dustofappearance" or t:HasModifier "modifier_truesight" or t:HasModifier"modifier_bounty_hunter_track" or t:HasModifier"modifier_slardar_amplify_damage" then - return true - end - return false -end - -local itemNamePrefix = "item_" -function ItemFun.GetItemShortName(t) - return string.sub(t, #itemNamePrefix+1) -end - - - - - - - - -function Hero.MustBeIllusion(target) - if target:IsIllusion() then - return true - end - if GetTeam() == target:GetTeam() then - return target:IsIllusion() - end - if target.markedAsIllusion then - return true - end - if target.markedAsRealHero then - return false - end - if not IsHeroAlive(target:GetPlayerID()) then - return true - end - return false -end -function Hero.MayNotBeIllusion(t) - return not Hero.MustBeIllusion(t) -end - -function Hero.GetUniqueHeroNumber(heroes) - if #heroes == 0 then return 0 end - return Linq.Filter(heroes, Hero.MayNotBeIllusion):GroupBy { t -> t:GetPlayerID() }:Count() -end - -function Hero.HasScepter(npc) - return npc:HasScepter() or npc:HasModifier "modifier_wisp_tether_scepter" or npc:HasModifier "modifier_item_ultimate_scepter" or npc:HasModifier "modifier_item_ultimate_scepter_consumed_alchemist" -end -function Hero.HasBoughtScepter(npc) - return npc:HasScepter() or npc:HasModifier "modifier_item_ultimate_scepter" or npc:HasModifier "modifier_item_ultimate_scepter_consumed_alchemist" -end - -function Hero.PrintMode(npc) - print("bot "..npc:GetUnitName().." in mode "..DotaExt.BotModeToString(npc:GetActiveMode())..", desire = "..npc:GetActiveModeDesire()) -end - -Hero.teleportAbilities = Linq.NewTable("furion_teleportation", "item_tpscroll") -function Hero.IsTeleporting(npc) -> if local activeAbility = npc:GetCurrentActiveAbility(); activeAbility and Hero.teleportAbilities:Contains(activeAbility:GetName()) { true } else { false } - - - - -local oldRoleUtils = require(GetScriptDirectory().."/util/RoleUtility") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - - - - - -local ItemUse = {} - -function ItemUse.GetItemInfo(bot, item) - local itemAuxTable - if bot.itemAuxTable then - itemAuxTable = bot.itemAuxTable - else - itemAuxTable = {} - bot.itemAuxTable = itemAuxTable - end - local thisItemTable - local itemKey = tostring(item) - if itemAuxTable[itemKey] then - thisItemTable = itemAuxTable[itemKey] - else - itemAuxTable[itemKey] = {} - thisItemTable = itemAuxTable[itemKey] - end - return thisItemTable -end - -local primaryAbilityHasBonus = Linq.NewTable("obsidian_destroyer", "enchantress", "silencer", "drow_ranger") - -local function GetWantedPowerTreadsAttribute(npcBot, info) - local mode = npcBot:GetActiveMode() - if mode == BOT_MODE_RETREAT and npcBot:WasRecentlyDamagedByAnyHero(3) then - return ATTRIBUTE_STRENGTH, "MoreHealthWhenRetreat" - elseif UnitFun.IsAttackingEnemies(npcBot) then - local name = UnitFun.GetHeroShortName(npcBot:GetUnitName()) - if primaryAbilityHasBonus:Contains(name) then - return npcBot:GetPrimaryAttribute(), "PrimaryWithAbilityBonus" - else - return ATTRIBUTE_AGILITY, "AgilityWhenAttacking" - end - elseif mode == BOT_MODE_LANING then - return info.primAttr, "PrimaryForLH" - elseif npcBot:WasRecentlyDamagedByAnyHero(2) then - return ATTRIBUTE_STRENGTH, "StrengthWhenAttacked" - else - return info.primAttr, "PrimaryWhenIdle" - end -end - -local function UsePowerTreads(pt, bot, info) - if bot:HasModifier "modifier_ice_blast" then - return - end - if AbilInfo.HasAnyModifier(bot, AbilInfo.invisibleModifiers) and bot:UsingItemBreaksInvisibility() then - if bot:HasModifier("modifier_item_dustofappearance") then - bot:Action_UseAbility(pt) - return "BreakInvisibility" - end - if not AbilInfo.HasAnyModifier(bot, AbilInfo.truesightModifiers) then - return - end - end - local wantedAttribute, reason = GetWantedPowerTreadsAttribute(bot, info) - print(bot:GetUnitName().." want "..DotaExt.AttributeTypeToString(wantedAttribute)..", currently "..DotaExt.AttributeTypeToString(pt:GetPowerTreadsStat())..", reason = "..reason..", mode = "..DotaExt.BotModeToString(bot:GetActiveMode())) - if wantedAttribute ~= pt:GetPowerTreadsStat() then - return reason - end -end - --- function ItemUseDefaultImpl.power_treads(item, bot, info) --- print(bot:GetUnitName().." pt attribute: "..DotaExt.AttributeTypeToString(item:GetPowerTreadsStat())) --- if bot:HasModifier "modifier_ice_blast" or math.floor(GameLoop.GetFrameNumber() % 4) ~= 0 then --- return 0 --- end --- if local reason = UsePowerTreads(item, bot, info) then --- return BOT_ACTION_DESIRE_HIGH, reason --- end --- return 0 --- end - -function ItemUseDefaultImpl.branch(item, bot, info) - -end - -local function CountInventoryItemCooldown(bot, inventoryItems) - inventoryItems:ForEach { t -> - local r = ItemUse.GetItemInfo(bot, t) - if r.cooldownFromBackpack then - r.cooldownFromBackpack -= deltaTime - if r.cooldownFromBackpack <= 0 then - r.cooldownFromBackpack = 0 - end - end - } -end - -local entityOnlyItems = Linq.NewTable( -) -local noTargetOnlyItems = Linq.NewTable( - "arcane_boots", - "phase_boots", - "power_treads" -) -local treeOnlyItems = Linq.NewTable( -) -local locationOnlyItems = Linq.NewTable( - "travel_boots", - "travel_boots_2" -) - -local function ConsiderAvailableItem(item, bot, itemUsageAuxiliaryInfo) - local name = ItemFun.GetItemShortName(item:GetName()) - local itemFunc = bot.ItemUsage and bot.ItemUsage[name] or ItemUseDefaultImpl[name] - if itemFunc == nil then - GameLoop.EveryManySeconds(5, "NotifyUnimplementedItem "..name) { -> - -- print("Item not implemented: "..name) - } - return 0 - else - local castTarget, targetType, cause - local desire, b, c, d = itemFunc(item, bot, itemUsageAuxiliaryInfo) - if noTargetOnlyItems:Contains(name) then - castTarget, targetType, cause = nil, "none", b - elif treeOnlyItems:Contains(name) then - castTarget, targetType, cause = b, "tree", c - elif locationOnlyItems:Contains(name) then - castTarget, targetType, cause = b, "location", c - elif entityOnlyItems:Contains(name) then - castTarget, targetType, cause = b, "entity", c - else - castTarget, targetType, cause = b, c, d - end - return desire, castTarget, targetType, cause - end -end - -local function UseAvailableItems(bot, inventoryItems) - local itemUsageAuxiliaryInfo = Linq.NewTable() - local info = itemUsageAuxiliaryInfo - info.hp = bot:GetHealth() - info.hpm = bot:GetMaxHealth() - info.hpp = bot:GetHealth() / bot:GetMaxHealth() - info.mn = bot:GetMana() - info.mnm = bot:GetMaxMana() - info.mnp = info.mn / info.mnm - info.lev = bot:GetLevel() - info.allEnemies1400 = DotaExt.GetNearbyHeroes(bot, 1400) - info.e1400 = info.allEnemies1400:Filter(Hero.MayNotBeIllusion) - info.ec1400 = Hero.GetUniqueHeroNumber(info.e1400) - info.allEnemies1600 = DotaExt.GetNearbyHeroes(bot, 1600) - info.e1600 = info.allEnemies1600:Filter(Hero.MayNotBeIllusion) - info.ec1600 = Hero.GetUniqueHeroNumber(info.e1600) - info.allEnemies1200 = DotaExt.GetNearbyHeroes(bot, 1200) - info.e1200 = info.allEnemies1200:Filter(Hero.MayNotBeIllusion) - info.ec1200 = Hero.GetUniqueHeroNumber(info.e1200) - info.allEnemies900 = DotaExt.GetNearbyHeroes(bot, 900) - info.e900 = info.allEnemies900:Filter(Hero.MayNotBeIllusion) - info.ec900 = Hero.GetUniqueHeroNumber(info.e900) - info.allEnemies650 = DotaExt.GetNearbyHeroes(bot, 650) - info.e650 = info.allEnemies650:Filter(Hero.MayNotBeIllusion) - info.ec650 = Hero.GetUniqueHeroNumber(info.e650) - info.allAllies = DotaExt.GetNearbyHeroes(bot, 1500) - info.allies = info.allAllies:Filter(Hero.MayNotBeIllusion) - info.allyCount = Hero.GetUniqueHeroNumber(info.allies) - info.nw = bot:GetNetWorth() - info.bp = fun1:GetBattlePower(bot) - info.primAttr = bot:GetPrimaryAttribute() - info.blasted = bot:HasModifier "modifier_ice_blast" - info.target = bot:GetTarget() - - - local highDesireItem = inventoryItems:Map { t -> - local pack = { ConsiderAvailableItem(t, bot, itemUsageAuxiliaryInfo) } - pack[5] = t - return pack - }:Filter { t -> t[1] > 0 } - :MaxKey { t -> t[1] } - if local t = highDesireItem then - if t[3] == "none" then - if t[5]:GetName() == "item_power_treads" then - print(bot:GetUnitName().." use power treads") - end - ItemFun.UseItemNoTarget(bot, t[5], t[4]) - elseif t[3] == "location" then - ItemFun.UseItemOnLocation(bot, t[5], t[2], t[4]) - elseif t[3] == "tree" then - ItemFun.UseItemOnTree(bot, t[5], t[2], t[4]) - else - ItemFun.UseItemOnEntity(bot, t[5], t[2], t[4]) - end - end -end - -function ItemUse.CanUseAnyItem(t) - return not (fun1:IsMuted(t) or fun1:IsHypnosed(t) or fun1:IsFeared(t) or t:IsHexed() or t:IsChanneling()) -end - -function ItemUse.ItemUsageThink() - local bot = GetBot() - if not UnitFun.CanUseItem(bot) then - return - end - GameLoop.EveryManySeconds(3, "SwapUsefulItems "..bot:GetUnitName()) { -> - ItemFun.SwapUsefulOnes(bot) - } - local inventoryItems = ItemFun.GetInventoryItems(bot) - CountInventoryItemCooldown(bot, inventoryItems) - if ItemUse.CanUseAnyItem(bot) then - UseAvailableItems(bot, inventoryItems:Filter { t -> - t:IsFullyCastable() and (not bot:IsIllusion() or bot:HasModifier "modifier_skeleton_king_reincarnation_active" or bot:HasModifier "modifier_vengefulspirit_hybrid_special" or bot:HasModifier "modifier_arc_warden_tempest_double") - and ItemUse.GetItemInfo(bot, t).cooldownFromBackpack == nil - }) - end -end - - - - -local Role = {} -function Role.GetRoleValue(npc, role) - return oldRoleUtils.hero_roles[npc:GetUnitName()][role] -end -function Role.Push(npc) - return Role.GetRoleValue(npc, "pusher") -end - - - - -function Math.PointToPointDistance(a, b) - local x = a.x-b.x - local y = a.y-b.y - return (x*x+y*y)^0.5 -end - - - - - - -local Push_impl = {} -function Push_impl.GetCarryRate(hero) - return oldRoleUtils.hero_roles[hero:GetUnitName()].carry -end - -function Push_impl.GetLane( nTeam ,hHero ) - local vBot = GetLaneFrontLocation(nTeam, LANE_BOT, 0) - local vTop = GetLaneFrontLocation(nTeam, LANE_TOP, 0) - local vMid = GetLaneFrontLocation(nTeam, LANE_MID, 0) - return if GetUnitToLocationDistance(hHero, vBot) < 2500 { LANE_BOT } - elif GetUnitToLocationDistance(hHero, vTop) < 2500 { LANE_TOP } - elif GetUnitToLocationDistance(hHero, vMid) < 2500 { LANE_MID } - else { LANE_NONE } -end - -function Push_impl.CreepRate(creep) - local rate = 1 - rate *= if string.match(t, "upgraded_mega") {3.5} - elif string.match(t, "upgraded") {2} - else {1} - rate *= if string.match(t, "melee") {1} - elif string.match(t, "ranged") {1.2} - else {1.8} - return rate -end - -function Push_impl.CreepReward(creep) - local rate = 1 - rate *= if string.match(t, "upgraded_mega") {0.25} - elif string.match(t, "upgraded") {0.5} - else {1} - rate *= if string.match(t, "melee") {1} - elif string.match(t, "ranged") {1.7} - else {2} - return rate -end - -function Push_impl.GetAllyTower(towerIndex) - return GetTower(GetTeam(), towerIndex) -end -local allyTower1 = fun1:Map({TOWER_TOP_1, TOWER_MID_1, TOWER_BOT_1}, Push_impl.GetAllyTower) -local allyTower2 = fun1:Map({TOWER_TOP_2, TOWER_MID_2, TOWER_BOT_2}, Push_impl.GetAllyTower) -local allyTower3 = fun1:Map({TOWER_TOP_3, TOWER_MID_3, TOWER_BOT_3}, Push_impl.GetAllyTower) -local allyTower4 = fun1:Map({TOWER_BASE_1, TOWER_BASE_2}, Push_impl.GetAllyTower) - -function Push_impl.TowerRate(tower) - return if allyTower1:Contains(tower) { 1 } - elif allyTower2:Contains(tower) { 1.5 } - elif allyTower3:Contains(tower) { - if allyTower3:All { t -> t:IsAlive() } { 2 } else { 1.5 } - } - else { 1.7 } -end - -function Push_impl.CleanLaneDesire(npc, lane) - local front = GetLaneFrontLocation(GetTeam(), lane, 0) - local allyTower = GetNearestBuilding(GetTeam(), front) - local distanceToFront = GetUnitToUnitDistance(npc, allyTower:GetLocation()) - local creeps = fun1:Filter(GetUnitList(UNIT_LIST_ENEMY_CREEPS)) { t -> - GetUnitToLocationDistance(t, front) <= 1500 - } - local allyCreeps = fun1:Filter(GetUnitList(UNIT_LIST_FRIEND_CREEPS)) { t -> - GetUnitToLocationDistance(t, front) <= 1500 - } - local creepRateDiff = fun1:Aggregate(0, creeps:Map(Push_impl.CreepRate), { + }) - fun1:Aggregate(0, allyCreeps:Map(Push_impl.CreepRate), { + }) - local desire = 0 - local necessity = 0 - if distanceToFront <= 3000 then - if creepRateDiff >= DotaTime()/300 and creepRateDiff >= 3 then - necessity += creepRateDiff - end - if creepRateDiff >= 2 and creepRateDiff then - desire += fun1:Aggregate(0, creeps:Map(Push_impl.CreepReward), { + }) - end - end - necessity *= TowerRate(allyTower) - desire *= TowerRate(allyTower) - return desire, necessity -end - -function Push_impl.DefendLaneDesire() - return 0 -end - -function Push_impl.PushLaneDesire(npc, lane) - local team = GetTeam() - local teamPush = TeamPushLaneDesire(lane) - - local levelFactor = if npc:GetLevel() < 6 { 0 } else { 0.2 } - local myLane = GetLane(team, npc) - if myLane ~= LANE_NONE then - if Push_impl.CleanLaneDesire(myLane) > Push_impl.CleanLaneDesire(lane) then - return 0 - end - end - local healthRate = npcBot:GetHealth() / npcBot:GetMaxHealth() + fun1:GetLifeSteal(npc) * 2 - if healthRate > 1 then healthRate = 0 end - local manaRate = npcBot:GetMana() / npcBot:GetMaxMana() - local stateFactor = healthRate * 0.7 + manaRate * 0.3 - if stateFactor < 0.6 then - return 0 - end - - local roleFactor = if Role.Push(npc) { Role.Push(npc) * 0.2 } - elif Role.Support(npc) { Role.Support(npc) * 0.1 } - else { 0 } - local laneFront = GetLaneFrontLocation(team, lane, 0) - local distanceToFront = GetUnitToUnitDistance(npc, laneFront) - local nearestBuilding = Push_impl.GetNearestBuilding(team, laneFront) - local ddis = GetUnitToUnitDistance(nearestBuilding, laneFront) - - local tp = ItemFun.GetAvailableTp(npc) - local canCastTp = ItemFun.CanUseAvailableTp(npc, tp) - local distanceFactor = if distanceToFront <= 1000 or canCastTp { 1 } - elif distanceToFront - ddis >= 3000 and canCastTp { - if ddis <= 1000 { 0.7 } - elif ddis >= 6000 { 0 } - else { -(ddis-6000)*0.7/5000 } - } - elif distanceToFront >= 10000 { 0 } - else { -(distanceToFront-10000) / 9000 } - local factor = 0.2 + levelFactor + roleFactor + 0.4 * distanceFactor + 0.2 * stateFactor - if stateFactor < 1.2 then - factor *= RemapVal(stateFactor, 0.6, 1.2, 0, 0.7) - end - return Clamp(factor, 0, 0.8) -end - -function Push_impl.NoCreepsOnLane(npc, lane) - local team = GetTeam() - local laneFront = GetLaneFrontLocation(team, lane, 0) - local allyTower = Push_impl.GetNearestBuilding(team, laneFront) - local enemyTower = Push_impl.GetNearestBuilding(GetOpposingTeam(), laneFront) - local enemySpawnLocation = Push_impl.GetEnemySpawnLocation() - local maxDiveDistance = 400 - local towerToEnemyHomeDistance = GetUnitToLocationDistance(enemyTower, enemySpawnLocation) - return towerToEnemyHomeDistance < GetUnitToUnitDistance(enemyTower, allyTower) and Math.PointToPointDistance(laneFront, enemySpawnLocation) < towerToEnemyHomeDistance - maxDiveDistance -end - -function Push_impl.GetAttackBuildingLocation(npc, lane) - local team = GetTeam() - local laneFront = GetLaneFrontLocation(team, lane, 0) - local allyTower = Push_impl.GetNearestBuilding(team, laneFront) - local enemyTower = Push_impl.GetNearestBuilding(GetOpposingTeam(), laneFront) - local enemySpawnLocation = Push_impl.GetEnemySpawnLocation() - local maxDiveDistance = 400 - local towerToEnemyHomeDistance = GetUnitToLocationDistance(enemyTower, enemySpawnLocation) - local distanceToTower = GetUnitToUnitDistance(npc, enemyTower) - - if distanceToTower < 1000 then - return Push_impl.GetSafeLocation(npc, enemyTower) - else - if Math.PointToPointDistance(laneFront, enemySpawnLocation) < towerToEnemyHomeDistance - maxDiveDistance and npc:GetLevel() <= 11 then - return Push_impl.GetSafeLocation(npc, allyTower) - else - return Push_impl.GetSafeLocation(npc, enemyTower) - end - end -end - -function Push_impl.CreepAttackingTower(creeps, tower) - return Linq.Any(creeps) { t -> - t:GetAttackTarget() == tower - } -end - -function Push_impl.IsSafeToAttack(npc, lane, creeps) - local team = GetTeam() - local laneFront = GetLaneFrontLocation(team, lane, 0) - local allyTower = Push_impl.GetNearestBuilding(team, laneFront) - local enemyTower = Push_impl.GetNearestBuilding(GetOpposingTeam(), laneFront) - local enemySpawnLocation = Push_impl.GetEnemySpawnLocation() - local maxDiveDistance = 400 - local distanceToEnemyHome = GetUnitToLocationDistance(npc, enemySpawnLocation) - local towerToEnemyHomeDistance = GetUnitToLocationDistance(enemyTower, enemySpawnLocation) - local distanceToTower = GetUnitToUnitDistance(npc, enemyTower) - - local safe = distanceToTower > 1500 or GetUnitToUnitDistanceSqr(npc, allyTower) <= 490000 - local creepMinDistance = creeps:Min { t -> - GetUnitToUnitDistanceSqr(t, enemyTower) - } - if creepMinDistance and (distanceToTower < creepMinDistance or distanceToEnemyHome < towerToEnemyHomeDistance - maxDiveDistance) then - safe = true - end - if enemyTower:GetAttackDamage() < 20 then - safe = true - end - return safe -end - -function Push_impl.TryTp(npc, lane) - local team = GetTeam() - local laneFront = GetLaneFrontLocation(team, lane, 0) - local distanceToFront = GetUnitToLocationDistance(npc, laneFront) - local nearestBuilding = Push_impl.GetNearestBuilding(team, laneFront) - local distanceToNearestBuilding = GetUnitToLocationDistance(nearestBuilding, laneFront) - local amount = Push_impl.GetAmountAlongLane(lane, npc:GetLocation()) - - local tp = Push_impl.GetAvailableTp(npc) - if distanceToFront > 3000 and distanceToFront - distanceToNearestBuilding > 3000 then - npc.Push_impl_TryTp = GameLoop.StartCoroutine { -> Push_impl.UseAvailableTp(npc, tp) } - end -end - -function Push_impl.GetCreepsNearTower(npc, tower) - return DotaExt.GetNearbyCreeps(npc, 1400, false):Filter { t -> - GetUnitToLocationDistanceSqr(t, tower) < 640000 - } -end - -function Push.UnitPushLaneThink(npc, lane) - if (npc:IsChanneling() or npc:IsUsingAbility() or npc:GetQueuedActionType(0) == BOT_ACTION_TYPE_USE_ABILITY) then - return - end - - if npc.Push_impl_TryTp then - if coroutine.status(npc.Push_impl_TryTp) == "dead" then - npc.Push_impl_TryTp = nil - else - return - end - else - Push_impl.TryTp(npc, lane) - end - local team = GetTeam() - local laneFront = GetLaneFrontLocation(team, lane, 0) - local allyTower = Push_impl.GetNearestBuilding(team, laneFront) - local enemyTower = Push_impl.GetNearestBuilding(GetOpposingTeam(), laneFront) - local enemySpawnLocation = Push_impl.GetEnemySpawnLocation() - local distanceToFront = GetUnitToLocationDistance(npc, laneFront) - local nearestBuilding = Push_impl.GetNearestBuilding(team, laneFront) - local distanceToNearestBuilding = GetUnitToLocationDistance(nearestBuilding, laneFront) - local creeps = Push_impl.GetCreepsNearTower(npc, enemyTower) - local targetLocation = Push_impl.GetTargetLocation(npc, lane) - local buildingAttackedByTower = Push_impl.CreepAttackingTower(creeps, enemyTower) - local isSafeToAttack = Push_impl.IsSafeToAttack(npc, lane, creeps) - local noCreeps = Push_impl.NoCreepsOnLane(npc, lane) - - local enemies = DotaExt.GetNearbyHeroes(npc, 1200) - local target = Push_impl.GetMyTarget(npc, lane, targetLocation) - if target then - targetLocation = Push_impl.GetSafeLocation(npc, target) - end - - local goodSituation = true - if (npc:GetLevel() >= 12 or npc:GetLevel() >= DotaTime() / 120) and npc:GetHealth() >= 700 and #enemeis == 0 then - goodSituation = true - end - if (not isSafeToAttack or noCreeps) and (fun1:GetHealthPercent(enemyTower) >= 0.2 and enemyTower:GetAttackDamage() > 20) then - goodSituation = false - end - - if Push_impl.TooManyEnemies() then - Push_impl.AssembleWithAlly(npc) - elseif not goodSituation then - Push_impl.StepBack(npc) - end -end - - - - - - - -M.Linq = Linq -M.Debug = Debug -M.Dota = DotaExt -M.Unit = UnitFun -M.Game = GameLoop -M.Item = ItemFun -M.ItemUse = ItemUse -M.Hero = Hero -M.Building = Building - -return M \ No newline at end of file diff --git a/util/PushUtility2.lua b/util/PushUtility2.lua index 652a5b6..a7e5017 100644 --- a/util/PushUtility2.lua +++ b/util/PushUtility2.lua @@ -1,8 +1,3 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local role = require(GetScriptDirectory() .. "/util/RoleUtility") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") local function GetCarryRate(hero) diff --git a/util/PushUtility2.mira b/util/PushUtility2.mira deleted file mode 100644 index 568df7b..0000000 --- a/util/PushUtility2.mira +++ /dev/null @@ -1,87 +0,0 @@ - -local role = require(GetScriptDirectory() .. "/util/RoleUtility") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") - -local function GetCarryRate(hero) - return role.hero_roles[hero:GetUnitName()].carry -end - -local function GetLane( nTeam ,hHero ) - local vBot = GetLaneFrontLocation(nTeam, LANE_BOT, 0) - local vTop = GetLaneFrontLocation(nTeam, LANE_TOP, 0) - local vMid = GetLaneFrontLocation(nTeam, LANE_MID, 0) - return if GetUnitToLocationDistance(hHero, vBot) < 2500 { LANE_BOT } - elif GetUnitToLocationDistance(hHero, vTop) < 2500 { LANE_TOP } - elif GetUnitToLocationDistance(hHero, vMid) < 2500 { LANE_MID } - else { LANE_NONE } -end - -local function CreepRate(creep) - local rate = 1 - rate *= if string.match(t, "upgraded_mega") {3.5} - elif string.match(t, "upgraded") {2} - else {1} - rate *= if string.match(t, "melee") {1} - elif string.match(t, "ranged") {1.2} - else {1.8} - return rate -end - -local function CreepReward(creep) - local rate = 1 - rate *= if string.match(t, "upgraded_mega") {0.25} - elif string.match(t, "upgraded") {0.5} - else {1} - rate *= if string.match(t, "melee") {1} - elif string.match(t, "ranged") {1.7} - else {2} - return rate -end - -local function GetAllyTower(towerIndex) - return GetTower(GetTeam(), towerIndex) -end -local allyTower1 = fun1:Map({TOWER_TOP_1, TOWER_MID_1, TOWER_BOT_1}, GetAllyTower) -local allyTower2 = fun1:Map({TOWER_TOP_2, TOWER_MID_2, TOWER_BOT_2}, GetAllyTower) -local allyTower3 = fun1:Map({TOWER_TOP_3, TOWER_MID_3, TOWER_BOT_3}, GetAllyTower) -local allyTower4 = fun1:Map({TOWER_BASE_1, TOWER_BASE_2}, GetAllyTower) - -local function TowerRate(tower) - return if allyTower1:Contains(tower) { 1 } - elif allyTower2:Contains(tower) { 1.5 } - elif allyTower3:Contains(tower) { - if allyTower3:All { t -> t:IsAlive() } { 2 } else { 1.5 } - } - else { 1.7 } -end - -local function CleanLaneDesire(npc, lane) - local front = GetLaneFrontLocation(GetTeam(), lane, 0) - local allyTower = GetNearestBuilding(GetTeam(), front) - local distanceToFront = GetUnitToUnitDistance(npc, allyTower:GetLocation()) - local creeps = fun1:Filter(GetUnitList(UNIT_LIST_ENEMY_CREEPS)) { t -> - GetUnitToLocationDistance(t, front) <= 1500 - } - local allyCreeps = fun1:Filter(GetUnitList(UNIT_LIST_FRIEND_CREEPS)) { t -> - GetUnitToLocationDistance(t, front) <= 1500 - } - local creepRateDiff = fun1:Aggregate(0, creeps:Map(CreepRate), { + }) - fun1:Aggregate(0, allyCreeps:Map(CreepRate), { + }) - local desire = 0 - local necessity = 0 - if distanceToFront <= 3000 then - if creepRateDiff >= DotaTime()/300 and creepRateDiff >= 3 then - necessity += creepRateDiff - end - if creepRateDiff >= 2 and creepRateDiff then - desire += fun1:Aggregate(0, creeps:Map(CreepReward), { + }) - end - end - necessity *= TowerRate(allyTower) - desire *= TowerRate(allyTower) - return desire -end - -local function DefendLaneDesire() - return 0 -end - diff --git a/util/TeamItemThink.lua b/util/TeamItemThink.lua index 307bc80..963dfb3 100644 --- a/util/TeamItemThink.lua +++ b/util/TeamItemThink.lua @@ -1,8 +1,3 @@ ---------------------------------------------- --- Generated from Mirana Compiler version 1.6.2 --- Do not modify --- https://github.com/AaronSong321/Mirana ---------------------------------------------- local M = {} local ItemUsage = require(GetScriptDirectory() .. "/util/ItemUsage-New") local fun1 = require(GetScriptDirectory() .. "/util/AbilityAbstraction") @@ -712,6 +707,7 @@ local function AddArcaneBoots() if bootsToReplaceIndex ~= -1 then local bootsToReplaceName = hero.itemInformationTable[bootsToReplaceIndex].name if bootsToReplaceName == "item_arcane_boots" then + -- do nothing else local arcaneBoots = M.ExpandTeamThinkItem "item_arcane_boots" RemoveItemsInNewItemTable(hero.itemInformationTable, arcaneBoots, bootsToReplaceIndex) diff --git a/util/TeamItemThink.mira b/util/TeamItemThink.mira deleted file mode 100644 index 9305a13..0000000 --- a/util/TeamItemThink.mira +++ /dev/null @@ -1,556 +0,0 @@ - -local M = {} -local ItemUsage = require(GetScriptDirectory().."/util/ItemUsage-New") -local fun1 = require(GetScriptDirectory().."/util/AbilityAbstraction") -local A = require(GetScriptDirectory().."/util/MiraDota") - -M.ImplmentedTeamItems = { - "item_mekansm", - "item_guardian_greaves", -} - -local roles = { - abaddon = {9,6,}, - abyssal_underlord = {4,7,}, - alchemist={0,1,}, - ancient_apparition={2,9,}, - antimage={1,0,}, - arc_warden={0,2,}, - axe={2,2,}, - bane={3,7,}, - batrider={4,6,}, - beastmaster={0,2,}, - bloodseeker={1,1,}, - bounty_hunter={3,5,}, - brewmaster={0,1,}, - bristleback={4,7,}, - broodmother={5,1,}, - centaur={3,3,}, - chaos_knight={2,2,}, - chen={9,8,}, - clinkz={1,1,}, - crystal_maiden={8,3,}, - dark_seer={7,7,}, - dazzle={9,5,}, - death_prophet={5,6,}, - disruptor={6,3,}, - doom_bringer={1,2,}, - dragon_knight={0,1,}, - drow_ranger={0,0,}, - earth_spirit={6,5,}, - earthshaker={5,6,}, - ember_spirit={2,2,}, - enchantress={3,4,}, - enigma={8,6,}, - faceless_void={1,0,}, - furion={5,0,}, - gyrocopter={4,2,}, - hoodwink={5,4,}, - huskar={1,0,}, - jakiro={7,5,}, - juggernaut={0,0,}, - keeper_of_the_light={4,0,}, - kunkka={1,2,}, - legion_commander={1,0,}, - leshrac={4,6,}, - lich={5,8,}, - life_stealer={2,0,}, - lina={5,6,}, - lion={5,3,}, - luna={1,1,}, - lycan={4,0,}, - magnataur={0,5,}, - medusa={0,3,}, - mirana={1,5,}, - monkey_king={0,0,}, - naga_siren={3,2,}, - necrolyte={7,8,}, - nevermore={3,2,}, - night_stalker={2,0,}, - nyx_assassin={5,7,}, - obsidian_destroyer={4,0,}, - ogre_magi={4,7,}, - omniknight={8,7,}, - oracle={8,8,}, - phantom_assassin={1,0,}, - phantom_lancer={1,1,}, - pugna={5,8,}, - puck={4,5,}, - pudge={1,4,}, - queenofpain={3,3,}, - rattletrap={4,2,}, - razor={6,0,}, - riki={3,0,}, - sand_king={5,7,}, - shadow_demon={6,6,}, - shadow_shaman={8,8,}, - shredder={3,9,}, - silencer={6,3,}, - skeleton_king={1,0,}, - skywrath_mage={4,9,}, - slardar={2,1,}, - slark={1,0,}, - sniper={0,0,}, - spectre={4,0,}, - spirit_breaker={3,1,}, - sven={1,2,}, - templar_assassin={1,0,}, - terrorblade={1,0,}, - tidehunter={7,7,}, - tinker={0,5,}, - tiny={2,4,}, - treant={7,7,}, - troll_warlord={0,0,}, - tusk={4,2,}, - undying={6,8,}, - ursa={0,0,}, - vengefulspirit={5,6,}, - venomancer={7,5,}, - viper={6,1,}, - warlock={7,8,}, - weaver={2,1,}, - windrunner={4,6,}, - winter_wyvern={7,5,}, - witch_doctor={6,5,}, - zuus={3,9,}, -} - -local function heroItemMetaFunc(tb, key) -> - if key == "mekansm" { tb[1] } - elif key == "arcaneBoots" { tb[2] } - else { 0 } - -local heroItemMetatable = { - __index = heroItemMetaFunc -} -fun1:ForEachDic(roles) { it -> - setmetatable(it, heroItemMetatable) -} -local zeroTable = {} -setmetatable(zeroTable, { - __index = { _ -> 0 } -}) -setmetatable(roles, { - __index = { _, heroName -> - print(heroName.." doesn't have a table") - zeroTable - } -}) - -local humanPlayers -local dustBuyers -local defaultDustBuyerNumber = 2 -local teamMembers = {} -local gemPlayers -local nonDefaultGemPlayers -local enemyStates = fun1:NewTable() - -local finishInit - -local runned -local function TeamItemInit() - if finishInit then - return - end - finishInit = true - fun1:Range(1, 5):ForEach { t -> - enemyStates[t] = {} - } - humanPlayers = fun1:Range(1, 5):Filter { it -> - not GetTeamMember(it):IsBot() - } - dustBuyers = fun1:SortByMaxFirst(teamMembers) { -> math.random() } - dustBuyers = if #dustBuyers >= defaultDustBuyerNumber { dustBuyers:Take(defaultDustBuyerNumber) } else { dustBuyers } -end - - -local function IsLeaf(item) -> next(GetItemComponents(item)) == nil -local function NextNodes(item) -> GetItemComponents(item)[1] - -function M.ExpandFirstLevel(item) -> - if IsLeaf(item) { { name = item, isSingleItem = true } } - else { { name = item, recipe = NextNodes(item) } } - -function M.ExpandOnce(item) - local g = {} - local expandSomething = false - for _,v in ipairs(item.recipe) do - if IsLeaf(v) then - table.insert(g, v) - else - expandSomething = true - for _, i in ipairs(NextNodes(v)) do - table.insert(g, i) - end - end - end - item.recipe = g - return expandSomething -end -function M.FullyExpandItem(itemName) - local p = M.ExpandFirstLevel(itemName) - while M.ExpandOnce(p) do end - return p -end -function M.ExpandTeamThinkItem(itemName) - local p = M.FullyExpandItem(itemName) - p.origin = "TeamItemThink" - return p -end - -local function AddBefore(tb, item, before) - for index, v in ipairs(tb) do - if before(v) then - table.insert(tb, index, item) - return - end - end - table.insert(tb, #tb + 1, item) -end - -local function GeneratePutBeforeFilter(maxCost, putBefore, putAfter) -> { itemInfo -> - local itemName = itemInfo.name - local shortName = string.sub(itemName, 6) - if fun1:Contains(putAfter, shortName) { false } - else { fun1:Contains(putBefore, shortName) or GetItemCost(itemName) > maxCost } - } - -local teamItemEvents = fun1:NewTable() -local function NotifyTeam(npcBot, itemName) - fun1:StartCoroutine { -> - fun1:WaitForSeconds(math.random(20, 28)) - table.insert(teamItemEvents, { npcBot, "I'll buy "..itemName, false }) - } -end - -local function TeamItemEventThink() - local index = 1 - while index <= #teamItemEvents do - local b = teamItemEvents[index] - if b[1] == GetBot() then - b[1]:ActionImmediate_Chat(b[2], b[3]) - table.remove(teamItemEvents, index) - else - ++index - end - end -end - -local function PrintItemInfoTableOf(npcBot) - local tb = npcBot.itemInformationTable - print(npcBot:GetUnitName().." items to buy: ") - A.Linq.ForEach(tb) { t, index -> - if t.isSingleItem then print(index..": "..t.name) - else - local s = "" - A.Linq.ForEach(t.recipe) { t1, t1Index -> - s = s..t1 - if t1Index ~= #t.recipe then - s = s..", " - end - } - print(index..": "..t.name.." { "..s.." }") - end - } -end - -local function AddMekansm() - local AddMekansmBefore = GeneratePutBeforeFilter(2000, { "glimmer_cape", "ghost" }, { "travel_boots", "hand_of_midas", "bfury" }) - local function Rate(hero) - local heroName = fun1:GetHeroShortName(hero:GetUnitName()) - local rate = roles[heroName].mekansm + math.random() * 1.5 - if hero:GetPrimaryAttribute() == ATTRIBUTE_INTELLECT and rate <= 7 then - rate += 1 - end - return rate - end - local heroRates = fun1:Map(teamMembers) { it -> - { it, Rate(it) } - }:SortByMaxFirst { it -> it[2] } - - local function BuyMekansm(hero) - NotifyTeam(hero, "mekansm") - AddBefore(hero.itemInformationTable, M.ExpandTeamThinkItem "item_mekansm", AddMekansmBefore) - local guardianGreavesTable = M.ExpandFirstLevel "item_guardian_greaves" - fun1:Remove_Modify(guardianGreavesTable.recipe, "item_mekansm") - if local arcaneBoots = fun1:First(hero.itemInformationTable) { t -> - t.name == "item_arcane_boots" - } then - arcaneBoots.usedAsRecipeOf = guardianGreavesTable - fun1:Remove_Modify(guardianGreavesTable) { t -> - t.name == "item_boots" or t.name == "item_energy_booster" - } - end - while M.ExpandOnce(guardianGreavesTable) do end - AddBefore(hero.itemInformationTable, guardianGreavesTable, GeneratePutBeforeFilter(4800, {}, {})) - hero.itemInformationTable:Remove_Modify { t -> t.name == "item_urn_of_shadows" } - hero.itemInformationTable:Remove_Modify { t -> t.name == "item_spirit_vessel" } - -- PrintItemInfoTableOf(hero) - end - - if #heroRates >= 3 then - if heroRates[1][2] > 2.85 then - local hero = heroRates[1][1] - BuyMekansm(hero) - end - elseif #heroRates == 2 then - hero = heroRates[1] - if hero[2] >= 5 then - BuyMekansm(hero[1]) - end - elseif #heroRate == 1 then - if heroRates[1][2] >= 7.5 then - BuyMekansm(heroRates[1][1]) - end - end -end - -local function AddArcaneBoots() - local AddArcaneBootsBefore = GeneratePutBeforeFilter(1200, { }, { }) - local function Rate(hero) - local heroName = fun1:GetHeroShortName(hero:GetUnitName()) - local rate = roles[heroName].arcaneBoots + math.random() * 1.5 - return rate - end - local heroRates = fun1:Map(teamMembers) { it -> - { it, Rate(it) } - }:SortByMaxFirst { it -> it[2] } - - local function IsUpgradedBoots(itemTable) - return A.Item.IsBoots(itemTable.name) and itemTable.name ~= "item_boots" and not string.match(itemTable.name, "item_travel_boots") - end - - local function RemoveItemsInNewItemTable(informationTable, newItemTable, newItemIndex) - informationTable[newItemIndex] = newItemTable - local function ShouldRemove(itemTable) - return A.Linq.Contains(newItemTable.recipe, itemTable.name) - end - informationTable:Take(newItemIndex-1) - :Filter(ShouldRemove) - :ForEach { t -> - t.usedAsRecipeOf = newItemTable - A.Linq.Remove_Modify(newItemTable.recipe, t.name) - } - end - - local function BuyArcaneBoots(hero) - NotifyTeam(hero, "arcane boots") - local bootsToReplaceIndex = A.Linq.IndexOf(hero.itemInformationTable, IsUpgradedBoots) - if bootsToReplaceIndex ~= -1 then - local bootsToReplaceName = hero.itemInformationTable[bootsToReplaceIndex].name - if bootsToReplaceName == "item_arcane_boots" then - -- do nothing - else - local arcaneBoots = M.ExpandTeamThinkItem "item_arcane_boots" - RemoveItemsInNewItemTable(hero.itemInformationTable, arcaneBoots, bootsToReplaceIndex) - end - else - AddBefore(hero.itemInformationTable, M.ExpandTeamThinkItem "item_arcane_boots", AddArcaneBootsBefore) - end - -- PrintItemInfoTableOf(hero) - end - - local function DontBuyArcaneBoots(heroRateTable) - local hero = heroRateTable[1] - local arcaneBootsIndex = A.Linq.IndexOf(hero.itemInformationTable) { t -> t.name == "item_arcane_boots" } - if arcaneBootsIndex ~= -1 and not hero.itemInformationTable[arcaneBootsIndex].usedAsRecipeOf then - local rd = math.random() - local replaceBoots = if rd <= 0.666667 { "item_power_treads" } - else { "item_phase_boots" } - if heroRateTable[2] >= 6.65 and rd <= 0.22 then - replaceBoots = "item_tranquil_boots" - end - NotifyTeam(hero, replaceBoots) - local newBoots = M.ExpandTeamThinkItem(replaceBoots) - RemoveItemsInNewItemTable(hero.itemInformationTable, newBoots, arcaneBootsIndex) - end - -- PrintItemInfoTableOf(hero) - end - - local teamArcaneBootsNumber = - if #heroRates >= 4 { 2 } - elif #heroRates >= 2 { 1 } - else { 0 } - local buyArcaneBootsHeroIndex = 0 - if teamArcaneBootsNumber >= 1 then - local hero = heroRates[1][1] - BuyArcaneBoots(hero) - ++buyArcaneBootsHeroIndex - end - teamArcaneBootsNumber -= 1 - local function HighDesireOfBuyingArcaneBoots(heroRateTable) -> heroRateTable[2] >= 7.55 - if teamArcaneBootsNumber >= 1 then - heroRates:Skip(buyArcaneBootsHeroIndex) - :Take(teamArcaneBootsNumber) - :Filter(HighDesireOfBuyingArcaneBoots) - :Map { t -> t[1] } - :ForEach { t -> - BuyArcaneBoots(t) - ++buyArcaneBootsHeroIndex - } - end - heroRates:Skip(buyArcaneBootsHeroIndex) - :FilterNot(HighDesireOfBuyingArcaneBoots) - :ForEach(DontBuyArcaneBoots) -end - -local function IdToEnemyStateTableIndex(id) -> if id <= 4 { id + 1 } else { id - 4 } - -local RefreshEnemyRespawnTime = fun1:EveryManySeconds(1) { -> - fun1:GroupBy(GetUnitList(UNIT_LIST_ENEMY_HEROES), { t -> t:GetPlayerID() }, { t -> t }, { k, v -> { k, v } }) - :Map { t -> - { - t[1], - t[2]:Max { g -> - g:GetRespawnTime() - }:GetRespawnTime() - } - } - :ForEach { t -> - local index = IdToEnemyStateTableIndex(t[1]) - enemyStates[index].respawnTime = t[2] - } -} - -function M.GetEnemyRespawnTime(id) - -> if id { - enemyStates[IdToEnemyStateTableIndex(id)].respawnTime or 0 - } else { - enemyStates:Map { t -> t.respawnTime } - } - -function M.EnemyReadyToFight(id) - -> if id { - (enemyStates[IdToEnemyStateTableIndex(id)].respawnTime or 0) <= 8 - } else { - enemyStates:Count { _, id -> M.EnemyReadyToFight(id) } - } - -local function TeamStateThink() - if not finishInit then - return - end - RefreshEnemyRespawnTime() -end - -local function GetOtherTeam() - if GetTeam() == TEAM_RADIANT then - return TEAM_DIRE - else - return TEAM_RADIANT - end -end - -local npcBot -local hasInvisibleEnemy -local function CheckInvisibleEnemy() - return fun1:Any(GetTeamPlayers(GetOtherTeam()) or {}) { t -> - local heroName = fun1:GetHeroShortName(GetSelectedHeroName(t)) - return fun1.invisibilityHeroes[heroName] and fun1.invisibilityHeroes[heroName] == 1 - } or - fun1:GetUnitList(UNIT_LIST_ENEMY_HEROES):Filter { t -> - fun1:MayNotBeIllusion(npcBot, t) - }:Any { t -> fun1:HasInvisibility(t) } -end - -local RefreshInvisibleEnemies_One = fun1:EveryManySeconds(2) { -> - gemPlayers = fun1:Range(1, 5):Map { t -> GetTeamMember(t) }:Filter { t -> - fun1:GetAvailableItem(t, "item_gem") - } - nonDefaultGemPlayers = gemPlayers:Filter { t -> not dustBuyers:Contains(t) } - hasInvisibleEnemy = CheckInvisibleEnemy() -} -local RefreshInvisibleEnemies = fun1:SingleForTeam { -> - RefreshInvisibleEnemies_One() -} - - -local BuyDustIfInvisibleEnemies = fun1:EveryManySeconds(2) { -> - RefreshInvisibleEnemies() - if dustBuyers:Take(defaultDustBuyerNumber - #nonDefaultGemPlayers):Contains(npcBot) and hasInvisibleEnemy then - local items = fun1:GetAllBoughtItems(npcBot):Map { t -> t:GetName() } - if not items:Contains("item_gem") and not items:Contains("item_dust") then - if npcBot:GetGold() >= GetItemCost("item_dust") then - npcBot:ActionImmediate_PurchaseItem("item_dust") - if DotaTime() >= 8 * 60 and npcBot:GetGold() >= GetItemCost("item_dust") * 2 then - npcBot:ActionImmediate_PurchaseItem("item_dust") - end - npcBot:ActionImmediate_Chat("Buying dusts", false) - end - end - end -} - -M.CheckInvisibleEnemy = CheckInvisibleEnemy - -M.dustAoeRadius = 1050 -M.dustDuration = 12 - -local dustTargets = fun1:NewTable() - -local function UseDustThink() - local enemies = fun1:GetPureHeroes(npcBot, M.dustAoeRadius) - local invisibleEnemies = enemies:Filter { t -> - fun1:HasAnyModifier(fun1.invisibleModifiers, t) - }:Filter { t -> - not fun1:HasAnyModifier(fun1.truesightModifiers) and fun1:GetPureHeroes(t, 800, true):All { t1 -> not fun1:GetAvailableItem(t1, "item_gem") } - } - invisibleEnemies:Filter { - t -> not dustTargets:Contains(t) - }:ForEach { - t -> dustTargets:InsertAfter_Modify(t) - } - - if local dust = fun1:GetAvailableItem(npcBot, "item_dust") then - local targets = dustTargets:Filter { t -> GetUnitToUnitDistance(npcBot, t) <= M.dustAoeRadius + t:GetBoundingRadius() } - if #targets > 0 and not npcBot:IsMuted() then - ItemUsage.UseItemNoTarget(npcBot, dust) - targets:ForEach { t -> - dustTargets:Remove_Modify(t) - } - end - end -end - -function M.Think() - if fun1:GameNotReallyStarting() then - return - end - npcBot = GetBot() - TeamItemInit() - TeamItemEventThink() - TeamStateThink() - BuyDustIfInvisibleEnemies() - UseDustThink() -end - -function M.TeamItemThink(npcBot) - if npcBot:IsIllusion() then - return - end - if not fun1:Contains(teamMembers, npcBot) then - if npcBot.teamItemEvents == nil then - npcBot.teamItemEvents = fun1:NewTable() - end - table.insert(teamMembers, npcBot) - end - fun1:StartCoroutine { it -> - while fun1:GameNotReallyStarting() do - coroutine.yield() - end - if not finishInit then - TeamItemInit() - end - if #teamMembers + #humanPlayers == 5 then - if runned then - return - else - runned = true - end - AddArcaneBoots() - AddMekansm() - end - } -end - -return M