296 lines
11 KiB
Lua
296 lines
11 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
|
|
local ____modifier_general_hunger = require("abilities.modifiers.modifier_general_hunger")
|
|
local modifier_general_hunger = ____modifier_general_hunger.modifier_general_hunger
|
|
local ____ability_pudge_flesh_heap_custom = require("abilities.heroes.pudge.ability_pudge_flesh_heap_custom")
|
|
local modifier_pudge_flesh_heap_custom = ____ability_pudge_flesh_heap_custom.modifier_pudge_flesh_heap_custom
|
|
____exports.ability_pudge_dismember_custom = __TS__Class()
|
|
local ability_pudge_dismember_custom = ____exports.ability_pudge_dismember_custom
|
|
ability_pudge_dismember_custom.name = "ability_pudge_dismember_custom"
|
|
ability_pudge_dismember_custom.____file_path = "scripts/vscripts/abilities/heroes/pudge/ability_pudge_dismember_custom.lua"
|
|
__TS__ClassExtends(ability_pudge_dismember_custom, BaseAbility)
|
|
function ability_pudge_dismember_custom.prototype.____constructor(self, ...)
|
|
BaseAbility.prototype.____constructor(self, ...)
|
|
self.pulseAccumulator = 0
|
|
self.channelTargetPoint = Vector(0, 0, 0)
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.Precache(self, context)
|
|
PrecacheResource("particle", "particles/econ/items/pudge/pudge_arcana/pudge_arcana_dismember_default.vpcf", context)
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.GetBehavior(self)
|
|
return bit.bor(
|
|
bit.bor(DOTA_ABILITY_BEHAVIOR_POINT, DOTA_ABILITY_BEHAVIOR_CHANNELLED),
|
|
DOTA_ABILITY_BEHAVIOR_AOE
|
|
)
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.GetCastRange(self, location, target)
|
|
return self:GetSpecialValueFor("cast_range")
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.GetChannelTime(self)
|
|
return self:GetSpecialValueFor("channel_time")
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.GetAOERadius(self)
|
|
return self:GetSpecialValueFor("width")
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.OnSpellStart(self)
|
|
local caster = self:GetCaster()
|
|
self.channelTargetPoint = self:GetCursorPosition()
|
|
self.pulseAccumulator = 0
|
|
caster:AddNewModifier(
|
|
caster,
|
|
self,
|
|
____exports.modifier_pudge_dismember_growth_custom.name,
|
|
{duration = self:GetChannelTime() + 0.1}
|
|
)
|
|
EmitSoundOn("Hero_Pudge.DismemberSwings", caster)
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.OnChannelThink(self, flInterval)
|
|
if not IsServer() then
|
|
return
|
|
end
|
|
local caster = self:GetCaster()
|
|
local maxRange = self:GetCastRange(
|
|
caster:GetAbsOrigin(),
|
|
nil
|
|
)
|
|
local width = self:GetSpecialValueFor("width")
|
|
local pullSpeedPerSec = self:GetSpecialValueFor("pull_speed")
|
|
local pulseInterval = self:GetSpecialValueFor("pulse_interval")
|
|
local toPoint = self.channelTargetPoint - caster:GetAbsOrigin()
|
|
toPoint.z = 0
|
|
if toPoint:Length2D() < 1 then
|
|
toPoint = caster:GetForwardVector() * maxRange
|
|
end
|
|
local clampedDistance = math.min(
|
|
toPoint:Length2D(),
|
|
maxRange
|
|
)
|
|
local centerPoint = caster:GetAbsOrigin() + toPoint:Normalized() * clampedDistance
|
|
local enemies = FindUnitsInRadius(
|
|
caster:GetTeamNumber(),
|
|
centerPoint,
|
|
nil,
|
|
width,
|
|
DOTA_UNIT_TARGET_TEAM_ENEMY,
|
|
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
|
|
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES,
|
|
FIND_ANY_ORDER,
|
|
false
|
|
)
|
|
if #enemies == 0 then
|
|
caster:InterruptChannel()
|
|
return
|
|
end
|
|
for ____, enemy in ipairs(enemies) do
|
|
local delta = centerPoint - enemy:GetAbsOrigin()
|
|
delta.z = 0
|
|
local distance = delta:Length2D()
|
|
local stopDistance = 60
|
|
if distance > stopDistance then
|
|
local move = math.min(distance - stopDistance, pullSpeedPerSec * flInterval)
|
|
local newPos = enemy:GetAbsOrigin() + delta:Normalized() * move
|
|
enemy:SetAbsOrigin(GetGroundPosition(newPos, enemy))
|
|
GridNav:DestroyTreesAroundPoint(newPos, 80, false)
|
|
else
|
|
FindClearSpaceForUnit(
|
|
enemy,
|
|
enemy:GetAbsOrigin(),
|
|
true
|
|
)
|
|
end
|
|
end
|
|
self.pulseAccumulator = self.pulseAccumulator + flInterval
|
|
if self.pulseAccumulator < pulseInterval then
|
|
return
|
|
end
|
|
self.pulseAccumulator = 0
|
|
EmitSoundOn("Hero_Pudge.Dismember", caster)
|
|
for ____, enemy in ipairs(enemies) do
|
|
____exports.modifier_pudge_dismember_custom:apply(enemy, caster, self, {duration = pulseInterval + 0.1})
|
|
self:ApplyDismemberTickDamage(caster, enemy)
|
|
end
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.OnChannelFinish(self, interrupted)
|
|
local caster = self:GetCaster()
|
|
StopSoundOn("Hero_Pudge.DismemberSwings", caster)
|
|
local toPoint = self.channelTargetPoint - caster:GetAbsOrigin()
|
|
toPoint.z = 0
|
|
local maxRange = self:GetCastRange(
|
|
caster:GetAbsOrigin(),
|
|
nil
|
|
)
|
|
if toPoint:Length2D() < 1 then
|
|
toPoint = caster:GetForwardVector() * maxRange
|
|
end
|
|
local clampedDistance = math.min(
|
|
toPoint:Length2D(),
|
|
maxRange
|
|
)
|
|
local centerPoint = caster:GetAbsOrigin() + toPoint:Normalized() * clampedDistance
|
|
local width = self:GetSpecialValueFor("width")
|
|
local enemies = FindUnitsInRadius(
|
|
caster:GetTeamNumber(),
|
|
centerPoint,
|
|
nil,
|
|
width,
|
|
DOTA_UNIT_TARGET_TEAM_ENEMY,
|
|
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
|
|
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES,
|
|
FIND_ANY_ORDER,
|
|
false
|
|
)
|
|
for ____, enemy in ipairs(enemies) do
|
|
FindClearSpaceForUnit(
|
|
enemy,
|
|
enemy:GetAbsOrigin(),
|
|
true
|
|
)
|
|
end
|
|
end
|
|
function ability_pudge_dismember_custom.prototype.ApplyDismemberTickDamage(self, caster, target)
|
|
local interval = self:GetSpecialValueFor("pulse_interval")
|
|
local baseDamage = self:GetSpecialValueFor("damage_per_second")
|
|
local strMultiplier = self:GetSpecialValueFor("strength_damage_pct") * 0.01
|
|
local maxHpDamagePct = self:GetSpecialValueFor("max_health_damage_pct") * 0.01
|
|
local healPct = self:GetSpecialValueFor("heal_from_damage_pct") * 0.01
|
|
local maxHpDamagePerSec = caster:GetMaxHealth() * maxHpDamagePct
|
|
local damagePerSecond = baseDamage + caster:GetStrength() * strMultiplier + maxHpDamagePerSec
|
|
local tickDamage = damagePerSecond * interval
|
|
ApplyDamage({
|
|
victim = target,
|
|
attacker = caster,
|
|
damage = tickDamage,
|
|
damage_type = DAMAGE_TYPE_MAGICAL,
|
|
ability = self
|
|
})
|
|
caster:Heal(tickDamage * healPct, self)
|
|
end
|
|
ability_pudge_dismember_custom = __TS__Decorate(
|
|
ability_pudge_dismember_custom,
|
|
ability_pudge_dismember_custom,
|
|
{registerAbility(nil)},
|
|
{kind = "class", name = "ability_pudge_dismember_custom"}
|
|
)
|
|
____exports.ability_pudge_dismember_custom = ability_pudge_dismember_custom
|
|
____exports.modifier_pudge_dismember_growth_custom = __TS__Class()
|
|
local modifier_pudge_dismember_growth_custom = ____exports.modifier_pudge_dismember_growth_custom
|
|
modifier_pudge_dismember_growth_custom.name = "modifier_pudge_dismember_growth_custom"
|
|
modifier_pudge_dismember_growth_custom.____file_path = "scripts/vscripts/abilities/heroes/pudge/ability_pudge_dismember_custom.lua"
|
|
__TS__ClassExtends(modifier_pudge_dismember_growth_custom, BaseModifier)
|
|
function modifier_pudge_dismember_growth_custom.prototype.IsHidden(self)
|
|
return false
|
|
end
|
|
function modifier_pudge_dismember_growth_custom.prototype.IsPurgable(self)
|
|
return false
|
|
end
|
|
function modifier_pudge_dismember_growth_custom.prototype.DeclareFunctions(self)
|
|
return {MODIFIER_PROPERTY_MODEL_SCALE}
|
|
end
|
|
function modifier_pudge_dismember_growth_custom.prototype.GetModifierModelScale(self)
|
|
local parent = self:GetParent()
|
|
if not parent then
|
|
return 0
|
|
end
|
|
return math.min(
|
|
100,
|
|
math.floor(parent:GetMaxHealth() / 120)
|
|
)
|
|
end
|
|
modifier_pudge_dismember_growth_custom = __TS__Decorate(
|
|
modifier_pudge_dismember_growth_custom,
|
|
modifier_pudge_dismember_growth_custom,
|
|
{registerModifier(nil)},
|
|
{kind = "class", name = "modifier_pudge_dismember_growth_custom"}
|
|
)
|
|
____exports.modifier_pudge_dismember_growth_custom = modifier_pudge_dismember_growth_custom
|
|
____exports.modifier_pudge_dismember_custom = __TS__Class()
|
|
local modifier_pudge_dismember_custom = ____exports.modifier_pudge_dismember_custom
|
|
modifier_pudge_dismember_custom.name = "modifier_pudge_dismember_custom"
|
|
modifier_pudge_dismember_custom.____file_path = "scripts/vscripts/abilities/heroes/pudge/ability_pudge_dismember_custom.lua"
|
|
__TS__ClassExtends(modifier_pudge_dismember_custom, BaseModifier)
|
|
function modifier_pudge_dismember_custom.prototype.IsDebuff(self)
|
|
return true
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.IsHidden(self)
|
|
return false
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.IsPurgable(self)
|
|
return false
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.GetEffectName(self)
|
|
return "particles/econ/items/pudge/pudge_arcana/pudge_arcana_dismember_default.vpcf"
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.GetEffectAttachType(self)
|
|
return PATTACH_OVERHEAD_FOLLOW
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.CheckState(self)
|
|
return {[MODIFIER_STATE_INVISIBLE] = false}
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.DeclareFunctions(self)
|
|
return {MODIFIER_PROPERTY_OVERRIDE_ANIMATION, MODIFIER_EVENT_ON_DEATH}
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.GetOverrideAnimation(self)
|
|
return ACT_DOTA_FLAIL
|
|
end
|
|
function modifier_pudge_dismember_custom.prototype.OnDeath(self, event)
|
|
if not IsServer() then
|
|
return
|
|
end
|
|
local caster = self:GetCaster()
|
|
local target = self:GetParent()
|
|
if not caster or not target or not event.unit then
|
|
return
|
|
end
|
|
if event.unit ~= target then
|
|
return
|
|
end
|
|
if target:IsAlive() then
|
|
return
|
|
end
|
|
if target:GetTeamNumber() == caster:GetTeamNumber() then
|
|
return
|
|
end
|
|
if target:IsBuilding() or target:IsOther() or target:IsIllusion() then
|
|
return
|
|
end
|
|
local fleshHeap = caster:FindModifierByName(modifier_pudge_flesh_heap_custom.name)
|
|
if fleshHeap then
|
|
fleshHeap:AddHeapStack(1)
|
|
end
|
|
local ability = self:GetAbility()
|
|
if not ability then
|
|
return
|
|
end
|
|
local hungerModifier = caster:AddNewModifier(caster, ability, modifier_general_hunger.name, {})
|
|
if not hungerModifier then
|
|
return
|
|
end
|
|
local hungerBonus = math.max(
|
|
1,
|
|
math.floor(ability:GetSpecialValueFor("hunger_bonus"))
|
|
)
|
|
do
|
|
local i = 0
|
|
while i < hungerBonus do
|
|
hungerModifier:IncrementStackCount()
|
|
i = i + 1
|
|
end
|
|
end
|
|
end
|
|
modifier_pudge_dismember_custom = __TS__Decorate(
|
|
modifier_pudge_dismember_custom,
|
|
modifier_pudge_dismember_custom,
|
|
{registerModifier(nil)},
|
|
{kind = "class", name = "modifier_pudge_dismember_custom"}
|
|
)
|
|
____exports.modifier_pudge_dismember_custom = modifier_pudge_dismember_custom
|
|
return ____exports
|