Dota Bot Scripting: Difference between revisions
(Created page with "== Overview == Bot scripting in Dota is done via lua scripting. This is done at the server level, so there's no need to do things like examine screen pixels or simulate mous...") |
No edit summary |
||
Line 283: | Line 283: | ||
* GetActualDamage | * GetActualDamage | ||
=== | == Bot Difficulties == | ||
There are five bot difficulties: | |||
==== Passive ==== | |||
* Cannot use abilities or items or the courier. | |||
* Will always remaining in laning mode. | |||
* When attempting to last hit creeps, their estimation of the best time to land the attack randomly varies by 0.4 seconds. | |||
* When attempting to last hit allied creeps, their estimation of the best time to land the attack randomly varies by 0.2 seconds. | |||
==== Easy ==== | |||
* Ability and item usage gets a random delay of 0.5 to 1.0 seconds | |||
* Every 8 seconds, ability and item usage is disallowed for 6 seconds. | |||
* Whenever an ability or item is used, ability and item usage is disallowed for 6 seconds. | |||
* When attempting to last hit enemy creeps, their estimation of the best time to land the attack randomly varies by 0.4 seconds. | |||
* When attempting to last hit allied creeps, their estimation of the best time to land the attack randomly varies by 0.2 seconds. | |||
==== Medium ==== | |||
* Ability and item usage gets a random delay of 0.3 to 0.6 seconds | |||
* Every 10 seconds, ability and item usage is disallowed for 3 seconds. | |||
* Whenever an ability or item is used, ability and item usage is disallowed for 3 seconds. | |||
* When attempting to last hit creeps, their estimation of the best time to land the attack randomly varies by 0.2 seconds. | |||
* When attempting to last hit allied creeps, their estimation of the best time to land the attack randomly varies by 0.1 seconds. | |||
==== Hard ==== | |||
* Ability and item usage gets a random delay of 0.1 to 0.2 seconds. | |||
==== Unfair ==== | |||
* Ability and item usage gets a random delay of 0.075 to 0.15 seconds. | |||
* XP and Gold earned gets a 25% bonus. | |||
== Debugging == | |||
There are a number of commands that help you debug what's happening with bots. | |||
<br /> | |||
''dota_bot_debug_team'' | |||
Brings up a panel for the specified team (2 is Radiant, 3 is Dire) that displays: | |||
* Team-level desires for pushing/defending/farming lanes, and Roshan. | |||
* Bot names and levels | |||
* Bot current and maximum "power" levels (see Appendex D for how power levels are calculated). Can be disabled with "dota_bot_debug_team_power 0". | |||
* Active modes, and those mode desires. | |||
* All modes for a bot ( individually collapsable), and each of those modes' desires. | |||
* Current bot action along with that action's target if applicable. | |||
* Total bot execution time for the overall team calculations, and each individual bot. | |||
It additionally enables the line-sphere rendering of dota_bot_select_debug for all bots on the specified team. | |||
<br /> | |||
''dota_bot_debug_grid''<br /> | |||
''dota_bot_debug_grid_cycle''<br /> | |||
''dota_bot_debug_minimap''<br /> | |||
''dota_bot_debug_minimap_cycle''<br /> | |||
Causes a grid to draw on the world or the minimap. The *_cycle variants just cycle through all the values, whereas the other commands just set the mode directly. | |||
* 0 - Off | |||
* 1 - Radiant avoidance | |||
* 2 - Dire avoidance | |||
* 3 - Potential enemy locations for the Radiant | |||
* 4 - Potential enemy locations for the Dire | |||
* 5 - Enemy visibility to the Radiant | |||
* 6 - Enemy visibility to the Dire | |||
* 7 - Height Values | |||
* 8 - Passability | |||
<br /> | |||
''dota_bot_select_debug'' | |||
Activates the following displays on the under-the-cursor bot: | |||
* The current mode and action of the selected bot. | |||
* A white line-sphere list to it current pathfind. | |||
* A blue line-sphere to its current laning last-hit target. | |||
* A red line-sphere to its current attack target. | |||
<br /> | |||
''dota_bot_select_debug_attack'' | |||
Displays how much the under-the-cursor bot wants to attack any nearby enemies. | |||
<br /> | |||
''dota_bot_debug_clear'' | |||
Clears the dota_bot_select_debug and dota_bot_select_debug_attack states of the under-the-cursor bot. | |||
<br /> | |||
''dota_bot_debug_lanes'' | |||
Shows the path of all of the lanes, along with a sphere at the "lane front". | |||
<br /> | |||
''dota_bot_debug_ward_locations'' | |||
Shows small yellow spheres at each of ward locations the bots will consider. |
Revision as of 11:05, 11 December 2016
Overview
Bot scripting in Dota is done via lua scripting. This is done at the server level, so there's no need to do things like examine screen pixels or simulate mouse clicks; instead scripts can query the game state and issue orders directly to units. Scripts have full have access to all the entity locations, cooldowns, mana values, etc that a player on that team would expect to. The API is restricted such that scripts can't cheat -- units in FoW can't be queried, commands can't be issued to units the script doesn't control, etc.
In addition to lua scripting, the underlying C++ bot code still exists, and scripts can decide how much or little of the underlying bot structure to use.
Bots are organized into three levels of evaluation and decisionmaking:
Team Level
This is code that determines how much the overall team wants to push each lane, defend each lane, farm each lane, or kill Roshan. These desires exist independent of the state of any of the bots. They are not authoritative; that is, they do not dictate any actions taken by any of the bots. They are instead just desires that the bots can use for decisionmaking.
Mode Level
Modes are the high-level desires that individual bots are constantly evaluating, with the highest-scoring mode being their currently active mode. Examples of modes are laning, trying to kill a unit, farming, retreating, and pushing a tower.
Action Level
Actions are the individual things that bots are actively doing on a moment-to-moment basis. These loosely correspond to mouse clicks or button presses -- things like moving to a location, or attacking a unit, or using an ability, or purchasing an item.
The overall flow is that the team level is providing top-level guidance on the current strategy of the team. Each bot is then evaluating their desire score for each of its modes, which are taking into account both the team-level desires as well as bot-level desires. The highest scoring mode becomes the active mode, which is solely responsible for issuing actions for the bot to perform.
Directory Structure
All in-development bot scripts live in the game/dota/scripts/vscripts/bots directory within your Dota 2 install. When you upload your bot script to the workshop, it will upload the contents of this directory. Downloaded scripts live in their own location within your Steam install.
The bot scripting API is structured such that there are multiple elements that can be independently implemented by bot scripts. What logic is overriden is determined by which functions you implement and the files in which they are implemented.
Each of the following scripting elements has its own script scope.
Complete takeover
If you'd like to completely take over control of a hero, you can implement a Think() function in a file called bot_generic.lua, which is called every frame in lieu of the normal bot thinking code. This will completely take over all bots -- no team-level or mode-level thinking will happen. You will be responsible for issuing all action-level commands to all bots. If you'd like to just take over a specific hero's bot, for example Lina, you can implement a Think() function in a file called bot_lina.lua.
Bots that have been completely taken over still respect the difficulty modifiers (see Appendix B), and still calculate their estimated damage.
Mode Override
If you'd like to work within the existing mode architecture but override the logic for mode desire and behavior, for example the Laning mode, you can implement the following functions in a mode_laning_generic.lua file:
- GetDesire() - Called every frame, and needs to return a floating-point value between 0 and 1 that indicates how much this mode wants to be the active mode.
- OnStart() - Called when a mode takes control as the active mode.
- OnEnd() - Called when a mode relinquishes control to another active mode.
- Think() - Called every frame while this is the active mode. Responsible for issuing actions for the bot to take.
You can additionally just override the mode logic for a specific hero, such as Lina, with a mode_laning_lina.lua file. Please see Appendix A for implementation details if you'd like to chain calls from a hero-specific mode override back to a generic mode override.
The list of valid bot modes to override are:
- laning
- attack
- roam
- retreat
- secret_shop
- side_shop
- rune
- push_tower_top
- push_tower_mid
- push_tower_bot
- defend_tower_top
- defend_tower_mid
- defend_tower_bottom
- assemble
- team_roam
- farm
- defend_ally
- evasive_maneuvers
- roshan
- item
- ward
Ability and Item usage
If you'd like to just override decisionmaking around ability and item usage, you can implement the following functions in an ability_item_usage_generic.lua file:
- ItemUsageThink() - Called every frame. Responsible for issuing item usage actions.
- AbilityUsageThink() - Called every frame. Responsible for issuing ability usage actions.
- CourierUsageThink() - Called every frame. Responsible for issuing commands to the courier.
- BuybackUsageThink() - Called every frame. Responsible for issuing a command to buyback.
If any of these functions are not implemented, it will fall back to the default C++ implementation.
You can additionally just override the ability/item usage logic for a single hero, such as Lina, with an ability_item_usage_lina.lua file. Please see Appendix A for implementation details if you'd like to chain calls from a hero-specific item/ability implementation back to a generic item/ability implementation.
Item Purchasing
If you'd like to just override decisionmaking around item purchasing, you can implement the following function in an item_purchase_generic.lua file:
- ItemPurchaseThink() - Called every frame. Responsible for purchasing items.
You can additionally just override the item purchasing logic for a single hero, such as Lina, with an item_purchase_lina.lua file.
Team Level Desires
If you'd like to supply team-level desires, you can implement the following functions in a team_desires.lua file:
- UpdatePushLaneDesires() - Called every frame. Returns floating point values between 0 and 1 that represent the desires for pushing the top, middle, and bottom lanes, respectively.
- UpdateDefendLaneDesires() - Called every frame. Returns floating point values between 0 and 1 that represent the desires for defending the top, middle, and bottom lanes, respectively.
- UpdateFarmLaneDesires() - Called every frame. Returns floating point values between 0 and 1 that represent the desires for farming the top, middle, and bottom lanes, respectively.
- UpdateRoamDesire() - Called every frame. Returns a floating point value between 0 and 1 and a unit handle that represents the desire for someone to roam and gank a specified target.
- UpdateRoshanDesire() - Called every frame. Returns a floating point value between 0 and 1 that represents the desire for the team to kill Roshan.
If any of these functions are not implemented, it will fall back to the default C++ implementation.
Hero Selection
If you'd like to handle hero picking and lane assignment, you can implement the following functions in a hero_selection.lua file:
- Think() - Called every frame. Responsible for selecting heroes for bots.
- UpdateLaneAssignments() - Called every frame prior to the game starting. Returns ten PlayerID-Lane pairs.
API Reference
There are two basic levels at which the API is available: globally, and on individual units. The following is a list of functions available at each level.
Global
(details WIP)
- GetBot
- GetTeam
- GetTeamMember
- DotaTime
- GameTime
- RealTime
- GetUnitToUnitDistance
- GetUnitToLocationDistance
- GetWorldBounds
- IsLocationPassable
- GetHeightLevel
- GetLocationAlongLane
- GetNeutralSpawners
- GetItemCost
- IsItemPurchasedFromSecretShop
- IsItemPurchasedFromSideShop
- GetItemStockCount
- GetPushLaneDesire
- GetDefendLaneDesire
- GetFarmLaneDesire
- GetRoamDesire
- GetRoamTarget
- GetRoshanDesire
- int GetGameState()
- Returns the current game state [LINK HERE]
- float GetGameStateTimeRemaining()
- Returns how much time is remaining in the curren game state, if applicable
- int GetGameMode()
- Returns the current game mode [LINK HERE]
- int GetHeroPickState()
- Returns the current hero pick state [LINK HERE]
- IsPlayerInHeroSelectionControl
- SelectHero
- GetSelectedHeroName
- IsInCMBanPhase
- IsInCMPickPhase
- GetCMPhaseTimeRemaining
- GetCMCaptain
- SetCMCaptain
- IsCMBannedHero
- IsCMPickedHero
- CMBanHero
- CMPickHero
- RandomInt
- RandomFloat
- RandomYawVector
- RollPercentage
- Min
- Max
- Clamp
- RemapVal
- RemapValClamped
- DebugDrawLine
- DebugDrawCircle
- DebugDrawText
Unit-Scoped
- Action_ClearActions
- Action_MoveToLocation
- Action_MoveToUnit
- Action_AttackUnit
- Action_AttackMove
- Action_UseAbility
- Action_UseAbilityOnEntity
- Action_UseAbilityOnLocation
- Action_UseAbilityOnTree
- Action_PickUpRune
- Action_PickUpItem
- Action_DropItem
- Action_PurchaseItem
- Action_SellItem
- Action_Buyback
- Action_LevelAbility
- GetDifficulty
- GetUnitName
- GetPlayer
- IsHero
- IsCreep
- IsTower
- IsBuilding
- IsFort
- IsIllusion
- CanBeSeen
- GetActiveMode
- GetActiveModeDesire
- GetHealth
- GetMaxHealth
- GetMana
- GetMaxMana
- IsAlive
- GetRespawnTime
- HasBuyback
- GetGold
- GetStashValue
- GetCourierValue
- GetLocation
- GetFacing
- GetGroundHeight
- GetAbilityByName
- GetItemInSlot
- IsChanneling
- IsUsingAbility
- GetVelocity
- GetAttackTarget
- GetLastSeenLocation
- GetTimeSinceLastSeen
- IsRooted
- IsDisarmed
- IsAttackImmune
- IsSilenced
- IsMuted
- IsStunned
- IsHexed
- IsInvulnerable
- IsMagicImmune
- IsNightmared
- IsBlockDisabled
- IsEvadeDisabled
- IsUnableToMiss
- IsSpeciallyDeniable
- IsDominated
- IsBlind
- HasScepter
- WasRecentlyDamagedByAnyHero
- WasRecentlyDamagedByHero
- TimeSinceDamagedByAnyHero
- TimeSinceDamagedByHero
- DistanceFromFountain
- DistanceFromSideShop
- DistanceFromSecretShop
- SetTarget
- GetTarget
- SetNextItemPurchaseValue
- GetNextItemPurchaseValue
- GetAssignedLane
- GetEstimatedDamageToTarget
- GetStunDuration
- GetSlowDuration
- HasBlink
- HasMinistunOnAttack
- HasSilence
- HasInvisibility
- UsingItemBreaksInvisibility
- GetNearbyHeroes
- GetNearbyTowers
- GetNearbyCreeps
- FindAoELocation
- GetExtrapolatedLocation
- GetMovementDirectionStability
- GetActualDamage
Bot Difficulties
There are five bot difficulties:
Passive
- Cannot use abilities or items or the courier.
- Will always remaining in laning mode.
- When attempting to last hit creeps, their estimation of the best time to land the attack randomly varies by 0.4 seconds.
- When attempting to last hit allied creeps, their estimation of the best time to land the attack randomly varies by 0.2 seconds.
Easy
- Ability and item usage gets a random delay of 0.5 to 1.0 seconds
- Every 8 seconds, ability and item usage is disallowed for 6 seconds.
- Whenever an ability or item is used, ability and item usage is disallowed for 6 seconds.
- When attempting to last hit enemy creeps, their estimation of the best time to land the attack randomly varies by 0.4 seconds.
- When attempting to last hit allied creeps, their estimation of the best time to land the attack randomly varies by 0.2 seconds.
Medium
- Ability and item usage gets a random delay of 0.3 to 0.6 seconds
- Every 10 seconds, ability and item usage is disallowed for 3 seconds.
- Whenever an ability or item is used, ability and item usage is disallowed for 3 seconds.
- When attempting to last hit creeps, their estimation of the best time to land the attack randomly varies by 0.2 seconds.
- When attempting to last hit allied creeps, their estimation of the best time to land the attack randomly varies by 0.1 seconds.
Hard
- Ability and item usage gets a random delay of 0.1 to 0.2 seconds.
Unfair
- Ability and item usage gets a random delay of 0.075 to 0.15 seconds.
- XP and Gold earned gets a 25% bonus.
Debugging
There are a number of commands that help you debug what's happening with bots.
dota_bot_debug_team
Brings up a panel for the specified team (2 is Radiant, 3 is Dire) that displays:
- Team-level desires for pushing/defending/farming lanes, and Roshan.
- Bot names and levels
- Bot current and maximum "power" levels (see Appendex D for how power levels are calculated). Can be disabled with "dota_bot_debug_team_power 0".
- Active modes, and those mode desires.
- All modes for a bot ( individually collapsable), and each of those modes' desires.
- Current bot action along with that action's target if applicable.
- Total bot execution time for the overall team calculations, and each individual bot.
It additionally enables the line-sphere rendering of dota_bot_select_debug for all bots on the specified team.
dota_bot_debug_grid
dota_bot_debug_grid_cycle
dota_bot_debug_minimap
dota_bot_debug_minimap_cycle
Causes a grid to draw on the world or the minimap. The *_cycle variants just cycle through all the values, whereas the other commands just set the mode directly.
- 0 - Off
- 1 - Radiant avoidance
- 2 - Dire avoidance
- 3 - Potential enemy locations for the Radiant
- 4 - Potential enemy locations for the Dire
- 5 - Enemy visibility to the Radiant
- 6 - Enemy visibility to the Dire
- 7 - Height Values
- 8 - Passability
dota_bot_select_debug
Activates the following displays on the under-the-cursor bot:
- The current mode and action of the selected bot.
- A white line-sphere list to it current pathfind.
- A blue line-sphere to its current laning last-hit target.
- A red line-sphere to its current attack target.
dota_bot_select_debug_attack
Displays how much the under-the-cursor bot wants to attack any nearby enemies.
dota_bot_debug_clear
Clears the dota_bot_select_debug and dota_bot_select_debug_attack states of the under-the-cursor bot.
dota_bot_debug_lanes
Shows the path of all of the lanes, along with a sphere at the "lane front".
dota_bot_debug_ward_locations
Shows small yellow spheres at each of ward locations the bots will consider.