272 lines
8.1 KiB
Lua
Executable File
272 lines
8.1 KiB
Lua
Executable File
require( "ai/boss_base" )
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
if CBossTimbersaw == nil then
|
|
CBossTimbersaw = class( {}, {}, CBossBase )
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function Precache( context )
|
|
PrecacheUnitByNameSync( "npc_dota_furion_treant_4", context, -1 )
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function Spawn( entityKeyValues )
|
|
if IsServer() then
|
|
if thisEntity == nil then
|
|
return
|
|
end
|
|
|
|
thisEntity.AI = CBossTimbersaw( thisEntity, 1.0 )
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:constructor( hUnit, flInterval )
|
|
CBossBase.constructor( self, hUnit, flInterval )
|
|
|
|
self.nTreeListener = ListenToGameEvent( "tree_cut", Dynamic_Wrap( getclass( self ), 'OnTreeCut' ), self )
|
|
self.bEnraged = false
|
|
self.nEnragePct = 60
|
|
self.nNumTreantsPerTree = 1
|
|
self.nMaxTreants = 40
|
|
|
|
self.me:SetThink( "OnBossTimbersawThink", self, "OnBossTimbersawThink", self.flDefaultInterval )
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:SetupAbilitiesAndItems()
|
|
CBossBase.SetupAbilitiesAndItems( self )
|
|
|
|
self.hWhirlingDeath = self.me:FindAbilityByName( "boss_timbersaw_whirling_death" )
|
|
if self.hWhirlingDeath ~= nil then
|
|
self.hWhirlingDeath.Evaluate = self.EvaluateWhirlingDeath
|
|
self.AbilityPriority[ self.hWhirlingDeath:GetAbilityName() ] = 4
|
|
end
|
|
|
|
self.hTimberChain = self.me:FindAbilityByName( "boss_timbersaw_timber_chain" )
|
|
if self.hTimberChain ~= nil then
|
|
self.hTimberChain.Evaluate = self.EvaluateTimberChain
|
|
self.AbilityPriority[ self.hTimberChain:GetAbilityName() ] = 5
|
|
end
|
|
|
|
self.hChakram = self.me:FindAbilityByName( "shredder_chakram" )
|
|
if self.hChakram ~= nil then
|
|
self.hChakram.Evaluate = self.EvaluateChakram
|
|
self.AbilityPriority[ self.hChakram:GetAbilityName() ] = 2
|
|
end
|
|
|
|
self.hReturnChakram = self.me:FindAbilityByName( "shredder_return_chakram" )
|
|
if self.hReturnChakram ~= nil then
|
|
self.hReturnChakram.Evaluate = self.EvaluateReturnChakram
|
|
self.AbilityPriority[ self.hReturnChakram:GetAbilityName() ] = 6
|
|
end
|
|
|
|
self.hChakram2 = self.me:FindAbilityByName( "shredder_chakram_2" )
|
|
if self.hChakram2 ~= nil then
|
|
self.hChakram2:SetActivated( true )
|
|
self.hChakram2:SetHidden( false )
|
|
self.hChakram2:UpgradeAbility( true )
|
|
self.hChakram2.Evaluate = self.EvaluateChakram2
|
|
self.AbilityPriority[ self.hChakram2:GetAbilityName() ] = 3
|
|
end
|
|
|
|
self.hReturnChakram2 = self.me:FindAbilityByName( "shredder_return_chakram_2" )
|
|
if self.hReturnChakram2 ~= nil then
|
|
self.hReturnChakram2.Evaluate = self.EvaluateReturnChakram2
|
|
self.AbilityPriority[ self.hReturnChakram2:GetAbilityName() ] = 7
|
|
end
|
|
|
|
self.hChakramDance = self.me:FindAbilityByName( "boss_timbersaw_chakram_dance" )
|
|
if self.hChakramDance then
|
|
self.hChakramDance.Evaluate = self.EvaluateChakramDance
|
|
self.AbilityPriority[ self.hChakramDance:GetAbilityName() ] = 1
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:OnTreeCut( event )
|
|
|
|
if self.me:IsNull() or not self.me:IsAlive() then
|
|
StopListeningToGameEvent( self.nTreeListener )
|
|
return
|
|
end
|
|
|
|
if self.Encounter and self.Encounter.SpawnedSecondaryEnemies and #self.Encounter.SpawnedSecondaryEnemies > self.nMaxTreants then
|
|
--print( "Timbersaw is not creating more treants; hit the maximum alive!" )
|
|
return
|
|
end
|
|
|
|
local vLocation = Vector( event.tree_x, event.tree_y, 0 )
|
|
for i=1,self.nNumTreantsPerTree do
|
|
local hTreant = CreateUnitByName( "npc_dota_creature_timbersaw_treant", vLocation, true, self.me, self.me:GetOwner(), self.me:GetTeamNumber() )
|
|
if hTreant ~= nil then
|
|
hTreant:SetControllableByPlayer( self.me:GetPlayerOwnerID(), false )
|
|
hTreant:SetOwner( self.me )
|
|
hTreant.bBossMinion = true
|
|
self.Encounter:SuppressRewardsOnDeath( hTreant )
|
|
|
|
if #self.hPlayerHeroes > 0 then
|
|
hTreant:SetInitialGoalEntity( self.hPlayerHeroes[ RandomInt( 1, #self.hPlayerHeroes ) ] )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:OnBossTimbersawThink()
|
|
return self:OnBaseThink()
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:OnFirstSeen()
|
|
CBossBase.OnFirstSeen( self )
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:OnHealthPercentThreshold( nPct )
|
|
CBossBase.OnHealthPercentThreshold( self, nPct )
|
|
if nPct <= self.nEnragePct and self.bEnraged == false then
|
|
self.bEnraged = true
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:EvaluateWhirlingDeath()
|
|
local Enemies = shallowcopy( self.hPlayerHeroes )
|
|
Enemies = FilterEntitiesOutsideOfRange( self.me:GetAbsOrigin(), Enemies, self.hWhirlingDeath:GetSpecialValueFor( "whirling_radius" ) )
|
|
|
|
local Order = nil
|
|
if #Enemies >= 1 then
|
|
Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
|
|
AbilityIndex = self.hWhirlingDeath:entindex(),
|
|
Queue = false,
|
|
}
|
|
Order.flOrderInterval = GetSpellCastTime( self.hWhirlingDeath )
|
|
end
|
|
|
|
return Order
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:EvaluateTimberChain()
|
|
local Order = nil
|
|
local vTargetLocation = GetBestDirectionalPointTarget( self.hTimberChain )
|
|
if vTargetLocation ~= nil then
|
|
Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_CAST_POSITION,
|
|
Position = vTargetLocation,
|
|
AbilityIndex = self.hTimberChain:entindex(),
|
|
Queue = false,
|
|
}
|
|
Order.flOrderInterval = GetSpellCastTime( self.hTimberChain ) + 0.5 -- Factor in a little travel time
|
|
end
|
|
|
|
return Order
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:EvaluateChakram()
|
|
local Order = nil
|
|
local vTargetLocation = GetBestAOEPointTarget( self.hChakram )
|
|
if vTargetLocation ~= nil then
|
|
Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_CAST_POSITION,
|
|
Position = vTargetLocation,
|
|
AbilityIndex = self.hChakram:entindex(),
|
|
Queue = false,
|
|
}
|
|
Order.flOrderInterval = GetSpellCastTime( self.hChakram )
|
|
self.hReturnChakram:StartCooldown( RandomFloat( 1.5, 4.5 ) )
|
|
end
|
|
return Order
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:EvaluateChakram2()
|
|
local Order = nil
|
|
local vTargetLocation = GetBestAOEPointTarget( self.hChakram2 )
|
|
if vTargetLocation ~= nil then
|
|
Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_CAST_POSITION,
|
|
Position = vTargetLocation,
|
|
AbilityIndex = self.hChakram2:entindex(),
|
|
Queue = false,
|
|
}
|
|
Order.flOrderInterval = GetSpellCastTime( self.hChakram2 )
|
|
self.hReturnChakram2:StartCooldown( RandomFloat( 1.5, 4.5 ) )
|
|
end
|
|
return Order
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:EvaluateReturnChakram()
|
|
local Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
|
|
AbilityIndex = self.hReturnChakram:entindex(),
|
|
Queue = false,
|
|
}
|
|
|
|
Order.flOrderInterval = 0.1
|
|
return Order
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:EvaluateReturnChakram2()
|
|
local Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
|
|
AbilityIndex = self.hReturnChakram2:entindex(),
|
|
Queue = false,
|
|
}
|
|
|
|
Order.flOrderInterval = 0.1
|
|
return Order
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function CBossTimbersaw:EvaluateChakramDance()
|
|
local Order = nil
|
|
if self.bEnraged == true then
|
|
Order =
|
|
{
|
|
UnitIndex = self.me:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
|
|
AbilityIndex = self.hChakramDance:entindex(),
|
|
Queue = false,
|
|
}
|
|
|
|
Order.flOrderInterval = self.hChakramDance:GetChannelTime() + 0.2
|
|
end
|
|
return Order
|
|
end
|
|
|
|
-------------------------------------------------------------------------------- |