├── mode_roam_generic.lua ├── mode_side_shop_generic.lua ├── mode_team_roam_generic.lua ├── mode_push_tower_top_generic.lua ├── mode_push_tower_mid_generic.lua ├── mode_push_tower_bot_generic.lua ├── hero_selection.lua ├── team_desires.lua ├── item_purchase_undying.lua ├── item_purchase_shadow_shaman.lua ├── item_purchase_keeper_of_the_light.lua ├── item_purchase_death_prophet.lua ├── item_purchase_venomancer.lua ├── ability_item_usage_keeper_of_the_light.lua ├── ability_item_usage_undying.lua ├── ability_item_usage_venomancer.lua ├── README.md ├── ability_item_usage_death_prophet.lua ├── ability_item_usage_shadow_shaman.lua ├── ability_item_usage_generic.lua ├── inspect.lua └── helper.lua /mode_roam_generic.lua: -------------------------------------------------------------------------------- 1 | function GetDesire() 2 | return 0.0; 3 | end -------------------------------------------------------------------------------- /mode_side_shop_generic.lua: -------------------------------------------------------------------------------- 1 | function GetDesire() 2 | return 0.0; 3 | end -------------------------------------------------------------------------------- /mode_team_roam_generic.lua: -------------------------------------------------------------------------------- 1 | function GetDesire() 2 | return 0.0; 3 | end -------------------------------------------------------------------------------- /mode_push_tower_top_generic.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | local Helper = require(GetScriptDirectory() .. "/helper"); 11 | 12 | function GetDesire() 13 | return Helper.GetPushDesire(GetBot(), LANE_TOP); 14 | end 15 | 16 | function OnStart() 17 | 18 | local npcBot = GetBot(); 19 | npcBot:ActionImmediate_Chat("Pushing Top", false); 20 | 21 | end 22 | 23 | function Think() 24 | Helper.PushThink(GetBot(), LANE_TOP); 25 | end -------------------------------------------------------------------------------- /mode_push_tower_mid_generic.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | function GetDesire() 14 | return Helper.GetPushDesire(GetBot(), LANE_MID); 15 | end 16 | 17 | function OnStart() 18 | 19 | local npcBot = GetBot(); 20 | npcBot:ActionImmediate_Chat("Pushing Mid", false); 21 | 22 | end 23 | 24 | function Think() 25 | Helper.PushThink(GetBot(), LANE_MID); 26 | end -------------------------------------------------------------------------------- /mode_push_tower_bot_generic.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | function GetDesire() 14 | return Helper.GetPushDesire(GetBot(), LANE_BOT); 15 | end 16 | 17 | function OnStart() 18 | 19 | local npcBot = GetBot(); 20 | npcBot:ActionImmediate_Chat("Pushing Bottom", false); 21 | 22 | end 23 | 24 | function Think() 25 | 26 | Helper.PushThink(GetBot(), LANE_BOT); 27 | 28 | end -------------------------------------------------------------------------------- /hero_selection.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | 3 | local MyBots = { 4 | "npc_dota_hero_undying", 5 | "npc_dota_hero_keeper_of_the_light", 6 | "npc_dota_hero_death_prophet", 7 | "npc_dota_hero_venomancer", 8 | "npc_dota_hero_shadow_shaman" 9 | }; 10 | 11 | function Think() 12 | local IDs = GetTeamPlayers(GetTeam()); 13 | for i,id in pairs(IDs) do 14 | if IsPlayerBot(id) then 15 | SelectHero(id, MyBots[i]); 16 | end 17 | end 18 | 19 | end 20 | 21 | ---------------------------------------------------------------------------------------------------- 22 | 23 | function UpdateLaneAssignments() 24 | if ( GetTeam() == TEAM_RADIANT ) then 25 | return { 26 | [1] = LANE_TOP, 27 | [2] = LANE_TOP, 28 | [3] = LANE_MID, 29 | [4] = LANE_BOT, 30 | [5] = LANE_BOT, 31 | }; 32 | elseif ( GetTeam() == TEAM_DIRE ) then 33 | return { 34 | [1] = LANE_TOP, 35 | [2] = LANE_TOP, 36 | [3] = LANE_MID, 37 | [4] = LANE_BOT, 38 | [5] = LANE_BOT, 39 | }; 40 | end 41 | end 42 | 43 | ---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /team_desires.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | ---------------------------------------------------------------------------------------------------- 14 | 15 | -- function UpdatePushLaneDesires() 16 | 17 | -- -- { Top Middle Bottom } 18 | 19 | -- end 20 | 21 | ---------------------------------------------------------------------------------------------------- 22 | 23 | -- function UpdateDefendLaneDesires() 24 | -- -- { Top Middle Bottom } 25 | -- return { 0.5, 0.5, 0.5}; 26 | 27 | -- end 28 | 29 | ---------------------------------------------------------------------------------------------------- 30 | 31 | -- function UpdateFarmLaneDesires() 32 | -- { Top Middle Bottom } 33 | -- if (DotaTime() <= 60 * 5) then 34 | -- return { 0, 0, 0 }; 35 | -- end 36 | 37 | -- return { 0.5, 0.5, 0.5 } 38 | 39 | -- end 40 | 41 | ---------------------------------------------------------------------------------------------------- 42 | 43 | -- function UpdateRoamDesire() 44 | -- { Desire Unit } 45 | -- return { 0.5, GetTeamMember( TEAM_RADIANT, 1 ) }; 46 | 47 | -- end 48 | 49 | ---------------------------------------------------------------------------------------------------- 50 | 51 | -- function UpdateRoshanDesire() 52 | 53 | -- return 0; 54 | 55 | -- end 56 | 57 | ---------------------------------------------------------------------------------------------------- 58 | -------------------------------------------------------------------------------- /item_purchase_undying.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | local tableItemsToBuy = { 14 | 15 | "item_stout_shield", 16 | "item_branches", 17 | "item_branches", 18 | "item_tango", 19 | "item_tango", 20 | 21 | "item_boots", 22 | "item_energy_booster", 23 | 24 | "item_vitality_booster", 25 | "item_ring_of_health", 26 | 27 | "item_broadsword", 28 | "item_chainmail", 29 | "item_robe", 30 | 31 | "item_ring_of_regen", 32 | "item_recipe_headdress", 33 | "item_chainmail", 34 | "item_recipe_buckler", 35 | "item_recipe_mekansm", 36 | 37 | "item_platemail", 38 | "item_mystic_staff", 39 | "item_recipe_shivas_guard", 40 | 41 | "item_chainmail", 42 | "item_branches", 43 | "item_recipe_buckler", 44 | "item_recipe_crimson_guard", 45 | 46 | "item_vitality_booster", 47 | "item_reaver", 48 | "item_recipe_heart", 49 | 50 | "item_recipe_guardian_greaves", 51 | 52 | }; 53 | 54 | local abilities = { 55 | "special_bonus_gold_income_15", 56 | "special_bonus_hp_300", 57 | "special_bonus_unique_undying", 58 | "special_bonus_unique_undying_2", 59 | "undying_flesh_golem", 60 | "undying_decay", 61 | "undying_tombstone", 62 | "undying_soul_rip", 63 | } 64 | 65 | ---------------------------------------------------------------------------------------------------- 66 | 67 | function ItemPurchaseThink() 68 | 69 | local npcBot = GetBot(); 70 | local buildTable = tableItemsToBuy; 71 | 72 | Helper.AbilityUpgrade(npcBot, abilities); 73 | Helper.PurchaseBootsAndTP(npcBot); 74 | Helper.PurchaseItems(npcBot, buildTable); 75 | 76 | end 77 | 78 | 79 | ---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /item_purchase_shadow_shaman.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | local tableItemsToBuy = { 14 | 15 | "item_courier", 16 | "item_tango", 17 | "item_tango", 18 | 19 | "item_boots", 20 | "item_energy_booster", 21 | 22 | "item_flying_courier", 23 | 24 | "item_point_booster", 25 | "item_staff_of_wizardry", 26 | "item_ogre_axe", 27 | "item_blade_of_alacrity", 28 | 29 | "item_belt_of_strength", 30 | "item_staff_of_wizardry", 31 | "item_recipe_necronomicon", 32 | "item_recipe_necronomicon", 33 | "item_recipe_necronomicon", 34 | 35 | "item_ring_of_health", 36 | "item_cloak", 37 | "item_ring_of_regen", 38 | 39 | "item_ring_of_regen", 40 | "item_branches", 41 | "item_recipe_headdress", 42 | "item_recipe_pipe", 43 | 44 | "item_boots", 45 | "item_recipe_travel_boots", 46 | 47 | "item_void_stone", 48 | "item_ultimate_orb", 49 | "item_mystic_staff", 50 | }; 51 | 52 | local abilities = { 53 | "special_bonus_hp_150", 54 | "special_bonus_cast_range_100", 55 | "special_bonus_respawn_reduction_30", 56 | "special_bonus_unique_shadow_shaman_2", 57 | "shadow_shaman_mass_serpent_ward", 58 | "shadow_shaman_ether_shock", 59 | "shadow_shaman_voodoo", 60 | "shadow_shaman_shackles", 61 | } 62 | 63 | ---------------------------------------------------------------------------------------------------- 64 | 65 | function ItemPurchaseThink() 66 | 67 | local npcBot = GetBot(); 68 | local buildTable = tableItemsToBuy; 69 | 70 | Helper.AbilityUpgrade(npcBot, abilities); 71 | Helper.PurchaseBootsAndTP(npcBot); 72 | Helper.PurchaseItems(npcBot, buildTable); 73 | 74 | end 75 | 76 | 77 | ---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /item_purchase_keeper_of_the_light.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | local tableItemsToBuy = { 14 | 15 | "item_circlet", 16 | "item_tango", 17 | "item_tango", 18 | "item_mantle", 19 | 20 | "item_boots", 21 | "item_blades_of_attack", 22 | "item_blades_of_attack", 23 | 24 | "item_recipe_null_talisman", 25 | 26 | "item_point_booster", 27 | "item_staff_of_wizardry", 28 | "item_ogre_axe", 29 | "item_blade_of_alacrity", 30 | 31 | "item_belt_of_strength", 32 | "item_staff_of_wizardry", 33 | "item_recipe_necronomicon", 34 | "item_recipe_necronomicon", 35 | "item_recipe_necronomicon", 36 | 37 | "item_staff_of_wizardry", 38 | "item_recipe_dagon", 39 | 40 | "item_recipe_dagon", 41 | "item_recipe_dagon", 42 | "item_recipe_dagon", 43 | "item_recipe_dagon", 44 | 45 | "item_platemail", 46 | "item_mystic_staff", 47 | "item_recipe_shivas_guard", 48 | 49 | "item_boots", 50 | "item_recipe_travel_boots", 51 | 52 | "item_vitality_booster", 53 | "item_reaver", 54 | "item_recipe_heart" 55 | }; 56 | 57 | local abilities = { 58 | "special_bonus_strength_6", 59 | "special_bonus_respawn_reduction_25", 60 | "special_bonus_armor_7", 61 | "special_bonus_unique_keeper_of_the_light", 62 | "keeper_of_the_light_chakra_magic", 63 | "keeper_of_the_light_illuminate", 64 | "keeper_of_the_light_mana_leak", 65 | "keeper_of_the_light_spirit_form", 66 | } 67 | 68 | ---------------------------------------------------------------------------------------------------- 69 | 70 | function ItemPurchaseThink() 71 | 72 | local npcBot = GetBot(); 73 | local buildTable = tableItemsToBuy; 74 | 75 | Helper.AbilityUpgrade(npcBot, abilities); 76 | Helper.PurchaseBootsAndTP(npcBot); 77 | Helper.PurchaseItems(npcBot, buildTable); 78 | 79 | end 80 | 81 | 82 | ---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /item_purchase_death_prophet.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | local tableItemsToBuy = { 14 | 15 | "item_circlet", 16 | "item_tango", 17 | "item_tango", 18 | "item_mantle", 19 | 20 | "item_boots", 21 | "item_blades_of_attack", 22 | "item_blades_of_attack", 23 | 24 | "item_recipe_null_talisman", 25 | 26 | "item_vitality_booster", 27 | "item_energy_booster", 28 | "item_point_booster", 29 | "item_sobi_mask", 30 | "item_ring_of_regen", 31 | "item_recipe_soul_ring", 32 | "item_recipe_bloodstone", 33 | 34 | "item_belt_of_strength", 35 | "item_staff_of_wizardry", 36 | "item_recipe_necronomicon", 37 | "item_recipe_necronomicon", 38 | "item_recipe_necronomicon", 39 | 40 | "item_platemail", 41 | "item_mystic_staff", 42 | "item_recipe_shivas_guard", 43 | 44 | "item_vitality_booster", 45 | "item_reaver", 46 | "item_recipe_heart", 47 | 48 | "item_boots", 49 | "item_recipe_travel_boots", 50 | 51 | "item_vitality_booster", 52 | "item_energy_booster", 53 | "item_point_booster", 54 | "item_mystic_staff", 55 | 56 | }; 57 | 58 | local abilities = { 59 | "special_bonus_spell_amplify_4", 60 | "special_bonus_unique_death_prophet_2", 61 | "special_bonus_cooldown_reduction_10", 62 | "special_bonus_hp_400", 63 | "death_prophet_exorcism", 64 | "death_prophet_carrion_swarm", 65 | "death_prophet_spirit_siphon", 66 | "death_prophet_silence", 67 | } 68 | 69 | ---------------------------------------------------------------------------------------------------- 70 | 71 | function ItemPurchaseThink() 72 | 73 | local npcBot = GetBot(); 74 | local buildTable = tableItemsToBuy; 75 | 76 | Helper.AbilityUpgrade(npcBot, abilities); 77 | Helper.PurchaseBootsAndTP(npcBot); 78 | Helper.PurchaseItems(npcBot, buildTable); 79 | 80 | end 81 | 82 | 83 | ---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /item_purchase_venomancer.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)') 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | 13 | local tableItemsToBuy = { 14 | 15 | "item_ring_of_protection", 16 | "item_sobi_mask", 17 | "item_tango", 18 | "item_tango", 19 | 20 | "item_boots", 21 | "item_blades_of_attack", 22 | "item_blades_of_attack", 23 | 24 | "item_belt_of_strength", 25 | "item_staff_of_wizardry", 26 | "item_recipe_necronomicon", 27 | "item_recipe_necronomicon", 28 | "item_recipe_necronomicon", 29 | 30 | "item_point_booster", 31 | "item_staff_of_wizardry", 32 | "item_ogre_axe", 33 | "item_blade_of_alacrity", 34 | 35 | "item_platemail", 36 | "item_mystic_staff", 37 | "item_recipe_shivas_guard", 38 | 39 | "item_shadow_amulet", 40 | "item_claymore", 41 | "item_ultimate_orb", 42 | "item_recipe_silver_edge", 43 | 44 | "item_boots", 45 | "item_recipe_travel_boots", 46 | 47 | "item_quarterstaff", 48 | "item_robe", 49 | "item_sobi_mask", 50 | "item_quarterstaff", 51 | "item_robe", 52 | "item_sobi_mask", 53 | "item_recipe_orchid", 54 | 55 | "item_broadsword", 56 | "item_blades_of_attack", 57 | "item_recipe_lesser_crit", 58 | "item_recipe_bloodthorn", 59 | }; 60 | 61 | local abilities = { 62 | "special_bonus_exp_boost_20", 63 | "special_bonus_cast_range_150", 64 | "special_bonus_magic_resistance_15", 65 | "special_bonus_unique_venomancer", 66 | "venomancer_poison_nova", 67 | "venomancer_plague_ward", 68 | "venomancer_poison_sting", 69 | "venomancer_venomous_gale", 70 | } 71 | 72 | ---------------------------------------------------------------------------------------------------- 73 | 74 | function ItemPurchaseThink() 75 | 76 | local npcBot = GetBot(); 77 | local buildTable = tableItemsToBuy; 78 | 79 | Helper.AbilityUpgrade(npcBot, abilities); 80 | Helper.PurchaseBootsAndTP(npcBot); 81 | Helper.PurchaseItems(npcBot, buildTable); 82 | 83 | end 84 | 85 | 86 | ---------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /ability_item_usage_keeper_of_the_light.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)'); 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | require(GetScriptDirectory().."/ability_item_usage_generic"); 13 | 14 | local Abilities = { 15 | "keeper_of_the_light_illuminate", 16 | "keeper_of_the_light_mana_leak", 17 | "keeper_of_the_light_chakra_magic", 18 | "keeper_of_the_light_recall", 19 | "keeper_of_the_light_blinding_light", 20 | "keeper_of_the_light_spirit_form", 21 | "keeper_of_the_light_illuminate_end", 22 | "keeper_of_the_light_spirit_form_illuminate", 23 | "keeper_of_the_light_spirit_form_illuminate_end", 24 | }; 25 | 26 | function AbilityUsageThink() 27 | 28 | local npcBot = GetBot(); 29 | 30 | local wave = npcBot:GetAbilityInSlot(0); 31 | local leak = npcBot:GetAbilityByName(Abilities[2]); 32 | local mana = npcBot:GetAbilityByName(Abilities[3]); 33 | local ult = npcBot:GetAbilityByName(Abilities[6]); 34 | 35 | local creeps = npcBot:GetNearbyLaneCreeps(1500, true); 36 | local enemyHeroes = npcBot:GetNearbyHeroes(600, true, BOT_MODE_NONE); 37 | 38 | local function considerManaLeak() 39 | if leak:IsFullyCastable() and npcBot:GetMana() - leak:GetManaCost() > mana:GetManaCost() then 40 | local enemyHero = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', leak:GetCastRange(), true); 41 | if enemyHero ~= nil then 42 | return npcBot:ActionPush_UseAbilityOnEntity(leak, enemyHero); 43 | end 44 | end 45 | end 46 | 47 | if npcBot:IsChanneling() or (npcBot:IsUsingAbility() and (not wave:IsInAbilityPhase())) then 48 | return; 49 | end 50 | 51 | if mana:IsFullyCastable() then 52 | local target = Helper.GetHeroWith(npcBot, 'min', 'GetMana', mana:GetCastRange(), false); 53 | return npcBot:ActionPush_UseAbilityOnEntity(mana, target); 54 | end 55 | 56 | if #enemyHeroes >= 2 or npcBot:GetActiveMode() == BOT_MODE_RETREAT then 57 | return considerManaLeak(); 58 | end 59 | 60 | if wave:IsFullyCastable() and 61 | npcBot:GetMana() - wave:GetManaCost() > mana:GetManaCost() and 62 | npcBot:GetActiveMode() ~= BOT_MODE_RETREAT and 63 | #creeps >= 3 then 64 | return npcBot:ActionPush_UseAbilityOnLocation(wave, creeps[1]:GetLocation()); 65 | end 66 | 67 | considerManaLeak(); 68 | 69 | -- if ult:IsFullyCastable() and npcBot:GetMana() - ult:GetManaCost() > waveAndManaCombo then 70 | -- npcBot:ActionPush_UseAbility(ult); 71 | -- end 72 | end 73 | 74 | function ItemUsageThink() 75 | ability_item_usage_generic.ItemUsageThink(); 76 | end 77 | 78 | function BuybackUsageThink() 79 | ability_item_usage_generic.BuybackUsageThink(); 80 | end -------------------------------------------------------------------------------- /ability_item_usage_undying.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)'); 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | require(GetScriptDirectory().."/ability_item_usage_generic"); 13 | 14 | local Abilities = { 15 | "undying_decay", 16 | "undying_tombstone", 17 | "undying_soul_rip", 18 | "undying_flesh_golem", 19 | }; 20 | 21 | function AbilityUsageThink() 22 | 23 | local npcBot = GetBot(); 24 | 25 | local decay = npcBot:GetAbilityByName(Abilities[1]); 26 | local tombstone = npcBot:GetAbilityByName(Abilities[2]); 27 | local heal = npcBot:GetAbilityByName(Abilities[3]); 28 | local ult = npcBot:GetAbilityByName(Abilities[4]); 29 | 30 | if npcBot:IsChanneling() or npcBot:IsUsingAbility() then 31 | return; 32 | end 33 | 34 | local battleMayHappen = #npcBot:GetNearbyHeroes(1500, true, BOT_MODE_NONE) >= 3 or 35 | ( 36 | #npcBot:GetNearbyHeroes(1500, true, BOT_MODE_NONE) >= 2 and 37 | #npcBot:GetNearbyHeroes(1500, false, BOT_MODE_NONE) >= 2 38 | ); 39 | 40 | if tombstone:IsFullyCastable() and battleMayHappen then 41 | return npcBot:ActionPush_UseAbilityOnLocation(tombstone, npcBot:GetLocation()); 42 | end 43 | 44 | if ult:IsFullyCastable() and battleMayHappen then 45 | return npcBot:ActionPush_UseAbility(ult); 46 | end 47 | 48 | if decay:IsFullyCastable() and 49 | npcBot:GetMana() - decay:GetManaCost() > ult:GetManaCost() + tombstone:GetManaCost() then 50 | local aoe = npcBot:FindAoELocation( 51 | true, true, npcBot:GetLocation(), decay:GetCastRange(), 325, decay:GetCastPoint(), 100000); 52 | if aoe.count >= 2 or (aoe.count >= 1 and npcBot:GetActiveMode() == BOT_MODE_ATTACK) then 53 | return npcBot:ActionPush_UseAbilityOnLocation(decay, aoe.targetloc); 54 | end 55 | end 56 | 57 | if heal:IsFullyCastable() and 58 | npcBot:GetMana() - heal:GetManaCost() > ult:GetManaCost() + tombstone:GetManaCost() + 3 * decay:GetManaCost() then 59 | 60 | local enemy = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', heal:GetCastRange(), true); 61 | local friend = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', heal:GetCastRange(), false); 62 | 63 | local target = enemy or friend; 64 | if enemy ~= nil and friend ~= nil then 65 | target = enemy:GetHealth() < friend:GetHealth() and enemy or friend; 66 | end 67 | 68 | if target ~= nil then 69 | return npcBot:ActionPush_UseAbilityOnEntity(heal, target); 70 | end 71 | end 72 | 73 | end 74 | 75 | function ItemUsageThink() 76 | ability_item_usage_generic.ItemUsageThink(); 77 | end 78 | 79 | function BuybackUsageThink() 80 | ability_item_usage_generic.BuybackUsageThink(); 81 | end -------------------------------------------------------------------------------- /ability_item_usage_venomancer.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)'); 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | require(GetScriptDirectory().."/ability_item_usage_generic"); 13 | 14 | local Abilities = { 15 | "venomancer_venomous_gale", 16 | "venomancer_poison_sting", 17 | "venomancer_plague_ward", 18 | "venomancer_poison_nova", 19 | }; 20 | 21 | function AbilityUsageThink() 22 | 23 | local npcBot = GetBot(); 24 | 25 | local gale = npcBot:GetAbilityByName(Abilities[1]); 26 | local ward = npcBot:GetAbilityByName(Abilities[3]); 27 | local nova = npcBot:GetAbilityByName(Abilities[4]); 28 | 29 | if npcBot:IsChanneling() or npcBot:IsUsingAbility() then 30 | return; 31 | end 32 | 33 | if gale:IsFullyCastable() and 34 | npcBot:GetMana() - gale:GetManaCost() > nova:GetManaCost() and 35 | npcBot:GetActiveMode() == BOT_MODE_ATTACK then 36 | local target = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', gale:GetCastRange(), true); 37 | if target ~= nil then 38 | return npcBot:ActionPush_UseAbilityOnLocation(gale, target:GetLocation()); 39 | end 40 | end 41 | 42 | if ward:IsFullyCastable() and 43 | (#npcBot:GetNearbyHeroes(1500, true, BOT_MODE_NONE) > 0 or 44 | #npcBot:GetNearbyTowers(1500, true) > 0 or 45 | #npcBot:GetNearbyBarracks(1500, true) > 0 or 46 | #npcBot:GetNearbyLaneCreeps(1500, true) > 2 or 47 | npcBot:GetManaRegen() > 4 or 48 | npcBot:GetActiveMode() == BOT_MODE_ATTACK or 49 | npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT or 50 | npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID or 51 | npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP or 52 | npcBot:GetActiveMode() == BOT_MODE_DEFEND_ALLY 53 | ) and 54 | npcBot:GetMana() - ward:GetManaCost() > nova:GetManaCost() and 55 | ward:GetLevel() >= 2 then 56 | local target = npcBot:GetNearbyHeroes(ward:GetCastRange(), true, BOT_MODE_NONE)[1]; 57 | if target ~= nil then 58 | return npcBot:ActionPush_UseAbilityOnLocation(ward, target:GetLocation()); 59 | else 60 | return npcBot:ActionPush_UseAbilityOnLocation(ward, npcBot:GetLocation() + Helper.RandomForwardVector(ward:GetCastRange())); 61 | end 62 | end 63 | 64 | local enemyHeroes = npcBot:GetNearbyHeroes(575, true, BOT_MODE_NONE); 65 | if #enemyHeroes >= 3 or (#enemyHeroes >= 2 and npcBot:GetActiveMode() == BOT_MODE_ATTACK) then 66 | return npcBot:ActionPush_UseAbility(nova); 67 | end 68 | 69 | end 70 | 71 | function ItemUsageThink() 72 | ability_item_usage_generic.ItemUsageThink(); 73 | end 74 | 75 | function BuybackUsageThink() 76 | ability_item_usage_generic.BuybackUsageThink(); 77 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ExtremePush - Dota 2 Bot Scripts 2 | 3 | The aim of this bot is for extreme [pushing](http://dota2.gamepedia.com/Pushing). You can download the bot with name "ExtremePush" on workshop. 4 | 5 | **You might have to unsubscribe and resubscribe to update your bot scripts to the latest version.** 6 | 7 | ### v.20170218 8 | 9 | - Added Shadow Shaman 10 | - Added Death Prophet 11 | 12 | ### v.20170211 13 | 14 | - Fix broken bots caused by recent game updates. 15 | 16 | ### v.20170202 17 | 18 | **Venomancer** 19 | 20 | - Added Venomancer (item builds, ability usages, etc) 21 | 22 | **General** 23 | 24 | - Tweak the team push logic 25 | 26 | ### v.20170129 27 | 28 | **Keeper of the Light** 29 | 30 | - Improve push mode overrides with a better strategy 31 | - Fix some TP Scroll related issues 32 | - Improve Travel Boots usage 33 | 34 | ### v.20170128 35 | 36 | **Keeper of the Light** 37 | 38 | - Override default bot push mode, now it uses custom push logic. 39 | - Improve item builds for late game. 40 | - Fix crashes caused by default require statemet on Mac (only tested on dev script, probably will not work on Workshop) 41 | 42 | ### v.20170121 43 | 44 | **Keeper of the Light** 45 | 46 | Huge improvements for KOTL, including: 47 | 48 | - Now bots know how to purchase from secret shop. This results in much better item builds. 49 | One of the KOTL will be named as support and will purchase support items: Mekansm and Pipe. 50 | Other bots will purchase Shadow Blade and Shivas Guard. 51 | - Now bots know how to purcahse and use TP Scroll. The TP logic is based on the **default** team desires. So it's more of a double-edged sword: Good decisions result in better results and bad decisions result in bigger mess. 52 | - Now bots will have custom ability upgrade path and will also be able to upgrade talents. 53 | - Chakra Magic will be casted on teammates also. 54 | - Illuminate will end if the casting hero is in danger. Also it will ignore neutral creeps. 55 | - Mana leak will be casted more aggressively. 56 | 57 | ### v.20170117 58 | 59 | **Keeper of the Light** 60 | 61 | - Chakra Magic: cast when available 62 | - Illuminate: cast and channel when there are creeps within range. Cancel channelling when the hero is "threatened". 63 | - Mana leak: cast on the enenmy hero within the range that has lowest HP. 64 | - Illuminate and Mana leak are casted when there is enough mana left for Chakra Magic. 65 | - Other abilities are not casted at all. I found out when Spirit Form is on, the hero will have weird behaviors. 66 | - Phase Boots and Necronomicon: purchase and cast when available. 67 | - Mekansm and Pipe of Insight: purchase and cast when a nearby teammates has HP <= 400. 68 | - Dagon: purcahse and cast on the enenmy hero within the range that has lowest HP. 69 | 70 | For test runs, please see [Issue #1](https://github.com/insraq/dota2bots/issues/1) 71 | 72 |  73 | -------------------------------------------------------------------------------- /ability_item_usage_death_prophet.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)'); 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | require(GetScriptDirectory().."/ability_item_usage_generic"); 13 | 14 | local Abilities = { 15 | "death_prophet_carrion_swarm", 16 | "death_prophet_silence", 17 | "death_prophet_spirit_siphon", 18 | "death_prophet_exorcism", 19 | }; 20 | 21 | function AbilityUsageThink() 22 | 23 | local npcBot = GetBot(); 24 | 25 | local swarm = npcBot:GetAbilityByName(Abilities[1]); 26 | local silence = npcBot:GetAbilityByName(Abilities[2]); 27 | local siphon = npcBot:GetAbilityByName(Abilities[3]); 28 | local ult = npcBot:GetAbilityByName(Abilities[4]); 29 | 30 | if npcBot:IsChanneling() or npcBot:IsUsingAbility() then 31 | return; 32 | end 33 | 34 | local battleMayHappen = #npcBot:GetNearbyHeroes(1500, true, BOT_MODE_NONE) >= 3 or 35 | ( 36 | #npcBot:GetNearbyHeroes(1500, true, BOT_MODE_NONE) >= 2 and 37 | #npcBot:GetNearbyHeroes(1500, false, BOT_MODE_NONE) >= 2 38 | ); 39 | local isPushing = ( 40 | #npcBot:GetNearbyTowers(700, true) > 0 or #npcBot:GetNearbyBarracks(700, true) > 0 41 | ) and #npcBot:GetNearbyHeroes(700, false, BOT_MODE_NONE) >= 2; 42 | 43 | if ult:IsFullyCastable() and (battleMayHappen or isPushing) then 44 | return npcBot:ActionPush_UseAbility(ult); 45 | end 46 | 47 | if swarm:IsFullyCastable() and 48 | npcBot:GetMana() - swarm:GetManaCost() > ult:GetManaCost() and 49 | swarm:GetLevel() >= 2 then 50 | local target = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', swarm:GetCastRange(), true); 51 | 52 | if target == nil and 53 | npcBot:GetMana() > swarm:GetManaCost() + silence:GetManaCost() + siphon:GetManaCost() + ult:GetManaCost() then 54 | target = npcBot:GetNearbyLaneCreeps(swarm:GetCastRange(), true)[1]; 55 | end 56 | 57 | if target ~= nil then 58 | return npcBot:ActionPush_UseAbilityOnEntity(swarm, target); 59 | end 60 | end 61 | 62 | if silence:IsFullyCastable() then 63 | local aoe = npcBot:FindAoELocation(true, true, npcBot:GetLocation(), silence:GetCastRange(), 425, 0.0, 100000); 64 | if aoe.count >= 2 then 65 | return npcBot:ActionPush_UseAbilityOnLocation(silence, aoe.targetloc); 66 | end 67 | end 68 | 69 | if siphon:IsFullyCastable() and swarm:GetLevel() >= 3 and npcBot:GetActiveMode() ~= BOT_MODE_RETREAT then 70 | local target = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', siphon:GetCastRange(), true); 71 | if target ~= nil then 72 | npcBot:ActionQueue_MoveToUnit(target); 73 | return npcBot:ActionPush_UseAbilityOnEntity(siphon, target); 74 | end 75 | end 76 | 77 | end 78 | 79 | function ItemUsageThink() 80 | ability_item_usage_generic.ItemUsageThink(); 81 | end 82 | 83 | function BuybackUsageThink() 84 | ability_item_usage_generic.BuybackUsageThink(); 85 | end -------------------------------------------------------------------------------- /ability_item_usage_shadow_shaman.lua: -------------------------------------------------------------------------------- 1 | -- Include this before require to fix Mac 2 | local dir = GetScriptDirectory(); 3 | local function GetScriptDirectory() 4 | if string.sub(dir, 1, 6) == "/Users" then 5 | return string.match(dir, '.*/(.+)'); 6 | end 7 | return dir; 8 | end 9 | ----------------------------------------- 10 | 11 | local Helper = require(GetScriptDirectory() .. "/helper"); 12 | require(GetScriptDirectory().."/ability_item_usage_generic"); 13 | 14 | local Abilities = { 15 | "shadow_shaman_ether_shock", 16 | "shadow_shaman_voodoo", 17 | "shadow_shaman_shackles", 18 | "shadow_shaman_mass_serpent_ward", 19 | }; 20 | 21 | function AbilityUsageThink() 22 | 23 | local npcBot = GetBot(); 24 | 25 | local shock = npcBot:GetAbilityByName(Abilities[1]); 26 | local hex = npcBot:GetAbilityByName(Abilities[2]); 27 | local shackles = npcBot:GetAbilityByName(Abilities[3]); 28 | local ult = npcBot:GetAbilityByName(Abilities[4]); 29 | 30 | if npcBot:IsChanneling() or npcBot:IsUsingAbility() then 31 | return; 32 | end 33 | 34 | local ultTarget = nil; 35 | 36 | local enemyHeroes = npcBot:GetNearbyHeroes(ult:GetCastRange(), true, BOT_MODE_NONE); 37 | if #enemyHeroes >= 2 then 38 | ultTarget = enemyHeroes[1]:GetLocation(); 39 | end 40 | 41 | local towers = npcBot:GetNearbyTowers(ult:GetCastRange(), true); 42 | if #towers > 0 then 43 | ultTarget = towers[1]:GetLocation(); 44 | end 45 | 46 | local barracks = npcBot:GetNearbyBarracks(ult:GetCastRange(), true); 47 | if #barracks > 0 then 48 | ultTarget = barracks[1]:GetLocation(); 49 | end 50 | 51 | if ultTarget ~= nil and ult:IsFullyCastable() then 52 | return npcBot:ActionPush_UseAbilityOnLocation(ult, ultTarget); 53 | end 54 | 55 | if shock:IsFullyCastable() and 56 | npcBot:GetMana() - shock:GetManaCost() > ult:GetManaCost() and 57 | shock:GetLevel() >= 2 then 58 | local target = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', shock:GetCastRange(), true); 59 | 60 | if target == nil and 61 | npcBot:GetMana() > shock:GetManaCost() + hex:GetManaCost() + shackles:GetManaCost() + ult:GetManaCost() then 62 | target = npcBot:GetNearbyLaneCreeps(shock:GetCastRange(), true)[1]; 63 | end 64 | 65 | if target ~= nil then 66 | return npcBot:ActionPush_UseAbilityOnEntity(shock, target); 67 | end 68 | end 69 | 70 | if hex:IsFullyCastable() and 71 | npcBot:GetMana() - hex:GetManaCost() > ult:GetManaCost() + shock:GetManaCost() then 72 | local target = Helper.GetHeroWith(npcBot, 'max', 'GetRawOffensivePower', hex:GetCastRange(), true); 73 | if target ~= nil then 74 | return npcBot:ActionPush_UseAbilityOnEntity(hex, target); 75 | end 76 | end 77 | 78 | if shackles:IsFullyCastable() and 79 | #npcBot:GetNearbyHeroes(ult:GetCastRange(), false, BOT_MODE_NONE) >= 2 and 80 | npcBot:GetMana() - shackles:GetManaCost() > ult:GetManaCost() + shock:GetManaCost() then 81 | local target = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', shackles:GetCastRange(), true); 82 | if target ~= nil then 83 | return npcBot:ActionPush_UseAbilityOnEntity(shackles, target); 84 | end 85 | end 86 | 87 | end 88 | 89 | function ItemUsageThink() 90 | ability_item_usage_generic.ItemUsageThink(); 91 | end 92 | 93 | function BuybackUsageThink() 94 | ability_item_usage_generic.BuybackUsageThink(); 95 | end -------------------------------------------------------------------------------- /ability_item_usage_generic.lua: -------------------------------------------------------------------------------- 1 | _G._savedEnv = getfenv() 2 | module("ability_item_usage_generic", package.seeall) 3 | 4 | -- Include this before require to fix Mac 5 | local dir = GetScriptDirectory(); 6 | local function GetScriptDirectory() 7 | if string.sub(dir, 1, 6) == "/Users" then 8 | return string.match(dir, '.*/(.+)') 9 | end 10 | return dir; 11 | end 12 | ----------------------------------------- 13 | 14 | local Helper = require(GetScriptDirectory() .. "/helper"); 15 | 16 | local function considerGlyph(tower) 17 | if tower ~= nil then return end 18 | local recentValues = Helper.GetLastValues('Health:' .. tower:GetUnitName(), tower:GetHealth()); 19 | if recentValues[5][1] - recentValues[1][1] > tower:GetHealth() * 0.5 and 20 | GetGlyphCooldown() == 0 then 21 | GetBot():ActionImmediate_Glyph(); 22 | end 23 | end 24 | 25 | function ItemUsageThink() 26 | 27 | local npcBot = GetBot(); 28 | 29 | considerGlyph(Helper.GetOutermostTower(GetTeam(), LANE_TOP)); 30 | considerGlyph(Helper.GetOutermostTower(GetTeam(), LANE_MID)); 31 | considerGlyph(Helper.GetOutermostTower(GetTeam(), LANE_BOT)); 32 | 33 | if npcBot:IsChanneling() or npcBot:IsUsingAbility() then 34 | return; 35 | end 36 | 37 | local teammates = npcBot:GetNearbyHeroes(900, false, BOT_MODE_NONE); 38 | local enemies = npcBot:GetNearbyHeroes(900, true, BOT_MODE_NONE); 39 | 40 | for i = 0,5 do 41 | local item = npcBot:GetItemInSlot(i); 42 | 43 | if (item) and string.find(item:GetName(), "item_necronomicon") and item:IsFullyCastable() and #enemies >= 1 then 44 | npcBot:ActionPush_UseAbility(item); 45 | end 46 | 47 | if (item) and string.find(item:GetName(), "item_dagon") and item:IsFullyCastable() and #enemies >= 1 then 48 | local weakestEnemy = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', item:GetCastRange(), true); 49 | if (weakestEnemy ~= nil) then 50 | npcBot:ActionPush_UseAbilityOnEntity(item, weakestEnemy); 51 | end 52 | end 53 | 54 | if (item) and (item:GetName() == "item_tpscroll" or item:GetName() == "item_travel_boots") and item:IsFullyCastable() then 55 | 56 | local target = nil; 57 | 58 | local enemy = Helper.GetEnemyLastSeenInfo(5.0); 59 | 60 | if npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_BOT then 61 | target = Helper.GetOutermostTower(GetTeam(), LANE_BOT):GetLocation(); 62 | elseif npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_MID then 63 | target = Helper.GetOutermostTower(GetTeam(), LANE_MID):GetLocation(); 64 | elseif npcBot:GetActiveMode() == BOT_MODE_DEFEND_TOWER_TOP then 65 | target = Helper.GetOutermostTower(GetTeam(), LANE_TOP):GetLocation(); 66 | elseif npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_BOT and item:GetName() == "item_travel_boots" and #enemy[LANE_BOT] < 3 then 67 | target = GetLaneFrontLocation(GetTeam(), LANE_BOT, 0.0); 68 | elseif npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_MID and item:GetName() == "item_travel_boots" and #enemy[LANE_MID] < 3 then 69 | target = GetLaneFrontLocation(GetTeam(), LANE_MID, 0.0); 70 | elseif npcBot:GetActiveMode() == BOT_MODE_PUSH_TOWER_TOP and item:GetName() == "item_travel_boots" and #enemy[LANE_TOP] < 3 then 71 | target = GetLaneFrontLocation(GetTeam(), LANE_TOP, 0.0); 72 | end 73 | 74 | if target ~= nil and #teammates < 2 and 75 | GetUnitToLocationDistance(npcBot, target) > 5000 and 76 | Helper.IsForward(npcBot:GetLocation(), target) then 77 | local offset = Vector(-500, -500); 78 | if (GetTeam() == TEAM_DIRE) then 79 | offset = Vector(500, 500) 80 | end 81 | npcBot:ActionPush_UseAbilityOnLocation(item, target + offset); 82 | end 83 | 84 | end 85 | 86 | if (item) and ( 87 | item:GetName() == "item_mekansm" or 88 | item:GetName() == "item_pipe" or 89 | item:GetName() == "item_guardian_greaves" or 90 | item:GetName() == "item_crimson_guard" 91 | ) and item:IsFullyCastable() and teammates ~= nil and #teammates >=2 then 92 | if npcBot:GetHealth() <= 400 then 93 | npcBot:ActionPush_UseAbility(item); 94 | end 95 | for _, hero in pairs(teammates) do 96 | if (hero:GetHealth() <= 400) then 97 | npcBot:ActionPush_UseAbility(item); 98 | end 99 | end 100 | end 101 | 102 | if (item) and item:GetName() == "item_phase_boots" and item:IsFullyCastable() then 103 | npcBot:ActionPush_UseAbility(item); 104 | end 105 | 106 | if (item) and item:GetName() == "item_arcane_boots" and item:IsFullyCastable() then 107 | npcBot:ActionPush_UseAbility(item); 108 | end 109 | 110 | if (item) and item:GetName() == "item_shivas_guard" and item:IsFullyCastable() and #enemies >= 2 then 111 | npcBot:ActionPush_UseAbility(item); 112 | end 113 | 114 | if (item) and (item:GetName() == "item_invis_sword" or item:GetName() == "item_silver_edge") and 115 | item:IsFullyCastable() and 116 | npcBot:GetActiveMode() == BOT_MODE_RETREAT and 117 | npcBot:DistanceFromFountain() > 1500 then 118 | npcBot:ActionPush_UseAbility(item); 119 | end 120 | 121 | if (item) and 122 | (item:GetName() == "item_orchid" or item:GetName() == "item_recipe_bloodthorn") and 123 | item:IsFullyCastable() then 124 | local weakestEnemy = Helper.GetHeroWith(npcBot, 'min', 'GetHealth', item:GetCastRange(), true); 125 | if (weakestEnemy ~= nil) then 126 | npcBot:ActionPush_UseAbilityOnEntity(item, weakestEnemy); 127 | end 128 | end 129 | 130 | if (item) and 131 | item:GetName() == "item_sheepstick" and 132 | item:IsFullyCastable() then 133 | local target = Helper.GetHeroWith(npcBot, 'max', 'GetRawOffensivePower', item:GetCastRange(), true); 134 | if target ~= nil then 135 | npcBot:ActionPush_UseAbilityOnEntity(item, target); 136 | end 137 | end 138 | 139 | if (item) and 140 | item:GetName() == "item_blade_mail" and 141 | npcBot:WasRecentlyDamagedByAnyHero(2.0) and 142 | item:IsFullyCastable() then 143 | npcBot:ActionPush_UseAbility(item); 144 | end 145 | 146 | if (item) and 147 | npcBot:GetHealth() < npcBot:GetMaxHealth() - 200 and 148 | (not npcBot:HasModifier("modifier_tango_heal")) and 149 | item:GetName() == "item_tango" then 150 | local trees = npcBot:GetNearbyTrees(300); 151 | if (#trees > 0) then 152 | npcBot:Action_UseAbilityOnTree(item, trees[1]); 153 | end 154 | end 155 | 156 | if (item) and item:GetName() == "item_courier" and item:IsFullyCastable() then 157 | npcBot:ActionPush_UseAbility(item); 158 | end 159 | 160 | if (item) and item:GetName() == "item_flask" and item:IsFullyCastable() and npcBot:GetHealth() <= 200 then 161 | npcBot:ActionPush_UseAbilityOnEntity(item, npcBot); 162 | end 163 | 164 | if (item) and item:GetName() == "item_clarity" and item:IsFullyCastable() and npcBot:GetMana() <= 200 then 165 | npcBot:ActionPush_UseAbilityOnEntity(item, npcBot); 166 | end 167 | end 168 | 169 | end 170 | 171 | function BuybackUsageThink() 172 | local npcBot = GetBot(); 173 | if npcBot:HasBuyback() then 174 | print(npcBot:GetUnitName()); 175 | end 176 | if npcBot:IsAlive() or (not npcBot:HasBuyback()) then 177 | return; 178 | end 179 | if GetLaneFrontAmount(GetTeam(), LANE_TOP, false) < 0.2 or 180 | GetLaneFrontAmount(GetTeam(), LANE_MID, false) < 0.2 or 181 | GetLaneFrontAmount(GetTeam(), LANE_BOT, false) < 0.2 then 182 | npcBot:ActionImmediate_Buyback(); 183 | end 184 | end 185 | 186 | function CourierUsageThink() 187 | local npcBot = GetBot(); 188 | 189 | if not IsCourierAvailable() then 190 | return 191 | end 192 | 193 | if GetCourierState(GetCourier(GetNumCouriers() -1)) ~= COURIER_STATE_IDLE 194 | and GetCourierState(GetCourier(GetNumCouriers() -1)) ~= COURIER_STATE_AT_BASE then 195 | return 196 | end 197 | 198 | if GetCourierState(GetCourier(GetNumCouriers() -1)) == COURIER_STATE_IDLE 199 | and GetCourier(GetNumCouriers() -1):DistanceFromFountain() > 200 then 200 | npcBot:ActionImmediate_Courier(GetCourier(GetNumCouriers() -1), COURIER_ACTION_RETURN); 201 | return 202 | end 203 | 204 | local limit = math.min(DotaTime(), 1000); 205 | 206 | if npcBot:IsAlive() and (npcBot:GetStashValue() >= limit or npcBot:GetCourierValue() >= limit) then 207 | npcBot:ActionImmediate_Courier(GetCourier(GetNumCouriers() -1), COURIER_ACTION_TAKE_AND_TRANSFER_ITEMS); 208 | return 209 | end 210 | end 211 | 212 | 213 | for k,v in pairs(ability_item_usage_generic) do _G._savedEnv[k] = v end -------------------------------------------------------------------------------- /inspect.lua: -------------------------------------------------------------------------------- 1 | local inspect ={ 2 | _VERSION = 'inspect.lua 3.1.0', 3 | _URL = 'http://github.com/kikito/inspect.lua', 4 | _DESCRIPTION = 'human-readable representations of tables', 5 | _LICENSE = [[ 6 | MIT LICENSE 7 | 8 | Copyright (c) 2013 Enrique García Cota 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a 11 | copy of this software and associated documentation files (the 12 | "Software"), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included 19 | in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | ]] 29 | } 30 | 31 | local tostring = tostring 32 | 33 | inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end}) 34 | inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end}) 35 | 36 | -- Apostrophizes the string if it has quotes, but not aphostrophes 37 | -- Otherwise, it returns a regular quoted string 38 | local function smartQuote(str) 39 | if str:match('"') and not str:match("'") then 40 | return "'" .. str .. "'" 41 | end 42 | return '"' .. str:gsub('"', '\\"') .. '"' 43 | end 44 | 45 | -- \a => '\\a', \0 => '\\0', 31 => '\31' 46 | local shortControlCharEscapes = { 47 | ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", 48 | ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v" 49 | } 50 | local longControlCharEscapes = {} -- \a => nil, \0 => \000, 31 => \031 51 | for i=0, 31 do 52 | local ch = string.char(i) 53 | if not shortControlCharEscapes[ch] then 54 | shortControlCharEscapes[ch] = "\\"..i 55 | longControlCharEscapes[ch] = string.format("\\%03d", i) 56 | end 57 | end 58 | 59 | local function escape(str) 60 | return (str:gsub("\\", "\\\\") 61 | :gsub("(%c)%f[0-9]", longControlCharEscapes) 62 | :gsub("%c", shortControlCharEscapes)) 63 | end 64 | 65 | local function isIdentifier(str) 66 | return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" ) 67 | end 68 | 69 | local function isSequenceKey(k, sequenceLength) 70 | return type(k) == 'number' 71 | and 1 <= k 72 | and k <= sequenceLength 73 | and math.floor(k) == k 74 | end 75 | 76 | local defaultTypeOrders = { 77 | ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, 78 | ['function'] = 5, ['userdata'] = 6, ['thread'] = 7 79 | } 80 | 81 | local function sortKeys(a, b) 82 | local ta, tb = type(a), type(b) 83 | 84 | -- strings and numbers are sorted numerically/alphabetically 85 | if ta == tb and (ta == 'string' or ta == 'number') then return a < b end 86 | 87 | local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb] 88 | -- Two default types are compared according to the defaultTypeOrders table 89 | if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb] 90 | elseif dta then return true -- default types before custom ones 91 | elseif dtb then return false -- custom types after default ones 92 | end 93 | 94 | -- custom types are sorted out alphabetically 95 | return ta < tb 96 | end 97 | 98 | -- For implementation reasons, the behavior of rawlen & # is "undefined" when 99 | -- tables aren't pure sequences. So we implement our own # operator. 100 | local function getSequenceLength(t) 101 | local len = 1 102 | local v = rawget(t,len) 103 | while v ~= nil do 104 | len = len + 1 105 | v = rawget(t,len) 106 | end 107 | return len - 1 108 | end 109 | 110 | local function getNonSequentialKeys(t) 111 | local keys = {} 112 | local sequenceLength = getSequenceLength(t) 113 | for k,_ in pairs(t) do 114 | if not isSequenceKey(k, sequenceLength) then table.insert(keys, k) end 115 | end 116 | table.sort(keys, sortKeys) 117 | return keys, sequenceLength 118 | end 119 | 120 | local function getToStringResultSafely(t, mt) 121 | local __tostring = type(mt) == 'table' and rawget(mt, '__tostring') 122 | local str, ok 123 | if type(__tostring) == 'function' then 124 | ok, str = pcall(__tostring, t) 125 | str = ok and str or 'error: ' .. tostring(str) 126 | end 127 | if type(str) == 'string' and #str > 0 then return str end 128 | end 129 | 130 | local function countTableAppearances(t, tableAppearances) 131 | tableAppearances = tableAppearances or {} 132 | 133 | if type(t) == 'table' then 134 | if not tableAppearances[t] then 135 | tableAppearances[t] = 1 136 | for k,v in pairs(t) do 137 | countTableAppearances(k, tableAppearances) 138 | countTableAppearances(v, tableAppearances) 139 | end 140 | countTableAppearances(getmetatable(t), tableAppearances) 141 | else 142 | tableAppearances[t] = tableAppearances[t] + 1 143 | end 144 | end 145 | 146 | return tableAppearances 147 | end 148 | 149 | local copySequence = function(s) 150 | local copy, len = {}, #s 151 | for i=1, len do copy[i] = s[i] end 152 | return copy, len 153 | end 154 | 155 | local function makePath(path, ...) 156 | local keys = {...} 157 | local newPath, len = copySequence(path) 158 | for i=1, #keys do 159 | newPath[len + i] = keys[i] 160 | end 161 | return newPath 162 | end 163 | 164 | local function processRecursive(process, item, path, visited) 165 | 166 | if item == nil then return nil end 167 | if visited[item] then return visited[item] end 168 | 169 | local processed = process(item, path) 170 | if type(processed) == 'table' then 171 | local processedCopy = {} 172 | visited[item] = processedCopy 173 | local processedKey 174 | 175 | for k,v in pairs(processed) do 176 | processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) 177 | if processedKey ~= nil then 178 | processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited) 179 | end 180 | end 181 | 182 | local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited) 183 | setmetatable(processedCopy, mt) 184 | processed = processedCopy 185 | end 186 | return processed 187 | end 188 | 189 | 190 | 191 | ------------------------------------------------------------------- 192 | 193 | local Inspector = {} 194 | local Inspector_mt = {__index = Inspector} 195 | 196 | function Inspector:puts(...) 197 | local args = {...} 198 | local buffer = self.buffer 199 | local len = #buffer 200 | for i=1, #args do 201 | len = len + 1 202 | buffer[len] = args[i] 203 | end 204 | end 205 | 206 | function Inspector:down(f) 207 | self.level = self.level + 1 208 | f() 209 | self.level = self.level - 1 210 | end 211 | 212 | function Inspector:tabify() 213 | self:puts(self.newline, string.rep(self.indent, self.level)) 214 | end 215 | 216 | function Inspector:alreadyVisited(v) 217 | return self.ids[v] ~= nil 218 | end 219 | 220 | function Inspector:getId(v) 221 | local id = self.ids[v] 222 | if not id then 223 | local tv = type(v) 224 | id = (self.maxIds[tv] or 0) + 1 225 | self.maxIds[tv] = id 226 | self.ids[v] = id 227 | end 228 | return tostring(id) 229 | end 230 | 231 | function Inspector:putKey(k) 232 | if isIdentifier(k) then return self:puts(k) end 233 | self:puts("[") 234 | self:putValue(k) 235 | self:puts("]") 236 | end 237 | 238 | function Inspector:putTable(t) 239 | if t == inspect.KEY or t == inspect.METATABLE then 240 | self:puts(tostring(t)) 241 | elseif self:alreadyVisited(t) then 242 | self:puts('