diff --git a/dotaservice/__init__.py b/dotaservice/__init__.py index 80eb7f9..bfeb9e7 100644 --- a/dotaservice/__init__.py +++ b/dotaservice/__init__.py @@ -1 +1 @@ -__version__ = '0.3.3' +__version__ = '0.3.4' diff --git a/dotaservice/dotaservice.py b/dotaservice/dotaservice.py index 81f87c0..d6f0835 100644 --- a/dotaservice/dotaservice.py +++ b/dotaservice/dotaservice.py @@ -34,6 +34,7 @@ logger = logging.getLogger(__name__) LUA_FILES_GLOB = pkg_resources.resource_filename('dotaservice', 'lua/*.lua') +LUA_FILES_GLOB_ACTIONS = pkg_resources.resource_filename('dotaservice', 'lua/actions/*.lua') def verify_game_path(game_path): @@ -156,6 +157,13 @@ def _create_bot_path(self): for filename in lua_files: shutil.copy(filename, bot_path) + # Copy all the bot action files into the actions subdirectory + action_path = os.path.join(bot_path, "actions") + os.mkdir(action_path) + action_files = glob.glob(LUA_FILES_GLOB_ACTIONS) + for filename in action_files: + shutil.copy(filename, action_path) + # shutil.copy('/Users/tzaman/dev/dotaservice/botcpp/botcpp_radiant.so', bot_path) # Finally, symlink DOTA to this folder. diff --git a/dotaservice/lua/action_processor.lua b/dotaservice/lua/action_processor.lua new file mode 100644 index 0000000..5ce2096 --- /dev/null +++ b/dotaservice/lua/action_processor.lua @@ -0,0 +1,100 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local pprint = require( "bots/pprint" ) + +-- Atomic Actions +local actionGlyph = require( "bots/actions/atomic_glyph" ) +local actionLevelAbility = require( "bots/actions/atomic_level_ability" ) + +-- Hero Functions +local actionNone = require( "bots/actions/none" ) +local actionClearAction = require( "bots/actions/clear" ) +local actionBuyback = require( "bots/actions/buyback" ) +local actionChat = require( "bots/actions/chat" ) + +--local actionMoveToLocation = require( "bots/actions/move_to_location" ) +local actionMoveDirectly = require( "bots/actions/move_directly" ) +local actionAttackUnit = require( "bots/actions/attack_unit" ) + +local actionUseAbilityOnEntity = require( "bots/actions/use_ability_on_entity" ) +local actionUseAbilityOnLocation= require( "bots/actions/use_ability_on_location" ) +local actionUseAbilityOnTree = require( "bots/actions/use_ability_on_tree" ) +local actionUseAbility = require( "bots/actions/use_ability" ) +local actionToggleAbility = require( "bots/actions/toggle_ability" ) + +-- Global Variables +ABILITY_STANDARD = 0 +ABILITY_PUSH = 1 +ABILITY_QUEUE = 2 + +local ActionProcessor = {} + +LookUpTable = { + ['DOTA_UNIT_ORDER_NONE'] = actionNone, + ['DOTA_UNIT_ORDER_MOVE_TO_POSITION'] = actionMoveDirectly, + ['DOTA_UNIT_ORDER_ATTACK_TARGET'] = actionAttackUnit, + ['DOTA_UNIT_ORDER_GLYPH'] = actionGlyph, + ['DOTA_UNIT_ORDER_STOP'] = actionClearAction, + ['DOTA_UNIT_ORDER_TRAIN_ABILITY'] = actionLevelAbility, + ['DOTA_UNIT_ORDER_BUYBACK'] = actionBuyback, + ['ACTION_CHAT'] = actionChat, + ['DOTA_UNIT_ORDER_CAST_POSITION'] = actionUseAbilityOnLocation, + ['DOTA_UNIT_ORDER_CAST_TARGET'] = actionUseAbilityOnEntity, + ['DOTA_UNIT_ORDER_CAST_TARGET_TREE'] = actionUseAbilityOnTree, + ['DOTA_UNIT_ORDER_CAST_NO_TARGET'] = actionUseAbility, + ['DOTA_UNIT_ORDER_CAST_TOGGLE'] = actionToggleAbility, +} + +local function table_length(tbl) + local lenNum = 0 + for k,v in pairs(tbl) do + lenNum = lenNum + 1 + end + return lenNum +end + +function ActionProcessor:Run(hBot, tblActions) + if table_length(tblActions) == 0 then + print("Got EMPTY tblActions") + -- If we have no action, draw a big red circle around the hero. + DebugDrawCircle(hBot:GetLocation(), 200, 255, 0, 0) + do return end + end + + -- print('Actions: ', pprint.pformat(tblActions)) + + for key, value in pairs(tblActions) do + local cmd = LookUpTable[key] + if cmd ~= nil then + -- print("Executing Action: ", cmd.Name) + -- NOTE: It is assumed that the first arguement (if args required) + -- will be the handle to the bot, followed by arguments + -- provided by the `agent`. + -- `Agent` args are double nested lists [[]], as some args + -- specify a location. + -- Example: [[-7000,-7000,128], [2]] + -- to do a move_to_location (X,Y,Z) in Queued fashion + if cmd.NumArgs == 2 then + cmd:Call(hBot, value[1]) + elseif cmd.NumArgs == 3 then + cmd:Call(hBot, value[1], value[2]) + elseif cmd.NumArgs == 0 then + cmd:Call() + elseif cmd.NumArgs == 1 then + cmd:Call(hBot) + elseif cmd.NumArgs == 4 then + cmd:Call(hBot, value[1], value[2], value[3]) + else + print("Unimplemented number of Cmd Args for ", cmd.Name, ": ", cmd.NumArgs) + -- DebugPause() + do return end + end + else + print(" [", key, "] does not exist in action table!") + end + end +end + +return ActionProcessor diff --git a/dotaservice/lua/actions/atomic_glyph.lua b/dotaservice/lua/actions/atomic_glyph.lua new file mode 100644 index 0000000..1776e29 --- /dev/null +++ b/dotaservice/lua/actions/atomic_glyph.lua @@ -0,0 +1,18 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local ActionGlyph = {} + +ActionGlyph.Name = "Glyph Action" +ActionGlyph.NumArgs = 1 + +------------------------------------------------- + +function ActionGlyph:Call(hHero) + hHero:ActionImmediate_Glyph() +end + +------------------------------------------------- + +return ActionGlyph diff --git a/dotaservice/lua/actions/atomic_level_ability.lua b/dotaservice/lua/actions/atomic_level_ability.lua new file mode 100644 index 0000000..10b3c94 --- /dev/null +++ b/dotaservice/lua/actions/atomic_level_ability.lua @@ -0,0 +1,31 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local LevelAbility = {} + +LevelAbility.Name = "Level Ability" +LevelAbility.NumArgs = 2 + +------------------------------------------------- + +function LevelAbility:Call( hHero, sAbilityName ) + print("Leveling: ", sAbilityName[1]) + -- Sanity Check + local nAbilityPoints = hHero:GetAbilityPoints() + if nAbilityPoints > 0 then + -- Another sanity check + local hAbility = hHero:GetAbilityByName(sAbilityName[1]) + if hAbility and hAbility:CanAbilityBeUpgraded() then + -- actually do the leveling + hHero:ActionImmediate_LevelAbility(sAbilityName[1]) + else + print("Trying to level an ability I cannot", sAbilityName[1]) + do return end + end + end +end + +------------------------------------------------- + +return LevelAbility diff --git a/dotaservice/lua/actions/attack_unit.lua b/dotaservice/lua/actions/attack_unit.lua new file mode 100644 index 0000000..ccea63e --- /dev/null +++ b/dotaservice/lua/actions/attack_unit.lua @@ -0,0 +1,41 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local AttackUnit = {} + +AttackUnit.Name = "Attack Unit" +AttackUnit.NumArgs = 4 + +------------------------------------------------- +function AttackUnit:Call( hUnit, hTarget, bOnce, iType ) + hTarget = hTarget[1] + if hTarget == -1 then -- Invalid target. Do nothing. + do return end + end + hTarget = GetBotByHandle(hTarget) + + iType = iType[1] + + -- Note: we do not test if target can be attacked due + -- to modifiers (e.g., invulnerable), range, or any + -- debuffs on the hUnit (e.g., disarmed). We assume + -- only valid and legal actions are agent selected + if not hTarget:IsNull() and hTarget:IsAlive() then + vLoc = hTarget:GetLocation() + DebugDrawCircle(vLoc, 25, 255, 0, 0) + DebugDrawLine(hUnit:GetLocation(), vLoc, 255, 0, 0) + + bOnce = bOnce[1] + if iType == nil or iType == ABILITY_STANDARD then + hUnit:Action_AttackUnit(hTarget, bOnce) + elseif iType == ABILITY_PUSH then + hUnit:ActionPush_AttackUnit(hTarget, bOnce) + elseif iType == ABILITY_QUEUE then + hUnit:ActionQueue_AttackUnit(hTarget, bOnce) + end + end +end +------------------------------------------------- + +return AttackUnit diff --git a/dotaservice/lua/actions/buyback.lua b/dotaservice/lua/actions/buyback.lua new file mode 100644 index 0000000..19e97e4 --- /dev/null +++ b/dotaservice/lua/actions/buyback.lua @@ -0,0 +1,20 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local ActionBuyback = {} + +ActionBuyback.Name = "Buyback Action" +ActionBuyback.NumArgs = 1 + +------------------------------------------------- + +function ActionBuyback:Call( hHero ) + if not hHero:IsAlive() then + hHero:ActionImmediate_Buyback() + end +end + +------------------------------------------------- + +return ActionBuyback diff --git a/dotaservice/lua/actions/chat.lua b/dotaservice/lua/actions/chat.lua new file mode 100644 index 0000000..54e51cf --- /dev/null +++ b/dotaservice/lua/actions/chat.lua @@ -0,0 +1,18 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local Chat = {} + +Chat.Name = "Chat" +Chat.NumArgs = 3 + +------------------------------------------------- + +function Chat:Call( hHero, sMsg, bAllChat ) + hHero:ActionImmediate_Chat(sMsg[1], bAllChat[1]) +end + +------------------------------------------------- + +return Chat diff --git a/dotaservice/lua/actions/clear.lua b/dotaservice/lua/actions/clear.lua new file mode 100644 index 0000000..5294709 --- /dev/null +++ b/dotaservice/lua/actions/clear.lua @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local ActionClear = {} + +ActionClear.Name = "Clear Action" +ActionClear.NumArgs = 2 + +local function toboolean(number) + if number >= 1 then return true end + return false +end + +------------------------------------------------- + +function ActionClear:Call( hHero, bStop ) + hHero:Action_ClearActions(toboolean(bStop[1])) +end + +------------------------------------------------- + +return ActionClear diff --git a/dotaservice/lua/actions/move_directly.lua b/dotaservice/lua/actions/move_directly.lua new file mode 100644 index 0000000..4581514 --- /dev/null +++ b/dotaservice/lua/actions/move_directly.lua @@ -0,0 +1,42 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local MoveDirectly = {} + +MoveDirectly.Name = "Move Directly to Location" +MoveDirectly.NumArgs = 3 + +------------------------------------------------- + +function MoveDirectly:Call( hUnit, vLoc, iType ) + -- Note: we test for valid conditions here on hUnit, but we shouldn't + -- as the agent should only suggest legal and valid actions + if not hUnit:IsAlive() or hUnit:IsRooted() or hUnit:IsStunned() then + print("[ERROR] - MoveDirectly under death/root/stun") + do return end + end + + -- print("Moving to: <", vLoc[1],", " vLoc[2], "> from <", hUnit:GetLocation().x, ", ", hUnit:GetLocation().y, ">") + + iType = iType[1] + + vLoc = Vector(vLoc[1], vLoc[2], vLoc[3]) + DebugDrawCircle(vLoc, 25, 255, 255 ,255) + DebugDrawLine(hUnit:GetLocation(), vLoc, 255, 255, 255) + + if iType == nil or iType == ABILITY_STANDARD then + hUnit:Action_MoveDirectly(vLoc) + elseif iType == ABILITY_PUSH then + hUnit:ActionPush_MoveDirectly(vLoc) + elseif iType == ABILITY_QUEUE then + hUnit:ActionQueue_MoveDirectly(vLoc) + else + print("[ERROR] - Unknown iType: ", iType) + do return end + end +end + +------------------------------------------------- + +return MoveDirectly diff --git a/dotaservice/lua/actions/none.lua b/dotaservice/lua/actions/none.lua new file mode 100644 index 0000000..fa96ad2 --- /dev/null +++ b/dotaservice/lua/actions/none.lua @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local ActionNone = {} + +ActionNone.Name = "No Action" +ActionNone.NumArgs = 0 + +------------------------------------------------- + +function ActionNone:Call() + print("No Action") + DebugDrawCircle(GetBot():GetLocation(), 50, 127, 127, 127) +end + +------------------------------------------------- + +return ActionNone diff --git a/dotaservice/lua/actions/toggle_ability.lua b/dotaservice/lua/actions/toggle_ability.lua new file mode 100644 index 0000000..3cceaa7 --- /dev/null +++ b/dotaservice/lua/actions/toggle_ability.lua @@ -0,0 +1,21 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local ToggleAbility = {} + +ToggleAbility.Name = "Toggle Ability" +ToggleAbility.NumArgs = 2 + +------------------------------------------------- +function ToggleAbility:Call( hUnit, intAbilitySlot ) + local hAbility = hUnit:GetAbilityInSlot(intAbilitySlot[1]) + if not hAbility then + print('[ERROR]: ', hUnit:GetUnitName(), " failed to find ability in slot ", intAbilitySlot[1]) + do return end + end + hAbility:ToggleAutoCast() +end +------------------------------------------------- + +return ToggleAbility diff --git a/dotaservice/lua/actions/use_ability.lua b/dotaservice/lua/actions/use_ability.lua new file mode 100644 index 0000000..bbc8e37 --- /dev/null +++ b/dotaservice/lua/actions/use_ability.lua @@ -0,0 +1,32 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local UseAbility = {} + +UseAbility.Name = "Use Ability" +UseAbility.NumArgs = 3 + +------------------------------------------------- +function UseAbility:Call( hUnit, intAbilitySlot, iType ) + local hAbility = hUnit:GetAbilityInSlot(intAbilitySlot[1]) + if not hAbility then + print('[ERROR]: ', hUnit:GetUnitName(), " failed to find ability in slot ", intAbilitySlot[1]) + do return end + end + + iType = iType[1] + + -- Note: we do not test for range, mana/cooldowns or any debuffs on the hUnit (e.g., silenced). + + if iType == nil or iType == ABILITY_STANDARD then + hUnit:Action_UseAbility(hAbility) + elseif iType == ABILITY_PUSH then + hUnit:ActionPush_UseAbility(hAbility) + elseif iType == ABILITY_QUEUE then + hUnit:ActionQueue_UseAbility(hAbility) + end +end +------------------------------------------------- + +return UseAbility diff --git a/dotaservice/lua/actions/use_ability_on_entity.lua b/dotaservice/lua/actions/use_ability_on_entity.lua new file mode 100644 index 0000000..ef6da42 --- /dev/null +++ b/dotaservice/lua/actions/use_ability_on_entity.lua @@ -0,0 +1,46 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local UseAbilityOnEntity = {} + +UseAbilityOnEntity.Name = "Use Ability On Entity" +UseAbilityOnEntity.NumArgs = 4 + +------------------------------------------------- +function UseAbilityOnEntity:Call( hUnit, intAbilitySlot, hTarget, iType ) + hTarget = hTarget[1] + if hTarget == -1 then -- Invalid target. Do nothing. + do return end + end + hTarget = GetBotByHandle(hTarget) + + local hAbility = hUnit:GetAbilityInSlot(intAbilitySlot[1]) + if not hAbility then + print('[ERROR]: ', hUnit:GetUnitName(), " failed to find ability in slot ", intAbilitySlot[1]) + do return end + end + + iType = iType[1] + + -- Note: we do not test if target can be ability-targeted due + -- to modifiers (e.g., spell-immunity), range, mana/cooldowns + -- or any debuffs on the hUnit (e.g., silenced). We assume + -- only valid and legal actions are agent selected + if not hTarget:IsNull() and hTarget:IsAlive() then + local vLoc = hTarget:GetLocation() + DebugDrawCircle(vLoc, 25, 255, 0, 0) + DebugDrawLine(hUnit:GetLocation(), vLoc, 255, 0, 0) + + if iType == nil or iType == ABILITY_STANDARD then + hUnit:Action_UseAbilityOnEntity(hAbility, hTarget) + elseif iType == ABILITY_PUSH then + hUnit:ActionPush_UseAbilityOnEntity(hAbility, hTarget) + elseif iType == ABILITY_QUEUE then + hUnit:ActionQueue_UseAbilityOnEntity(hAbility, hTarget) + end + end +end +------------------------------------------------- + +return UseAbilityOnEntity diff --git a/dotaservice/lua/actions/use_ability_on_location.lua b/dotaservice/lua/actions/use_ability_on_location.lua new file mode 100644 index 0000000..718a556 --- /dev/null +++ b/dotaservice/lua/actions/use_ability_on_location.lua @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local UseAbilityOnLocation = {} + +UseAbilityOnLocation.Name = "Use Ability On Location" +UseAbilityOnLocation.NumArgs = 4 + +------------------------------------------------- +function UseAbilityOnLocation:Call( hUnit, intAbilitySlot, vLoc, iType ) + local hAbility = hUnit:GetAbilityInSlot(intAbilitySlot[1]) + if not hAbility then + print('[ERROR]: ', hUnit:GetUnitName(), " failed to find ability in slot ", intAbilitySlot[1]) + do return end + end + + vLoc = Vector(vLoc[1], vLoc[2], vLoc[3]) + + iType = iType[1] + + -- Note: we do not test if the location can be ability-targeted due + -- range, mana/cooldowns or any debuffs on the hUnit (e.g., silenced). + -- We assume only valid and legal actions are agent selected + + DebugDrawCircle(vLoc, 25, 255, 0, 0) + DebugDrawLine(hUnit:GetLocation(), vLoc, 255, 0, 0) + + if iType == nil or iType == ABILITY_STANDARD then + hUnit:Action_UseAbilityOnLocation(hAbility, vLoc) + elseif iType == ABILITY_PUSH then + hUnit:ActionPush_UseAbilityOnLocation(hAbility, vLoc) + elseif iType == ABILITY_QUEUE then + hUnit:ActionQueue_UseAbilityOnLocation(hAbility, vLoc) + end +end +------------------------------------------------- + +return UseAbilityOnLocation diff --git a/dotaservice/lua/actions/use_ability_on_tree.lua b/dotaservice/lua/actions/use_ability_on_tree.lua new file mode 100644 index 0000000..095ff16 --- /dev/null +++ b/dotaservice/lua/actions/use_ability_on_tree.lua @@ -0,0 +1,40 @@ +------------------------------------------------------------------------------- +--- AUTHOR: Nostrademous +------------------------------------------------------------------------------- + +local UseAbilityOnTree = {} + +UseAbilityOnTree.Name = "Use Ability On Tree" +UseAbilityOnTree.NumArgs = 4 + +------------------------------------------------- +function UseAbilityOnTree:Call( hUnit, intAbilitySlot, intTree, iType ) + local hAbility = hUnit:GetAbilityInSlot(intAbilitySlot[1]) + if not hAbility then + print('[ERROR]: ', hUnit:GetUnitName(), " failed to find ability in slot ", intAbilitySlot[1]) + do return end + end + + intTree = intTree[1] + + iType = iType[1] + + -- Note: we do not test if the tree can be ability-targeted due to + -- range, mana/cooldowns or any debuffs on the hUnit (e.g., silenced). + -- We assume only valid and legal actions are agent selected + + local vLoc = GetTreeLocation(intTree) + DebugDrawCircle(vLoc, 25, 255, 0, 0) + DebugDrawLine(hUnit:GetLocation(), vLoc, 255, 0, 0) + + if iType == nil or iType == ABILITY_STANDARD then + hUnit:Action_UseAbilityOnTree(hAbility, intTree) + elseif iType == ABILITY_PUSH then + hUnit:ActionPush_UseAbilityOnTree(hAbility, intTree) + elseif iType == ABILITY_QUEUE then + hUnit:ActionQueue_UseAbilityOnTree(hAbility, intTree) + end +end +------------------------------------------------- + +return UseAbilityOnTree diff --git a/dotaservice/lua/bot_generic.lua b/dotaservice/lua/bot_generic.lua index 9325e7a..2806273 100644 --- a/dotaservice/lua/bot_generic.lua +++ b/dotaservice/lua/bot_generic.lua @@ -1,6 +1,7 @@ local config = require('bots/config') local dkjson = require('game/dkjson') local pprint = require('bots/pprint') +local action_proc = require('bots/action_processor') local ACTION_FILENAME = 'bots/actions_t' .. GetTeam() local LIVE_CONFIG_FILENAME = 'bots/live_config_auto' @@ -10,44 +11,35 @@ local live_config = nil local function act(action) - if action == nil then - -- If we have no action, draw a big red circle around the hero. - DebugDrawCircle(bot:GetLocation(), 200, 255, 0, 0) - do return end - end - local bot = GetBot() - action_type = action.actionType - if action_type == 'DOTA_UNIT_ORDER_NONE' then - DebugDrawCircle(bot:GetLocation(), 50, 127, 127, 127) - elseif action_type == 'DOTA_UNIT_ORDER_MOVE_TO_POSITION' then - move_location = Vector(action.moveToLocation.location.x, action.moveToLocation.location.y) - DebugDrawLine(bot:GetLocation(), move_location, 255, 255, 255) - bot:Action_MoveDirectly(move_location) - elseif action_type == 'DOTA_UNIT_ORDER_ATTACK_TARGET' then - if action.attackTarget.target == -1 then -- Invalid target. Do nothing. - do return end - end - unit = GetBotByHandle(action.attackTarget.target) - - d = GetUnitToUnitDistance(bot, unit) - if d > bot:GetAttackRange() then - -- Too far, cannot attack - DebugDrawCircle(bot:GetLocation(), 200, 255, 0, 0) - do return end - end - if bot:GetTeam() == unit:GetTeam() then - -- Can only deny < 0.5 unit - if unit:GetHealth() / unit:GetMaxHealth() > 0.5 then - DebugDrawCircle(bot:GetLocation(), 200, 255, 0, 0) - do return end - end - end - - DebugDrawCircle(unit:GetLocation(), 50, 255, 0, 0) - bot:Action_AttackUnit(unit, action.attackTarget.once) - else - print('Invalid action_type=', action_type) + local tblActions = {} + if action.actionType == "DOTA_UNIT_ORDER_NONE" then + tblActions[action.actionType] = {} + elseif action.actionType == "DOTA_UNIT_ORDER_MOVE_TO_POSITION" then + tblActions[action.actionType] = {{action.moveToLocation.location.x, action.moveToLocation.location.y, 0.0}, {0}} + elseif action.actionType == "DOTA_UNIT_ORDER_ATTACK_TARGET" then + tblActions[action.actionType] = {{action.attackTarget.target}, {action.attackTarget.once}, {0}} + elseif action.actionType == "DOTA_UNIT_ORDER_TRAIN_ABILITY" then + tblActions[action.actionType] = {{action.trainAbility.ability}} + elseif action.actionType == "DOTA_UNIT_ORDER_GLYPH" then + tblActions[action.actionType] = {} + elseif action.actionType == "DOTA_UNIT_ORDER_STOP" then + tblActions[action.actionType] = {{1}} + elseif action.actionType == "DOTA_UNIT_ORDER_BUYBACK" then + tblActions[action.actionType] = {} + elseif action.actionType == "ACTION_CHAT" then + tblActions[action.actionType] = {{action.chat.message}, {action.chat.to_allchat}} + elseif action.actionType == "DOTA_UNIT_ORDER_CAST_POSITION" then + tblactions[action.actionType] = {{action.castLocation.abilitySlot}, {action.castLocation.location.x, action.castLocation.location.y, 0.0}, {0}} + elseif action.actionType == "DOTA_UNIT_ORDER_CAST_TARGET" then + tblactions[action.actionType] = {{action.castTarget.abilitySlot}, {action.castTarget.target}, {0}} + elseif action.actionType == "DOTA_UNIT_ORDER_CAST_TARGET_TREE" then + tblactions[action.actionType] = {{action.castTree.abilitySlot}, {action.castTree.tree}, {0}} + elseif action.actionType == "DOTA_UNIT_ORDER_CAST_NO_TARGET" then + tblactions[action.actionType] = {{action.cast.abilitySlot}, {0}} + elseif action.actionType == "DOTA_UNIT_ORDER_CAST_TOGGLE" then + tblactions[action.actionType] = {{action.castToggle.abilitySlot}} end + action_proc:Run(GetBot(), tblActions) end diff --git a/setup.py b/setup.py index d1b97c4..841e1e9 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="dotaservice", - version="0.3.3", + version="0.3.4", author="Tim Zaman", author_email="timbobel@gmail.com", description="DotaService is a service to play Dota 2 through gRPC",