258 lines
10 KiB
Lua
258 lines
10 KiB
Lua
local ____lualib = require("lualib_bundle")
|
|
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
|
|
require("utils.utils")
|
|
local ____axe_battle_hunger_custom = require("abilities.heroes.axe.axe_battle_hunger_custom")
|
|
local axeApplyBattleHungerFromCall = ____axe_battle_hunger_custom.axeApplyBattleHungerFromCall
|
|
local NEVERMORE_RAID_BOSS = "npc_boss_nevermore"
|
|
local function isNevermoreRaidBoss(self, unit)
|
|
return unit:GetUnitName() == NEVERMORE_RAID_BOSS
|
|
end
|
|
--- Berserker's Call — как в доте: тантует врагов в радиусе, броня на Акса; шард вешает Battle Hunger.
|
|
____exports.axe_berserkers_call_custom = __TS__Class()
|
|
local axe_berserkers_call_custom = ____exports.axe_berserkers_call_custom
|
|
axe_berserkers_call_custom.name = "axe_berserkers_call_custom"
|
|
axe_berserkers_call_custom.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_berserkers_call_custom.lua"
|
|
__TS__ClassExtends(axe_berserkers_call_custom, BaseAbility)
|
|
function axe_berserkers_call_custom.prototype.Precache(self, context)
|
|
PrecacheResource("particle", "particles/units/heroes/hero_axe/axe_beserkers_call_owner.vpcf", context)
|
|
PrecacheResource("particle", "particles/status_fx/status_effect_beserkers_call.vpcf", context)
|
|
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_axe.vsndevts", context)
|
|
end
|
|
function axe_berserkers_call_custom.prototype.OnAbilityPhaseStart(self)
|
|
if IsServer() then
|
|
EmitSoundOn(
|
|
"Hero_Axe.BerserkersCall.Start",
|
|
self:GetCaster()
|
|
)
|
|
end
|
|
return true
|
|
end
|
|
function axe_berserkers_call_custom.prototype.OnAbilityPhaseInterrupted(self)
|
|
if IsServer() then
|
|
StopSoundOn(
|
|
"Hero_Axe.BerserkersCall.Start",
|
|
self:GetCaster()
|
|
)
|
|
end
|
|
end
|
|
function axe_berserkers_call_custom.prototype.OnSpellStart(self)
|
|
if not IsServer() then
|
|
return
|
|
end
|
|
local caster = self:GetCaster()
|
|
local radius = self:GetSpecialValueFor("radius")
|
|
local duration = self:GetSpecialValueFor("duration")
|
|
caster:AddNewModifier(caster, self, ____exports.modifier_axe_berserkers_call_armor.name, {duration = duration})
|
|
local enemies = FindUnitsInRadius(
|
|
caster:GetTeamNumber(),
|
|
caster:GetAbsOrigin(),
|
|
nil,
|
|
radius,
|
|
DOTA_UNIT_TARGET_TEAM_ENEMY,
|
|
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
|
|
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES,
|
|
FIND_ANY_ORDER,
|
|
false
|
|
)
|
|
local shard = HasShard(nil, caster)
|
|
local hungerDur = self:GetSpecialValueFor("shard_hunger_duration")
|
|
for ____, enemy in ipairs(enemies) do
|
|
do
|
|
if not enemy or not enemy:IsAlive() then
|
|
goto __continue10
|
|
end
|
|
if isNevermoreRaidBoss(nil, enemy) then
|
|
goto __continue10
|
|
end
|
|
self:issueAttackOrder(enemy, caster)
|
|
enemy:AddNewModifier(caster, self, ____exports.modifier_axe_berserkers_call_taunt.name, {duration = duration})
|
|
if shard then
|
|
axeApplyBattleHungerFromCall(nil, caster, enemy, hungerDur)
|
|
end
|
|
end
|
|
::__continue10::
|
|
end
|
|
if shard then
|
|
local allies = FindUnitsInRadius(
|
|
caster:GetTeamNumber(),
|
|
caster:GetAbsOrigin(),
|
|
nil,
|
|
radius,
|
|
DOTA_UNIT_TARGET_TEAM_FRIENDLY,
|
|
DOTA_UNIT_TARGET_HERO,
|
|
DOTA_UNIT_TARGET_FLAG_NONE,
|
|
FIND_ANY_ORDER,
|
|
false
|
|
)
|
|
for ____, ally in ipairs(allies) do
|
|
do
|
|
if not ally or not ally:IsAlive() then
|
|
goto __continue16
|
|
end
|
|
axeApplyBattleHungerFromCall(nil, caster, ally, hungerDur)
|
|
end
|
|
::__continue16::
|
|
end
|
|
end
|
|
if #enemies > 0 then
|
|
EmitSoundOn("Hero_Axe.Berserkers_Call", caster)
|
|
end
|
|
local particle_cast = "particles/units/heroes/hero_axe/axe_beserkers_call_owner.vpcf"
|
|
local effect_cast = ParticleManager:CreateParticle(particle_cast, PATTACH_ABSORIGIN_FOLLOW, caster)
|
|
ParticleManager:SetParticleControlEnt(
|
|
effect_cast,
|
|
1,
|
|
caster,
|
|
PATTACH_ABSORIGIN_FOLLOW,
|
|
"attach_mouth",
|
|
Vector(0, 0, 0),
|
|
true
|
|
)
|
|
ParticleManager:SetParticleControl(
|
|
effect_cast,
|
|
2,
|
|
Vector(radius, radius, radius)
|
|
)
|
|
ParticleManager:ReleaseParticleIndex(effect_cast)
|
|
end
|
|
function axe_berserkers_call_custom.prototype.issueAttackOrder(self, attacker, target)
|
|
local canAttack = attacker:GetAttackCapability() ~= DOTA_UNIT_CAP_NO_ATTACK and not attacker:IsDisarmed()
|
|
if not canAttack then
|
|
ExecuteOrderFromTable({
|
|
UnitIndex = attacker:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
|
Position = target:GetAbsOrigin(),
|
|
Queue = false
|
|
})
|
|
return
|
|
end
|
|
ExecuteOrderFromTable({
|
|
UnitIndex = attacker:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_ATTACK_TARGET,
|
|
TargetIndex = target:entindex(),
|
|
Queue = false
|
|
})
|
|
end
|
|
axe_berserkers_call_custom = __TS__Decorate(
|
|
axe_berserkers_call_custom,
|
|
axe_berserkers_call_custom,
|
|
{registerAbility(nil)},
|
|
{kind = "class", name = "axe_berserkers_call_custom"}
|
|
)
|
|
____exports.axe_berserkers_call_custom = axe_berserkers_call_custom
|
|
____exports.modifier_axe_berserkers_call_armor = __TS__Class()
|
|
local modifier_axe_berserkers_call_armor = ____exports.modifier_axe_berserkers_call_armor
|
|
modifier_axe_berserkers_call_armor.name = "modifier_axe_berserkers_call_armor"
|
|
modifier_axe_berserkers_call_armor.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_berserkers_call_custom.lua"
|
|
__TS__ClassExtends(modifier_axe_berserkers_call_armor, BaseModifier)
|
|
function modifier_axe_berserkers_call_armor.prototype.IsHidden(self)
|
|
return false
|
|
end
|
|
function modifier_axe_berserkers_call_armor.prototype.IsPurgable(self)
|
|
return false
|
|
end
|
|
function modifier_axe_berserkers_call_armor.prototype.DeclareFunctions(self)
|
|
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
|
|
end
|
|
function modifier_axe_berserkers_call_armor.prototype.GetModifierPhysicalArmorBonus(self)
|
|
return self:GetAbility():GetSpecialValueFor("bonus_armor")
|
|
end
|
|
function modifier_axe_berserkers_call_armor.prototype.GetStatusEffectName(self)
|
|
return "particles/status_fx/status_effect_beserkers_call.vpcf"
|
|
end
|
|
modifier_axe_berserkers_call_armor = __TS__Decorate(
|
|
modifier_axe_berserkers_call_armor,
|
|
modifier_axe_berserkers_call_armor,
|
|
{registerModifier(nil)},
|
|
{kind = "class", name = "modifier_axe_berserkers_call_armor"}
|
|
)
|
|
____exports.modifier_axe_berserkers_call_armor = modifier_axe_berserkers_call_armor
|
|
____exports.modifier_axe_berserkers_call_taunt = __TS__Class()
|
|
local modifier_axe_berserkers_call_taunt = ____exports.modifier_axe_berserkers_call_taunt
|
|
modifier_axe_berserkers_call_taunt.name = "modifier_axe_berserkers_call_taunt"
|
|
modifier_axe_berserkers_call_taunt.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_berserkers_call_custom.lua"
|
|
__TS__ClassExtends(modifier_axe_berserkers_call_taunt, BaseModifier)
|
|
function modifier_axe_berserkers_call_taunt.prototype.IsHidden(self)
|
|
return false
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.IsPurgable(self)
|
|
return false
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.IsDebuff(self)
|
|
return true
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.CheckState(self)
|
|
return {[MODIFIER_STATE_COMMAND_RESTRICTED] = true}
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.GetStatusEffectName(self)
|
|
return "particles/status_fx/status_effect_beserkers_call.vpcf"
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.OnCreated(self)
|
|
if not IsServer() then
|
|
return
|
|
end
|
|
local parent = self:GetParent()
|
|
local caster = self:GetCaster()
|
|
if not caster or not parent then
|
|
return
|
|
end
|
|
self.reissueTimer = Timers:CreateTimer(
|
|
0.25,
|
|
function()
|
|
if not IsValidEntity(parent) or not IsValidEntity(caster) then
|
|
return nil
|
|
end
|
|
if not parent:IsAlive() or not caster:IsAlive() then
|
|
return nil
|
|
end
|
|
local canAttack = parent:GetAttackCapability() ~= DOTA_UNIT_CAP_NO_ATTACK and not parent:IsDisarmed()
|
|
if not canAttack then
|
|
ExecuteOrderFromTable({
|
|
UnitIndex = parent:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_MOVE_TO_POSITION,
|
|
Position = caster:GetAbsOrigin(),
|
|
Queue = false
|
|
})
|
|
return 0.25
|
|
end
|
|
ExecuteOrderFromTable({
|
|
UnitIndex = parent:entindex(),
|
|
OrderType = DOTA_UNIT_ORDER_ATTACK_TARGET,
|
|
TargetIndex = caster:entindex(),
|
|
Queue = false
|
|
})
|
|
return 0.25
|
|
end
|
|
)
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.OnDestroy(self)
|
|
if self.reissueTimer ~= nil then
|
|
Timers:RemoveTimer(self.reissueTimer)
|
|
self.reissueTimer = nil
|
|
end
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.OnDeath(self, event)
|
|
if IsServer() and event.unit == self:GetCaster() then
|
|
self:Destroy()
|
|
end
|
|
end
|
|
function modifier_axe_berserkers_call_taunt.prototype.DeclareFunctions(self)
|
|
return {MODIFIER_EVENT_ON_DEATH}
|
|
end
|
|
modifier_axe_berserkers_call_taunt = __TS__Decorate(
|
|
modifier_axe_berserkers_call_taunt,
|
|
modifier_axe_berserkers_call_taunt,
|
|
{registerModifier(nil)},
|
|
{kind = "class", name = "modifier_axe_berserkers_call_taunt"}
|
|
)
|
|
____exports.modifier_axe_berserkers_call_taunt = modifier_axe_berserkers_call_taunt
|
|
return ____exports
|