336 lines
12 KiB
Lua
336 lines
12 KiB
Lua
local ____lualib = require("lualib_bundle")
|
|
local __TS__StringIncludes = ____lualib.__TS__StringIncludes
|
|
local __TS__Class = ____lualib.__TS__Class
|
|
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
|
|
local __TS__Decorate = ____lualib.__TS__Decorate
|
|
local ____exports = {}
|
|
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
|
|
local BaseAbility = ____dota_ts_adapter.BaseAbility
|
|
local BaseModifier = ____dota_ts_adapter.BaseModifier
|
|
local registerAbility = ____dota_ts_adapter.registerAbility
|
|
local registerModifier = ____dota_ts_adapter.registerModifier
|
|
local ____sync_owner_modifiers_to_summon = require("utils.sync_owner_modifiers_to_summon")
|
|
local syncOwnerModifiersToSummon = ____sync_owner_modifiers_to_summon.syncOwnerModifiersToSummon
|
|
--- Подстроки в имени юнита: на таких целей призывы не агрятся.
|
|
local DARK_FRIENDS_NO_AGGRO_NAME_PARTS = {"boss", "wisp"}
|
|
local function darkFriendsIsNoAggroUnit(self, unitName)
|
|
if not unitName then
|
|
return false
|
|
end
|
|
local lowerName = string.lower(unitName)
|
|
for ____, part in ipairs(DARK_FRIENDS_NO_AGGRO_NAME_PARTS) do
|
|
if __TS__StringIncludes(lowerName, part) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
____exports.dark_friends = __TS__Class()
|
|
local dark_friends = ____exports.dark_friends
|
|
dark_friends.name = "dark_friends"
|
|
dark_friends.____file_path = "scripts/vscripts/abilities/heroes/nagash/dark_friends.lua"
|
|
__TS__ClassExtends(dark_friends, BaseAbility)
|
|
function dark_friends.prototype.GetIntrinsicModifierName(self)
|
|
return "modifier_dark_friends_create"
|
|
end
|
|
dark_friends = __TS__Decorate(
|
|
dark_friends,
|
|
dark_friends,
|
|
{registerAbility(nil)},
|
|
{kind = "class", name = "dark_friends"}
|
|
)
|
|
____exports.dark_friends = dark_friends
|
|
____exports.modifier_dark_friends_create = __TS__Class()
|
|
local modifier_dark_friends_create = ____exports.modifier_dark_friends_create
|
|
modifier_dark_friends_create.name = "modifier_dark_friends_create"
|
|
modifier_dark_friends_create.____file_path = "scripts/vscripts/abilities/heroes/nagash/dark_friends.lua"
|
|
__TS__ClassExtends(modifier_dark_friends_create, BaseModifier)
|
|
function modifier_dark_friends_create.prototype.spawnFriendForLevel(self, level, caster, ability)
|
|
local unitNames = {"npc_dota_melee_nagash_summon", "npc_dota_ranged_nagash_summon", "npc_dota_mage_nagash_summon", "npc_dota_shield_nagash_summon"}
|
|
local unitIndex = math.min(level, #unitNames) - 1
|
|
local unitName = unitNames[unitIndex + 1] or unitNames[1]
|
|
local dark_friends = CreateUnitByName(
|
|
unitName,
|
|
caster:GetAbsOrigin() + RandomVector(100),
|
|
true,
|
|
caster,
|
|
caster,
|
|
caster:GetTeamNumber()
|
|
)
|
|
dark_friends:SetOwner(caster)
|
|
dark_friends:SetBaseDamageMin(caster:GetBaseDamageMin())
|
|
dark_friends:SetBaseDamageMax(caster:GetBaseDamageMax())
|
|
dark_friends:SetBaseMoveSpeed(caster:GetBaseMoveSpeed() + 65)
|
|
dark_friends:AddNewModifier(caster, ability, "modifier_dark_friends", {})
|
|
dark_friends:AddAbility("ability_stacking_crit"):SetLevel(1)
|
|
EmitSoundOn("Hero_AbyssalUnderlord.DarkRift.Aftershock", caster)
|
|
end
|
|
function modifier_dark_friends_create.prototype.OnCreated(self, params)
|
|
local caster = self:GetCaster()
|
|
local ability = self:GetAbility()
|
|
if not caster or not ability then
|
|
return
|
|
end
|
|
if caster:PassivesDisabled() then
|
|
return
|
|
end
|
|
local level = math.max(
|
|
1,
|
|
ability:GetLevel()
|
|
)
|
|
if self:GetStackCount() < level then
|
|
self:spawnFriendForLevel(level, caster, ability)
|
|
self:SetStackCount(level)
|
|
end
|
|
end
|
|
function modifier_dark_friends_create.prototype.OnRefresh(self, params)
|
|
local caster = self:GetCaster()
|
|
local ability = self:GetAbility()
|
|
if not caster or not ability then
|
|
return
|
|
end
|
|
if caster:PassivesDisabled() then
|
|
return
|
|
end
|
|
local level = math.max(
|
|
1,
|
|
ability:GetLevel()
|
|
)
|
|
if self:GetStackCount() < level then
|
|
self:spawnFriendForLevel(level, caster, ability)
|
|
self:SetStackCount(level)
|
|
end
|
|
end
|
|
modifier_dark_friends_create = __TS__Decorate(
|
|
modifier_dark_friends_create,
|
|
modifier_dark_friends_create,
|
|
{registerModifier(nil)},
|
|
{kind = "class", name = "modifier_dark_friends_create"}
|
|
)
|
|
____exports.modifier_dark_friends_create = modifier_dark_friends_create
|
|
____exports.modifier_dark_friends = __TS__Class()
|
|
local modifier_dark_friends = ____exports.modifier_dark_friends
|
|
modifier_dark_friends.name = "modifier_dark_friends"
|
|
modifier_dark_friends.____file_path = "scripts/vscripts/abilities/heroes/nagash/dark_friends.lua"
|
|
__TS__ClassExtends(modifier_dark_friends, BaseModifier)
|
|
function modifier_dark_friends.prototype.____constructor(self, ...)
|
|
BaseModifier.prototype.____constructor(self, ...)
|
|
self.ownerIsDead = false
|
|
end
|
|
function modifier_dark_friends.prototype.IsHidden(self)
|
|
return true
|
|
end
|
|
function modifier_dark_friends.prototype.IsPurgable(self)
|
|
return false
|
|
end
|
|
function modifier_dark_friends.prototype.OnCreated(self)
|
|
if not IsServer() then
|
|
return
|
|
end
|
|
self:StartIntervalThink(0.1)
|
|
self:OnIntervalThink()
|
|
end
|
|
function modifier_dark_friends.prototype.GetRealOwner(self)
|
|
local parent = self:GetParent()
|
|
if not parent then
|
|
return nil
|
|
end
|
|
if parent:IsRealHero() then
|
|
return parent
|
|
end
|
|
local owner = parent:GetOwner()
|
|
if not owner then
|
|
return nil
|
|
end
|
|
local ownerUnit = owner
|
|
if ownerUnit:IsRealHero() then
|
|
return ownerUnit
|
|
end
|
|
return nil
|
|
end
|
|
function modifier_dark_friends.prototype.OnIntervalThink(self)
|
|
if not IsServer() then
|
|
return
|
|
end
|
|
local parent = self:GetParent()
|
|
if not parent then
|
|
return
|
|
end
|
|
local realOwner = self:GetRealOwner()
|
|
if not realOwner then
|
|
self.ownerIsDead = true
|
|
parent:Stop()
|
|
return
|
|
end
|
|
if not realOwner:IsAlive() then
|
|
self.ownerIsDead = true
|
|
parent:Stop()
|
|
local distanceToOwnerDead = (parent:GetAbsOrigin() - realOwner:GetAbsOrigin()):Length2D()
|
|
if distanceToOwnerDead > 300 then
|
|
parent:MoveToPosition(toVectorWS(
|
|
nil,
|
|
realOwner:GetAbsOrigin() + RandomVector(150)
|
|
))
|
|
end
|
|
return
|
|
else
|
|
self.ownerIsDead = false
|
|
end
|
|
syncOwnerModifiersToSummon(nil, realOwner, parent)
|
|
parent:SetBaseAttackTime(realOwner:GetBaseAttackTime())
|
|
parent:SetBaseDamageMin(realOwner:GetAverageTrueAttackDamage(nil))
|
|
parent:SetBaseDamageMax(realOwner:GetAverageTrueAttackDamage(nil))
|
|
parent:SetBaseMoveSpeed(realOwner:GetBaseMoveSpeed())
|
|
local distanceToOwner = (parent:GetAbsOrigin() - realOwner:GetAbsOrigin()):Length2D()
|
|
if distanceToOwner > 250 then
|
|
parent:MoveToPosition(toVectorWS(
|
|
nil,
|
|
realOwner:GetAbsOrigin() + RandomVector(200)
|
|
))
|
|
end
|
|
if distanceToOwner > 450 then
|
|
FindClearSpaceForUnit(
|
|
parent,
|
|
toVectorWS(
|
|
nil,
|
|
realOwner:GetAbsOrigin() + RandomVector(200)
|
|
),
|
|
true
|
|
)
|
|
end
|
|
if distanceToOwner <= 425 and realOwner:IsAlive() then
|
|
local enemies = FindUnitsInRadius(
|
|
parent:GetTeamNumber(),
|
|
parent:GetAbsOrigin(),
|
|
nil,
|
|
425,
|
|
DOTA_UNIT_TARGET_TEAM_ENEMY,
|
|
bit.bor(DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_HERO),
|
|
DOTA_UNIT_TARGET_FLAG_NONE,
|
|
FIND_CLOSEST,
|
|
false
|
|
)
|
|
local enemyTarget
|
|
for ____, u in ipairs(enemies) do
|
|
if not darkFriendsIsNoAggroUnit(
|
|
nil,
|
|
u:GetUnitName()
|
|
) then
|
|
enemyTarget = u
|
|
break
|
|
end
|
|
end
|
|
if enemyTarget then
|
|
enemyTarget:MoveToTargetToAttack(realOwner)
|
|
parent:MoveToTargetToAttack(enemyTarget)
|
|
end
|
|
end
|
|
end
|
|
function modifier_dark_friends.prototype.IsAura(self)
|
|
return true
|
|
end
|
|
function modifier_dark_friends.prototype.GetAuraRadius(self)
|
|
local ability = self:GetAbility()
|
|
local level = ability and math.max(
|
|
1,
|
|
ability:GetLevel()
|
|
) or 1
|
|
return self:GetAbility():GetSpecialValueFor("aura_radius") + level * 50
|
|
end
|
|
function modifier_dark_friends.prototype.GetAuraSearchTeam(self)
|
|
return DOTA_UNIT_TARGET_TEAM_FRIENDLY
|
|
end
|
|
function modifier_dark_friends.prototype.GetAuraSearchType(self)
|
|
return bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC)
|
|
end
|
|
function modifier_dark_friends.prototype.GetAuraSearchFlags(self)
|
|
return DOTA_UNIT_TARGET_FLAG_NONE
|
|
end
|
|
function modifier_dark_friends.prototype.GetModifierAura(self)
|
|
return "modifier_dark_friends_aura_buff"
|
|
end
|
|
function modifier_dark_friends.prototype.GetAuraEntityReject(self, target)
|
|
local caster = self:GetCaster()
|
|
if caster and caster:PassivesDisabled() then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
function modifier_dark_friends.prototype.DeclareFunctions(self)
|
|
return {MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE}
|
|
end
|
|
function modifier_dark_friends.prototype.CheckState(self)
|
|
return {
|
|
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
|
|
[MODIFIER_STATE_INVULNERABLE] = true,
|
|
[MODIFIER_STATE_NO_UNIT_COLLISION] = true,
|
|
[MODIFIER_STATE_NO_TEAM_SELECT] = true,
|
|
[MODIFIER_STATE_NO_TEAM_MOVE_TO] = true,
|
|
[MODIFIER_STATE_DISARMED] = self.ownerIsDead
|
|
}
|
|
end
|
|
function modifier_dark_friends.prototype.GetModifierDamageOutgoing_Percentage(self, event)
|
|
return self:GetAbility():GetSpecialValueFor("outgoing_damage_pct")
|
|
end
|
|
modifier_dark_friends = __TS__Decorate(
|
|
modifier_dark_friends,
|
|
modifier_dark_friends,
|
|
{registerModifier(nil)},
|
|
{kind = "class", name = "modifier_dark_friends"}
|
|
)
|
|
____exports.modifier_dark_friends = modifier_dark_friends
|
|
____exports.modifier_dark_friends_aura_buff = __TS__Class()
|
|
local modifier_dark_friends_aura_buff = ____exports.modifier_dark_friends_aura_buff
|
|
modifier_dark_friends_aura_buff.name = "modifier_dark_friends_aura_buff"
|
|
modifier_dark_friends_aura_buff.____file_path = "scripts/vscripts/abilities/heroes/nagash/dark_friends.lua"
|
|
__TS__ClassExtends(modifier_dark_friends_aura_buff, BaseModifier)
|
|
function modifier_dark_friends_aura_buff.prototype.IsHidden(self)
|
|
return true
|
|
end
|
|
function modifier_dark_friends_aura_buff.prototype.IsPurgable(self)
|
|
return false
|
|
end
|
|
function modifier_dark_friends_aura_buff.prototype.DeclareFunctions(self)
|
|
return {MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE, MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT, MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
|
|
end
|
|
function modifier_dark_friends_aura_buff.prototype.GetModifierPreAttack_BonusDamage(self)
|
|
local ability = self:GetAbility()
|
|
local level = ability and math.max(
|
|
1,
|
|
ability:GetLevel()
|
|
) or 1
|
|
return level * self:GetAbility():GetSpecialValueFor("aura_bonus_damage")
|
|
end
|
|
function modifier_dark_friends_aura_buff.prototype.GetModifierAttackSpeedBonus_Constant(self)
|
|
local ability = self:GetAbility()
|
|
local level = ability and math.max(
|
|
1,
|
|
ability:GetLevel()
|
|
) or 1
|
|
return level * self:GetAbility():GetSpecialValueFor("aura_bonus_attack_speed")
|
|
end
|
|
function modifier_dark_friends_aura_buff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
|
|
local ability = self:GetAbility()
|
|
local level = ability and math.max(
|
|
1,
|
|
ability:GetLevel()
|
|
) or 1
|
|
return level * self:GetAbility():GetSpecialValueFor("aura_bonus_movespeed_pct")
|
|
end
|
|
function modifier_dark_friends_aura_buff.prototype.GetModifierPhysicalArmorBonus(self, event)
|
|
local ability = self:GetAbility()
|
|
local level = ability and math.max(
|
|
1,
|
|
ability:GetLevel()
|
|
) or 1
|
|
return level * self:GetAbility():GetSpecialValueFor("aura_bonus_armor")
|
|
end
|
|
modifier_dark_friends_aura_buff = __TS__Decorate(
|
|
modifier_dark_friends_aura_buff,
|
|
modifier_dark_friends_aura_buff,
|
|
{registerModifier(nil)},
|
|
{kind = "class", name = "modifier_dark_friends_aura_buff"}
|
|
)
|
|
____exports.modifier_dark_friends_aura_buff = modifier_dark_friends_aura_buff
|
|
return ____exports
|