initial commit
This commit is contained in:
271
aghanim_singleplayer/scripts/vscripts/ai/storegga.lua
Executable file
271
aghanim_singleplayer/scripts/vscripts/ai/storegga.lua
Executable file
@@ -0,0 +1,271 @@
|
||||
|
||||
function Spawn( entityKeyValues )
|
||||
if not IsServer() then
|
||||
return
|
||||
end
|
||||
|
||||
if thisEntity == nil then
|
||||
return
|
||||
end
|
||||
|
||||
thisEntity:AddNewModifier( nil, nil, "modifier_invulnerable", { duration = -1 } )
|
||||
|
||||
SlamAbility = thisEntity:FindAbilityByName( "storegga_arm_slam" )
|
||||
GrabAbility = thisEntity:FindAbilityByName( "storegga_grab" )
|
||||
ThrowAbility = thisEntity:FindAbilityByName( "storegga_grab_throw" )
|
||||
GroundPoundAbility = thisEntity:FindAbilityByName( "storegga_ground_pound" )
|
||||
AvalancheAbility = thisEntity:FindAbilityByName( "storegga_avalanche" )
|
||||
|
||||
thisEntity.flThrowTimer = 0.0 -- externally updated
|
||||
|
||||
thisEntity.fLongWaitTime = 5
|
||||
|
||||
thisEntity.fEnemySearchRange = 2500
|
||||
thisEntity.fRockSearchRange = 2500
|
||||
|
||||
thisEntity:SetContextThink( "StoreggaThink", StoreggaThink, 1 )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function StoreggaThink()
|
||||
if ( not thisEntity:IsAlive() ) then
|
||||
return -1
|
||||
end
|
||||
|
||||
if GameRules:IsGamePaused() == true then
|
||||
return 0.1
|
||||
end
|
||||
|
||||
if ( not thisEntity.bInitialInvulnRemoved ) then
|
||||
thisEntity:RemoveModifierByName( "modifier_invulnerable" )
|
||||
thisEntity.bInitialInvulnRemoved = true
|
||||
end
|
||||
|
||||
if thisEntity:IsChanneling() then
|
||||
return 0.1
|
||||
end
|
||||
|
||||
if AvalancheAbility ~= nil and AvalancheAbility:IsFullyCastable() and thisEntity:GetHealthPercent() < 60 then
|
||||
return CastAvalanche()
|
||||
end
|
||||
|
||||
local enemies = FindUnitsInRadius( thisEntity:GetTeamNumber(), thisEntity:GetOrigin(), nil, thisEntity.fEnemySearchRange, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE + DOTA_UNIT_TARGET_FLAG_INVULNERABLE, FIND_CLOSEST, false )
|
||||
local rocks = FindUnitsInRadius( thisEntity:GetTeamNumber(), thisEntity:GetOrigin(), nil, thisEntity.fRockSearchRange, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_CREEP, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE + DOTA_UNIT_TARGET_FLAG_INVULNERABLE, FIND_CLOSEST, false )
|
||||
|
||||
local nEnemiesAliveInRange = 0
|
||||
for i = 1, #enemies do
|
||||
local enemy = enemies[ i ]
|
||||
if enemy ~= nil then
|
||||
if enemy:IsRealHero() and enemy:IsAlive() then
|
||||
nEnemiesAliveInRange = nEnemiesAliveInRange + 1
|
||||
if enemy:FindModifierByName( "modifier_storegga_grabbed_debuff" ) ~= nil then
|
||||
--printf( "removed %s from enemies table", enemy:GetUnitName() )
|
||||
table.remove( enemies, i )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local hNearestEnemy = enemies[ 1 ]
|
||||
local hFarthestEnemy = enemies[ #enemies ]
|
||||
|
||||
local hGrabbedEnemyBuff = thisEntity:FindModifierByName( "modifier_storegga_grabbed_buff" )
|
||||
local hGrabbedTarget = nil
|
||||
if hGrabbedEnemyBuff == nil then
|
||||
if GrabAbility ~= nil and GrabAbility:IsFullyCastable() then
|
||||
if hNearestEnemy ~= nil and nEnemiesAliveInRange > 1 and RandomInt( 0, 1 ) == 0 then
|
||||
printf( " Grab the nearest enemy (%s)", hNearestEnemy:GetUnitName() )
|
||||
return CastGrab( hNearestEnemy )
|
||||
elseif #rocks > 0 then
|
||||
local hRandomRock = rocks[ RandomInt( 1, #rocks ) ]
|
||||
if hRandomRock ~= nil then
|
||||
printf( " Grab a random rock" )
|
||||
return CastGrab( hRandomRock )
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Note: hThrowObject and flThrowTimer are both set by the modifier
|
||||
local hGrabbedTarget = hGrabbedEnemyBuff.hThrowObject
|
||||
if GameRules:GetGameTime() > thisEntity.flThrowTimer and hGrabbedTarget ~= nil then
|
||||
if ThrowAbility ~= nil and ThrowAbility:IsFullyCastable() then
|
||||
if hFarthestEnemy ~= nil then
|
||||
printf( " Throw at the farthest enemy; pos: %s", hFarthestEnemy:GetOrigin() )
|
||||
return CastThrow( hFarthestEnemy:GetOrigin() )
|
||||
elseif #rocks > 0 then
|
||||
local hFarthestRock = rocks[ #rocks ]
|
||||
if hFarthestRock ~= nil then
|
||||
printf( " Throw at the farthest.. rock?; pos: %s", hFarthestRock:GetOrigin() )
|
||||
return CastThrow( hFarthestRock:GetOrigin() )
|
||||
end
|
||||
elseif GameRules:GetGameTime() > ( thisEntity.flThrowTimer + thisEntity.fLongWaitTime ) then
|
||||
printf( " a lot of time has passed and we're still holding onto an object, so just throw it somewhere pathable" )
|
||||
|
||||
-- If I've been waiting too long, throw grabbed object at some random location
|
||||
local nMaxDistance = 1400
|
||||
local vRandomThrowPos = nil
|
||||
|
||||
local nMaxAttempts = 7
|
||||
local nAttempts = 0
|
||||
|
||||
repeat
|
||||
if nAttempts > nMaxAttempts then
|
||||
vRandomThrowPos = nil
|
||||
printf( "WARNING - storegga - failed to find valid position for throw target pos" )
|
||||
break
|
||||
end
|
||||
|
||||
local vPos = thisEntity:GetAbsOrigin() + RandomVector( nMaxDistance )
|
||||
vRandomThrowPos = FindPathablePositionNearby( vPos, 0, 500 )
|
||||
nAttempts = nAttempts + 1
|
||||
until ( GridNav:CanFindPath( thisEntity:GetOrigin(), vRandomThrowPos ) )
|
||||
--until ( GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vRandomThrowPos ) )
|
||||
|
||||
if vRandomThrowPos == nil then
|
||||
printf( " never found a good random pos to throw to, so just use my own origin" )
|
||||
vRandomThrowPos = thisEntity:GetAbsOrigin()
|
||||
end
|
||||
|
||||
return CastThrow( vRandomThrowPos )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if GroundPoundAbility and GroundPoundAbility:IsFullyCastable() then
|
||||
local fGroundPoundSearchRadius = 1000
|
||||
local hGroundPoundEnemies = FindUnitsInRadius( thisEntity:GetTeamNumber(), thisEntity:GetOrigin(), nil, fGroundPoundSearchRadius, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES + DOTA_UNIT_TARGET_FLAG_FOW_VISIBLE + DOTA_UNIT_TARGET_FLAG_INVULNERABLE, FIND_CLOSEST, false )
|
||||
if #hGroundPoundEnemies > 0 then
|
||||
return CastGroundPound()
|
||||
end
|
||||
end
|
||||
|
||||
if SlamAbility ~= nil and SlamAbility:IsFullyCastable() then
|
||||
if RandomInt( 0, 1 ) == 1 then
|
||||
if hNearestEnemy ~= nil then
|
||||
--printf( "Slam the nearest enemy (%s)", hNearestEnemy:GetUnitName() )
|
||||
return CastSlam( hNearestEnemy )
|
||||
end
|
||||
else
|
||||
if hFarthestEnemy ~= nil then
|
||||
--printf( "Slam the farthest enemy (%s)", hFarthestEnemy:GetUnitName() )
|
||||
return CastSlam( hFarthestEnemy )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0.1
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function CastSlam( enemy )
|
||||
if enemy == nil or enemy:IsAlive() == false then
|
||||
return 0.1
|
||||
end
|
||||
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_CAST_TARGET,
|
||||
TargetIndex = enemy:entindex(),
|
||||
AbilityIndex = SlamAbility:entindex(),
|
||||
})
|
||||
|
||||
local fInterval = SlamAbility:GetCastPoint() + 0.1
|
||||
|
||||
-- Enemies may run away from us so we don't want to try to calculate exactly what our return interval should
|
||||
-- be (e.g. based on the distance and our movespeed), so for larger distances we're just adding a little extra time
|
||||
local fDistToEnemy = ( enemy:GetOrigin() - thisEntity:GetOrigin() ):Length2D()
|
||||
local fNearDistance = 800
|
||||
local fMediumDistance = 1300
|
||||
if fDistToEnemy > fMediumDistance then
|
||||
printf( " enemy is beyond medium distance" )
|
||||
fInterval = fInterval + 1.0
|
||||
elseif fDistToEnemy > fNearDistance then
|
||||
printf( " enemy is beyond near distance" )
|
||||
fInterval = fInterval + 0.5
|
||||
end
|
||||
|
||||
return fInterval
|
||||
--return 1.2
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function CastGrab( enemy )
|
||||
if enemy == nil or enemy:IsAlive() == false then
|
||||
return 0.1
|
||||
end
|
||||
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_CAST_TARGET,
|
||||
TargetIndex = enemy:entindex(),
|
||||
AbilityIndex = GrabAbility:entindex(),
|
||||
})
|
||||
|
||||
local fInterval = GrabAbility:GetCastPoint() + 0.1
|
||||
return fInterval
|
||||
--return 1.5
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function CastThrow( vPos )
|
||||
local vDir = vPos - thisEntity:GetOrigin()
|
||||
local flDist = vDir:Length2D()
|
||||
vDir.z = 0.0
|
||||
vDir = vDir:Normalized()
|
||||
|
||||
local vFinalPos = vPos
|
||||
if flDist < 200 then
|
||||
-- The target's too close and we don't want to throw the unit into our feet, so throw it forward instead
|
||||
vFinalPos = thisEntity:GetOrigin() + vDir * flDist
|
||||
end
|
||||
|
||||
printf( "Casting throw at %s", vPos )
|
||||
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_CAST_POSITION,
|
||||
Position = vFinalPos,
|
||||
--Position = thisEntity:GetOrigin() + vDir * flDist,
|
||||
AbilityIndex = ThrowAbility:entindex(),
|
||||
Queue = false,
|
||||
})
|
||||
|
||||
local fInterval = ThrowAbility:GetCastPoint() + 0.1
|
||||
return fInterval
|
||||
--return 1.5
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function CastAvalanche()
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
|
||||
AbilityIndex = AvalancheAbility:entindex(),
|
||||
Queue = false,
|
||||
})
|
||||
|
||||
local fInterval = AvalancheAbility:GetCastPoint() + AvalancheAbility:GetChannelTime() + 0.1
|
||||
return fInterval
|
||||
--return 11
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function CastGroundPound()
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
|
||||
AbilityIndex = GroundPoundAbility:entindex(),
|
||||
Queue = false,
|
||||
})
|
||||
|
||||
local fInterval = GroundPoundAbility:GetCastPoint() + GroundPoundAbility:GetChannelTime() + 0.1
|
||||
return fInterval
|
||||
--return 4.0
|
||||
end
|
||||
Reference in New Issue
Block a user