Skip to content
Tobias Mahlmann edited this page May 23, 2016 · 1 revision

The framework uses HTTP POST calls to communicate with your bot. It's similar to what your web browser does when you submit a form or click a button on a website. With simpler words: your bot has to provide a little webservice to take this calls. Unfortunately, that requires ai programmers to know a little bit about web programming, but we'll sort this out in the future.

For now, you have to set a URL in game/dota_addons/dota2ai/scripts/vscripts/config.lua to where your bot is waiting, e.g. http://localhost:8080/Dota2AIService/ . This is the base URL. Relative the base url, your bot has to provide a few URLs that I'll describe and discuss in the following. So if I'll name a function /test, that means that your bot provides http://localhost:8080/Dota2AIService/test . "Providing" here means that it accepts a POST request with the MIME type "application/json". The functions which return something also have to return "application/json" as MIME.

Without digressing too much into web programming, that also implies that all messages between the mod and your bot are formatted in JSON. So if talk below about a parameter "index" set to "0", that means that the function is actually supposed to return {"index":0}. Last words on web stuff: all HTTP return codes except 200 are treated as errors by the mod and piped to the console.

Keep also in mind, that the function calls are synchronized with the game, i.e. the time your bots needs for a reply, the game will wait. Thinking time will for sure be an issue in the future. For now, the game engine will just spit out warnings.

So the following is a dynamic list of functions that are currently implemented. Keep in mind that this is a live document and most functions, humans can do in the game, are not implemented yet.

#/reset# Reset is called when the game is launched and serves no other purpose than to tell your bot that a new match starts. If you have process running with your bot, this prevents to restart it every time your start a new game. Instead, reset your bot's internal state or something similar.

Input parameters: none

Return values: none

#/select# Select is called right before the game starts to determine which hero the game should spawn for you. The game mode is currently set to "all pick", so no restrictions are applied. The hero name is the internal name as listed here

Input parameters: none

Return values:

  • String hero - internal hero name
  • String command - SELECT (literal, added to harmonize all calls)

Example:

{"hero":"npc_dota_hero_lina","command":"SELECT"}

#/chat# Chat is called whenever another player submits a text message in the game. The message is simply transmitted to the bot and it may or may not react to it (Yay! Finally bots who flame back). This useful to interact with bots but also to test them, i.e. the mod currently starts in single player mode and the interface is not locked; meaning you can send commands to your own bot using the team chat.

Input parameters:

  • Boolean teamOnly - true if this was sent to the team chat, false if all chat
  • Integer player - the internal id of the player who said it
  • String text - the text of the message

Example:

{"teamOnly":false,"text":"Humans are n00bs!","player":5}

Return values: None

#/levelup# Level up is called when the bot's hero gained a level, or still has undistributed skill points. A bot may delay upgrading a skill or attribute (see below). Then, this function is called every tick until all skill points have been distributed. The skill indexes are ordered ascending with the ability upgrade being the last index. So, Lina's Dragon Slave is 0, Light Strike Array is 1, Fiery Soul 2, Laguna Blade 3 and Attribute Upgrade 4. To delay an upgrade, return -1 The mod discards any non-sensical value, e.g. upgrading an ability that has already been maxed out, and just call /levelup again.

Input parameters: None

Return values:

  • Integer abilityIndex - the ability to upgrade, or -1 to delay the upgrade

Example:

{"abilityIndex":0}

#/update# This is the main update loop, and called every time the game's internal state is updated. To my knowledge, this happens every 33ms. At the moment, the input parameter is the complete game state perceived by your hero in game. The game organises everything relevant to the logic in so called "entities". Each entity has an internal number and a class, describing what this entity actually is in the game. If you ever heard of "object oriented programming", you're familiar with the concept. Describing each class and what each of its properties means goes far beyond the scope of this document, but I list a few examples below. (Have a look at this page to get an idea. The relevant classes are derived from "CDOTA_BaseNPC")

Input parameters:

  • List entities - a comma separated list of pairs of Strings (the entity id) and entity data

Examples:

{
"entities": 
{
	"760": 
	{
		"level": 1,
		"mana": 0,
		"disarmed": false,
		"health": 1300,
		"alive": true,
		"attackRange": 700,
		"team": 3,
		"blind": false,
		"dominated": false,
		"origin": 
		[
			-4736,
			6016,
			383.99987792969
		],

		"type": "Tower",
		"rooted": false,
		"name": "dota_badguys_tower1_top",
		"deniable": false
	},

	"646": 
	{
		"level": 3,
		"mana": 0,
		"disarmed": false,
		"health": 550,
		"alive": true,
		"attackRange": 100,
		"team": 2,
		"blind": false,
		"dominated": false,
		"origin": 
		[
			-4658.5581054688,
			-4291.2250976563,
			384
		],

		"type": "BaseNPC",
		"rooted": false,
		"name": "npc_dota_creep_lane",
		"deniable": false
	},

	"345": 
	{
		"level": 1,
		"mana": 351,
		"disarmed": false,
		"alive": true,
		"health": 492,
		"abilities": 
		{
			"0": 
			{
				"targetFlags": 0,
				"targetTeam": 2,
				"abilityDamageType": 0,
				"level": 0,
				"abilityDamage": 0,
				"targetType": 19,
				"name": "lina_dragon_slave",
				"abilityType": 0
			},

			"1": 
			{
				"targetFlags": 0,
				"targetTeam": 0,
				"abilityDamageType": 0,
				"level": 0,
				"abilityDamage": 0,
				"targetType": 0,
				"name": "lina_light_strike_array",
				"abilityType": 0
			},

			"2": 
			{
				"targetFlags": 0,
				"targetTeam": 0,
				"abilityDamageType": 0,
				"level": 0,
				"abilityDamage": 0,
				"targetType": 0,
				"name": "lina_fiery_soul",
				"abilityType": 0
			},

			"3": 
			{
				"targetFlags": 16,
				"targetTeam": 2,
				"abilityDamageType": 0,
				"level": 0,
				"abilityDamage": 0,
				"targetType": 19,
				"name": "lina_laguna_blade",
				"abilityType": 1
			},

			"4": 
			{
				"targetFlags": 0,
				"targetTeam": 0,
				"abilityDamageType": 0,
				"level": 0,
				"abilityDamage": 0,
				"targetType": 0,
				"name": "attribute_bonus",
				"abilityType": 2
			}
		},

		"gold": 628,
		"attackRange": 670,
		"team": 2,
		"blind": false,
		"dominated": false,
		"origin": 
		[
			-6976,
			-6496,
			512
		],

		"type": "Hero",
		"rooted": false,
		"name": "npc_dota_hero_lina",
		"deniable": false
	},

	"326": 
	{
		"level": 3,
		"mana": 0,
		"disarmed": false,
		"health": 550,
		"alive": true,
		"attackRange": 100,
		"team": 3,
		"blind": false,
		"dominated": false,
		"origin": 
		[
			6326.2475585938,
			3643.0854492188,
			384
		],

		"type": "BaseNPC",
		"rooted": false,
		"name": "npc_dota_creep_lane",
		"deniable": false
	}
}
}

Return values The return value is the command the hero should be given. I'll list the options below. Like playing the game as a human, the hero will execute the last given last until something stops him or a new command is given, e.g. click on a spot on the ground and the hero moves there. In other words, your bot does not need to repeat commands. Instead, reply with a NOOP ("No operation") command.

##NOOP## Continue with whatever you're doing

{ "command" : "NOOP" }

##MOVE## Makes the hero move somewhere, much like a right click on the ground in the game. Enemies along the way are ignored. The game's internal path finding is used, i.e. if the coordinate is not accessible, the hero walks to the nearest empty position.

  • Float x - x-coordinate
  • Float y - y-coordinate
  • Float z - z-coordinate

X and Y specify the position on the map. Z is technically irrelevant, but changes between terrain and river.

Example:

{ "x" : "4000", "y" : "4000" , "z" : "380", "command" : "MOVE"}

Should move the hero to somewhat around the mid of the mid lane. I will post more on how to navigate on the map in a separate document.

##ATTACK## Equivalent of a right click on an enemy. The hero will more in attack range and start auto attacking. Note that this command requires a target. If the specified target does not exist or cannot be attacked, the hero will just move into attack range.

  • Integer target - the entity id of the target

Example:

{ "target" : 370 , "command" : "ATTACK"}

##CAST## Uses an ability. If the ability is not ready, skilled or otherwise unavailable, the command is ignored. Same goes for specifying the wrong parameters, e.g. a target for a location based ability or vice versa. The unrequired parameters are optional. Your bot needs to know what to pass here.

  • Float x - x-coordinate
  • Float y - y-coordinate
  • Float z - z-coordinate
  • Integer target - the target's entity id
  • Integer ability : the ability index (analogue to levelup)

Examples:

To cast Laguna Blade:

{ "command" , : "CAST" , "ability" : 3 , "target" : 370}

To cast Dragon Slave:

{ "command" , : "CAST" , "ability" : 0 , "x" : "4000", "y" : "4000" , "z" : "380"}

##BUY## Use this to buy an item into your inventory. If your hero is not in a shop or doesn't not have enough funds, this command is ignored. Unfortunately, I haven't figured out yet how to determine if the hero is in a side or secret shop, so your bot may actually cheat here by buying anything (much like SetUseUniversalShopMode = true).

  • String item - the name of the item. See this list

Example

{ "command" : "BUY" , "item" : "item_tango"}

##SELL## In opposite to BUY, SELL lets you sell items in a shop. Items to sell are identified by specifying the inventory slot (in case you have to items of the same type). Slots 0 to 5 are your hero's inventory, 6 to 12 the stash slots (selling from the latter doesn't work yet).

*Integer slot - the inventory slot. If that slot is empty, nothing happens

Example

{ "command" : "SELL" , "slot" : 0}

##USE_ITEM## There are many items in the game that have an active function. Via this command you can utilise these functions. Unfortunately, I'm not done yet implementing items that can be used on "something" (e.g. tangos on a tree) or "somebody" (e.g. euls on yourself) yet. However, you can use items like treads or similar. Items are, much like SELL, specified by their inventory slot.

  • Integer slot - the inventory slot. If that slot is empty, nothing happens

Example

{ "command" : "USE_ITEM" , "slot" : 0}
Clone this wiki locally