Files
Dota-Zombie-Invasion/scripts/vscripts/abilities/heroes/pudge/ability_pudge_dismember_custom.lua
T
2026-05-29 15:11:31 +07:00

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