initial commit
This commit is contained in:
276
aghanim_singleplayer/scripts/vscripts/ai/tornado_harpy_ai.lua
Executable file
276
aghanim_singleplayer/scripts/vscripts/ai/tornado_harpy_ai.lua
Executable file
@@ -0,0 +1,276 @@
|
||||
require( "ai/ai_core" )
|
||||
|
||||
|
||||
function Precache( context )
|
||||
|
||||
PrecacheResource( "particle", "particles/neutral_fx/harpy_chain_lightning_head.vpcf", context )
|
||||
PrecacheResource( "particle", "particles/units/heroes/hero_dark_seer/dark_seer_surge.vpcf", context )
|
||||
PrecacheResource( "particle", "particles/neutral_fx/harpy_chain_lightning.vpcf", context )
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function Spawn( entityKeyValues )
|
||||
|
||||
thisEntity.hSurgeAbility = thisEntity:FindAbilityByName( "tornado_harpy_intrinsic" )
|
||||
thisEntity.PreviousHealthPct = thisEntity:GetHealthPercent()
|
||||
thisEntity.PreviousHealthPctGameTime = GameRules:GetGameTime()
|
||||
|
||||
thisEntity:SetContextThink( "TornadoHarpyThink", TornadoHarpyThink, 0.5 )
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function TornadoHarpyThink()
|
||||
|
||||
if not IsServer() then
|
||||
return
|
||||
end
|
||||
|
||||
if ( not thisEntity:IsAlive() ) then
|
||||
return -1
|
||||
end
|
||||
|
||||
if GameRules:IsGamePaused() == true then
|
||||
return 0.5
|
||||
end
|
||||
|
||||
--check our health pct every 4 seconds
|
||||
if GameRules:GetGameTime() > thisEntity.PreviousHealthPctGameTime + 4 then
|
||||
thisEntity.PreviousHealthPctGameTime = GameRules:GetGameTime()
|
||||
thisEntity.PreviousHealthPct = thisEntity:GetHealthPercent()
|
||||
end
|
||||
local hEnemies = FindUnitsInRadius( thisEntity:GetTeamNumber(), thisEntity:GetOrigin(), nil, 5000, DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, FIND_CLOSEST, false )
|
||||
|
||||
if #hEnemies > 0 then
|
||||
for i = 1, #hEnemies do
|
||||
thisEntity.avoidTarget = hEnemies[i]
|
||||
if thisEntity.avoidTarget ~= nil then
|
||||
if thisEntity:GetHealthPercent() < thisEntity.PreviousHealthPct then
|
||||
return Retreat(thisEntity.avoidTarget )
|
||||
else
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_ATTACK_TARGET,
|
||||
TargetIndex = thisEntity.avoidTarget:entindex(),
|
||||
Queue = false
|
||||
})
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return 0.5
|
||||
end
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function Retreat(unit)
|
||||
|
||||
local vAwayFromEnemy = thisEntity:GetOrigin() - unit:GetOrigin()
|
||||
vAwayFromEnemy = vAwayFromEnemy:Normalized()
|
||||
local vMoveToPos = thisEntity:GetOrigin() + vAwayFromEnemy * thisEntity:GetIdealSpeed()*4
|
||||
|
||||
-- if away from enemy is an unpathable area, find a new direction to run to
|
||||
local nAttempts = 0
|
||||
while ( ( not GridNav:CanFindPath( thisEntity:GetOrigin(), vMoveToPos ) ) and ( nAttempts < 5 ) ) do
|
||||
vMoveToPos = thisEntity:GetOrigin() + RandomVector( thisEntity:GetIdealSpeed() * 4 )
|
||||
nAttempts = nAttempts + 1
|
||||
end
|
||||
|
||||
thisEntity.fTimeOfLastRetreat = GameRules:GetGameTime()
|
||||
|
||||
thisEntity:AddNewModifier(thisEntity, thisEntity.hSurgeAbility, "modifier_tornado_harpy_surge", {duration = 2.0})
|
||||
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
Position = vMoveToPos,
|
||||
})
|
||||
|
||||
return 2.5
|
||||
end
|
||||
|
||||
--[[
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
BehaviorNone = {}
|
||||
|
||||
function BehaviorNone:Evaluate()
|
||||
return 1 -- must return a value > 0, so we have a default
|
||||
end
|
||||
|
||||
function BehaviorNone:Begin()
|
||||
-- print( "BehaviorNone:Begin()" )
|
||||
local orders = nil
|
||||
local hTarget = AICore:ClosestEnemyHeroInRange( thisEntity, thisEntity:GetDayTimeVisionRange() )
|
||||
|
||||
if hTarget ~= nil then
|
||||
thisEntity.lastTargetPosition = hTarget:GetAbsOrigin()
|
||||
for i=1,6 do
|
||||
local vLoc = FindPathablePositionNearby(hTarget:GetAbsOrigin(), 650, 650 )
|
||||
--and thisEntity:IsMoving() == false
|
||||
if GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vLoc ) then
|
||||
--orders =
|
||||
--{
|
||||
-- UnitIndex = thisEntity:entindex(),
|
||||
-- OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
-- Position = vLoc,
|
||||
-- Queue = true,
|
||||
--}
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif thisEntity.lastTargetPosition ~= nil then
|
||||
for i=1,6 do
|
||||
local vLoc = FindPathablePositionNearby(thisEntity.lastTargetPosition, 650, 650 )
|
||||
|
||||
if GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( vLoc ) then
|
||||
--orders =
|
||||
--{
|
||||
-- UnitIndex = thisEntity:entindex(),
|
||||
-- OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
-- Position = vLoc
|
||||
--}
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
orders =
|
||||
{
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_STOP
|
||||
}
|
||||
end
|
||||
|
||||
return orders
|
||||
end
|
||||
|
||||
BehaviorNone.Continue = BehaviorNone.Begin
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
BehaviorAttack = {}
|
||||
|
||||
function BehaviorAttack:Evaluate()
|
||||
|
||||
local desire = 6
|
||||
|
||||
-- let's not choose this twice in a row
|
||||
if behaviorSystem.currentBehavior == self then
|
||||
return desire
|
||||
end
|
||||
|
||||
self.chainLightningAbility = thisEntity:FindAbilityByName( "harpy_storm_chain_lightning" )
|
||||
|
||||
if self.chainLightningAbility and self.chainLightningAbility:IsFullyCastable() then
|
||||
|
||||
self.target = AICore:ClosestEnemyHeroInRange( thisEntity, thisEntity:GetDayTimeVisionRange() )
|
||||
if self.target ~= nil and self.target:IsAlive() then
|
||||
desire = 6
|
||||
end
|
||||
end
|
||||
|
||||
return desire
|
||||
end
|
||||
|
||||
function BehaviorAttack:Begin()
|
||||
-- print( "BehaviorAttack:Begin()" )
|
||||
|
||||
--if self.chainLightningAbility and self.chainLightningAbility:IsFullyCastable() then
|
||||
if self.target and self.target:IsAlive() then
|
||||
--print( "Casting Chain Lightning" )
|
||||
local targetPoint = self.target:GetAbsOrigin() + RandomVector( 100 )
|
||||
thisEntity.lastTargetPosition = self.target:GetAbsOrigin()
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_ATTACK_TARGET,
|
||||
--AbilityIndex = self.chainLightningAbility:entindex(),
|
||||
TargetIndex = self.target:entindex(),
|
||||
Queue = false
|
||||
})
|
||||
end
|
||||
--end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
BehaviorAttack.Continue = BehaviorAttack.Begin
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
|
||||
BehaviorAvoid = {}
|
||||
|
||||
function BehaviorAvoid:Evaluate()
|
||||
|
||||
local desire = 0
|
||||
|
||||
-- let's not choose this twice in a row
|
||||
if behaviorSystem.currentBehavior == self then
|
||||
return desire
|
||||
end
|
||||
--don't even think about running if you can damage!
|
||||
if self.chainLightningAbility and self.chainLightningAbility:IsFullyCastable() then
|
||||
return desire
|
||||
end
|
||||
|
||||
--check our health pct every 5 seconds
|
||||
if GameRules:GetGameTime() > thisEntity.PreviousHealthPctGameTime + 5 then
|
||||
printf("reseting healthpct")
|
||||
thisEntity.PreviousHealthPctGameTime = GameRules:GetGameTime()
|
||||
thisEntity.PreviousHealthPct = thisEntity:GetHealthPercent()
|
||||
end
|
||||
|
||||
self.avoidTarget = AICore:ClosestEnemyHeroInRange( thisEntity, 650 )
|
||||
if self.avoidTarget ~= nil then
|
||||
desire = 4
|
||||
end
|
||||
|
||||
if thisEntity:GetHealthPercent() < thisEntity.PreviousHealthPct then
|
||||
printf("I'm hurt")
|
||||
desire = 8
|
||||
end
|
||||
|
||||
return desire
|
||||
end
|
||||
|
||||
function BehaviorAvoid:Begin()
|
||||
print( "BehaviorAvoid:Begin()" )
|
||||
|
||||
for i=1,6 do
|
||||
self.vEscapeLoc = FindPathablePositionNearby(thisEntity:GetAbsOrigin(), 350, 350 )
|
||||
|
||||
if GameRules.Aghanim:GetCurrentRoom():IsInRoomBounds( self.vEscapeLoc ) and ( self.vEscapeLoc - self.avoidTarget:GetAbsOrigin() ):Length2D() > 650 then
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
Position = self.vEscapeLoc
|
||||
})
|
||||
printf("function BehaviorAvoid: Executing order()")
|
||||
break
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function BehaviorAvoid:Think(dt)
|
||||
|
||||
-- keep moving towards our escape point
|
||||
ExecuteOrderFromTable({
|
||||
UnitIndex = thisEntity:entindex(),
|
||||
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
||||
Position = self.vEscapeLoc
|
||||
})
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
BehaviorAvoid.Continue = BehaviorAvoid.Begin ]]--
|
||||
Reference in New Issue
Block a user