Files
2HUCardTDGame/aghanim_singleplayer/scripts/vscripts/ai/boss_base.lua
2021-10-24 15:36:18 -04:00

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
--------------------------------------------------------------------------------