206 lines
5.5 KiB
Lua
Executable File
206 lines
5.5 KiB
Lua
Executable File
require( "ai/shared" )
|
|
require( "ai/basic_spell_casting_ai" )
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
if CBossBase == nil then
|
|
CBossBase = class({})
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:constructor( hUnit, flInterval )
|
|
self.me = hUnit
|
|
self.flDefaultInterval = flInterval
|
|
self.AbilityPriority = {}
|
|
self.hPlayerHeroes = {}
|
|
self.QueuedOrders = {}
|
|
self.Encounter = nil
|
|
self.bSeenAnyEnemy = false
|
|
self.nLastHealthPct = 10000
|
|
self.flInitialAcquireRange = 1800
|
|
self.flAggroAcquireRange = 4500
|
|
|
|
self:SetupAbilitiesAndItems()
|
|
|
|
self.nAbilityListener = ListenToGameEvent( "dota_non_player_used_ability", Dynamic_Wrap( getclass( self ), 'OnNonPlayerUsedAbility' ), self )
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:SetupAbilitiesAndItems()
|
|
--empty
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:SetEncounter( Encounter )
|
|
self.Encounter = Encounter
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:OnBaseThink()
|
|
if self.me == nil or self.me:IsNull() or self.me:IsAlive() == false then
|
|
StopListeningToGameEvent( self.nAbilityListener )
|
|
return -1
|
|
end
|
|
|
|
Order = nil
|
|
|
|
if self.Encounter == nil or self.Encounter:HasStarted() == false then
|
|
return 0.01
|
|
end
|
|
|
|
if GameRules:IsGamePaused() then
|
|
return 0.01
|
|
end
|
|
|
|
local flRange = self.flInitialAcquireRange
|
|
if self.bSeenAnyEnemy == true then
|
|
flRange = self.flAggroAcquireRange
|
|
end
|
|
self.hPlayerHeroes = GetVisibleEnemyHeroesInRange( self.me, flRange )
|
|
|
|
if #self.hPlayerHeroes == 0 then
|
|
goto autoattack
|
|
elseif self.bSeenAnyEnemy == false then
|
|
self.bSeenAnyEnemy = true
|
|
self:OnFirstSeen()
|
|
end
|
|
|
|
if self.nLastHealthPct > self.me:GetHealthPercent() then
|
|
self.nLastHealthPct = self.me:GetHealthPercent()
|
|
self:OnHealthPercentThreshold( self.nLastHealthPct )
|
|
end
|
|
|
|
AbilitiesReady = self:GetReadyAbilitiesAndItems()
|
|
if #AbilitiesReady == 0 then
|
|
goto autoattack
|
|
end
|
|
|
|
if #self.QueuedOrders > 0 then
|
|
Order = self.QueuedOrders[ 1 ]
|
|
table.remove( self.QueuedOrders, 1 )
|
|
goto execute_order
|
|
else
|
|
for _,Ability in pairs ( AbilitiesReady ) do
|
|
if Ability.Evaluate ~= nil then
|
|
local TryOrder = Ability.Evaluate( self )
|
|
if TryOrder ~= nil then
|
|
Order = TryOrder
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
::autoattack::
|
|
|
|
NonAbilityOrder = nil
|
|
if Order == nil then
|
|
NonAbilityOrder = self:GetNonAbilityOrder()
|
|
if NonAbilityOrder ~= nil then
|
|
--print( 'NON ABILITY ORDER' )
|
|
Order = NonAbilityOrder
|
|
end
|
|
end
|
|
|
|
if Order == nil and #self.hPlayerHeroes > 0 then
|
|
--print( 'autoattack for ' .. self.flDefaultInterval )
|
|
Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_ATTACK_MOVE,
|
|
Position = self.hPlayerHeroes[ 1 ]:GetAbsOrigin(),
|
|
}
|
|
Order.flOrderInterval = self.flDefaultInterval
|
|
end
|
|
|
|
::execute_order::
|
|
if Order then
|
|
--print( 'Executing Order ' .. Order.OrderType .. ' and sleeping for ' .. Order.flOrderInterval )
|
|
ExecuteOrderFromTable( Order )
|
|
return Order.flOrderInterval
|
|
end
|
|
|
|
::idle::
|
|
return self.flDefaultInterval
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:GetReadyAbilitiesAndItems()
|
|
local AbilitiesReady = {}
|
|
for n=0,self.me:GetAbilityCount() - 1 do
|
|
local hAbility = self.me:GetAbilityByIndex( n )
|
|
if hAbility and hAbility:IsFullyCastable() and not hAbility:IsPassive() and not hAbility:IsHidden() and hAbility:IsActivated() then
|
|
--print( 'Adding ABILITY ' .. hAbility:GetAbilityName() )
|
|
if self.AbilityPriority[ hAbility:GetAbilityName() ] ~= nil then
|
|
table.insert( AbilitiesReady, hAbility )
|
|
end
|
|
end
|
|
end
|
|
|
|
for i = 0, DOTA_ITEM_MAX - 1 do
|
|
local hItem = self.me:GetItemInSlot( i )
|
|
if hItem and hItem:IsFullyCastable() and not hItem:IsPassive() and not hItem:IsHidden() and hItem:IsActivated() then
|
|
--print( 'Adding ITEM ' .. hItem:GetAbilityName() )
|
|
if self.AbilityPriority[ hItem:GetAbilityName() ] ~= nil then
|
|
table.insert( AbilitiesReady, hItem )
|
|
end
|
|
end
|
|
end
|
|
|
|
if #AbilitiesReady > 1 then
|
|
table.sort( AbilitiesReady, function( h1, h2 )
|
|
local nAbility1Priority = self.AbilityPriority[ h1:GetAbilityName() ]
|
|
local nAbility2Priority = self.AbilityPriority[ h2:GetAbilityName() ]
|
|
return nAbility1Priority > nAbility2Priority
|
|
end
|
|
)
|
|
end
|
|
|
|
return AbilitiesReady
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:GetNonAbilityOrder()
|
|
return nil
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:OnFirstSeen()
|
|
-- empty
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:OnHealthPercentThreshold( nPct )
|
|
-- empty
|
|
end
|
|
---------------------------------------------------------
|
|
-- dota_non_player_used_ability
|
|
-- * abilityname
|
|
-- * caster_entindex
|
|
---------------------------------------------------------
|
|
function CBossBase:OnNonPlayerUsedAbility( event )
|
|
|
|
local hCaster = nil
|
|
if event.caster_entindex ~= nil and event.abilityname ~= nil then
|
|
hCaster = EntIndexToHScript( event.caster_entindex )
|
|
if hCaster ~= nil and hCaster == self.me then
|
|
self:OnBossUsedAbility( event.abilityname )
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossBase:OnBossUsedAbility( szAbilityName )
|
|
-- empty
|
|
end
|
|
|
|
-------------------------------------------------------------------------------- |