initial commit

This commit is contained in:
achmad
2026-05-29 15:11:31 +07:00
commit 777ee9bad8
1539 changed files with 172449 additions and 0 deletions
@@ -0,0 +1,125 @@
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
--- Пассивка для npc_capture_point: при приближении героя спавнит npc_teleport один раз.
____exports.ability_capture_point = __TS__Class()
local ability_capture_point = ____exports.ability_capture_point
ability_capture_point.name = "ability_capture_point"
ability_capture_point.____file_path = "scripts/vscripts/abilities/ability_capture_point.lua"
__TS__ClassExtends(ability_capture_point, BaseAbility)
function ability_capture_point.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_ability_capture_point.name
end
ability_capture_point = __TS__Decorate(
ability_capture_point,
ability_capture_point,
{registerAbility(nil)},
{kind = "class", name = "ability_capture_point"}
)
____exports.ability_capture_point = ability_capture_point
____exports.modifier_ability_capture_point = __TS__Class()
local modifier_ability_capture_point = ____exports.modifier_ability_capture_point
modifier_ability_capture_point.name = "modifier_ability_capture_point"
modifier_ability_capture_point.____file_path = "scripts/vscripts/abilities/ability_capture_point.lua"
__TS__ClassExtends(modifier_ability_capture_point, BaseModifier)
function modifier_ability_capture_point.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.activated = false
self.intervalThinkCount = 0
end
function modifier_ability_capture_point.prototype.IsHidden(self)
return true
end
function modifier_ability_capture_point.prototype.IsPurgable(self)
return false
end
function modifier_ability_capture_point.prototype.OnCreated(self)
if IsServer() then
local p = self:GetParent()
local o = p and p:GetAbsOrigin()
local ____opt_2 = p and p.GetEntityIndex
local idx = ____opt_2 and ____opt_2(p) or -1
self:StartIntervalThink(0.25)
end
end
function modifier_ability_capture_point.prototype.OnIntervalThink(self)
if not IsServer() or self.activated then
return
end
self:GetParent():StartGesture(ACT_DOTA_RUN)
local parent = self:GetParent()
if not parent or not IsValidEntity(parent) or not parent:IsAlive() then
return
end
local ability = self:GetAbility()
local radius = ability:GetSpecialValueFor("activation_radius")
local spawnDistance = ability:GetSpecialValueFor("spawn_distance")
local heroes = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_FRIENDLY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
self.intervalThinkCount = self.intervalThinkCount + 1
local realHeroCount = 0
for ____, u in ipairs(heroes) do
if u and u:IsAlive() and u:IsRealHero() then
realHeroCount = realHeroCount + 1
end
end
for ____, h in ipairs(heroes) do
if h and h:IsAlive() and h:IsRealHero() then
parent:RemoveGesture(ACT_DOTA_RUN)
self:spawnTeleport(parent, spawnDistance)
self.activated = true
self:StartIntervalThink(-1)
return
end
end
end
function modifier_ability_capture_point.prototype.spawnTeleport(self, capture, distance)
local origin = capture:GetAbsOrigin()
local forward = capture:GetForwardVector()
local rawPos = Vector(origin.x + forward.x * distance, origin.y + forward.y * distance, -origin.z)
local pos = GetGroundPosition(rawPos, nil)
capture:StartGesture(ACT_DOTA_CAPTURE)
local tp = CreateUnitByName(
"npc_teleport",
pos,
false,
nil,
nil,
capture:GetTeamNumber()
)
if tp and IsValidEntity(tp) then
local pfx = ParticleManager:CreateParticle(
"particles/econ/events/fall_2021/fountain_regen_fall_2021_lvl3.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:ReleaseParticleIndex(pfx)
tp:SetEntityName("npc_teleport")
tp:SetAbsOrigin(pos)
tp:SetForwardVector(forward)
end
end
modifier_ability_capture_point = __TS__Decorate(
modifier_ability_capture_point,
modifier_ability_capture_point,
{registerModifier(nil)},
{kind = "class", name = "modifier_ability_capture_point"}
)
____exports.modifier_ability_capture_point = modifier_ability_capture_point
return ____exports
@@ -0,0 +1,136 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
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
____exports.agro_leader = __TS__Class()
local agro_leader = ____exports.agro_leader
agro_leader.name = "agro_leader"
agro_leader.____file_path = "scripts/vscripts/abilities/creep/agro_leader.lua"
__TS__ClassExtends(agro_leader, BaseAbility)
function agro_leader.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 agro_leader.prototype.OnAbilityPhaseStart(self)
if IsServer() then
self:GetCaster():StartGestureWithPlaybackRate(ACT_DOTA_CAST_ABILITY_4, 0.7)
self.preParticle = ParticleManager:CreateParticle(
"particles/darkmoon_creep_warning.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetCaster()
)
ParticleManager:SetParticleControlEnt(
self.preParticle,
0,
self:GetCaster(),
PATTACH_ABSORIGIN_FOLLOW,
"",
self:GetCaster():GetOrigin(),
true
)
ParticleManager:SetParticleControl(
self.preParticle,
1,
Vector(100, 100, 100)
)
end
return true
end
function agro_leader.prototype.OnAbilityPhaseInterrupted(self)
if IsClient() or not self.preParticle then
return
end
self:GetCaster():FadeGesture(ACT_DOTA_CAST_ABILITY_4)
ParticleManager:DestroyParticle(self.preParticle, false)
end
function agro_leader.prototype.OnSpellStart(self)
local caster = self:GetCaster()
if self.preParticle then
ParticleManager:DestroyParticle(self.preParticle, false)
end
caster:FadeGesture(ACT_DOTA_CAST_ABILITY_4)
local radius = self:GetSpecialValueFor("radius")
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_axe/axe_beserkers_call_owner.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:SetParticleControl(
particle,
2,
Vector(radius, radius, radius)
)
caster:EmitSound("Hero_Axe.Berserkers_Call")
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
)
__TS__ArrayForEach(
enemies,
function(____, enemy)
enemy:MoveToTargetToAttack(caster)
____exports.modifier_agro_leader_debuff:apply(
enemy,
caster,
self,
{duration = self:GetSpecialValueFor("duration")}
)
end
)
end
agro_leader = __TS__Decorate(
agro_leader,
agro_leader,
{registerAbility(nil)},
{kind = "class", name = "agro_leader"}
)
____exports.agro_leader = agro_leader
____exports.modifier_agro_leader_debuff = __TS__Class()
local modifier_agro_leader_debuff = ____exports.modifier_agro_leader_debuff
modifier_agro_leader_debuff.name = "modifier_agro_leader_debuff"
modifier_agro_leader_debuff.____file_path = "scripts/vscripts/abilities/creep/agro_leader.lua"
__TS__ClassExtends(modifier_agro_leader_debuff, BaseModifier)
function modifier_agro_leader_debuff.prototype.IsHidden(self)
return false
end
function modifier_agro_leader_debuff.prototype.IsPurgable(self)
return false
end
function modifier_agro_leader_debuff.prototype.IsDebuff(self)
return true
end
function modifier_agro_leader_debuff.prototype.CheckState(self)
return {[MODIFIER_STATE_COMMAND_RESTRICTED] = true}
end
function modifier_agro_leader_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_DEATH}
end
function modifier_agro_leader_debuff.prototype.OnDeath(self, event)
if event.unit == self:GetCaster() then
self:Destroy()
end
end
function modifier_agro_leader_debuff.prototype.OnDestroy(self)
end
function modifier_agro_leader_debuff.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_beserkers_call.vpcf"
end
modifier_agro_leader_debuff = __TS__Decorate(
modifier_agro_leader_debuff,
modifier_agro_leader_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_agro_leader_debuff"}
)
____exports.modifier_agro_leader_debuff = modifier_agro_leader_debuff
return ____exports
@@ -0,0 +1,150 @@
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 ____item_shameful_pipe = require("items.quest_items.item_shameful_pipe")
local modifier_item_shameful_pipe = ____item_shameful_pipe.modifier_item_shameful_pipe
local ____luck = require("utils.luck")
local rollLuckChance = ____luck.rollLuckChance
____exports.bone_armor = __TS__Class()
local bone_armor = ____exports.bone_armor
bone_armor.name = "bone_armor"
bone_armor.____file_path = "scripts/vscripts/abilities/creep/bone_armor.lua"
__TS__ClassExtends(bone_armor, BaseAbility)
function bone_armor.prototype.Precache(self, context)
PrecacheResource("particle", "particles/econ/items/centaur/centaur_crownfall_belt/centaur_crownfall_belt_retaliate.vpcf", context)
end
function bone_armor.prototype.GetIntrinsicModifierName(self)
return "modifier_bone_armor_passive"
end
bone_armor = __TS__Decorate(
bone_armor,
bone_armor,
{registerAbility(nil)},
{kind = "class", name = "bone_armor"}
)
____exports.bone_armor = bone_armor
____exports.modifier_bone_armor_passive = __TS__Class()
local modifier_bone_armor_passive = ____exports.modifier_bone_armor_passive
modifier_bone_armor_passive.name = "modifier_bone_armor_passive"
modifier_bone_armor_passive.____file_path = "scripts/vscripts/abilities/creep/bone_armor.lua"
__TS__ClassExtends(modifier_bone_armor_passive, BaseModifier)
function modifier_bone_armor_passive.prototype.IsHidden(self)
return true
end
function modifier_bone_armor_passive.prototype.IsDebuff(self)
return false
end
function modifier_bone_armor_passive.prototype.IsPurgable(self)
return false
end
function modifier_bone_armor_passive.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS, MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_bone_armor_passive.prototype.GetModifierPhysicalArmorBonus(self)
local ____opt_0 = self:GetAbility()
return ____opt_0 and ____opt_0:GetSpecialValueFor("armor_bonus") or 0
end
function modifier_bone_armor_passive.prototype.playRetaliateParticle(self)
ParticleManager:CreateParticle(
"particles/econ/items/centaur/centaur_crownfall_belt/centaur_crownfall_belt_retaliate.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
end
function modifier_bone_armor_passive.prototype.hasHeroNearCreep(self, creep, radius)
local heroes = FindUnitsInRadius(
creep:GetTeamNumber(),
creep:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, hero in ipairs(heroes) do
if hero and IsValidEntity(hero) and hero:IsAlive() and hero:IsRealHero() then
return true
end
end
return false
end
function modifier_bone_armor_passive.prototype.applyReflectedDamage(self, attacker, parent, ability, eventDamage)
local reflectChance = ability:GetSpecialValueFor("damage_reflect_chance")
if not rollLuckChance(nil, attacker, reflectChance / 100) then
return
end
local reflectPct = ability:GetSpecialValueFor("damage_reflect_pct")
local reflectDamage = eventDamage * (reflectPct / 100)
if reflectDamage <= 0 then
return
end
ApplyDamage({
victim = attacker,
attacker = parent,
damage = reflectDamage,
damage_type = DAMAGE_TYPE_PHYSICAL,
ability = ability
})
self:playRetaliateParticle()
end
function modifier_bone_armor_passive.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
if event.target ~= self:GetParent() then
return
end
local attacker = event.attacker
if not attacker or not IsValidEntity(attacker) or not attacker:IsAlive() then
return
end
if not attacker:IsHero() or not attacker:IsRealHero() then
return
end
if not attacker:IsRangedAttacker() then
return
end
if attacker:HasModifier(modifier_item_shameful_pipe.name) then
return
end
local ability = self:GetAbility()
if not ability then
return
end
local parent = self:GetParent()
local heroProximityRadius = ability:GetSpecialValueFor("hero_proximity_radius")
local heroNearCreep = self:hasHeroNearCreep(parent, heroProximityRadius)
if not heroNearCreep then
local isolatedMultiplier = ability:GetSpecialValueFor("isolated_damage_multiplier")
local damage = event.damage * isolatedMultiplier
if damage > 0 then
ApplyDamage({
victim = attacker,
attacker = parent,
damage = damage,
damage_type = DAMAGE_TYPE_PHYSICAL,
ability = ability
})
self:playRetaliateParticle()
end
return
end
self:applyReflectedDamage(attacker, parent, ability, event.damage)
end
modifier_bone_armor_passive = __TS__Decorate(
modifier_bone_armor_passive,
modifier_bone_armor_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_bone_armor_passive"}
)
____exports.modifier_bone_armor_passive = modifier_bone_armor_passive
return ____exports
@@ -0,0 +1,362 @@
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 modifier_boss_nevermore_coil_beam_lock
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_boss_nevermore_coil_debuff = require("abilities.creep.modifier_boss_nevermore_coil_debuff")
local modifier_boss_nevermore_coil_debuff = ____modifier_boss_nevermore_coil_debuff.modifier_boss_nevermore_coil_debuff
--- Как 1-я способность (две волны по «шахматке»), но слоты в линию от босса к точке каста — «к врагу».
____exports.boss_nevermore_coil_beam = __TS__Class()
local boss_nevermore_coil_beam = ____exports.boss_nevermore_coil_beam
boss_nevermore_coil_beam.name = "boss_nevermore_coil_beam"
boss_nevermore_coil_beam.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_coil_beam.lua"
__TS__ClassExtends(boss_nevermore_coil_beam, BaseAbility)
function boss_nevermore_coil_beam.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", context)
PrecacheResource("particle", "particles/darkmoon_creep_warning.vpcf", context)
PrecacheResource("particle", "particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", context)
PrecacheResource("soundfile", "sounds/units/heroes/nevermore/shadowraze.vsnd", context)
end
function boss_nevermore_coil_beam.prototype.GetAOERadius(self)
local r = self:GetSpecialValueFor("radius")
local start = self:getSpecialOrDefault("beam_start_dist", ____exports.boss_nevermore_coil_beam.DEFAULT_BEAM_START)
local step = self:getBeamStepDistance()
local slots = self:getSlotCountForPhase(self:getBossPhase())
return start + step * math.max(0, slots - 1) + r * 2
end
function boss_nevermore_coil_beam.prototype.getSpecialOrDefault(self, name, fallback)
local value = self:GetSpecialValueFor(name)
if not value or value <= 0 then
return fallback
end
return value
end
function boss_nevermore_coil_beam.prototype.getBossPhase(self)
local caster = self:GetCaster()
if not caster or caster:IsNull() then
return 1
end
local hp = caster:GetHealthPercent()
if hp <= 25 then
return 4
end
if hp <= 50 then
return 3
end
if hp <= 75 then
return 2
end
return 1
end
function boss_nevermore_coil_beam.prototype.getSlotCountForPhase(self, phase)
local baseSlots = math.floor(self:getSpecialOrDefault("lane_slot_count", ____exports.boss_nevermore_coil_beam.DEFAULT_SLOT_COUNT))
local perPhase = math.floor(self:getSpecialOrDefault("lane_slot_phase_bonus", ____exports.boss_nevermore_coil_beam.DEFAULT_SLOT_PHASE_BONUS))
return baseSlots + (phase - 1) * perPhase
end
function boss_nevermore_coil_beam.prototype.getBeamStepDistance(self)
local radius = self:GetSpecialValueFor("radius")
local stepKv = self:GetSpecialValueFor("beam_step")
if stepKv > 0 then
return stepKv
end
return math.max(radius * 1.22, ____exports.boss_nevermore_coil_beam.DEFAULT_BEAM_STEP)
end
function boss_nevermore_coil_beam.prototype.buildBeamSlots(self, origin, direction, phase)
local dir2d = direction:Normalized()
dir2d.z = 0
local slotCount = self:getSlotCountForPhase(phase)
local startDist = self:getSpecialOrDefault("beam_start_dist", ____exports.boss_nevermore_coil_beam.DEFAULT_BEAM_START)
local step = self:getBeamStepDistance()
local firstWaveHitsEvenIndex = RandomInt(0, 1) == 0
local slots = {}
do
local i = 0
while i < slotCount do
local along = startDist + i * step
local pos = GetGroundPosition(origin + dir2d * along, nil)
local isEven = i % 2 == 0
local ____firstWaveHitsEvenIndex_0
if firstWaveHitsEvenIndex then
____firstWaveHitsEvenIndex_0 = isEven
else
____firstWaveHitsEvenIndex_0 = not isEven
end
local hitsOnFirstWave = ____firstWaveHitsEvenIndex_0
slots[#slots + 1] = {position = pos, hitsOnFirstWave = hitsOnFirstWave}
i = i + 1
end
end
return slots
end
function boss_nevermore_coil_beam.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local origin = caster:GetAbsOrigin()
local point = self:GetCursorPosition()
local toPoint = point - origin
local direction = toPoint:Length2D() < 1 and caster:GetForwardVector() or toPoint:Normalized()
local phase = self:getBossPhase()
self:spawnBeamPattern(origin, direction, phase)
end
function boss_nevermore_coil_beam.prototype.spawnBeamPattern(self, origin, direction, phase)
local caster = self:GetCaster()
local slots = self:buildBeamSlots(origin, direction, phase)
if #slots == 0 then
return
end
local radius = self:GetSpecialValueFor("radius")
local startDelay = self:getSpecialOrDefault("start_delay", ____exports.boss_nevermore_coil_beam.DEFAULT_START_DELAY)
local warningTime = self:getSpecialOrDefault("precast_warning_time", ____exports.boss_nevermore_coil_beam.DEFAULT_WARNING_TIME)
local secondDelayRaw = self:GetSpecialValueFor("second_wave_delay")
local secondWaveDelay = secondDelayRaw > 0 and secondDelayRaw or ____exports.boss_nevermore_coil_beam.DEFAULT_SECOND_WAVE_DELAY
local firstHitTime = startDelay
local secondHitTime = firstHitTime + secondWaveDelay
local firstWarningStart = math.max(0, firstHitTime - warningTime)
local secondWarningStart = math.max(firstHitTime + 0.1, secondHitTime - warningTime)
caster:AddNewModifier(caster, self, modifier_boss_nevermore_coil_beam_lock.name, {duration = secondHitTime + 0.35})
local warnings = {}
local function destroyWarningPair(____, pair)
ParticleManager:DestroyParticle(pair[1], true)
ParticleManager:ReleaseParticleIndex(pair[1])
ParticleManager:DestroyParticle(pair[2], true)
ParticleManager:ReleaseParticleIndex(pair[2])
end
local function clearWarning(____, idx)
local pair = warnings[idx + 1]
if not pair then
return
end
destroyWarningPair(nil, pair)
warnings[idx + 1] = nil
end
Timers:CreateTimer(
firstWarningStart,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
do
local i = 0
while i < #slots do
do
if not slots[i + 1].hitsOnFirstWave then
goto __continue25
end
warnings[i + 1] = self:createPulseWarningColored(slots[i + 1].position, radius, true)
end
::__continue25::
i = i + 1
end
end
return nil
end
)
Timers:CreateTimer(
firstHitTime,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
local impactPhase = self:getBossPhase()
local baseDamage = caster:GetAttackDamage()
local bonusDamagePerStack = self:GetSpecialValueFor("coil_stack_bonus_damage")
local damageMultiplier = 1 + (impactPhase - 1) * 0.3
do
local i = 0
while i < #slots do
do
if not slots[i + 1].hitsOnFirstWave then
goto __continue29
end
clearWarning(nil, i)
self:applyPulseDamage(
slots[i + 1].position,
radius,
baseDamage,
bonusDamagePerStack,
damageMultiplier
)
end
::__continue29::
i = i + 1
end
end
return nil
end
)
Timers:CreateTimer(
secondWarningStart,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
do
local i = 0
while i < #slots do
do
if slots[i + 1].hitsOnFirstWave then
goto __continue33
end
if warnings[i + 1] then
goto __continue33
end
warnings[i + 1] = self:createPulseWarningColored(slots[i + 1].position, radius, false)
end
::__continue33::
i = i + 1
end
end
return nil
end
)
Timers:CreateTimer(
secondHitTime,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
local impactPhase = self:getBossPhase()
local baseDamage = caster:GetAttackDamage()
local bonusDamagePerStack = self:GetSpecialValueFor("coil_stack_bonus_damage")
local damageMultiplier = 1 + (impactPhase - 1) * 0.3
do
local i = 0
while i < #slots do
do
if slots[i + 1].hitsOnFirstWave then
goto __continue38
end
clearWarning(nil, i)
self:applyPulseDamage(
slots[i + 1].position,
radius,
baseDamage,
bonusDamagePerStack,
damageMultiplier
)
end
::__continue38::
i = i + 1
end
end
return nil
end
)
end
function boss_nevermore_coil_beam.prototype.createPulseWarningColored(self, pulsePoint, radius, firstWaveStrike)
local caster = self:GetCaster()
local warningParticle = ParticleManager:CreateParticle("particles/darkmoon_creep_warning.vpcf", PATTACH_CUSTOMORIGIN, caster)
local aoeParticle = ParticleManager:CreateParticle("particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControl(warningParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
warningParticle,
1,
Vector(radius, 100, 100)
)
ParticleManager:SetParticleControl(aoeParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
aoeParticle,
1,
Vector(radius, 0, 0)
)
ParticleManager:SetParticleControl(
aoeParticle,
2,
Vector(6, 0, 1)
)
local rgb = firstWaveStrike and Vector(240, 40, 40) or Vector(70, 170, 255)
ParticleManager:SetParticleControl(aoeParticle, 3, rgb)
ParticleManager:SetParticleControl(aoeParticle, 4, pulsePoint)
return {warningParticle, aoeParticle}
end
function boss_nevermore_coil_beam.prototype.applyPulseDamage(self, pulsePoint, radius, baseDamage, bonusDamagePerStack, damageMultiplier)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or caster:IsNull() or not caster:IsAlive() then
return
end
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
pulsePoint,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
local coilDebuff = enemy:FindModifierByName(modifier_boss_nevermore_coil_debuff.name)
local stacks = coilDebuff and coilDebuff:GetStackCount() or 0
local damage = (baseDamage + stacks * bonusDamagePerStack) * damageMultiplier
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local updatedDebuff = enemy:AddNewModifier(caster, self, modifier_boss_nevermore_coil_debuff.name, {})
if updatedDebuff ~= nil then
if stacks > 0 then
updatedDebuff:SetStackCount(stacks + 1)
else
updatedDebuff:SetStackCount(1)
end
end
end
EmitSoundOnLocationWithCaster(pulsePoint, "Hero_Nevermore.Shadowraze", caster)
local hitParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(hitParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
hitParticle,
1,
Vector(radius, 1, 1)
)
ParticleManager:ReleaseParticleIndex(hitParticle)
end
boss_nevermore_coil_beam.DEFAULT_START_DELAY = 0.9
boss_nevermore_coil_beam.DEFAULT_SECOND_WAVE_DELAY = 1
boss_nevermore_coil_beam.DEFAULT_WARNING_TIME = 0.85
boss_nevermore_coil_beam.DEFAULT_SLOT_COUNT = 12
boss_nevermore_coil_beam.DEFAULT_SLOT_PHASE_BONUS = 2
boss_nevermore_coil_beam.DEFAULT_BEAM_START = 140
boss_nevermore_coil_beam.DEFAULT_BEAM_STEP = 195
boss_nevermore_coil_beam = __TS__Decorate(
boss_nevermore_coil_beam,
boss_nevermore_coil_beam,
{registerAbility(nil)},
{kind = "class", name = "boss_nevermore_coil_beam"}
)
____exports.boss_nevermore_coil_beam = boss_nevermore_coil_beam
modifier_boss_nevermore_coil_beam_lock = __TS__Class()
modifier_boss_nevermore_coil_beam_lock.name = "modifier_boss_nevermore_coil_beam_lock"
modifier_boss_nevermore_coil_beam_lock.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_coil_beam.lua"
__TS__ClassExtends(modifier_boss_nevermore_coil_beam_lock, BaseModifier)
function modifier_boss_nevermore_coil_beam_lock.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_coil_beam_lock.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_coil_beam_lock.prototype.CheckState(self)
return {[MODIFIER_STATE_DISARMED] = true}
end
modifier_boss_nevermore_coil_beam_lock = __TS__Decorate(
modifier_boss_nevermore_coil_beam_lock,
modifier_boss_nevermore_coil_beam_lock,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_coil_beam_lock"}
)
return ____exports
@@ -0,0 +1,353 @@
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 modifier_boss_nevermore_coil_wave_lock
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_boss_nevermore_coil_debuff = require("abilities.creep.modifier_boss_nevermore_coil_debuff")
local modifier_boss_nevermore_coil_debuff = ____modifier_boss_nevermore_coil_debuff.modifier_boss_nevermore_coil_debuff
____exports.boss_nevermore_coil_wave = __TS__Class()
local boss_nevermore_coil_wave = ____exports.boss_nevermore_coil_wave
boss_nevermore_coil_wave.name = "boss_nevermore_coil_wave"
boss_nevermore_coil_wave.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_coil_wave.lua"
__TS__ClassExtends(boss_nevermore_coil_wave, BaseAbility)
function boss_nevermore_coil_wave.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", context)
PrecacheResource("particle", "particles/darkmoon_creep_warning.vpcf", context)
PrecacheResource("particle", "particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", context)
PrecacheResource("soundfile", "sounds/units/heroes/nevermore/shadowraze.vsnd", context)
end
function boss_nevermore_coil_wave.prototype.GetAOERadius(self)
local r = self:GetSpecialValueFor("radius")
local forward = self:getSpecialOrDefault("lane_forward_dist", ____exports.boss_nevermore_coil_wave.DEFAULT_FORWARD_DIST)
return forward + r * 2
end
function boss_nevermore_coil_wave.prototype.getSpecialOrDefault(self, name, fallback)
local value = self:GetSpecialValueFor(name)
if not value or value <= 0 then
return fallback
end
return value
end
function boss_nevermore_coil_wave.prototype.getBossPhase(self)
local caster = self:GetCaster()
if not caster or caster:IsNull() then
return 1
end
local hp = caster:GetHealthPercent()
if hp <= 25 then
return 4
end
if hp <= 50 then
return 3
end
if hp <= 75 then
return 2
end
return 1
end
function boss_nevermore_coil_wave.prototype.buildGapLaneSlots(self, origin, direction, phase)
local radius = self:GetSpecialValueFor("radius")
local baseSlots = math.floor(self:getSpecialOrDefault("lane_slot_count", ____exports.boss_nevermore_coil_wave.DEFAULT_SLOT_COUNT))
local slotCount = baseSlots + (phase - 1)
local forwardDist = self:getSpecialOrDefault("lane_forward_dist", ____exports.boss_nevermore_coil_wave.DEFAULT_FORWARD_DIST) + (phase - 1) * 35
local spacing = math.max(
radius * self:getSpecialOrDefault("lane_slot_spacing", ____exports.boss_nevermore_coil_wave.DEFAULT_SLOT_SPACING_FACTOR),
185
)
local dir2d = direction:Normalized()
dir2d.z = 0
local right = Vector(-dir2d.y, dir2d.x, 0):Normalized()
local centerRow = GetGroundPosition(origin + dir2d * forwardDist, nil)
local firstWaveHitsEvenIndex = RandomInt(0, 1) == 0
local slots = {}
local mid = (slotCount - 1) / 2
do
local i = 0
while i < slotCount do
local lateral = (i - mid) * spacing
local pos = GetGroundPosition(centerRow + right * lateral, nil)
local isEven = i % 2 == 0
local ____firstWaveHitsEvenIndex_0
if firstWaveHitsEvenIndex then
____firstWaveHitsEvenIndex_0 = isEven
else
____firstWaveHitsEvenIndex_0 = not isEven
end
local hitsOnFirstWave = ____firstWaveHitsEvenIndex_0
slots[#slots + 1] = {position = pos, hitsOnFirstWave = hitsOnFirstWave}
i = i + 1
end
end
return slots
end
function boss_nevermore_coil_wave.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local origin = caster:GetAbsOrigin()
local point = self:GetCursorPosition()
local toPoint = point - origin
local direction = toPoint:Length2D() < 1 and caster:GetForwardVector() or toPoint:Normalized()
local phase = self:getBossPhase()
self:spawnGapLanePattern(origin, direction, phase)
end
function boss_nevermore_coil_wave.prototype.spawnGapLanePattern(self, origin, direction, phase)
local caster = self:GetCaster()
local slots = self:buildGapLaneSlots(origin, direction, phase)
if #slots == 0 then
return
end
local radius = self:GetSpecialValueFor("radius")
local startDelay = self:getSpecialOrDefault("start_delay", ____exports.boss_nevermore_coil_wave.DEFAULT_START_DELAY)
local warningTime = self:getSpecialOrDefault("precast_warning_time", ____exports.boss_nevermore_coil_wave.DEFAULT_WARNING_TIME)
local secondDelayRaw = self:GetSpecialValueFor("second_wave_delay")
local secondWaveDelay = secondDelayRaw > 0 and secondDelayRaw or ____exports.boss_nevermore_coil_wave.DEFAULT_SECOND_WAVE_DELAY
local firstHitTime = startDelay
local secondHitTime = firstHitTime + secondWaveDelay
local firstWarningStart = math.max(0, firstHitTime - warningTime)
local secondWarningStart = math.max(firstHitTime + 0.1, secondHitTime - warningTime)
caster:AddNewModifier(caster, self, modifier_boss_nevermore_coil_wave_lock.name, {duration = secondHitTime + 0.35})
local warnings = {}
local function destroyWarningPair(____, pair)
ParticleManager:DestroyParticle(pair[1], true)
ParticleManager:ReleaseParticleIndex(pair[1])
ParticleManager:DestroyParticle(pair[2], true)
ParticleManager:ReleaseParticleIndex(pair[2])
end
local function clearWarning(____, idx)
local pair = warnings[idx + 1]
if not pair then
return
end
destroyWarningPair(nil, pair)
warnings[idx + 1] = nil
end
Timers:CreateTimer(
firstWarningStart,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
do
local i = 0
while i < #slots do
do
if not slots[i + 1].hitsOnFirstWave then
goto __continue22
end
warnings[i + 1] = self:createPulseWarningColored(slots[i + 1].position, radius, true)
end
::__continue22::
i = i + 1
end
end
return nil
end
)
Timers:CreateTimer(
firstHitTime,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
local impactPhase = self:getBossPhase()
local baseDamage = caster:GetAttackDamage()
local bonusDamagePerStack = self:GetSpecialValueFor("coil_stack_bonus_damage")
local damageMultiplier = 1 + (impactPhase - 1) * 0.3
do
local i = 0
while i < #slots do
do
if not slots[i + 1].hitsOnFirstWave then
goto __continue26
end
clearWarning(nil, i)
self:applyPulseDamage(
slots[i + 1].position,
radius,
baseDamage,
bonusDamagePerStack,
damageMultiplier
)
end
::__continue26::
i = i + 1
end
end
return nil
end
)
Timers:CreateTimer(
secondWarningStart,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
do
local i = 0
while i < #slots do
do
if slots[i + 1].hitsOnFirstWave then
goto __continue30
end
if warnings[i + 1] then
goto __continue30
end
warnings[i + 1] = self:createPulseWarningColored(slots[i + 1].position, radius, false)
end
::__continue30::
i = i + 1
end
end
return nil
end
)
Timers:CreateTimer(
secondHitTime,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
local impactPhase = self:getBossPhase()
local baseDamage = caster:GetAttackDamage()
local bonusDamagePerStack = self:GetSpecialValueFor("coil_stack_bonus_damage")
local damageMultiplier = 1 + (impactPhase - 1) * 0.3
do
local i = 0
while i < #slots do
do
if slots[i + 1].hitsOnFirstWave then
goto __continue35
end
clearWarning(nil, i)
self:applyPulseDamage(
slots[i + 1].position,
radius,
baseDamage,
bonusDamagePerStack,
damageMultiplier
)
end
::__continue35::
i = i + 1
end
end
return nil
end
)
end
function boss_nevermore_coil_wave.prototype.createPulseWarningColored(self, pulsePoint, radius, firstWaveStrike)
local caster = self:GetCaster()
local warningParticle = ParticleManager:CreateParticle("particles/darkmoon_creep_warning.vpcf", PATTACH_CUSTOMORIGIN, caster)
local aoeParticle = ParticleManager:CreateParticle("particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControl(warningParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
warningParticle,
1,
Vector(radius, 100, 100)
)
ParticleManager:SetParticleControl(aoeParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
aoeParticle,
1,
Vector(radius, 0, 0)
)
ParticleManager:SetParticleControl(
aoeParticle,
2,
Vector(6, 0, 1)
)
local rgb = firstWaveStrike and Vector(240, 40, 40) or Vector(70, 170, 255)
ParticleManager:SetParticleControl(aoeParticle, 3, rgb)
ParticleManager:SetParticleControl(aoeParticle, 4, pulsePoint)
return {warningParticle, aoeParticle}
end
function boss_nevermore_coil_wave.prototype.applyPulseDamage(self, pulsePoint, radius, baseDamage, bonusDamagePerStack, damageMultiplier)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or caster:IsNull() or not caster:IsAlive() then
return
end
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
pulsePoint,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
local coilDebuff = enemy:FindModifierByName(modifier_boss_nevermore_coil_debuff.name)
local stacks = coilDebuff and coilDebuff:GetStackCount() or 0
local damage = (baseDamage + stacks * bonusDamagePerStack) * damageMultiplier
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local updatedDebuff = enemy:AddNewModifier(caster, self, modifier_boss_nevermore_coil_debuff.name, {})
if updatedDebuff ~= nil then
if stacks > 0 then
updatedDebuff:SetStackCount(stacks + 1)
else
updatedDebuff:SetStackCount(1)
end
end
end
EmitSoundOnLocationWithCaster(pulsePoint, "Hero_Nevermore.Shadowraze", caster)
local hitParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(hitParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
hitParticle,
1,
Vector(radius, 1, 1)
)
ParticleManager:ReleaseParticleIndex(hitParticle)
end
boss_nevermore_coil_wave.DEFAULT_START_DELAY = 0.9
boss_nevermore_coil_wave.DEFAULT_SECOND_WAVE_DELAY = 1
boss_nevermore_coil_wave.DEFAULT_WARNING_TIME = 0.85
boss_nevermore_coil_wave.DEFAULT_SLOT_COUNT = 5
boss_nevermore_coil_wave.DEFAULT_FORWARD_DIST = 360
boss_nevermore_coil_wave.DEFAULT_SLOT_SPACING_FACTOR = 1.32
boss_nevermore_coil_wave = __TS__Decorate(
boss_nevermore_coil_wave,
boss_nevermore_coil_wave,
{registerAbility(nil)},
{kind = "class", name = "boss_nevermore_coil_wave"}
)
____exports.boss_nevermore_coil_wave = boss_nevermore_coil_wave
modifier_boss_nevermore_coil_wave_lock = __TS__Class()
modifier_boss_nevermore_coil_wave_lock.name = "modifier_boss_nevermore_coil_wave_lock"
modifier_boss_nevermore_coil_wave_lock.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_coil_wave.lua"
__TS__ClassExtends(modifier_boss_nevermore_coil_wave_lock, BaseModifier)
function modifier_boss_nevermore_coil_wave_lock.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_coil_wave_lock.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_coil_wave_lock.prototype.CheckState(self)
return {[MODIFIER_STATE_DISARMED] = true}
end
modifier_boss_nevermore_coil_wave_lock = __TS__Decorate(
modifier_boss_nevermore_coil_wave_lock,
modifier_boss_nevermore_coil_wave_lock,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_coil_wave_lock"}
)
return ____exports
@@ -0,0 +1,284 @@
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 modifier_boss_nevermore_hub_crossburst_lock
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_boss_nevermore_coil_debuff = require("abilities.creep.modifier_boss_nevermore_coil_debuff")
local modifier_boss_nevermore_coil_debuff = ____modifier_boss_nevermore_coil_debuff.modifier_boss_nevermore_coil_debuff
--- Случайная точка-хаб: от неё волны взрывов по 4 лучам (плюс или крест).
____exports.boss_nevermore_hub_crossburst = __TS__Class()
local boss_nevermore_hub_crossburst = ____exports.boss_nevermore_hub_crossburst
boss_nevermore_hub_crossburst.name = "boss_nevermore_hub_crossburst"
boss_nevermore_hub_crossburst.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_hub_crossburst.lua"
__TS__ClassExtends(boss_nevermore_hub_crossburst, BaseAbility)
function boss_nevermore_hub_crossburst.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", context)
PrecacheResource("particle", "particles/darkmoon_creep_warning.vpcf", context)
PrecacheResource("particle", "particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", context)
PrecacheResource("soundfile", "sounds/units/heroes/nevermore/shadowraze.vsnd", context)
end
function boss_nevermore_hub_crossburst.prototype.GetAOERadius(self)
local pick = self:getSpecialOrDefault("spawn_pick_radius", ____exports.boss_nevermore_hub_crossburst.DEFAULT_PICK_RADIUS)
local start = self:getSpecialOrDefault("ring_start_dist", ____exports.boss_nevermore_hub_crossburst.DEFAULT_RING_START)
local step = self:getSpecialOrDefault("ring_step", ____exports.boss_nevermore_hub_crossburst.DEFAULT_RING_STEP)
local n = self:getRingCountForPhase(self:getBossPhase())
local reach = start + (n - 1) * step + self:GetSpecialValueFor("radius")
return pick + reach
end
function boss_nevermore_hub_crossburst.prototype.getSpecialOrDefault(self, name, fallback)
local v = self:GetSpecialValueFor(name)
if not v or v <= 0 then
return fallback
end
return v
end
function boss_nevermore_hub_crossburst.prototype.getBossPhase(self)
local c = self:GetCaster()
if not c or c:IsNull() then
return 1
end
local hp = c:GetHealthPercent()
if hp <= 25 then
return 4
end
if hp <= 50 then
return 3
end
if hp <= 75 then
return 2
end
return 1
end
function boss_nevermore_hub_crossburst.prototype.getRingCountForPhase(self, phase)
local base = math.floor(self:getSpecialOrDefault("ring_count", ____exports.boss_nevermore_hub_crossburst.DEFAULT_RING_COUNT))
local perPhase = math.floor(self:getSpecialOrDefault("ring_count_phase_bonus", ____exports.boss_nevermore_hub_crossburst.DEFAULT_RING_COUNT_PHASE_BONUS))
return math.max(1, base + (phase - 1) * perPhase)
end
function boss_nevermore_hub_crossburst.prototype.pickRandomHub(self, groundOrigin)
local maxR = self:getSpecialOrDefault("spawn_pick_radius", ____exports.boss_nevermore_hub_crossburst.DEFAULT_PICK_RADIUS)
local ang = RandomFloat(0, 360)
local dist = maxR * math.sqrt(RandomFloat(0.001, 1))
local rad = ang * math.pi / 180
local dx = math.cos(rad) * dist
local dy = math.sin(rad) * dist
return GetGroundPosition(
groundOrigin + Vector(dx, dy, 0),
nil
)
end
function boss_nevermore_hub_crossburst.prototype.getDirections(self, pattern)
if pattern == "plus" then
return {
Vector(1, 0, 0),
Vector(-1, 0, 0),
Vector(0, 1, 0),
Vector(0, -1, 0)
}
end
local s = 1 / math.sqrt(2)
return {
Vector(s, s, 0),
Vector(s, -s, 0),
Vector(-s, s, 0),
Vector(-s, -s, 0)
}
end
function boss_nevermore_hub_crossburst.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or caster:IsNull() or not caster:IsAlive() then
return
end
local bossGround = GetGroundPosition(
caster:GetAbsOrigin(),
nil
)
local hub = self:pickRandomHub(bossGround)
local pattern = RandomInt(0, 1) == 0 and "plus" or "cross"
local radius = self:GetSpecialValueFor("radius")
local rEff = radius > 0 and radius or ____exports.boss_nevermore_hub_crossburst.DEFAULT_RADIUS
local phaseNow = self:getBossPhase()
local ringCount = self:getRingCountForPhase(phaseNow)
local ringStep = self:getSpecialOrDefault("ring_step", ____exports.boss_nevermore_hub_crossburst.DEFAULT_RING_STEP)
local ringStart = self:getSpecialOrDefault("ring_start_dist", ____exports.boss_nevermore_hub_crossburst.DEFAULT_RING_START)
local baseInterval = self:getSpecialOrDefault("ring_interval", ____exports.boss_nevermore_hub_crossburst.DEFAULT_RING_INTERVAL)
--- Ниже фаза — чуть быстрее волны (до ~−12% на фазе 4).
local ringInterval = baseInterval * math.max(0.72, 1 - (phaseNow - 1) * 0.06)
local firstDelay = self:getSpecialOrDefault("first_ring_delay", ____exports.boss_nevermore_hub_crossburst.DEFAULT_FIRST_DELAY)
local warningTime = self:getSpecialOrDefault("precast_warning_time", ____exports.boss_nevermore_hub_crossburst.DEFAULT_WARNING_TIME)
local dirs = self:getDirections(pattern)
local function ringPositionsForIndex(____, ringIdx)
local along = ringStart + ringIdx * ringStep
local out = {}
for ____, d in ipairs(dirs) do
local scaled = Vector(d.x * along, d.y * along, 0)
out[#out + 1] = GetGroundPosition(hub + scaled, nil)
end
return out
end
local lastHitTime = firstDelay + (ringCount - 1) * ringInterval
caster:AddNewModifier(caster, self, modifier_boss_nevermore_hub_crossburst_lock.name, {duration = lastHitTime + 0.5})
do
local r = 0
while r < ringCount do
local hitTime = firstDelay + r * ringInterval
local warnT = math.max(0, hitTime - warningTime)
local positions = ringPositionsForIndex(nil, r)
local isRedWave = r % 2 == 0
Timers:CreateTimer(
warnT,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
local ____pairs = {}
for ____, p in ipairs(positions) do
____pairs[#____pairs + 1] = self:createWarningPair(p, rEff, isRedWave)
end
Timers:CreateTimer(
hitTime - warnT,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
for ____, pair in ipairs(____pairs) do
do
if not pair then
goto __continue28
end
ParticleManager:DestroyParticle(pair[1], true)
ParticleManager:ReleaseParticleIndex(pair[1])
ParticleManager:DestroyParticle(pair[2], true)
ParticleManager:ReleaseParticleIndex(pair[2])
end
::__continue28::
end
for ____, p in ipairs(positions) do
self:applyRingDamage(p, rEff)
end
return nil
end
)
return nil
end
)
r = r + 1
end
end
end
function boss_nevermore_hub_crossburst.prototype.createWarningPair(self, pos, rad, firstStyle)
local caster = self:GetCaster()
local warningParticle = ParticleManager:CreateParticle("particles/darkmoon_creep_warning.vpcf", PATTACH_CUSTOMORIGIN, caster)
local aoeParticle = ParticleManager:CreateParticle("particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControl(warningParticle, 0, pos)
ParticleManager:SetParticleControl(
warningParticle,
1,
Vector(rad, 100, 100)
)
ParticleManager:SetParticleControl(aoeParticle, 0, pos)
ParticleManager:SetParticleControl(
aoeParticle,
1,
Vector(rad, 0, 0)
)
ParticleManager:SetParticleControl(
aoeParticle,
2,
Vector(6, 0, 1)
)
local rgb = firstStyle and Vector(230, 80, 40) or Vector(180, 80, 230)
ParticleManager:SetParticleControl(aoeParticle, 3, rgb)
ParticleManager:SetParticleControl(aoeParticle, 4, pos)
return {warningParticle, aoeParticle}
end
function boss_nevermore_hub_crossburst.prototype.applyRingDamage(self, pulsePoint, rad)
local caster = self:GetCaster()
if not caster or caster:IsNull() or not caster:IsAlive() then
return
end
local phase = self:getBossPhase()
local baseDamage = caster:GetAttackDamage()
local bonusDamagePerStack = self:GetSpecialValueFor("coil_stack_bonus_damage")
local damageMultiplier = 1 + (phase - 1) * 0.3
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
pulsePoint,
nil,
rad,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
local coilDebuff = enemy:FindModifierByName(modifier_boss_nevermore_coil_debuff.name)
local stacks = coilDebuff and coilDebuff:GetStackCount() or 0
local damage = (baseDamage + stacks * bonusDamagePerStack) * damageMultiplier * 0.85
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local updatedDebuff = enemy:AddNewModifier(caster, self, modifier_boss_nevermore_coil_debuff.name, {})
if updatedDebuff ~= nil then
updatedDebuff:SetStackCount(stacks > 0 and stacks + 1 or 1)
end
end
EmitSoundOnLocationWithCaster(pulsePoint, "Hero_Nevermore.Shadowraze", caster)
local hitParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(hitParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
hitParticle,
1,
Vector(rad, 1, 1)
)
ParticleManager:ReleaseParticleIndex(hitParticle)
end
boss_nevermore_hub_crossburst.DEFAULT_PICK_RADIUS = 1500
boss_nevermore_hub_crossburst.DEFAULT_RADIUS = 165
boss_nevermore_hub_crossburst.DEFAULT_RING_COUNT = 7
boss_nevermore_hub_crossburst.DEFAULT_RING_COUNT_PHASE_BONUS = 1
boss_nevermore_hub_crossburst.DEFAULT_RING_STEP = 190
boss_nevermore_hub_crossburst.DEFAULT_RING_START = 90
boss_nevermore_hub_crossburst.DEFAULT_RING_INTERVAL = 0.52
boss_nevermore_hub_crossburst.DEFAULT_FIRST_DELAY = 0.55
boss_nevermore_hub_crossburst.DEFAULT_WARNING_TIME = 0.82
boss_nevermore_hub_crossburst = __TS__Decorate(
boss_nevermore_hub_crossburst,
boss_nevermore_hub_crossburst,
{registerAbility(nil)},
{kind = "class", name = "boss_nevermore_hub_crossburst"}
)
____exports.boss_nevermore_hub_crossburst = boss_nevermore_hub_crossburst
modifier_boss_nevermore_hub_crossburst_lock = __TS__Class()
modifier_boss_nevermore_hub_crossburst_lock.name = "modifier_boss_nevermore_hub_crossburst_lock"
modifier_boss_nevermore_hub_crossburst_lock.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_hub_crossburst.lua"
__TS__ClassExtends(modifier_boss_nevermore_hub_crossburst_lock, BaseModifier)
function modifier_boss_nevermore_hub_crossburst_lock.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_hub_crossburst_lock.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_hub_crossburst_lock.prototype.CheckState(self)
return {[MODIFIER_STATE_DISARMED] = true}
end
modifier_boss_nevermore_hub_crossburst_lock = __TS__Decorate(
modifier_boss_nevermore_hub_crossburst_lock,
modifier_boss_nevermore_hub_crossburst_lock,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_hub_crossburst_lock"}
)
return ____exports
@@ -0,0 +1,494 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
local __TS__ArrayPush = ____lualib.__TS__ArrayPush
local __TS__SparseArrayNew = ____lualib.__TS__SparseArrayNew
local __TS__SparseArrayPush = ____lualib.__TS__SparseArrayPush
local __TS__SparseArraySpread = ____lualib.__TS__SparseArraySpread
local __TS__Decorate = ____lualib.__TS__Decorate
local ____exports = {}
local modifier_boss_nevermore_requiem_barrage_casting
local ____nevermore_boss_requiem_bridge = require("ai.nevermore_boss_requiem_bridge")
local nevermoreIncrementRequiemCastCount = ____nevermore_boss_requiem_bridge.nevermoreIncrementRequiemCastCount
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_boss_nevermore_requiem_magic_resist_debuff = require("abilities.creep.modifier_boss_nevermore_requiem_magic_resist_debuff")
local modifier_boss_nevermore_requiem_magic_resist_debuff = ____modifier_boss_nevermore_requiem_magic_resist_debuff.modifier_boss_nevermore_requiem_magic_resist_debuff
--- Глобальный множитель урона залпа (подогнан под KV-бафф ~+60%).
local REQUIEM_BARRAGE_DAMAGE_MULT = 1.6
--- Доп. дальность волны за стадию HP босса (согласовано с KV wave_distance ×1.6).
local REQUIEM_PHASE_DISTANCE_BONUS = 192
____exports.boss_nevermore_requiem_barrage = __TS__Class()
local boss_nevermore_requiem_barrage = ____exports.boss_nevermore_requiem_barrage
boss_nevermore_requiem_barrage.name = "boss_nevermore_requiem_barrage"
boss_nevermore_requiem_barrage.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_requiem_barrage.lua"
__TS__ClassExtends(boss_nevermore_requiem_barrage, BaseAbility)
function boss_nevermore_requiem_barrage.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.castSerial = 0
self.phasePreviewParticles = {}
self.phasePreviewRotationOffset = 0
self.activePreviewParticles = {}
self.gestureLoopSerial = 0
end
function boss_nevermore_requiem_barrage.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_nevermore/nevermore_requiemofsouls_line.vpcf", context)
PrecacheResource("particle", "particles/boss_tinker_laser_preview_vector.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_nevermore.vsndevts", context)
end
function boss_nevermore_requiem_barrage.prototype.GetChannelTime(self)
local channel = self:GetSpecialValueFor("channel_time")
return channel > 0 and channel or 3
end
function boss_nevermore_requiem_barrage.prototype.getBossPhase(self)
local caster = self:GetCaster()
if not caster or caster:IsNull() then
return 1
end
local hp = caster:GetHealthPercent()
if hp <= 25 then
return 4
end
if hp <= 50 then
return 3
end
if hp <= 75 then
return 2
end
return 1
end
function boss_nevermore_requiem_barrage.prototype.OnAbilityPhaseStart(self)
if not IsServer() then
return true
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local toPoint = point - caster:GetAbsOrigin()
local baseDirection = toPoint:Length2D() < 1 and caster:GetForwardVector() or toPoint:Normalized()
self:clearPhasePreview()
self.phasePreviewRotationOffset = self:getWaveRotationOffset(1)
local previewDirections = self:buildBurstDirections(
baseDirection,
self.phasePreviewRotationOffset,
self:getBossPhase()
)
local previewDuration = self:GetCastPoint() > 0 and self:GetCastPoint() or 0.3
self.phasePreviewParticles = self:createWavePreview(previewDirections, previewDuration)
return true
end
function boss_nevermore_requiem_barrage.prototype.OnAbilityPhaseInterrupted(self)
if not IsServer() then
return
end
self:clearPhasePreview()
end
function boss_nevermore_requiem_barrage.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
nevermoreIncrementRequiemCastCount(nil, caster)
local point = self:GetCursorPosition()
local toPoint = point - caster:GetAbsOrigin()
local baseDirection = toPoint:Length2D() < 1 and caster:GetForwardVector() or toPoint:Normalized()
self.castSerial = self.castSerial + 1
local currentCast = self.castSerial
local channelTime = self:GetChannelTime()
local phase = self:getBossPhase()
local baseWaveInterval = self:GetSpecialValueFor("wave_interval") > 0 and self:GetSpecialValueFor("wave_interval") or 1
local waveInterval = math.max(0.35, baseWaveInterval - (phase - 1) * 0.12)
local wavesCount = math.max(
1,
math.floor(channelTime / waveInterval)
)
local previewTime = self:GetSpecialValueFor("wave_preview_time") > 0 and self:GetSpecialValueFor("wave_preview_time") or 0.35
local waveDistanceKv = self:GetSpecialValueFor("wave_distance") > 0 and self:GetSpecialValueFor("wave_distance") or 850
local travelDist = waveDistanceKv + (phase - 1) * REQUIEM_PHASE_DISTANCE_BONUS
local waveTravelTimeMax = self:getMaxWaveTravelTime(travelDist)
self:clearPhasePreview()
caster:AddNewModifier(caster, self, modifier_boss_nevermore_requiem_barrage_casting.name, {duration = channelTime + 0.1})
EmitSoundOn("Hero_Nevermore.RequiemOfSoulsCast", caster)
self:startGestureLoop(caster)
local firstRotationOffset = self.phasePreviewRotationOffset
self:fireSoulWaveBurst(baseDirection, firstRotationOffset)
Timers:CreateTimer(
waveTravelTimeMax,
function()
self:destroyPreviewParticles(self.phasePreviewParticles)
self.phasePreviewParticles = {}
return nil
end
)
do
local i = 1
while i <= wavesCount do
local fireTime = i * waveInterval
local waveRotationOffset = self:getWaveRotationOffset(i + 1)
local wavePreviewParticles = {}
local wasPreviewShown = false
local speedsForWave
Timers:CreateTimer(
math.max(0, fireTime - previewTime),
function()
if self.castSerial ~= currentCast then
return nil
end
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
local previewDirections = self:buildBurstDirections(
baseDirection,
waveRotationOffset,
self:getBossPhase()
)
speedsForWave = __TS__ArrayMap(
previewDirections,
function() return self:sampleWaveSpeed() end
)
wavePreviewParticles = self:createWavePreview(previewDirections, previewTime, speedsForWave)
wasPreviewShown = true
return nil
end
)
Timers:CreateTimer(
fireTime,
function()
if not wasPreviewShown then
return nil
end
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
self:fireSoulWaveBurst(baseDirection, waveRotationOffset, speedsForWave)
Timers:CreateTimer(
waveTravelTimeMax,
function()
self:destroyPreviewParticles(wavePreviewParticles)
return nil
end
)
return nil
end
)
i = i + 1
end
end
end
function boss_nevermore_requiem_barrage.prototype.OnChannelFinish(self, _bInterrupted)
if not IsServer() then
return
end
self.castSerial = self.castSerial + 1
local caster = self:GetCaster()
self:clearPhasePreview()
self:clearAllActivePreviews()
self:stopGestureLoop(caster)
caster:RemoveModifierByName(modifier_boss_nevermore_requiem_barrage_casting.name)
StopSoundOn("Hero_Nevermore.RequiemOfSoulsCast", caster)
end
function boss_nevermore_requiem_barrage.prototype.startGestureLoop(self, caster)
self.gestureLoopSerial = self.gestureLoopSerial + 1
local serial = self.gestureLoopSerial
local interval = 0.45
local tick
tick = function()
if self.gestureLoopSerial ~= serial then
return
end
if not caster or caster:IsNull() or not caster:IsAlive() then
return
end
if not caster:HasModifier(modifier_boss_nevermore_requiem_barrage_casting.name) then
return
end
caster:StartGestureWithPlaybackRate(ACT_DOTA_RAZE_1, 1)
Timers:CreateTimer(
interval,
function()
tick(nil)
return nil
end
)
end
tick(nil)
end
function boss_nevermore_requiem_barrage.prototype.stopGestureLoop(self, caster)
self.gestureLoopSerial = self.gestureLoopSerial + 1
if not caster or caster:IsNull() then
return
end
caster:FadeGesture(ACT_DOTA_RAZE_1)
end
function boss_nevermore_requiem_barrage.prototype.getWaveSpeedBounds(self)
local base = self:GetSpecialValueFor("wave_speed") > 0 and self:GetSpecialValueFor("wave_speed") or 800
local minKv = self:GetSpecialValueFor("wave_speed_min")
local maxKv = self:GetSpecialValueFor("wave_speed_max")
if minKv > 0 and maxKv > 0 and maxKv >= minKv then
return {minKv, maxKv}
end
local lo = math.max(120, base * 0.72)
local hi = base * 1.32
return {lo, hi}
end
function boss_nevermore_requiem_barrage.prototype.sampleWaveSpeed(self)
local mn, mx = unpack(self:getWaveSpeedBounds())
return RandomFloat(mn, mx)
end
function boss_nevermore_requiem_barrage.prototype.getMaxWaveTravelTime(self, distance)
local mn, _ = unpack(self:getWaveSpeedBounds())
return distance / mn
end
function boss_nevermore_requiem_barrage.prototype.fireSoulWaveBurst(self, baseDirection, rotationOffset, precomputedSpeeds)
local phase = self:getBossPhase()
local directions = self:buildBurstDirections(baseDirection, rotationOffset, phase)
local waveDistanceBase = self:GetSpecialValueFor("wave_distance") > 0 and self:GetSpecialValueFor("wave_distance") or 850
local startRadius = self:GetSpecialValueFor("wave_width_start") > 0 and self:GetSpecialValueFor("wave_width_start") or 45
local endRadius = self:GetSpecialValueFor("wave_width_end") > 0 and self:GetSpecialValueFor("wave_width_end") or 45
local distance = waveDistanceBase + (phase - 1) * REQUIEM_PHASE_DISTANCE_BONUS
do
local i = 0
while i < #directions do
local direction = directions[i + 1]
local spd = precomputedSpeeds ~= nil and precomputedSpeeds[i + 1] ~= nil and precomputedSpeeds[i + 1] or self:sampleWaveSpeed()
self:fireSoulWave(
direction,
distance,
spd,
startRadius,
endRadius
)
i = i + 1
end
end
EmitSoundOn(
"Hero_Nevermore.RequiemOfSouls",
self:GetCaster()
)
end
function boss_nevermore_requiem_barrage.prototype.getWaveRotationOffset(self, waveIndex)
local randomOffset = RandomInt(0, 359)
local waveOffset = waveIndex * 17
return (randomOffset + waveOffset) % 360
end
function boss_nevermore_requiem_barrage.prototype.buildBurstDirections(self, baseDirection, rotationOffset, phase)
local dirs = {}
local baseAngles = {
0,
90,
180,
270,
45,
135,
225,
315
}
local phaseAngles = {}
if phase >= 1 then
__TS__ArrayPush(
phaseAngles,
22.5,
112.5,
202.5,
292.5
)
end
if phase >= 2 then
__TS__ArrayPush(
phaseAngles,
30,
120,
210,
300
)
end
if phase >= 3 then
__TS__ArrayPush(
phaseAngles,
67.5,
157.5,
247.5,
337.5
)
end
if phase >= 4 then
__TS__ArrayPush(
phaseAngles,
15,
105,
195,
285
)
end
local ____array_0 = __TS__SparseArrayNew(unpack(baseAngles))
__TS__SparseArrayPush(
____array_0,
unpack(phaseAngles)
)
local angles = {__TS__SparseArraySpread(____array_0)}
for ____, angle in ipairs(angles) do
local q = QAngle(0, angle + rotationOffset, 0)
dirs[#dirs + 1] = RotatePosition(
Vector(0, 0, 0),
q,
baseDirection
)
end
return dirs
end
function boss_nevermore_requiem_barrage.prototype.createWavePreview(self, directions, previewDuration, speeds)
local caster = self:GetCaster()
local phase = self:getBossPhase()
local distance = (self:GetSpecialValueFor("wave_distance") > 0 and self:GetSpecialValueFor("wave_distance") or 850) + (phase - 1) * REQUIEM_PHASE_DISTANCE_BONUS
local defaultSpeed = self:GetSpecialValueFor("wave_speed") > 0 and self:GetSpecialValueFor("wave_speed") or 800
local casterPos = caster:GetAbsOrigin()
local casterZ = casterPos.z
local particles = {}
do
local i = 0
while i < #directions do
local direction = directions[i + 1]
local spd = speeds ~= nil and speeds[i + 1] ~= nil and speeds[i + 1] or defaultSpeed
local travelTime = distance / spd
local startPos = casterPos + direction * 110
startPos.z = casterZ
local endPos = startPos + direction * distance
endPos.z = casterZ
local previewFx = ParticleManager:CreateParticle("particles/boss_tinker_laser_preview_vector.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(previewFx, 0, startPos)
ParticleManager:SetParticleControl(previewFx, 1, endPos)
ParticleManager:SetParticleControl(
previewFx,
2,
Vector(
math.max(previewDuration, travelTime),
0,
0
)
)
particles[#particles + 1] = previewFx
local ____self_activePreviewParticles_1 = self.activePreviewParticles
____self_activePreviewParticles_1[#____self_activePreviewParticles_1 + 1] = previewFx
i = i + 1
end
end
return particles
end
function boss_nevermore_requiem_barrage.prototype.destroyPreviewParticles(self, particles)
if #particles == 0 then
return
end
local toRemove = {}
for ____, p in ipairs(particles) do
toRemove[p] = true
end
for ____, particle in ipairs(particles) do
ParticleManager:DestroyParticle(particle, false)
ParticleManager:ReleaseParticleIndex(particle)
end
local nextActive = {}
for ____, p in ipairs(self.activePreviewParticles) do
if not (toRemove[p] ~= nil) then
nextActive[#nextActive + 1] = p
end
end
self.activePreviewParticles = nextActive
end
function boss_nevermore_requiem_barrage.prototype.clearPhasePreview(self)
self:destroyPreviewParticles(self.phasePreviewParticles)
self.phasePreviewParticles = {}
end
function boss_nevermore_requiem_barrage.prototype.clearAllActivePreviews(self)
self:destroyPreviewParticles(self.activePreviewParticles)
self.activePreviewParticles = {}
end
function boss_nevermore_requiem_barrage.prototype.fireSoulWave(self, direction, distance, speed, startRadius, endRadius)
local caster = self:GetCaster()
local casterPos = caster:GetAbsOrigin()
local startPos = casterPos + direction * 110
startPos.z = casterPos.z
local velocity = direction * speed
velocity.z = 0
ProjectileManager:CreateLinearProjectile({
Ability = self,
EffectName = "",
vSpawnOrigin = startPos,
fDistance = distance,
fStartRadius = startRadius,
fEndRadius = endRadius,
Source = caster,
bHasFrontalCone = false,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
vVelocity = velocity,
bProvidesVision = false
})
local travelTime = distance / speed
local lineParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_nevermore/nevermore_requiemofsouls_line.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(lineParticle, 0, startPos)
ParticleManager:SetParticleControl(lineParticle, 1, velocity)
ParticleManager:SetParticleControl(
lineParticle,
2,
Vector(0, travelTime, 0)
)
ParticleManager:ReleaseParticleIndex(lineParticle)
end
function boss_nevermore_requiem_barrage.prototype.OnProjectileHit(self, target, _location)
if not target then
return false
end
local caster = self:GetCaster()
local phase = self:getBossPhase()
local baseDamage = caster:GetAverageTrueAttackDamage(target)
local damage = baseDamage * (1 + (phase - 1) * 0.28) * REQUIEM_BARRAGE_DAMAGE_MULT
ApplyDamage({
victim = target,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local debuff = target:AddNewModifier(caster, self, modifier_boss_nevermore_requiem_magic_resist_debuff.name, {duration = -1})
if debuff ~= nil then
debuff:SetStackCount(debuff:GetStackCount() + 1)
end
return false
end
boss_nevermore_requiem_barrage = __TS__Decorate(
boss_nevermore_requiem_barrage,
boss_nevermore_requiem_barrage,
{registerAbility(nil)},
{kind = "class", name = "boss_nevermore_requiem_barrage"}
)
____exports.boss_nevermore_requiem_barrage = boss_nevermore_requiem_barrage
modifier_boss_nevermore_requiem_barrage_casting = __TS__Class()
modifier_boss_nevermore_requiem_barrage_casting.name = "modifier_boss_nevermore_requiem_barrage_casting"
modifier_boss_nevermore_requiem_barrage_casting.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_requiem_barrage.lua"
__TS__ClassExtends(modifier_boss_nevermore_requiem_barrage_casting, BaseModifier)
function modifier_boss_nevermore_requiem_barrage_casting.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_requiem_barrage_casting.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_requiem_barrage_casting.prototype.CheckState(self)
return {
[MODIFIER_STATE_STUNNED] = false,
[MODIFIER_STATE_DISARMED] = true,
[MODIFIER_STATE_SILENCED] = false,
[MODIFIER_STATE_ROOTED] = true,
[MODIFIER_STATE_COMMAND_RESTRICTED] = true
}
end
modifier_boss_nevermore_requiem_barrage_casting = __TS__Decorate(
modifier_boss_nevermore_requiem_barrage_casting,
modifier_boss_nevermore_requiem_barrage_casting,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_requiem_barrage_casting"}
)
return ____exports
@@ -0,0 +1,431 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__NumberToFixed = ____lualib.__TS__NumberToFixed
local __TS__Decorate = ____lualib.__TS__Decorate
local ____exports = {}
local modifier_boss_nevermore_time_walk
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
local BaseAbility = ____dota_ts_adapter.BaseAbility
local BaseModifierMotionHorizontal = ____dota_ts_adapter.BaseModifierMotionHorizontal
local registerAbility = ____dota_ts_adapter.registerAbility
local registerModifier = ____dota_ts_adapter.registerModifier
local DEBUG_TIME_WALK = false
local twDebugNextAt = {}
local function timeWalkDebug(self, tag, message, throttle)
if throttle == nil then
throttle = 0.35
end
if not DEBUG_TIME_WALK then
return
end
local now = GameRules:GetGameTime()
local nextAt = twDebugNextAt[tag] or 0
if now < nextAt then
return
end
twDebugNextAt[tag] = now + throttle
print((("[NevermoreTimeWalk][" .. tag) .. "] ") .. message)
end
____exports.boss_nevermore_time_walk = __TS__Class()
local boss_nevermore_time_walk = ____exports.boss_nevermore_time_walk
boss_nevermore_time_walk.name = "boss_nevermore_time_walk"
boss_nevermore_time_walk.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_time_walk.lua"
__TS__ClassExtends(boss_nevermore_time_walk, BaseAbility)
function boss_nevermore_time_walk.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", context)
PrecacheResource("particle", "particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", context)
PrecacheResource("soundfile", "sounds/units/heroes/nevermore/shadowraze.vsnd", context)
PrecacheResource("particle", "particles/units/heroes/hero_faceless_void/faceless_void_time_walk_slow.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_faceless_void/faceless_void_time_walk_preimage.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_faceless_void/faceless_void_time_walk.vpcf", context)
end
function boss_nevermore_time_walk.prototype.GetCastRange(self, _location, _target)
return self:GetSpecialValueFor("range")
end
function boss_nevermore_time_walk.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
if caster:HasModifier(modifier_boss_nevermore_time_walk.name) then
timeWalkDebug(nil, "cast_skip", "already moving, skip recast", 0.2)
return
end
local range = self:GetSpecialValueFor("range")
local speed = math.max(
1,
self:GetSpecialValueFor("speed")
)
local radius = self:GetSpecialValueFor("radius")
local point = self:GetCursorPosition()
local origin = caster:GetAbsOrigin()
local direction = point - origin
local distance = direction:Length2D()
if distance < 1 then
direction = caster:GetForwardVector()
distance = range
else
direction = direction:Normalized()
end
local clampedDistance = math.min(distance, range)
local targetPosition = GetGroundPosition(origin + direction * clampedDistance, nil)
local duration = clampedDistance / speed
timeWalkDebug(
nil,
"cast",
(((("distance=" .. __TS__NumberToFixed(clampedDistance, 0)) .. " duration=") .. __TS__NumberToFixed(duration, 2)) .. " speed=") .. tostring(speed),
0.1
)
EmitSoundOn("Hero_FacelessVoid.TimeWalk", caster)
local startFx = ParticleManager:CreateParticle("particles/units/heroes/hero_faceless_void/faceless_void_time_walk_slow.vpcf", PATTACH_WORLDORIGIN, caster)
ParticleManager:SetParticleControl(startFx, 0, origin)
ParticleManager:SetParticleControl(
startFx,
1,
Vector(radius, 0, 0)
)
ParticleManager:ReleaseParticleIndex(startFx)
local preimageFx = ParticleManager:CreateParticle("particles/units/heroes/hero_faceless_void/faceless_void_time_walk_preimage.vpcf", PATTACH_WORLDORIGIN, caster)
ParticleManager:SetParticleControl(preimageFx, 0, origin)
ParticleManager:SetParticleControl(preimageFx, 1, targetPosition)
ParticleManager:SetParticleControl(preimageFx, 2, targetPosition)
ParticleManager:ReleaseParticleIndex(preimageFx)
caster:AddNewModifier(
caster,
self,
modifier_boss_nevermore_time_walk.name,
{
duration = duration,
target_x = targetPosition.x,
target_y = targetPosition.y,
target_z = targetPosition.z,
speed = speed,
radius = radius,
damage = self:GetSpecialValueFor("damage")
}
)
ProjectileManager:ProjectileDodge(caster)
end
function boss_nevermore_time_walk.prototype.OnProjectileHit(self, target, _location)
if not IsServer() or not target then
return false
end
local caster = self:GetCaster()
if not caster or caster:IsNull() or not caster:IsAlive() then
return false
end
local base = self:GetSpecialValueFor("damage")
local damage = math.max(1, base * 0.35)
ApplyDamage({
victim = target,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
return false
end
boss_nevermore_time_walk = __TS__Decorate(
boss_nevermore_time_walk,
boss_nevermore_time_walk,
{registerAbility(nil)},
{kind = "class", name = "boss_nevermore_time_walk"}
)
____exports.boss_nevermore_time_walk = boss_nevermore_time_walk
modifier_boss_nevermore_time_walk = __TS__Class()
modifier_boss_nevermore_time_walk.name = "modifier_boss_nevermore_time_walk"
modifier_boss_nevermore_time_walk.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_time_walk.lua"
__TS__ClassExtends(modifier_boss_nevermore_time_walk, BaseModifierMotionHorizontal)
function modifier_boss_nevermore_time_walk.prototype.____constructor(self, ...)
BaseModifierMotionHorizontal.prototype.____constructor(self, ...)
self.direction = Vector(0, 0, 0)
self.remainingDistance = 0
self.speed = 0
self.damage = 0
self.radius = 0
self.coilInterval = 0.25
self.sideWaveInterval = 0.7
self.nextSideWaveAt = 0
self.sideWaveToggle = false
self.maxTargetsPerTick = 8
self.nextCoilSoundAllowedAt = 0
self.coilPulseIndex = 0
end
function modifier_boss_nevermore_time_walk.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_time_walk.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_time_walk.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
local target = Vector(
params.target_x or parent:GetAbsOrigin().x,
params.target_y or parent:GetAbsOrigin().y,
params.target_z or parent:GetAbsOrigin().z
)
local toTarget = target - parent:GetAbsOrigin()
self.remainingDistance = toTarget:Length2D()
self.direction = self.remainingDistance < 1 and parent:GetForwardVector() or toTarget:Normalized()
local ____math_max_3 = math.max
local ____params_speed_2 = params.speed
if ____params_speed_2 == nil then
local ____opt_0 = self:GetAbility()
____params_speed_2 = ____opt_0 and ____opt_0:GetSpecialValueFor("speed")
end
self.speed = ____math_max_3(1, ____params_speed_2 or 1)
local ____math_max_7 = math.max
local ____params_radius_6 = params.radius
if ____params_radius_6 == nil then
local ____opt_4 = self:GetAbility()
____params_radius_6 = ____opt_4 and ____opt_4:GetSpecialValueFor("radius")
end
self.radius = ____math_max_7(1, ____params_radius_6 or 180)
local ____params_damage_10 = params.damage
if ____params_damage_10 == nil then
local ____opt_8 = self:GetAbility()
____params_damage_10 = ____opt_8 and ____opt_8:GetSpecialValueFor("damage")
end
self.damage = ____params_damage_10 or 0
local ____math_max_13 = math.max
local ____opt_11 = self:GetAbility()
self.coilInterval = ____math_max_13(
0.22,
____opt_11 and ____opt_11:GetSpecialValueFor("coil_interval") or 0.25
)
local ____math_max_16 = math.max
local ____opt_14 = self:GetAbility()
self.sideWaveInterval = ____math_max_16(
0.45,
____opt_14 and ____opt_14:GetSpecialValueFor("side_wave_interval") or 0.7
)
local ____math_max_19 = math.max
local ____opt_17 = self:GetAbility()
self.maxTargetsPerTick = ____math_max_19(
1,
____opt_17 and ____opt_17:GetSpecialValueFor("max_targets_per_tick") or 8
)
local now = GameRules:GetGameTime()
self.nextSideWaveAt = now + self.sideWaveInterval
self.nextCoilSoundAllowedAt = now
timeWalkDebug(
nil,
"start",
(((((("dist=" .. __TS__NumberToFixed(self.remainingDistance, 0)) .. " speed=") .. tostring(self.speed)) .. " coilInt=") .. __TS__NumberToFixed(self.coilInterval, 2)) .. " sideInt=") .. __TS__NumberToFixed(self.sideWaveInterval, 2),
0.1
)
if not self:ApplyHorizontalMotionController() then
self:Destroy()
return
end
self.cachedRequiemAbility = parent:FindAbilityByName("boss_nevermore_requiem_barrage") or nil
self:StartIntervalThink(self.coilInterval)
self:runCoilPulse(now)
end
function modifier_boss_nevermore_time_walk.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not parent or parent:IsNull() or not ability then
return
end
local now = GameRules:GetGameTime()
if now >= self.nextSideWaveAt then
self.nextSideWaveAt = now + self.sideWaveInterval
self.sideWaveToggle = not self.sideWaveToggle
self:fireSideWaves(
parent,
ability,
GetGroundPosition(
parent:GetAbsOrigin(),
nil
),
self.sideWaveToggle
)
timeWalkDebug(nil, "side_waves", "spawn side=" .. (self.sideWaveToggle and "L" or "R"), 0.25)
end
self:runCoilPulse(now)
end
function modifier_boss_nevermore_time_walk.prototype.runCoilPulse(self, now)
local parent = self:GetParent()
local ability = self:GetAbility()
if not parent or parent:IsNull() or not ability then
return
end
local pulsePoint = GetGroundPosition(
parent:GetAbsOrigin(),
nil
)
local enemies = FindUnitsInRadius(
parent:GetTeamNumber(),
pulsePoint,
nil,
self.radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local targetCount = math.min(#enemies, self.maxTargetsPerTick)
do
local i = 0
while i < targetCount do
local enemy = enemies[i + 1]
ApplyDamage({
victim = enemy,
attacker = parent,
damage = self.damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
i = i + 1
end
end
self.coilPulseIndex = self.coilPulseIndex + 1
timeWalkDebug(
nil,
"coil_tick",
(("enemies=" .. tostring(#enemies)) .. " applied=") .. tostring(targetCount),
0.25
)
if now >= self.nextCoilSoundAllowedAt then
self.nextCoilSoundAllowedAt = now + 0.45
EmitSoundOnLocationWithCaster(pulsePoint, "Hero_Nevermore.Shadowraze", parent)
end
if self.coilPulseIndex % 2 == 0 then
local hitParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(hitParticle, 0, pulsePoint)
ParticleManager:SetParticleControl(
hitParticle,
1,
Vector(self.radius, 1, 1)
)
ParticleManager:ReleaseParticleIndex(hitParticle)
else
local aoeFx = ParticleManager:CreateParticle("particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", PATTACH_CUSTOMORIGIN, parent)
ParticleManager:SetParticleControl(aoeFx, 0, pulsePoint)
ParticleManager:SetParticleControl(
aoeFx,
1,
Vector(self.radius, 0, 0)
)
ParticleManager:SetParticleControl(
aoeFx,
2,
Vector(5, 0, 1)
)
ParticleManager:SetParticleControl(
aoeFx,
3,
Vector(200, 50, 0)
)
ParticleManager:SetParticleControl(aoeFx, 4, pulsePoint)
ParticleManager:ReleaseParticleIndex(aoeFx)
end
end
function modifier_boss_nevermore_time_walk.prototype.fireSideWaves(self, caster, sourceAbility, origin, fireLeft)
local requiem = self.cachedRequiemAbility
if not requiem or requiem:IsNull() then
requiem = caster:FindAbilityByName("boss_nevermore_requiem_barrage") or nil
self.cachedRequiemAbility = requiem
end
local distance = requiem and not requiem:IsNull() and math.max(
200,
requiem:GetSpecialValueFor("wave_distance") or 900
) or 900
local waveSpeed = requiem and not requiem:IsNull() and math.max(
200,
requiem:GetSpecialValueFor("wave_speed") or 700
) or 700
local startRadius = requiem and not requiem:IsNull() and math.max(
10,
requiem:GetSpecialValueFor("wave_width_start") or 45
) or 45
local endRadius = requiem and not requiem:IsNull() and math.max(
10,
requiem:GetSpecialValueFor("wave_width_end") or 45
) or 45
local dir = fireLeft and Vector(-self.direction.y, self.direction.x, 0):Normalized() or Vector(self.direction.y, -self.direction.x, 0):Normalized()
local startPos = origin + dir * 80
startPos.z = origin.z
local velocity = dir * waveSpeed
velocity.z = 0
ProjectileManager:CreateLinearProjectile({
Ability = sourceAbility,
EffectName = "",
vSpawnOrigin = startPos,
fDistance = distance,
fStartRadius = startRadius,
fEndRadius = endRadius,
Source = caster,
bHasFrontalCone = false,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
vVelocity = velocity,
bProvidesVision = false
})
end
function modifier_boss_nevermore_time_walk.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
parent:RemoveHorizontalMotionController(self)
FindClearSpaceForUnit(
parent,
parent:GetAbsOrigin(),
true
)
parent:StartGesture(ACT_DOTA_CAST_ABILITY_1_END)
timeWalkDebug(nil, "end", "modifier destroyed", 0.1)
end
function modifier_boss_nevermore_time_walk.prototype.UpdateHorizontalMotion(self, me, dt)
if not IsServer() then
return
end
local step = self.speed * dt
if self.remainingDistance > 0 then
local oldPos = me:GetAbsOrigin()
local nextPos = GetGroundPosition(
oldPos + self.direction * math.min(step, self.remainingDistance),
nil
)
me:SetAbsOrigin(nextPos)
self.remainingDistance = self.remainingDistance - step
return
end
self:Destroy()
end
function modifier_boss_nevermore_time_walk.prototype.OnHorizontalMotionInterrupted(self)
if not IsServer() then
return
end
self:Destroy()
end
function modifier_boss_nevermore_time_walk.prototype.CheckState(self)
return {[MODIFIER_STATE_COMMAND_RESTRICTED] = true, [MODIFIER_STATE_NO_UNIT_COLLISION] = true, [MODIFIER_STATE_FLYING_FOR_PATHING_PURPOSES_ONLY] = true}
end
function modifier_boss_nevermore_time_walk.prototype.GetEffectName(self)
return "particles/units/heroes/hero_faceless_void/faceless_void_time_walk.vpcf"
end
function modifier_boss_nevermore_time_walk.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_abaddon_borrowed_time.vpcf"
end
function modifier_boss_nevermore_time_walk.prototype.StatusEffectPriority(self)
return 10
end
modifier_boss_nevermore_time_walk = __TS__Decorate(
modifier_boss_nevermore_time_walk,
modifier_boss_nevermore_time_walk,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_time_walk"}
)
return ____exports
@@ -0,0 +1,382 @@
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 modifier_boss_nevermore_triple_coil_aoe_lock
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_boss_nevermore_coil_debuff = require("abilities.creep.modifier_boss_nevermore_coil_debuff")
local modifier_boss_nevermore_coil_debuff = ____modifier_boss_nevermore_coil_debuff.modifier_boss_nevermore_coil_debuff
____exports.boss_nevermore_triple_coil_aoe = __TS__Class()
local boss_nevermore_triple_coil_aoe = ____exports.boss_nevermore_triple_coil_aoe
boss_nevermore_triple_coil_aoe.name = "boss_nevermore_triple_coil_aoe"
boss_nevermore_triple_coil_aoe.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_triple_coil_aoe.lua"
__TS__ClassExtends(boss_nevermore_triple_coil_aoe, BaseAbility)
function boss_nevermore_triple_coil_aoe.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", context)
PrecacheResource("particle", "particles/darkmoon_creep_warning.vpcf", context)
PrecacheResource("particle", "particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", context)
PrecacheResource("soundfile", "sounds/units/heroes/nevermore/shadowraze.vsnd", context)
end
function boss_nevermore_triple_coil_aoe.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function boss_nevermore_triple_coil_aoe.prototype.getSpecialOrDefault(self, name, fallback)
local value = self:GetSpecialValueFor(name)
if not value or value <= 0 then
return fallback
end
return value
end
function boss_nevermore_triple_coil_aoe.prototype.getBossPhase(self)
local caster = self:GetCaster()
if not caster or caster:IsNull() then
return 1
end
local hp = caster:GetHealthPercent()
if hp <= 25 then
return 4
end
if hp <= 50 then
return 3
end
if hp <= 75 then
return 2
end
return 1
end
function boss_nevermore_triple_coil_aoe.prototype.getConfiguredDelay(self)
local delay = self:GetSpecialValueFor("delay")
local startDelay = self:GetSpecialValueFor("start_delay")
local best = math.max(delay or 0, startDelay or 0)
if best > 0 then
return best
end
return ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_DELAY
end
function boss_nevermore_triple_coil_aoe.prototype.buildCoilPoints(self, centerPoint, forward, sideDir)
local sideOffset = self:getSpecialOrDefault("side_offset", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_SIDE_OFFSET)
local forwardOffset = self:getSpecialOrDefault("forward_offset", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_FORWARD_OFFSET)
local leftPoint = GetGroundPosition(centerPoint + sideDir * sideOffset, nil)
local rightPoint = GetGroundPosition(centerPoint - sideDir * sideOffset, nil)
local frontPoint = GetGroundPosition(centerPoint + forward * forwardOffset, nil)
local backPoint = GetGroundPosition(centerPoint - forward * forwardOffset, nil)
return {
centerPoint,
leftPoint,
rightPoint,
frontPoint,
backPoint
}
end
function boss_nevermore_triple_coil_aoe.prototype.getCoilRadiusForPhase(self, phase)
return self:getSpecialOrDefault("coil_radius", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_COIL_RADIUS) + (phase - 1) * 15
end
function boss_nevermore_triple_coil_aoe.prototype.randomPointNearHero(self, heroOrigin, minDist, maxDist)
local angleDeg = RandomFloat(0, 360)
local dist = RandomFloat(minDist, maxDist)
local rad = angleDeg * math.pi / 180
local ox = math.cos(rad) * dist
local oy = math.sin(rad) * dist
return GetGroundPosition(
heroOrigin + Vector(ox, oy, 0),
nil
)
end
function boss_nevermore_triple_coil_aoe.prototype.spawnAoeAtPoint(self, centerPoint, phase, lockDuration, delayOverride)
local caster = self:GetCaster()
local castOrigin = caster:GetAbsOrigin()
local toCenter = centerPoint - castOrigin
local forward = toCenter:Length2D() < 1 and caster:GetForwardVector() or toCenter:Normalized()
local sideDir = Vector(-forward.y, forward.x, 0):Normalized()
local delay = delayOverride ~= nil and delayOverride or self:getConfiguredDelay()
local warningTime = self:getSpecialOrDefault("precast_warning_time", delay)
local coilRadius = self:getCoilRadiusForPhase(phase)
local coilPoints = self:buildCoilPoints(centerPoint, forward, sideDir)
caster:AddNewModifier(caster, self, modifier_boss_nevermore_triple_coil_aoe_lock.name, {duration = lockDuration})
local warningParticles = {}
for ____, coilPoint in ipairs(coilPoints) do
warningParticles[#warningParticles + 1] = self:createWarning(coilPoint, coilRadius, warningTime)
end
Timers:CreateTimer(
delay,
function()
for ____, ____value in ipairs(warningParticles) do
local warningParticle = ____value[1]
local aoeParticle = ____value[2]
ParticleManager:DestroyParticle(warningParticle, true)
ParticleManager:ReleaseParticleIndex(warningParticle)
ParticleManager:DestroyParticle(aoeParticle, true)
ParticleManager:ReleaseParticleIndex(aoeParticle)
end
local impactPhase = self:getBossPhase()
local baseDamage = caster:GetAttackDamage()
local bonusDamagePerStack = self:GetSpecialValueFor("coil_stack_bonus_damage")
local damageMultiplier = 1 + (impactPhase - 1) * 0.3
EmitSoundOn("Hero_Nevermore.Shadowraze", caster)
for ____, coilPoint in ipairs(coilPoints) do
self:applyMiniCoil(
coilPoint,
coilRadius,
baseDamage,
bonusDamagePerStack,
damageMultiplier
)
end
return nil
end
)
end
function boss_nevermore_triple_coil_aoe.prototype.scheduleHeroProximityCoils(self, phase, mainHitDelay, lockDuration)
if not IsServer() or phase < 1 then
return
end
local caster = self:GetCaster()
if not caster or caster:IsNull() then
return
end
local minD = self:getSpecialOrDefault("hero_coil_radius_min", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_HERO_RING_MIN)
local maxD = self:getSpecialOrDefault("hero_coil_radius_max", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_HERO_RING_MAX)
local stagger = self:getSpecialOrDefault("hero_coil_stagger", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_HERO_COIL_STAGGER)
local afterMain = self:getSpecialOrDefault("hero_coil_start_after_main", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_HERO_COIL_AFTER_MAIN)
local warningTime = self:getSpecialOrDefault("precast_warning_time", mainHitDelay)
local coilRadius = self:getCoilRadiusForPhase(phase)
local heroes = FindUnitsInRadius(
caster:GetTeamNumber(),
caster:GetAbsOrigin(),
nil,
____exports.boss_nevermore_triple_coil_aoe.HERO_SEARCH_RADIUS,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local slot = 0
for ____, hero in ipairs(heroes) do
do
if not hero or hero:IsNull() or not hero:IsAlive() then
goto __continue27
end
local heroGround = GetGroundPosition(
hero:GetAbsOrigin(),
nil
)
do
local j = 0
while j < phase do
local coilPos = self:randomPointNearHero(heroGround, minD, maxD)
local hitTime = mainHitDelay + afterMain + slot * stagger
slot = slot + 1
self:spawnDelayedSingleCoil(
coilPos,
hitTime,
warningTime,
coilRadius,
lockDuration
)
j = j + 1
end
end
end
::__continue27::
end
end
function boss_nevermore_triple_coil_aoe.prototype.spawnDelayedSingleCoil(self, coilPoint, hitTime, warningTime, coilRadius, _lockDuration)
local caster = self:GetCaster()
local warnAt = math.max(0, hitTime - warningTime)
local state = {pair = nil}
Timers:CreateTimer(
warnAt,
function()
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
state.pair = self:createWarning(coilPoint, coilRadius, warningTime)
return nil
end
)
Timers:CreateTimer(
hitTime,
function()
if state.pair then
ParticleManager:DestroyParticle(state.pair[1], true)
ParticleManager:ReleaseParticleIndex(state.pair[1])
ParticleManager:DestroyParticle(state.pair[2], true)
ParticleManager:ReleaseParticleIndex(state.pair[2])
state.pair = nil
end
if not caster or caster:IsNull() or not caster:IsAlive() then
return nil
end
local impactPhase = self:getBossPhase()
local baseDamage = caster:GetAttackDamage()
local bonusDamagePerStack = self:GetSpecialValueFor("coil_stack_bonus_damage")
local damageMultiplier = 1 + (impactPhase - 1) * 0.3
self:applyMiniCoil(
coilPoint,
coilRadius,
baseDamage,
bonusDamagePerStack,
damageMultiplier
)
return nil
end
)
end
function boss_nevermore_triple_coil_aoe.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local phase = self:getBossPhase()
local centerPoint = GetGroundPosition(
self:GetCursorPosition(),
nil
)
local mainDelay = self:getConfiguredDelay()
local stagger = self:getSpecialOrDefault("hero_coil_stagger", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_HERO_COIL_STAGGER)
local afterMain = self:getSpecialOrDefault("hero_coil_start_after_main", ____exports.boss_nevermore_triple_coil_aoe.DEFAULT_HERO_COIL_AFTER_MAIN)
local caster = self:GetCaster()
local heroes = FindUnitsInRadius(
caster:GetTeamNumber(),
caster:GetAbsOrigin(),
nil,
____exports.boss_nevermore_triple_coil_aoe.HERO_SEARCH_RADIUS,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local heroCount = 0
for ____, h in ipairs(heroes) do
if h and not h:IsNull() and h:IsAlive() then
heroCount = heroCount + 1
end
end
local extraCoils = heroCount * phase
local lastHeroCoilTime = extraCoils > 0 and mainDelay + afterMain + (extraCoils - 1) * stagger or mainDelay
local lockDuration = lastHeroCoilTime + 0.55
self:spawnAoeAtPoint(centerPoint, phase, lockDuration)
self:scheduleHeroProximityCoils(phase, mainDelay, lockDuration)
end
function boss_nevermore_triple_coil_aoe.prototype.createWarning(self, point, radius, _duration)
if not IsServer() then
return {-1, -1}
end
local caster = self:GetCaster()
local warningParticle = ParticleManager:CreateParticle("particles/darkmoon_creep_warning.vpcf", PATTACH_CUSTOMORIGIN, caster)
local aoeParticle = ParticleManager:CreateParticle("particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControl(warningParticle, 0, point)
ParticleManager:SetParticleControl(
warningParticle,
1,
Vector(radius, 100, 100)
)
ParticleManager:SetParticleControl(aoeParticle, 0, point)
ParticleManager:SetParticleControl(
aoeParticle,
1,
Vector(radius, 0, 0)
)
ParticleManager:SetParticleControl(
aoeParticle,
2,
Vector(6, 0, 1)
)
ParticleManager:SetParticleControl(
aoeParticle,
3,
Vector(220, 0, 0)
)
ParticleManager:SetParticleControl(aoeParticle, 4, point)
return {warningParticle, aoeParticle}
end
function boss_nevermore_triple_coil_aoe.prototype.applyMiniCoil(self, point, radius, baseDamage, bonusDamagePerStack, damageMultiplier)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or caster:IsNull() or not caster:IsAlive() then
return
end
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
point,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
local coilDebuff = enemy:FindModifierByName(modifier_boss_nevermore_coil_debuff.name)
local stacks = coilDebuff and coilDebuff:GetStackCount() or 0
local damage = (baseDamage + stacks * bonusDamagePerStack) * damageMultiplier
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local updatedDebuff = enemy:AddNewModifier(caster, self, modifier_boss_nevermore_coil_debuff.name, {})
if updatedDebuff ~= nil then
if stacks > 0 then
updatedDebuff:SetStackCount(stacks + 1)
else
updatedDebuff:SetStackCount(1)
end
end
end
local hitParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_nevermore/nevermore_shadowraze.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(hitParticle, 0, point)
ParticleManager:SetParticleControl(
hitParticle,
1,
Vector(radius, 1, 1)
)
ParticleManager:ReleaseParticleIndex(hitParticle)
end
boss_nevermore_triple_coil_aoe.DEFAULT_DELAY = 2
boss_nevermore_triple_coil_aoe.DEFAULT_SIDE_OFFSET = 170
boss_nevermore_triple_coil_aoe.DEFAULT_FORWARD_OFFSET = 170
boss_nevermore_triple_coil_aoe.DEFAULT_COIL_RADIUS = 120
boss_nevermore_triple_coil_aoe.DEFAULT_HERO_RING_MIN = 100
boss_nevermore_triple_coil_aoe.DEFAULT_HERO_RING_MAX = 200
boss_nevermore_triple_coil_aoe.DEFAULT_HERO_COIL_STAGGER = 0.32
boss_nevermore_triple_coil_aoe.DEFAULT_HERO_COIL_AFTER_MAIN = 0.45
boss_nevermore_triple_coil_aoe.HERO_SEARCH_RADIUS = 3200
boss_nevermore_triple_coil_aoe = __TS__Decorate(
boss_nevermore_triple_coil_aoe,
boss_nevermore_triple_coil_aoe,
{registerAbility(nil)},
{kind = "class", name = "boss_nevermore_triple_coil_aoe"}
)
____exports.boss_nevermore_triple_coil_aoe = boss_nevermore_triple_coil_aoe
modifier_boss_nevermore_triple_coil_aoe_lock = __TS__Class()
modifier_boss_nevermore_triple_coil_aoe_lock.name = "modifier_boss_nevermore_triple_coil_aoe_lock"
modifier_boss_nevermore_triple_coil_aoe_lock.____file_path = "scripts/vscripts/abilities/creep/boss_nevermore_triple_coil_aoe.lua"
__TS__ClassExtends(modifier_boss_nevermore_triple_coil_aoe_lock, BaseModifier)
function modifier_boss_nevermore_triple_coil_aoe_lock.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_triple_coil_aoe_lock.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_triple_coil_aoe_lock.prototype.CheckState(self)
return {[MODIFIER_STATE_DISARMED] = true}
end
modifier_boss_nevermore_triple_coil_aoe_lock = __TS__Decorate(
modifier_boss_nevermore_triple_coil_aoe_lock,
modifier_boss_nevermore_triple_coil_aoe_lock,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_triple_coil_aoe_lock"}
)
return ____exports
@@ -0,0 +1,468 @@
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 ____difficulty_manager = require("difficulty_manager")
local Difficulty = ____difficulty_manager.Difficulty
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
local BaseAbility = ____dota_ts_adapter.BaseAbility
local BaseModifier = ____dota_ts_adapter.BaseModifier
local BaseModifierMotionBoth = ____dota_ts_adapter.BaseModifierMotionBoth
local registerAbility = ____dota_ts_adapter.registerAbility
local registerModifier = ____dota_ts_adapter.registerModifier
--- Та же физика дуги, что у `frogmen_acid_jump` / `modifier_acid_blob_jump`.
local CONTRACT_HEAD_LEAP_MIN_HEIGHT_ABOVE_LOWEST = 400
local CONTRACT_HEAD_LEAP_MIN_HEIGHT_ABOVE_HIGHEST = 200
local CONTRACT_HEAD_LEAP_ACCELERATION_Z = 1500
local CONTRACT_HEAD_LEAP_MAX_HORIZONTAL_ACCELERATION = 1500
--- Пассивка контракта: прыжок дугой к точке, где стоял герой; урон только если к моменту приземления он не ушёл из зоны.
____exports.contract_head_leap = __TS__Class()
local contract_head_leap = ____exports.contract_head_leap
contract_head_leap.name = "contract_head_leap"
contract_head_leap.____file_path = "scripts/vscripts/abilities/creep/contract_head_leap.lua"
__TS__ClassExtends(contract_head_leap, BaseAbility)
function contract_head_leap.prototype.Precache(self, context)
PrecacheResource("particle", "particles/generic_gameplay/generic_hit_blood.vpcf", context)
PrecacheResource("particle", "particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", context)
PrecacheResource("particle", "particles/econ/events/darkmoon_2017/darkmoon_calldown_marker_arrows.vpcf", context)
end
function contract_head_leap.prototype.GetIntrinsicModifierName(self)
return "modifier_contract_head_leap_passive"
end
function contract_head_leap.prototype.showLeapPrecastVisuals(self, caster, strikeGround, damageRadius, warningDuration)
if not IsServer() or warningDuration <= 0 then
return
end
local groundPos = GetGroundPosition(strikeGround, nil)
local r = math.max(1, damageRadius)
local particleAoe = ParticleManager:CreateParticle("particles/econ/events/darkmoon_2017/darkmoon_generic_aoe.vpcf", PATTACH_CUSTOMORIGIN, nil)
if particleAoe ~= nil then
ParticleManager:SetParticleControl(particleAoe, 0, groundPos)
ParticleManager:SetParticleControl(
particleAoe,
1,
Vector(r, 0, 0)
)
ParticleManager:SetParticleControl(
particleAoe,
2,
Vector(6, 0, 1)
)
ParticleManager:SetParticleControl(
particleAoe,
3,
Vector(200, 0, 0)
)
ParticleManager:SetParticleControl(particleAoe, 4, groundPos)
Timers:CreateTimer(
warningDuration,
function()
ParticleManager:DestroyParticle(particleAoe, false)
ParticleManager:ReleaseParticleIndex(particleAoe)
end
)
end
local casterPos = GetGroundPosition(
caster:GetAbsOrigin(),
nil
)
local particleArrow = ParticleManager:CreateParticle("particles/econ/events/darkmoon_2017/darkmoon_calldown_marker_arrows.vpcf", PATTACH_CUSTOMORIGIN, nil)
if particleArrow ~= nil then
ParticleManager:SetParticleControl(particleArrow, 0, casterPos)
ParticleManager:SetParticleControl(particleArrow, 1, groundPos)
ParticleManager:SetParticleControl(
particleArrow,
2,
Vector(warningDuration, 0, 0)
)
Timers:CreateTimer(
warningDuration,
function()
ParticleManager:DestroyParticle(particleArrow, false)
ParticleManager:ReleaseParticleIndex(particleArrow)
end
)
end
end
function contract_head_leap.prototype.performLeapLanding(self, heroEntIndex, strikeGround)
if not IsServer() then
return
end
local creep = self:GetCaster()
if not creep or not IsValidEntity(creep) or not creep:IsAlive() then
return
end
local hero = EntIndexToHScript(heroEntIndex)
local hitRadius = math.max(
0,
self:GetSpecialValueFor("damage_radius")
)
local hpos = hero and IsValidEntity(hero) and hero:IsAlive() and hero:GetAbsOrigin() or nil
local inZone = false
if hpos ~= nil then
local dx = hpos.x - strikeGround.x
local dy = hpos.y - strikeGround.y
inZone = math.sqrt(dx * dx + dy * dy) <= hitRadius
end
if hero and IsValidEntity(hero) and hero:IsAlive() and not hero:IsInvulnerable() and inZone then
local scale = Difficulty:getNpcStatScale()
local flatDamage = math.max(
1,
math.floor(self:GetSpecialValueFor("leap_damage") * scale + 0.5)
)
local pctFromAttack = math.max(
0,
self:GetSpecialValueFor("damage_from_attack_pct")
)
local avgAtk = creep:GetAverageTrueAttackDamage(hero)
local fromAttack = math.floor(avgAtk * (pctFromAttack / 100) * scale + 0.5)
local totalDamage = flatDamage + fromAttack
ApplyDamage({
victim = hero,
attacker = creep,
damage = totalDamage,
damage_type = DAMAGE_TYPE_PHYSICAL,
ability = self
})
local hitFx = ParticleManager:CreateParticle("particles/generic_gameplay/generic_hit_blood.vpcf", PATTACH_CUSTOMORIGIN, nil)
ParticleManager:SetParticleControlEnt(
hitFx,
0,
hero,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
hero:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(hitFx)
EmitSoundOn("Hero_MonkeyKing.Spring.Channel", creep)
end
end
contract_head_leap = __TS__Decorate(
contract_head_leap,
contract_head_leap,
{registerAbility(nil)},
{kind = "class", name = "contract_head_leap"}
)
____exports.contract_head_leap = contract_head_leap
____exports.modifier_contract_head_leap_passive = __TS__Class()
local modifier_contract_head_leap_passive = ____exports.modifier_contract_head_leap_passive
modifier_contract_head_leap_passive.name = "modifier_contract_head_leap_passive"
modifier_contract_head_leap_passive.____file_path = "scripts/vscripts/abilities/creep/contract_head_leap.lua"
__TS__ClassExtends(modifier_contract_head_leap_passive, BaseModifier)
function modifier_contract_head_leap_passive.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.precastLockUntil = -1
end
function modifier_contract_head_leap_passive.prototype.IsHidden(self)
return true
end
function modifier_contract_head_leap_passive.prototype.IsDebuff(self)
return false
end
function modifier_contract_head_leap_passive.prototype.IsPurgable(self)
return false
end
function modifier_contract_head_leap_passive.prototype.OnCreated(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
local interval = ability and math.max(
0.35,
ability:GetSpecialValueFor("leap_interval")
) or 2.4
self:StartIntervalThink(interval)
end
function modifier_contract_head_leap_passive.prototype.OnRefresh(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
local interval = ability and math.max(
0.35,
ability:GetSpecialValueFor("leap_interval")
) or 2.4
self:StartIntervalThink(interval)
end
function modifier_contract_head_leap_passive.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability or not IsValidEntity(parent) or not parent:IsAlive() or parent:IsStunned() or parent:IsHexed() then
return
end
local now = GameRules:GetDOTATime(false, false)
if now < self.precastLockUntil then
return
end
local primary = parent:FindAbilityByName("contract_head_leap")
if not primary or primary ~= ability then
return
end
if parent:HasModifier("modifier_contract_head_leap_arc") then
return
end
local radius = math.max(
50,
ability:GetSpecialValueFor("search_radius")
)
local heroes = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_CLOSEST,
false
)
local hero
for ____, u in ipairs(heroes) do
do
if not u or not IsValidEntity(u) or not u:IsAlive() or not u:IsHero() then
goto __continue28
end
if not u:IsRealHero() then
goto __continue28
end
if u:IsInvulnerable() then
goto __continue28
end
if u:GetUnitName() == "npc_homer" then
goto __continue28
end
hero = u
break
end
::__continue28::
end
if not hero then
return
end
local height = math.max(
40,
ability:GetSpecialValueFor("height_above_hero")
)
local strikeGround = GetGroundPosition(
hero:GetAbsOrigin(),
hero
)
local headPos = Vector(strikeGround.x, strikeGround.y, strikeGround.z + height)
local warningTime = math.max(
0,
ability:GetSpecialValueFor("precast_warning_time")
)
local dmgRadius = math.max(
1,
ability:GetSpecialValueFor("damage_radius")
)
local arcPayload = {
vLocX = headPos.x,
vLocY = headPos.y,
vLocZ = headPos.z,
strikeX = strikeGround.x,
strikeY = strikeGround.y,
strikeZ = strikeGround.z,
hero_ei = hero:entindex()
}
if warningTime > 0 then
self.precastLockUntil = now + warningTime
ability:showLeapPrecastVisuals(parent, strikeGround, dmgRadius, warningTime)
local ____self = self
Timers:CreateTimer(
warningTime,
function()
____self.precastLockUntil = -1
if not IsServer() then
return
end
if not IsValidEntity(parent) or not parent:IsAlive() then
return
end
if parent:HasModifier("modifier_contract_head_leap_arc") then
return
end
local ab = parent:FindAbilityByName("contract_head_leap")
if not ab then
return
end
parent:AddNewModifier(parent, ab, "modifier_contract_head_leap_arc", arcPayload)
end
)
else
parent:AddNewModifier(parent, ability, "modifier_contract_head_leap_arc", arcPayload)
end
end
modifier_contract_head_leap_passive = __TS__Decorate(
modifier_contract_head_leap_passive,
modifier_contract_head_leap_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_contract_head_leap_passive"}
)
____exports.modifier_contract_head_leap_passive = modifier_contract_head_leap_passive
____exports.modifier_contract_head_leap_arc = __TS__Class()
local modifier_contract_head_leap_arc = ____exports.modifier_contract_head_leap_arc
modifier_contract_head_leap_arc.name = "modifier_contract_head_leap_arc"
modifier_contract_head_leap_arc.____file_path = "scripts/vscripts/abilities/creep/contract_head_leap.lua"
__TS__ClassExtends(modifier_contract_head_leap_arc, BaseModifierMotionBoth)
function modifier_contract_head_leap_arc.prototype.____constructor(self, ...)
BaseModifierMotionBoth.prototype.____constructor(self, ...)
self.bHorizontalMotionInterrupted = false
self.flCurrentTimeHoriz = 0
self.flCurrentTimeVert = 0
self.flInitialVelocityZ = 0
self.flPredictedTotalTime = 0
end
function modifier_contract_head_leap_arc.prototype.IsHidden(self)
return true
end
function modifier_contract_head_leap_arc.prototype.IsPurgable(self)
return false
end
function modifier_contract_head_leap_arc.prototype.RemoveOnDeath(self)
return true
end
function modifier_contract_head_leap_arc.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not parent or not ability then
self:Destroy()
return
end
local hx = params.hero_ei
if hx == nil or hx == nil then
self:Destroy()
return
end
self.heroEntIndex = hx
local sx = params.strikeX or parent:GetOrigin().x
local sy = params.strikeY or parent:GetOrigin().y
local sz = params.strikeZ or parent:GetOrigin().z
self.strikeGround = Vector(sx, sy, sz)
self.bHorizontalMotionInterrupted = false
if not self:ApplyHorizontalMotionController() or not self:ApplyVerticalMotionController() then
self:Destroy()
return
end
self.vStartPosition = GetGroundPosition(
parent:GetOrigin(),
parent
)
self.flCurrentTimeHoriz = 0
self.flCurrentTimeVert = 0
local x = params.vLocX or parent:GetOrigin().x
local y = params.vLocY or parent:GetOrigin().y
local z = params.vLocZ or parent:GetOrigin().z
self.vLoc = Vector(x, y, z)
self.vLastKnownTargetPos = self.vLoc
local duration = math.max(
0.08,
ability:GetSpecialValueFor("jump_duration")
)
local flDesiredHeight = CONTRACT_HEAD_LEAP_MIN_HEIGHT_ABOVE_LOWEST * duration * duration
local flLowZ = math.min(self.vLastKnownTargetPos.z, self.vStartPosition.z)
local flHighZ = math.max(self.vLastKnownTargetPos.z, self.vStartPosition.z)
local flArcTopZ = math.max(flLowZ + flDesiredHeight, flHighZ + CONTRACT_HEAD_LEAP_MIN_HEIGHT_ABOVE_HIGHEST)
local flArcDeltaZ = flArcTopZ - self.vStartPosition.z
self.flInitialVelocityZ = math.sqrt(2 * flArcDeltaZ * CONTRACT_HEAD_LEAP_ACCELERATION_Z)
local flDeltaZ = self.vLastKnownTargetPos.z - self.vStartPosition.z
local flSqrtDet = math.sqrt(math.max(0, self.flInitialVelocityZ * self.flInitialVelocityZ - 2 * CONTRACT_HEAD_LEAP_ACCELERATION_Z * flDeltaZ))
self.flPredictedTotalTime = math.max((self.flInitialVelocityZ + flSqrtDet) / CONTRACT_HEAD_LEAP_ACCELERATION_Z, (self.flInitialVelocityZ - flSqrtDet) / CONTRACT_HEAD_LEAP_ACCELERATION_Z)
self.vHorizontalVelocity = (self.vLastKnownTargetPos - self.vStartPosition) / self.flPredictedTotalTime
self.vHorizontalVelocity.z = 0
end
function modifier_contract_head_leap_arc.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if parent ~= nil then
parent:RemoveHorizontalMotionController(self)
parent:RemoveVerticalMotionController(self)
end
end
function modifier_contract_head_leap_arc.prototype.CheckState(self)
return {[MODIFIER_STATE_STUNNED] = true, [MODIFIER_STATE_UNSELECTABLE] = true}
end
function modifier_contract_head_leap_arc.prototype.UpdateHorizontalMotion(self, me, dt)
if not IsServer() then
return
end
self.flCurrentTimeHoriz = math.min(self.flCurrentTimeHoriz + dt, self.flPredictedTotalTime)
local t = self.flCurrentTimeHoriz / self.flPredictedTotalTime
local vStartToTarget = self.vLastKnownTargetPos - self.vStartPosition
local vDesiredPos = self.vStartPosition + vStartToTarget * t
local vOldPos = me:GetOrigin()
local vToDesired = vDesiredPos - vOldPos
vToDesired.z = 0
local vDesiredVel = vToDesired / dt
local vVelDif = vDesiredVel - self.vHorizontalVelocity
local flVelDif = vVelDif:Length2D()
vVelDif = vVelDif:Normalized()
local flVelDelta = math.min(flVelDif, CONTRACT_HEAD_LEAP_MAX_HORIZONTAL_ACCELERATION)
self.vHorizontalVelocity = self.vHorizontalVelocity + vVelDif * flVelDelta * dt
local vNewPos = vOldPos + self.vHorizontalVelocity * dt
me:SetOrigin(vNewPos)
end
function modifier_contract_head_leap_arc.prototype.UpdateVerticalMotion(self, me, dt)
if not IsServer() then
return
end
self.flCurrentTimeVert = self.flCurrentTimeVert + dt
local bGoingDown = -CONTRACT_HEAD_LEAP_ACCELERATION_Z * self.flCurrentTimeVert + self.flInitialVelocityZ < 0
local vNewPos = me:GetOrigin()
vNewPos.z = self.vStartPosition.z + (-0.5 * CONTRACT_HEAD_LEAP_ACCELERATION_Z * self.flCurrentTimeVert * self.flCurrentTimeVert + self.flInitialVelocityZ * self.flCurrentTimeVert)
local flGroundHeight = GetGroundHeight(
vNewPos,
self:GetParent()
)
local bLanded = false
if vNewPos.z < flGroundHeight and bGoingDown then
vNewPos.z = flGroundHeight
bLanded = true
end
me:SetOrigin(vNewPos)
if bLanded then
if not self.bHorizontalMotionInterrupted then
local ability = self:GetAbility()
if ability then
ability:performLeapLanding(self.heroEntIndex, self.strikeGround)
end
end
self:Destroy()
end
end
function modifier_contract_head_leap_arc.prototype.OnHorizontalMotionInterrupted(self)
if not IsServer() then
return
end
self.bHorizontalMotionInterrupted = true
end
function modifier_contract_head_leap_arc.prototype.OnVerticalMotionInterrupted(self)
if not IsServer() then
return
end
self:Destroy()
end
function modifier_contract_head_leap_arc.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_OVERRIDE_ANIMATION}
end
function modifier_contract_head_leap_arc.prototype.GetOverrideAnimation(self)
return ACT_DOTA_CAST_ABILITY_1
end
modifier_contract_head_leap_arc = __TS__Decorate(
modifier_contract_head_leap_arc,
modifier_contract_head_leap_arc,
{registerModifier(nil)},
{kind = "class", name = "modifier_contract_head_leap_arc"}
)
____exports.modifier_contract_head_leap_arc = modifier_contract_head_leap_arc
return ____exports
@@ -0,0 +1,50 @@
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
____exports.harpy_passive = __TS__Class()
local harpy_passive = ____exports.harpy_passive
harpy_passive.name = "harpy_passive"
harpy_passive.____file_path = "scripts/vscripts/abilities/creep/dead_harpy.lua"
__TS__ClassExtends(harpy_passive, BaseAbility)
function harpy_passive.prototype.GetIntrinsicModifierName(self)
return "modifier_harpy_passive"
end
harpy_passive = __TS__Decorate(
harpy_passive,
harpy_passive,
{registerAbility(nil)},
{kind = "class", name = "harpy_passive"}
)
____exports.harpy_passive = harpy_passive
____exports.modifier_harpy_passive = __TS__Class()
local modifier_harpy_passive = ____exports.modifier_harpy_passive
modifier_harpy_passive.name = "modifier_harpy_passive"
modifier_harpy_passive.____file_path = "scripts/vscripts/abilities/creep/dead_harpy.lua"
__TS__ClassExtends(modifier_harpy_passive, BaseModifier)
function modifier_harpy_passive.prototype.IsHidden(self)
return true
end
function modifier_harpy_passive.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_VISUAL_Z_DELTA}
end
function modifier_harpy_passive.prototype.CheckState(self)
return {[MODIFIER_STATE_FLYING] = true, [MODIFIER_STATE_NO_UNIT_COLLISION] = true}
end
function modifier_harpy_passive.prototype.GetVisualZDelta(self)
return 100
end
modifier_harpy_passive = __TS__Decorate(
modifier_harpy_passive,
modifier_harpy_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_harpy_passive"}
)
____exports.modifier_harpy_passive = modifier_harpy_passive
return ____exports
@@ -0,0 +1,117 @@
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 ____incoming_damage_reduction_combine = require("utils.incoming_damage_reduction_combine")
local removeIncomingDamageReductionSource = ____incoming_damage_reduction_combine.removeIncomingDamageReductionSource
local setIncomingDamageReductionSource = ____incoming_damage_reduction_combine.setIncomingDamageReductionSource
local ANIMATION_STUN_INCOMING_SOURCE = "modifier_animation_stun"
____exports.ability_animation = __TS__Class()
local ability_animation = ____exports.ability_animation
ability_animation.name = "ability_animation"
ability_animation.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/animation.lua"
__TS__ClassExtends(ability_animation, BaseAbility)
function ability_animation.prototype.GetIntrinsicModifierName(self)
return "modifier_animation_checker"
end
ability_animation = __TS__Decorate(
ability_animation,
ability_animation,
{registerAbility(nil)},
{kind = "class", name = "ability_animation"}
)
____exports.ability_animation = ability_animation
____exports.modifier_animation_checker = __TS__Class()
local modifier_animation_checker = ____exports.modifier_animation_checker
modifier_animation_checker.name = "modifier_animation_checker"
modifier_animation_checker.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/animation.lua"
__TS__ClassExtends(modifier_animation_checker, BaseModifier)
function modifier_animation_checker.prototype.IsHidden(self)
return true
end
function modifier_animation_checker.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_TAKEDAMAGE}
end
function modifier_animation_checker.prototype.OnTakeDamage(self, event)
if not IsServer() then
return
end
local unit = event.unit
if unit ~= self:GetParent() then
return
end
local maxHealth = unit:GetMaxHealth()
local currentHealth = unit:GetHealth()
local ability = self:GetAbility()
if currentHealth <= maxHealth * 0.75 and self:GetStackCount() < 1 then
self:IncrementStackCount()
unit:AddNewModifier(unit, ability, "modifier_animation_stun", {duration = 3.7})
end
if currentHealth <= maxHealth * 0.5 and self:GetStackCount() < 2 then
self:IncrementStackCount()
unit:AddNewModifier(unit, ability, "modifier_animation_stun", {duration = 3.7})
end
if currentHealth <= maxHealth * 0.25 and self:GetStackCount() < 3 then
self:IncrementStackCount()
unit:AddNewModifier(unit, ability, "modifier_animation_stun", {duration = 3.7})
end
end
modifier_animation_checker = __TS__Decorate(
modifier_animation_checker,
modifier_animation_checker,
{registerModifier(nil)},
{kind = "class", name = "modifier_animation_checker"}
)
____exports.modifier_animation_checker = modifier_animation_checker
____exports.modifier_animation_stun = __TS__Class()
local modifier_animation_stun = ____exports.modifier_animation_stun
modifier_animation_stun.name = "modifier_animation_stun"
modifier_animation_stun.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/animation.lua"
__TS__ClassExtends(modifier_animation_stun, BaseModifier)
function modifier_animation_stun.prototype.IsHidden(self)
return false
end
function modifier_animation_stun.prototype.OnCreated(self)
if not IsServer() then
return
end
local parent = self:GetParent()
parent:StartGestureWithFade(ACT_DOTA_NIAN_PIN_TO_STUN, 0.5, 0)
setIncomingDamageReductionSource(
nil,
parent,
ANIMATION_STUN_INCOMING_SOURCE,
function() return 50 end
)
end
function modifier_animation_stun.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
removeIncomingDamageReductionSource(nil, parent, ANIMATION_STUN_INCOMING_SOURCE)
parent:RemoveGesture(ACT_DOTA_NIAN_PIN_TO_STUN)
end
function modifier_animation_stun.prototype.CheckState(self)
return {
[MODIFIER_STATE_COMMAND_RESTRICTED] = false,
[MODIFIER_STATE_DISARMED] = true,
[MODIFIER_STATE_IGNORING_MOVE_AND_ATTACK_ORDERS] = true,
[MODIFIER_STATE_IGNORING_MOVE_ORDERS] = true,
[MODIFIER_STATE_SILENCED] = true
}
end
modifier_animation_stun = __TS__Decorate(
modifier_animation_stun,
modifier_animation_stun,
{registerModifier(nil)},
{kind = "class", name = "modifier_animation_stun"}
)
____exports.modifier_animation_stun = modifier_animation_stun
return ____exports
@@ -0,0 +1,92 @@
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
____exports.back_stun = __TS__Class()
local back_stun = ____exports.back_stun
back_stun.name = "back_stun"
back_stun.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/back_stun.lua"
__TS__ClassExtends(back_stun, BaseAbility)
function back_stun.prototype.Precache(self, context)
PrecacheResource("particle", "particles/econ/items/earthshaker/deep_magma/deep_magma_10th/deep_magma_10th_echoslam_start.vpcf", context)
PrecacheResource("particle", "particles/generic_gameplay/generic_stunned.vpcf", context)
end
function back_stun.prototype.GetCastRange(self)
return self:GetSpecialValueFor("cast_range")
end
function back_stun.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local duration = self:GetSpecialValueFor("duration")
local radius = self:GetSpecialValueFor("cast_range")
if not caster then
return
end
local direction = caster:GetForwardVector()
local backPosition = caster:GetOrigin():__sub(direction:__mul(radius))
self.particle = ParticleManager:CreateParticle("particles/econ/items/earthshaker/deep_magma/deep_magma_10th/deep_magma_10th_echoslam_start.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(self.particle, 0, backPosition)
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
backPosition,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, unit in ipairs(units) do
unit:AddNewModifier(caster, self, "modifier_back_stunned", {duration = duration})
local damage = self:GetSpecialValueFor("damage") + self:GetCaster():GetAverageTrueAttackDamage(unit) * 3
ApplyDamage({victim = unit, attacker = caster, damage = damage, damage_type = DAMAGE_TYPE_PURE})
EmitSoundOn("Hero_Centaur.HoofStomp", unit)
end
end
back_stun = __TS__Decorate(
back_stun,
back_stun,
{registerAbility(nil)},
{kind = "class", name = "back_stun"}
)
____exports.back_stun = back_stun
____exports.modifier_back_stunned = __TS__Class()
local modifier_back_stunned = ____exports.modifier_back_stunned
modifier_back_stunned.name = "modifier_back_stunned"
modifier_back_stunned.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/back_stun.lua"
__TS__ClassExtends(modifier_back_stunned, BaseModifier)
function modifier_back_stunned.prototype.IsHidden(self)
return false
end
function modifier_back_stunned.prototype.IsDebuff(self)
return true
end
function modifier_back_stunned.prototype.IsStunDebuff(self)
return true
end
function modifier_back_stunned.prototype.IsPurgable(self)
return true
end
function modifier_back_stunned.prototype.GetEffectName(self)
return "particles/generic_gameplay/generic_stunned.vpcf"
end
function modifier_back_stunned.prototype.GetEffectAttachType(self)
return PATTACH_OVERHEAD_FOLLOW
end
function modifier_back_stunned.prototype.CheckState(self)
return {[MODIFIER_STATE_STUNNED] = true}
end
modifier_back_stunned = __TS__Decorate(
modifier_back_stunned,
modifier_back_stunned,
{registerModifier(nil)},
{kind = "class", name = "modifier_back_stunned"}
)
____exports.modifier_back_stunned = modifier_back_stunned
return ____exports
@@ -0,0 +1,92 @@
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
____exports.face_stun = __TS__Class()
local face_stun = ____exports.face_stun
face_stun.name = "face_stun"
face_stun.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/face_stun.lua"
__TS__ClassExtends(face_stun, BaseAbility)
function face_stun.prototype.Precache(self, context)
PrecacheResource("particle", "particles/econ/items/earthshaker/deep_magma/deep_magma_10th/deep_magma_10th_echoslam_start.vpcf", context)
PrecacheResource("particle", "particles/generic_gameplay/generic_stunned.vpcf", context)
end
function face_stun.prototype.GetCastRange(self)
return self:GetSpecialValueFor("cast_range")
end
function face_stun.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local duration = self:GetSpecialValueFor("duration")
local radius = self:GetSpecialValueFor("cast_range")
if not caster then
return
end
local direction = caster:GetForwardVector()
local frontPosition = caster:GetOrigin():__add(direction:__mul(radius))
self.particle = ParticleManager:CreateParticle("particles/econ/items/earthshaker/deep_magma/deep_magma_10th/deep_magma_10th_echoslam_start.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(self.particle, 0, frontPosition)
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
frontPosition,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, unit in ipairs(units) do
unit:AddNewModifier(caster, self, "modifier_face_stunned", {duration = duration})
local damage = self:GetSpecialValueFor("damage") + self:GetCaster():GetAverageTrueAttackDamage(unit) * 3
ApplyDamage({victim = unit, attacker = caster, damage = damage, damage_type = DAMAGE_TYPE_PURE})
EmitSoundOn("Hero_Centaur.HoofStomp", unit)
end
end
face_stun = __TS__Decorate(
face_stun,
face_stun,
{registerAbility(nil)},
{kind = "class", name = "face_stun"}
)
____exports.face_stun = face_stun
____exports.modifier_face_stunned = __TS__Class()
local modifier_face_stunned = ____exports.modifier_face_stunned
modifier_face_stunned.name = "modifier_face_stunned"
modifier_face_stunned.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/face_stun.lua"
__TS__ClassExtends(modifier_face_stunned, BaseModifier)
function modifier_face_stunned.prototype.IsHidden(self)
return false
end
function modifier_face_stunned.prototype.IsDebuff(self)
return true
end
function modifier_face_stunned.prototype.IsStunDebuff(self)
return true
end
function modifier_face_stunned.prototype.IsPurgable(self)
return true
end
function modifier_face_stunned.prototype.GetEffectName(self)
return "particles/generic_gameplay/generic_stunned.vpcf"
end
function modifier_face_stunned.prototype.GetEffectAttachType(self)
return PATTACH_OVERHEAD_FOLLOW
end
function modifier_face_stunned.prototype.CheckState(self)
return {[MODIFIER_STATE_STUNNED] = true}
end
modifier_face_stunned = __TS__Decorate(
modifier_face_stunned,
modifier_face_stunned,
{registerModifier(nil)},
{kind = "class", name = "modifier_face_stunned"}
)
____exports.modifier_face_stunned = modifier_face_stunned
return ____exports
@@ -0,0 +1,132 @@
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
____exports.fear = __TS__Class()
local fear = ____exports.fear
fear.name = "fear"
fear.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/fear.lua"
__TS__ClassExtends(fear, BaseAbility)
function fear.prototype.GetCastRange(self)
return self:GetSpecialValueFor("cast_range")
end
function fear.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local duration = self:GetSpecialValueFor("duration")
if not caster then
return
end
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
caster:GetAbsOrigin(),
nil,
1200,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local particle = ParticleManager:CreateParticle("particles/econ/items/terrorblade/terrorblade_back_ti8/terrorblade_sunder_ti8_swirl_rope.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(
particle,
0,
caster:GetAbsOrigin()
)
ParticleManager:ReleaseParticleIndex(particle)
for ____, unit in ipairs(units) do
unit:AddNewModifier(caster, self, "modifier_fear_debuff", {duration = duration})
EmitSoundOn("Hero_NightStalker.Void", unit)
end
end
fear = __TS__Decorate(
fear,
fear,
{registerAbility(nil)},
{kind = "class", name = "fear"}
)
____exports.fear = fear
____exports.modifier_fear_debuff = __TS__Class()
local modifier_fear_debuff = ____exports.modifier_fear_debuff
modifier_fear_debuff.name = "modifier_fear_debuff"
modifier_fear_debuff.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/fear.lua"
__TS__ClassExtends(modifier_fear_debuff, BaseModifier)
function modifier_fear_debuff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.interval = 0.03
end
function modifier_fear_debuff.prototype.IsHidden(self)
return false
end
function modifier_fear_debuff.prototype.IsDebuff(self)
return true
end
function modifier_fear_debuff.prototype.IsPurgable(self)
return true
end
function modifier_fear_debuff.prototype.GetEffectName(self)
return "particles/econ/items/nightstalker/nightstalker_black_nihility/nightstalker_black_nihility_void.vpcf"
end
function modifier_fear_debuff.prototype.GetEffectAttachType(self)
return PATTACH_CENTER_FOLLOW
end
function modifier_fear_debuff.prototype.OnCreated(self)
if not IsServer() then
return
end
self.particle = ParticleManager:CreateParticle(
"particles/generic_gameplay/generic_feared.vpcf",
PATTACH_OVERHEAD_FOLLOW,
self:GetParent()
)
self:StartIntervalThink(self.interval)
local ____opt_0 = self:GetCaster()
self.casterPos = ____opt_0 and ____opt_0:GetAbsOrigin()
end
function modifier_fear_debuff.prototype.OnDestroy(self)
if not IsServer() then
return
end
if self.particle then
ParticleManager:DestroyParticle(self.particle, false)
ParticleManager:ReleaseParticleIndex(self.particle)
end
end
function modifier_fear_debuff.prototype.OnIntervalThink(self)
if not IsServer() or not self.casterPos then
return
end
local unit = self:GetParent()
local unitPos = unit:GetAbsOrigin()
local direction = unitPos:__sub(self.casterPos):Normalized()
unit:MoveToPosition(unitPos:__add(direction:__mul(150)))
end
function modifier_fear_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PROVIDES_FOW_POSITION, MODIFIER_PROPERTY_BONUS_VISION_PERCENTAGE, MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_fear_debuff.prototype.BonusVisionPercentage(self)
return -100
end
function modifier_fear_debuff.prototype.MovespeedBonusPercentage(self)
return -100
end
function modifier_fear_debuff.prototype.GetModifierProvidesFOWVision(self)
return 0
end
function modifier_fear_debuff.prototype.CheckState(self)
return {[MODIFIER_STATE_FEARED] = true, [MODIFIER_STATE_COMMAND_RESTRICTED] = true}
end
modifier_fear_debuff = __TS__Decorate(
modifier_fear_debuff,
modifier_fear_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_fear_debuff"}
)
____exports.modifier_fear_debuff = modifier_fear_debuff
return ____exports
@@ -0,0 +1,171 @@
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
____exports.ability_grab = __TS__Class()
local ability_grab = ____exports.ability_grab
ability_grab.name = "ability_grab"
ability_grab.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/grab.lua"
__TS__ClassExtends(ability_grab, BaseAbility)
function ability_grab.prototype.CancelGrabCast(self)
self:EndChannel(true)
self:EndCooldown()
self:RefundManaCost()
end
function ability_grab.prototype.GetCastRange(self)
return 150
end
function ability_grab.prototype.GetChannelTime(self)
return 4.37
end
function ability_grab.prototype.GetBehavior(self)
return bit.bor(DOTA_ABILITY_BEHAVIOR_POINT, DOTA_ABILITY_BEHAVIOR_CHANNELLED)
end
function ability_grab.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local direction = (point - caster:GetAbsOrigin()):Normalized()
local units = FindUnitsInLine(
caster:GetTeamNumber(),
caster:GetAbsOrigin(),
caster:GetAbsOrigin() + direction * self:GetCastRange(),
nil,
100,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE
)
if #units == 0 then
self:CancelGrabCast()
return
end
local target = units[1]
if not target then
self:CancelGrabCast()
return
end
target:AddNewModifier(
caster,
self,
"modifier_grab_stunned",
{duration = self:GetChannelTime()}
)
caster:AddNewModifier(
caster,
self,
"modifier_grab_caster",
{duration = self:GetChannelTime()}
)
caster:StartGesture(ACT_DOTA_NIAN_PIN_LOOP)
target:SetParent(caster, "attach_pindown")
target:SetOrigin(caster:GetAbsOrigin())
self.target = target
self.damageTimer = Timers:CreateTimer(
0.33,
function()
if self.target and not self.target:IsNull() and self.target:IsAlive() then
ParticleManager:CreateParticle("particles/econ/items/lifestealer/ls_ti9_immortal/ls_ti9_open_wounds_blood_bulk.vpcf", PATTACH_ABSORIGIN_FOLLOW, self.target)
EmitSoundOn("Hero_Pudge.Dismember", self.target)
ApplyDamage({
victim = self.target,
attacker = caster,
damage = self:GetSpecialValueFor("damage") + self:GetCaster():GetAverageTrueAttackDamage(target) * 3,
damage_type = DAMAGE_TYPE_PURE
})
return 0.33
end
return nil
end
)
end
function ability_grab.prototype.OnChannelFinish(self, interrupted)
if not IsServer() then
return
end
self:GetCaster():RemoveGesture(ACT_DOTA_NIAN_PIN_LOOP)
if self.damageTimer then
Timers:RemoveTimer(self.damageTimer)
self.damageTimer = nil
end
if self.target then
self.target:RemoveModifierByName("modifier_grab_stunned")
self.target:SetParent(nil, "")
self.target:RemoveHorizontalMotionController(self.target)
self.target:RemoveVerticalMotionController(self.target)
self.target:InterruptMotionControllers(true)
local casterPos = self:GetCaster():GetAbsOrigin()
local casterForward = self:GetCaster():GetForwardVector()
local dropPoint = casterPos + casterForward * 100
FindClearSpaceForUnit(self.target, dropPoint, true)
ApplyDamage({
victim = self.target,
attacker = self:GetCaster(),
damage = self:GetSpecialValueFor("damage"),
damage_type = DAMAGE_TYPE_PHYSICAL
})
end
self:GetCaster():RemoveModifierByName("modifier_grab_caster")
self.target = nil
end
ability_grab = __TS__Decorate(
ability_grab,
ability_grab,
{registerAbility(nil)},
{kind = "class", name = "ability_grab"}
)
____exports.ability_grab = ability_grab
____exports.modifier_grab_stunned = __TS__Class()
local modifier_grab_stunned = ____exports.modifier_grab_stunned
modifier_grab_stunned.name = "modifier_grab_stunned"
modifier_grab_stunned.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/grab.lua"
__TS__ClassExtends(modifier_grab_stunned, BaseModifier)
function modifier_grab_stunned.prototype.IsDebuff(self)
return true
end
function modifier_grab_stunned.prototype.IsStunDebuff(self)
return true
end
function modifier_grab_stunned.prototype.CheckState(self)
return {[MODIFIER_STATE_STUNNED] = true, [MODIFIER_STATE_NO_UNIT_COLLISION] = true}
end
function modifier_grab_stunned.prototype.GetEffectName(self)
return "particles/generic_gameplay/generic_stunned.vpcf"
end
function modifier_grab_stunned.prototype.GetEffectAttachType(self)
return PATTACH_OVERHEAD_FOLLOW
end
modifier_grab_stunned = __TS__Decorate(
modifier_grab_stunned,
modifier_grab_stunned,
{registerModifier(nil)},
{kind = "class", name = "modifier_grab_stunned"}
)
____exports.modifier_grab_stunned = modifier_grab_stunned
____exports.modifier_grab_caster = __TS__Class()
local modifier_grab_caster = ____exports.modifier_grab_caster
modifier_grab_caster.name = "modifier_grab_caster"
modifier_grab_caster.____file_path = "scripts/vscripts/abilities/creep/demon_dragon_satyr/grab.lua"
__TS__ClassExtends(modifier_grab_caster, BaseModifier)
function modifier_grab_caster.prototype.IsHidden(self)
return false
end
function modifier_grab_caster.prototype.CheckState(self)
return {[MODIFIER_STATE_DISARMED] = true, [MODIFIER_STATE_ROOTED] = true}
end
modifier_grab_caster = __TS__Decorate(
modifier_grab_caster,
modifier_grab_caster,
{registerModifier(nil)},
{kind = "class", name = "modifier_grab_caster"}
)
____exports.modifier_grab_caster = modifier_grab_caster
return ____exports
@@ -0,0 +1,290 @@
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 BaseModifierMotionBoth = ____dota_ts_adapter.BaseModifierMotionBoth
local registerAbility = ____dota_ts_adapter.registerAbility
local registerModifier = ____dota_ts_adapter.registerModifier
____exports.frogmen_acid_jump = __TS__Class()
local frogmen_acid_jump = ____exports.frogmen_acid_jump
frogmen_acid_jump.name = "frogmen_acid_jump"
frogmen_acid_jump.____file_path = "scripts/vscripts/abilities/creep/frogmen_acid_jump.lua"
__TS__ClassExtends(frogmen_acid_jump, BaseAbility)
function frogmen_acid_jump.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.radius = 0
self.stun_duration = 0
self.land_damage = 0
end
function frogmen_acid_jump.prototype.Precache(self, context)
PrecacheResource("particle", "particles/neutral_fx/ogre_bruiser_smash.vpcf", context)
end
function frogmen_acid_jump.prototype.OnAbilityPhaseStart(self)
if not IsServer() then
return true
end
return true
end
function frogmen_acid_jump.prototype.OnAbilityPhaseInterrupted(self)
if not IsServer() then
return
end
end
function frogmen_acid_jump.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster then
return
end
local cursorPos = self:GetCursorPosition()
local kv = {vLocX = cursorPos.x, vLocY = cursorPos.y, vLocZ = cursorPos.z}
caster:AddNewModifier(caster, self, "modifier_acid_blob_jump", kv)
self.radius = self:GetSpecialValueFor("radius")
self.stun_duration = self:GetSpecialValueFor("stun_duration")
self.land_damage = self:GetSpecialValueFor("land_damage")
end
function frogmen_acid_jump.prototype.Smash(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster then
return
end
local origin = caster:GetOrigin()
EmitSoundOnLocationWithCaster(origin, "OgreTank.GroundSmash", caster)
local smashFX = ParticleManager:CreateParticle("particles/neutral_fx/ogre_bruiser_smash.vpcf", PATTACH_WORLDORIGIN, caster)
ParticleManager:SetParticleControl(smashFX, 0, origin)
ParticleManager:SetParticleControl(
smashFX,
1,
Vector(self.radius, self.radius, self.radius)
)
ParticleManager:ReleaseParticleIndex(smashFX)
caster:Interrupt()
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
origin,
caster,
self.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
)
for ____, enemy in ipairs(enemies) do
do
if not enemy then
goto __continue13
end
if enemy:IsInvulnerable() then
goto __continue13
end
ApplyDamage({
victim = enemy,
attacker = caster,
damage = self.land_damage + self:GetCaster():GetAverageTrueAttackDamage(enemy) * 2,
damage_type = DAMAGE_TYPE_PHYSICAL,
ability = self
})
if not enemy:IsAlive() then
local critFX = ParticleManager:CreateParticle("particles/units/heroes/hero_phantom_assassin/phantom_assassin_crit_impact.vpcf", PATTACH_CUSTOMORIGIN, nil)
ParticleManager:SetParticleControlEnt(
critFX,
0,
enemy,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
enemy:GetOrigin(),
true
)
ParticleManager:SetParticleControl(
critFX,
1,
enemy:GetOrigin()
)
local forward = caster:GetForwardVector()
ParticleManager:SetParticleControlForward(critFX, 1, forward * -1)
ParticleManager:SetParticleControlEnt(
critFX,
10,
enemy,
PATTACH_ABSORIGIN_FOLLOW,
nil,
enemy:GetOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(critFX)
EmitSoundOn("Dungeon.BloodSplatterImpact", enemy)
else
enemy:AddNewModifier(caster, self, "modifier_stunned", {duration = self.stun_duration})
end
end
::__continue13::
end
end
frogmen_acid_jump = __TS__Decorate(
frogmen_acid_jump,
frogmen_acid_jump,
{registerAbility(nil)},
{kind = "class", name = "frogmen_acid_jump"}
)
____exports.frogmen_acid_jump = frogmen_acid_jump
local AMOEBA_MINIMUM_HEIGHT_ABOVE_LOWEST = 400
local AMOEBA_MINIMUM_HEIGHT_ABOVE_HIGHEST = 200
local AMOEBA_ACCELERATION_Z = 1500
local AMOEBA_MAX_HORIZONTAL_ACCELERATION = 1500
____exports.modifier_acid_blob_jump = __TS__Class()
local modifier_acid_blob_jump = ____exports.modifier_acid_blob_jump
modifier_acid_blob_jump.name = "modifier_acid_blob_jump"
modifier_acid_blob_jump.____file_path = "scripts/vscripts/abilities/creep/frogmen_acid_jump.lua"
__TS__ClassExtends(modifier_acid_blob_jump, BaseModifierMotionBoth)
function modifier_acid_blob_jump.prototype.____constructor(self, ...)
BaseModifierMotionBoth.prototype.____constructor(self, ...)
self.bHorizontalMotionInterrupted = false
self.flCurrentTimeHoriz = 0
self.flCurrentTimeVert = 0
self.flInitialVelocityZ = 0
self.flPredictedTotalTime = 0
end
function modifier_acid_blob_jump.prototype.IsHidden(self)
return true
end
function modifier_acid_blob_jump.prototype.IsPurgable(self)
return false
end
function modifier_acid_blob_jump.prototype.RemoveOnDeath(self)
return false
end
function modifier_acid_blob_jump.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not parent or not ability then
self:Destroy()
return
end
self.bHorizontalMotionInterrupted = false
if not self:ApplyHorizontalMotionController() or not self:ApplyVerticalMotionController() then
self:Destroy()
return
end
self.vStartPosition = GetGroundPosition(
parent:GetOrigin(),
parent
)
self.flCurrentTimeHoriz = 0
self.flCurrentTimeVert = 0
local x = params.vLocX or parent:GetOrigin().x
local y = params.vLocY or parent:GetOrigin().y
local z = params.vLocZ or parent:GetOrigin().z
self.vLoc = Vector(x, y, z)
self.vLastKnownTargetPos = self.vLoc
local duration = ability:GetSpecialValueFor("duration")
local flDesiredHeight = AMOEBA_MINIMUM_HEIGHT_ABOVE_LOWEST * duration * duration
local flLowZ = math.min(self.vLastKnownTargetPos.z, self.vStartPosition.z)
local flHighZ = math.max(self.vLastKnownTargetPos.z, self.vStartPosition.z)
local flArcTopZ = math.max(flLowZ + flDesiredHeight, flHighZ + AMOEBA_MINIMUM_HEIGHT_ABOVE_HIGHEST)
local flArcDeltaZ = flArcTopZ - self.vStartPosition.z
self.flInitialVelocityZ = math.sqrt(2 * flArcDeltaZ * AMOEBA_ACCELERATION_Z)
local flDeltaZ = self.vLastKnownTargetPos.z - self.vStartPosition.z
local flSqrtDet = math.sqrt(math.max(0, self.flInitialVelocityZ * self.flInitialVelocityZ - 2 * AMOEBA_ACCELERATION_Z * flDeltaZ))
self.flPredictedTotalTime = math.max((self.flInitialVelocityZ + flSqrtDet) / AMOEBA_ACCELERATION_Z, (self.flInitialVelocityZ - flSqrtDet) / AMOEBA_ACCELERATION_Z)
self.vHorizontalVelocity = (self.vLastKnownTargetPos - self.vStartPosition) / self.flPredictedTotalTime
self.vHorizontalVelocity.z = 0
end
function modifier_acid_blob_jump.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if parent ~= nil then
parent:RemoveHorizontalMotionController(self)
parent:RemoveVerticalMotionController(self)
end
end
function modifier_acid_blob_jump.prototype.CheckState(self)
return {[MODIFIER_STATE_STUNNED] = true, [MODIFIER_STATE_UNSELECTABLE] = true}
end
function modifier_acid_blob_jump.prototype.UpdateHorizontalMotion(self, me, dt)
if not IsServer() then
return
end
self.flCurrentTimeHoriz = math.min(self.flCurrentTimeHoriz + dt, self.flPredictedTotalTime)
local t = self.flCurrentTimeHoriz / self.flPredictedTotalTime
local vStartToTarget = self.vLastKnownTargetPos - self.vStartPosition
local vDesiredPos = self.vStartPosition + vStartToTarget * t
local vOldPos = me:GetOrigin()
local vToDesired = vDesiredPos - vOldPos
vToDesired.z = 0
local vDesiredVel = vToDesired / dt
local vVelDif = vDesiredVel - self.vHorizontalVelocity
local flVelDif = vVelDif:Length2D()
vVelDif = vVelDif:Normalized()
local flVelDelta = math.min(flVelDif, AMOEBA_MAX_HORIZONTAL_ACCELERATION)
self.vHorizontalVelocity = self.vHorizontalVelocity + vVelDif * flVelDelta * dt
local vNewPos = vOldPos + self.vHorizontalVelocity * dt
me:SetOrigin(vNewPos)
end
function modifier_acid_blob_jump.prototype.UpdateVerticalMotion(self, me, dt)
if not IsServer() then
return
end
self.flCurrentTimeVert = self.flCurrentTimeVert + dt
local bGoingDown = -AMOEBA_ACCELERATION_Z * self.flCurrentTimeVert + self.flInitialVelocityZ < 0
local vNewPos = me:GetOrigin()
vNewPos.z = self.vStartPosition.z + (-0.5 * AMOEBA_ACCELERATION_Z * self.flCurrentTimeVert * self.flCurrentTimeVert + self.flInitialVelocityZ * self.flCurrentTimeVert)
local flGroundHeight = GetGroundHeight(
vNewPos,
self:GetParent()
)
local bLanded = false
if vNewPos.z < flGroundHeight and bGoingDown then
vNewPos.z = flGroundHeight
bLanded = true
end
me:SetOrigin(vNewPos)
if bLanded then
if not self.bHorizontalMotionInterrupted then
local ability = self:GetAbility()
if ability then
ability:Smash()
end
end
self:Destroy()
end
end
function modifier_acid_blob_jump.prototype.OnHorizontalMotionInterrupted(self)
if not IsServer() then
return
end
self.bHorizontalMotionInterrupted = true
end
function modifier_acid_blob_jump.prototype.OnVerticalMotionInterrupted(self)
if not IsServer() then
return
end
self:Destroy()
end
function modifier_acid_blob_jump.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_OVERRIDE_ANIMATION}
end
function modifier_acid_blob_jump.prototype.GetOverrideAnimation(self)
return ACT_DOTA_CAST_ABILITY_1
end
modifier_acid_blob_jump = __TS__Decorate(
modifier_acid_blob_jump,
modifier_acid_blob_jump,
{registerModifier(nil)},
{kind = "class", name = "modifier_acid_blob_jump"}
)
____exports.modifier_acid_blob_jump = modifier_acid_blob_jump
return ____exports
@@ -0,0 +1,60 @@
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
____exports.ghost_evasive = __TS__Class()
local ghost_evasive = ____exports.ghost_evasive
ghost_evasive.name = "ghost_evasive"
ghost_evasive.____file_path = "scripts/vscripts/abilities/creep/ghost_evasive.lua"
__TS__ClassExtends(ghost_evasive, BaseAbility)
function ghost_evasive.prototype.GetIntrinsicModifierName(self)
return "modifier_ghost_evasive_passive"
end
ghost_evasive = __TS__Decorate(
ghost_evasive,
ghost_evasive,
{registerAbility(nil)},
{kind = "class", name = "ghost_evasive"}
)
____exports.ghost_evasive = ghost_evasive
____exports.modifier_ghost_evasive_passive = __TS__Class()
local modifier_ghost_evasive_passive = ____exports.modifier_ghost_evasive_passive
modifier_ghost_evasive_passive.name = "modifier_ghost_evasive_passive"
modifier_ghost_evasive_passive.____file_path = "scripts/vscripts/abilities/creep/ghost_evasive.lua"
__TS__ClassExtends(modifier_ghost_evasive_passive, BaseModifier)
function modifier_ghost_evasive_passive.prototype.IsHidden(self)
return true
end
function modifier_ghost_evasive_passive.prototype.IsDebuff(self)
return false
end
function modifier_ghost_evasive_passive.prototype.IsPurgable(self)
return false
end
function modifier_ghost_evasive_passive.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_EVASION_CONSTANT}
end
function modifier_ghost_evasive_passive.prototype.GetModifierEvasion_Constant(self, event)
local ab = self:GetAbility()
if not ab then
return 0
end
return ab:GetSpecialValueFor("evasive")
end
function modifier_ghost_evasive_passive.prototype.CheckState(self)
return {[MODIFIER_STATE_FLYING] = true, [MODIFIER_STATE_NO_UNIT_COLLISION] = true}
end
modifier_ghost_evasive_passive = __TS__Decorate(
modifier_ghost_evasive_passive,
modifier_ghost_evasive_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_ghost_evasive_passive"}
)
____exports.modifier_ghost_evasive_passive = modifier_ghost_evasive_passive
return ____exports
@@ -0,0 +1,158 @@
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
____exports.kaban_rofl_ability = __TS__Class()
local kaban_rofl_ability = ____exports.kaban_rofl_ability
kaban_rofl_ability.name = "kaban_rofl_ability"
kaban_rofl_ability.____file_path = "scripts/vscripts/abilities/creep/kaban_rofl_ability.lua"
__TS__ClassExtends(kaban_rofl_ability, BaseAbility)
function kaban_rofl_ability.prototype.GetIntrinsicModifierName(self)
return "modifier_kaban_rofl_ability"
end
kaban_rofl_ability = __TS__Decorate(
kaban_rofl_ability,
kaban_rofl_ability,
{registerAbility(nil)},
{kind = "class", name = "kaban_rofl_ability"}
)
____exports.kaban_rofl_ability = kaban_rofl_ability
____exports.modifier_kaban_rofl_ability = __TS__Class()
local modifier_kaban_rofl_ability = ____exports.modifier_kaban_rofl_ability
modifier_kaban_rofl_ability.name = "modifier_kaban_rofl_ability"
modifier_kaban_rofl_ability.____file_path = "scripts/vscripts/abilities/creep/kaban_rofl_ability.lua"
__TS__ClassExtends(modifier_kaban_rofl_ability, BaseModifier)
function modifier_kaban_rofl_ability.prototype.IsHidden(self)
return true
end
function modifier_kaban_rofl_ability.prototype.OnCreated(self, params)
Timers:CreateTimer(
30,
function()
UTIL_Remove(self:GetParent())
end
)
end
function modifier_kaban_rofl_ability.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_TAKEDAMAGE, MODIFIER_PROPERTY_MIN_HEALTH}
end
function modifier_kaban_rofl_ability.prototype.CheckState(self)
return {[MODIFIER_STATE_NO_HEALTH_BAR] = true}
end
function modifier_kaban_rofl_ability.prototype.GetMinHealth(self)
return 1
end
function modifier_kaban_rofl_ability.prototype.OnTakeDamage(self, event)
if not IsServer() then
return
end
if event.attacker ~= self:GetParent():GetOwner() then
return
end
if event.unit ~= self:GetParent() then
return
end
local parent = self:GetParent()
local parentPos = parent:GetAbsOrigin()
local attacker = event.attacker
local hasEasterEgg = self:GetParent():HasModifier("modifier_easter_egg_dropped")
if not hasEasterEgg and RandomFloat(0, 100) <= 2 then
local easterEgg = CreateItem("item_easter_egg", nil, nil)
if easterEgg then
local physicalItem = CreateItemOnPositionForLaunch(parentPos, easterEgg)
if physicalItem ~= nil then
local randomAngle = RandomFloat(0, 2 * math.pi)
local randomDistance = RandomFloat(100, 500)
local randomX = parentPos.x + randomDistance * math.cos(randomAngle)
local randomY = parentPos.y + randomDistance * math.sin(randomAngle)
local randomPos = Vector(randomX, randomY, parentPos.z)
local dropRadius = RandomFloat(50, 100)
easterEgg:LaunchLootInitialHeight(
false,
0,
150,
0.5,
randomPos + RandomVector(dropRadius)
)
self:GetParent():AddNewModifier(
self:GetParent(),
getModifierSourceAbility(
nil,
self:GetParent()
),
"modifier_easter_egg_dropped",
{}
)
end
end
elseif RandomFloat(0, 100) <= 20 then
local item = CreateItem("item_candy", nil, nil)
if item then
local physicalItem = CreateItemOnPositionForLaunch(parentPos, item)
if physicalItem ~= nil then
local randomAngle = RandomFloat(0, 2 * math.pi)
local randomDistance = RandomFloat(100, 500)
local randomX = parentPos.x + randomDistance * math.cos(randomAngle)
local randomY = parentPos.y + randomDistance * math.sin(randomAngle)
local randomPos = Vector(randomX, randomY, parentPos.z)
local dropRadius = RandomFloat(50, 100)
item:LaunchLootInitialHeight(
false,
0,
150,
0.5,
randomPos + RandomVector(dropRadius)
)
Timers:CreateTimer(
30,
function()
if IsValidEntity(physicalItem) then
UTIL_Remove(physicalItem)
end
end
)
end
end
end
if attacker and attacker:IsAlive() then
self:MakeUnitFlee(parent, attacker)
end
end
function modifier_kaban_rofl_ability.prototype.MakeUnitFlee(self, fleeingUnit, fromUnit)
local fleeingPos = fleeingUnit:GetAbsOrigin()
local fromPos = fromUnit:GetAbsOrigin()
local directionX = fleeingPos.x - fromPos.x
local directionY = fleeingPos.y - fromPos.y
local distance = math.sqrt(directionX * directionX + directionY * directionY)
if distance > 0 then
local normalizedX = directionX / distance
local normalizedY = directionY / distance
local fleeDistance = math.min(800, distance * 2)
local fleeX = fleeingPos.x + normalizedX * fleeDistance
local fleeY = fleeingPos.y + normalizedY * fleeDistance
local fleePos = Vector(fleeX, fleeY, fleeingPos.z)
local groundHeight = GetGroundHeight(fleePos, nil)
local validPos = Vector(fleeX, fleeY, groundHeight)
fleeingUnit:MoveToPosition(toVectorWS(nil, validPos))
fleeingUnit:AddNewModifier(
fleeingUnit,
getModifierSourceAbility(nil, fleeingUnit),
"modifier_phased",
{duration = 2}
)
end
end
modifier_kaban_rofl_ability = __TS__Decorate(
modifier_kaban_rofl_ability,
modifier_kaban_rofl_ability,
{registerModifier(nil)},
{kind = "class", name = "modifier_kaban_rofl_ability"}
)
____exports.modifier_kaban_rofl_ability = modifier_kaban_rofl_ability
return ____exports
@@ -0,0 +1,54 @@
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 BaseModifier = ____dota_ts_adapter.BaseModifier
local registerModifier = ____dota_ts_adapter.registerModifier
____exports.modifier_boss_nevermore_coil_debuff = __TS__Class()
local modifier_boss_nevermore_coil_debuff = ____exports.modifier_boss_nevermore_coil_debuff
modifier_boss_nevermore_coil_debuff.name = "modifier_boss_nevermore_coil_debuff"
modifier_boss_nevermore_coil_debuff.____file_path = "scripts/vscripts/abilities/creep/modifier_boss_nevermore_coil_debuff.lua"
__TS__ClassExtends(modifier_boss_nevermore_coil_debuff, BaseModifier)
function modifier_boss_nevermore_coil_debuff.prototype.IsHidden(self)
return false
end
function modifier_boss_nevermore_coil_debuff.prototype.IsPurgable(self)
return true
end
function modifier_boss_nevermore_coil_debuff.prototype.IsDebuff(self)
return true
end
function modifier_boss_nevermore_coil_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_TOOLTIP}
end
function modifier_boss_nevermore_coil_debuff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
local ability = self:GetAbility()
if not ability then
return 0
end
local slowPerStack = ability:GetSpecialValueFor("coil_slow_per_stack")
return -slowPerStack * self:GetStackCount()
end
function modifier_boss_nevermore_coil_debuff.prototype.OnTooltip(self)
local ability = self:GetAbility()
if not ability then
return 0
end
return ability:GetSpecialValueFor("coil_stack_bonus_damage") * self:GetStackCount()
end
function modifier_boss_nevermore_coil_debuff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_nevermore/nevermore_requiemofsouls_debuff.vpcf"
end
function modifier_boss_nevermore_coil_debuff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_boss_nevermore_coil_debuff = __TS__Decorate(
modifier_boss_nevermore_coil_debuff,
modifier_boss_nevermore_coil_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_coil_debuff"}
)
____exports.modifier_boss_nevermore_coil_debuff = modifier_boss_nevermore_coil_debuff
return ____exports
@@ -0,0 +1,47 @@
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 BaseModifier = ____dota_ts_adapter.BaseModifier
local registerModifier = ____dota_ts_adapter.registerModifier
--- Только для npc_boss_nevermore: без DEBUFF_IMMUNE на общем no_healthbar (Луна и др.),
-- чтобы там не ломать диспелы. Боссу сайленс/орчид и прочие дебаффы с героев не цепляются.
____exports.modifier_boss_nevermore_debuff_immune = __TS__Class()
local modifier_boss_nevermore_debuff_immune = ____exports.modifier_boss_nevermore_debuff_immune
modifier_boss_nevermore_debuff_immune.name = "modifier_boss_nevermore_debuff_immune"
modifier_boss_nevermore_debuff_immune.____file_path = "scripts/vscripts/abilities/creep/modifier_boss_nevermore_debuff_immune.lua"
__TS__ClassExtends(modifier_boss_nevermore_debuff_immune, BaseModifier)
function modifier_boss_nevermore_debuff_immune.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_debuff_immune.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_debuff_immune.prototype.IsDebuff(self)
return false
end
function modifier_boss_nevermore_debuff_immune.prototype.GetPriority(self)
return MODIFIER_PRIORITY_SUPER_ULTRA
end
function modifier_boss_nevermore_debuff_immune.prototype.CheckState(self)
return {[MODIFIER_STATE_SILENCED] = false, [MODIFIER_STATE_ROOTED] = false}
end
function modifier_boss_nevermore_debuff_immune.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PROVIDES_FOW_POSITION}
end
function modifier_boss_nevermore_debuff_immune.prototype.providesFOWPosition(self)
return true
end
function modifier_boss_nevermore_debuff_immune.prototype.GetModifierProvidesFOWVision(self)
return 1
end
modifier_boss_nevermore_debuff_immune = __TS__Decorate(
modifier_boss_nevermore_debuff_immune,
modifier_boss_nevermore_debuff_immune,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_debuff_immune"}
)
____exports.modifier_boss_nevermore_debuff_immune = modifier_boss_nevermore_debuff_immune
return ____exports
@@ -0,0 +1,152 @@
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 BaseModifier = ____dota_ts_adapter.BaseModifier
local registerModifier = ____dota_ts_adapter.registerModifier
local ____nevermore_boss_requiem_bridge = require("ai.nevermore_boss_requiem_bridge")
local tryForceNevermoreRequiemCast = ____nevermore_boss_requiem_bridge.tryForceNevermoreRequiemCast
local TERROR_WAVE_ABILITY = "terrorblade_terror_wave"
--- Задержка между несколькими волнами, если за один удар пересечено несколько порогов HP.
local MULTI_WAVE_STAGGER = 0.22
--- После последней Terror Wave — пауза перед телепортом в центр и реквиемом.
local AFTER_TERROR_WAVE_TO_REQUIEM = 0.72
--- Фаза босса Nevermore по HP (как у coil_wave / ИИ).
local function getNevermoreBossHpPhase(self, unit)
local hp = unit:GetHealthPercent()
if hp <= 25 then
return 4
end
if hp <= 50 then
return 3
end
if hp <= 75 then
return 2
end
return 1
end
local function tryCastTerrorWave(self, boss)
if not IsServer() then
return
end
if not boss or boss:IsNull() or not boss:IsAlive() then
return
end
local ab = boss:FindAbilityByName(TERROR_WAVE_ABILITY)
if not ab or ab:IsNull() then
return
end
if ab:GetLevel() < 1 then
ab:SetLevel(1)
end
ab:EndCooldown()
ExecuteOrderFromTable({
UnitIndex = boss:entindex(),
OrderType = DOTA_UNIT_ORDER_CAST_NO_TARGET,
AbilityIndex = ab:entindex()
})
end
--- Вешается на npc_boss_nevermore: при каждом переходе на новую фазу по HP — Terror Wave.
function ____exports.applyNevermorePhaseTerrorWave(self, boss)
if not IsServer() or not boss or boss:IsNull() or not boss:IsAlive() then
return
end
if boss:HasModifier(____exports.modifier_boss_nevermore_phase_terror_wave.name) then
return
end
boss:AddNewModifier(
boss,
getModifierSourceAbility(nil, boss),
____exports.modifier_boss_nevermore_phase_terror_wave.name,
{}
)
end
____exports.modifier_boss_nevermore_phase_terror_wave = __TS__Class()
local modifier_boss_nevermore_phase_terror_wave = ____exports.modifier_boss_nevermore_phase_terror_wave
modifier_boss_nevermore_phase_terror_wave.name = "modifier_boss_nevermore_phase_terror_wave"
modifier_boss_nevermore_phase_terror_wave.____file_path = "scripts/vscripts/abilities/creep/modifier_boss_nevermore_phase_terror_wave.lua"
__TS__ClassExtends(modifier_boss_nevermore_phase_terror_wave, BaseModifier)
function modifier_boss_nevermore_phase_terror_wave.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.storedPhase = 1
end
function modifier_boss_nevermore_phase_terror_wave.prototype.IsHidden(self)
return true
end
function modifier_boss_nevermore_phase_terror_wave.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_phase_terror_wave.prototype.RemoveOnDeath(self)
return true
end
function modifier_boss_nevermore_phase_terror_wave.prototype.OnCreated(self)
if not IsServer() then
return
end
self.parent = self:GetParent()
self.storedPhase = getNevermoreBossHpPhase(nil, self.parent)
self:StartIntervalThink(0.2)
end
function modifier_boss_nevermore_phase_terror_wave.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_TAKEDAMAGE}
end
function modifier_boss_nevermore_phase_terror_wave.prototype.OnTakeDamage(self)
self:checkPhaseTransitions()
end
function modifier_boss_nevermore_phase_terror_wave.prototype.OnIntervalThink(self)
if not IsValidEntity(self.parent) or not self.parent:IsAlive() then
self:StartIntervalThink(-1)
return
end
self:checkPhaseTransitions()
end
function modifier_boss_nevermore_phase_terror_wave.prototype.checkPhaseTransitions(self)
if not IsServer() then
return
end
if not IsValidEntity(self.parent) or not self.parent:IsAlive() then
return
end
local newPhase = getNevermoreBossHpPhase(nil, self.parent)
if newPhase <= self.storedPhase then
return
end
local wavesToFire = newPhase - self.storedPhase
self.storedPhase = newPhase
local entIndex = self.parent:entindex()
do
local i = 0
while i < wavesToFire do
local delay = i * MULTI_WAVE_STAGGER
Timers:CreateTimer(
delay,
function()
local u = EntIndexToHScript(entIndex)
tryCastTerrorWave(nil, u)
end
)
i = i + 1
end
end
local lastWaveDelay = wavesToFire > 0 and (wavesToFire - 1) * MULTI_WAVE_STAGGER or 0
local requiemDelay = lastWaveDelay + AFTER_TERROR_WAVE_TO_REQUIEM
Timers:CreateTimer(
requiemDelay,
function()
local u = EntIndexToHScript(entIndex)
if u and not u:IsNull() and u:IsAlive() then
tryForceNevermoreRequiemCast(nil, u)
end
end
)
end
modifier_boss_nevermore_phase_terror_wave = __TS__Decorate(
modifier_boss_nevermore_phase_terror_wave,
modifier_boss_nevermore_phase_terror_wave,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_phase_terror_wave"}
)
____exports.modifier_boss_nevermore_phase_terror_wave = modifier_boss_nevermore_phase_terror_wave
return ____exports
@@ -0,0 +1,116 @@
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 BaseModifier = ____dota_ts_adapter.BaseModifier
local registerModifier = ____dota_ts_adapter.registerModifier
local ____nevermore_boss_requiem_bridge = require("ai.nevermore_boss_requiem_bridge")
local NEVERMORE_REQUIEM_DAMAGE_REDUCTION_PCT = ____nevermore_boss_requiem_bridge.NEVERMORE_REQUIEM_DAMAGE_REDUCTION_PCT
local NEVERMORE_REQUIEM_HP_THRESHOLD = ____nevermore_boss_requiem_bridge.NEVERMORE_REQUIEM_HP_THRESHOLD
local NEVERMORE_REQUIEM_REQUIRED_CASTS = ____nevermore_boss_requiem_bridge.NEVERMORE_REQUIEM_REQUIRED_CASTS
local nevermoreGetRequiemCastCount = ____nevermore_boss_requiem_bridge.nevermoreGetRequiemCastCount
local nevermoreNeedsMandatoryRequiem = ____nevermore_boss_requiem_bridge.nevermoreNeedsMandatoryRequiem
local tryForceNevermoreRequiemCast = ____nevermore_boss_requiem_bridge.tryForceNevermoreRequiemCast
--- Снижение входящего урона, пока HP < 50% и реквием не скастован 3 раза; дожим каста ульты.
____exports.modifier_boss_nevermore_requiem_gate = __TS__Class()
local modifier_boss_nevermore_requiem_gate = ____exports.modifier_boss_nevermore_requiem_gate
modifier_boss_nevermore_requiem_gate.name = "modifier_boss_nevermore_requiem_gate"
modifier_boss_nevermore_requiem_gate.____file_path = "scripts/vscripts/abilities/creep/modifier_boss_nevermore_requiem_gate.lua"
__TS__ClassExtends(modifier_boss_nevermore_requiem_gate, BaseModifier)
function modifier_boss_nevermore_requiem_gate.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.nextForceCastAt = 0
end
function modifier_boss_nevermore_requiem_gate.prototype.IsHidden(self)
return false
end
function modifier_boss_nevermore_requiem_gate.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_requiem_gate.prototype.IsDebuff(self)
return false
end
function modifier_boss_nevermore_requiem_gate.prototype.RemoveOnDeath(self)
return true
end
function modifier_boss_nevermore_requiem_gate.prototype.OnCreated(self)
if not IsServer() then
return
end
self.parent = self:GetParent()
self:syncStacks()
self:StartIntervalThink(0.35)
end
function modifier_boss_nevermore_requiem_gate.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
if not IsValidEntity(self.parent) or not self.parent:IsAlive() then
self:StartIntervalThink(-1)
return
end
self:syncStacks()
if not nevermoreNeedsMandatoryRequiem(nil, self.parent) then
return
end
local now = GameRules:GetGameTime()
if now < self.nextForceCastAt then
return
end
if self.parent:IsChanneling() then
return
end
if tryForceNevermoreRequiemCast(nil, self.parent) then
self.nextForceCastAt = now + 5
else
self.nextForceCastAt = now + 1.25
end
end
function modifier_boss_nevermore_requiem_gate.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE, MODIFIER_EVENT_ON_TAKEDAMAGE}
end
function modifier_boss_nevermore_requiem_gate.prototype.OnTakeDamage(self)
if not IsServer() then
return
end
self:syncStacks()
end
function modifier_boss_nevermore_requiem_gate.prototype.GetModifierIncomingDamage_Percentage(self, event)
if event.target ~= self.parent then
return 0
end
if nevermoreGetRequiemCastCount(nil, self.parent) >= NEVERMORE_REQUIEM_REQUIRED_CASTS then
return 0
end
if self.parent:GetHealthPercent() >= NEVERMORE_REQUIEM_HP_THRESHOLD then
return 0
end
return -NEVERMORE_REQUIEM_DAMAGE_REDUCTION_PCT
end
function modifier_boss_nevermore_requiem_gate.prototype.syncStacks(self)
self:SetStackCount(nevermoreGetRequiemCastCount(nil, self.parent))
end
modifier_boss_nevermore_requiem_gate = __TS__Decorate(
modifier_boss_nevermore_requiem_gate,
modifier_boss_nevermore_requiem_gate,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_requiem_gate"}
)
____exports.modifier_boss_nevermore_requiem_gate = modifier_boss_nevermore_requiem_gate
function ____exports.applyNevermoreRequiemGate(self, boss)
if not IsServer() or not boss or boss:IsNull() or not boss:IsAlive() then
return
end
if boss:HasModifier(____exports.modifier_boss_nevermore_requiem_gate.name) then
return
end
boss:AddNewModifier(
boss,
getModifierSourceAbility(nil, boss),
____exports.modifier_boss_nevermore_requiem_gate.name,
{}
)
end
return ____exports
@@ -0,0 +1,57 @@
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 BaseModifier = ____dota_ts_adapter.BaseModifier
local registerModifier = ____dota_ts_adapter.registerModifier
____exports.modifier_boss_nevermore_requiem_magic_resist_debuff = __TS__Class()
local modifier_boss_nevermore_requiem_magic_resist_debuff = ____exports.modifier_boss_nevermore_requiem_magic_resist_debuff
modifier_boss_nevermore_requiem_magic_resist_debuff.name = "modifier_boss_nevermore_requiem_magic_resist_debuff"
modifier_boss_nevermore_requiem_magic_resist_debuff.____file_path = "scripts/vscripts/abilities/creep/modifier_boss_nevermore_requiem_magic_resist_debuff.lua"
__TS__ClassExtends(modifier_boss_nevermore_requiem_magic_resist_debuff, BaseModifier)
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.IsHidden(self)
return false
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.IsDebuff(self)
return true
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.IsPurgable(self)
return false
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.RemoveOnDeath(self)
return false
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MAGICAL_RESISTANCE_DECREPIFY_UNIQUE, MODIFIER_PROPERTY_TOOLTIP}
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.GetModifierMagicalResistanceDecrepifyUnique(self)
local ability = self:GetAbility()
if not ability then
return 0
end
local reducePerStack = ability:GetSpecialValueFor("permanent_magic_resist_reduce_per_hit")
return -reducePerStack * self:GetStackCount()
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.OnTooltip(self)
local ability = self:GetAbility()
if not ability then
return 0
end
return -ability:GetSpecialValueFor("permanent_magic_resist_reduce_per_hit") * self:GetStackCount()
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.GetEffectName(self)
return "particles/items4_fx/nullifier_mute_debuff.vpcf"
end
function modifier_boss_nevermore_requiem_magic_resist_debuff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_boss_nevermore_requiem_magic_resist_debuff = __TS__Decorate(
modifier_boss_nevermore_requiem_magic_resist_debuff,
modifier_boss_nevermore_requiem_magic_resist_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_boss_nevermore_requiem_magic_resist_debuff"}
)
____exports.modifier_boss_nevermore_requiem_magic_resist_debuff = modifier_boss_nevermore_requiem_magic_resist_debuff
return ____exports
@@ -0,0 +1,242 @@
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 registerModifier = ____dota_ts_adapter.registerModifier
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
local registerAbility = ____dota_ts_adapter.registerAbility
____exports.sheep_coil = __TS__Class()
local sheep_coil = ____exports.sheep_coil
sheep_coil.name = "sheep_coil"
sheep_coil.____file_path = "scripts/vscripts/abilities/creep/sheep_coil.lua"
__TS__ClassExtends(sheep_coil, BaseAbility)
function sheep_coil.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function sheep_coil.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local cursorPt = self:GetCursorPosition()
local targetPoint = GetGroundPosition(cursorPt, nil)
local spawnOrigin
do
local function ____catch()
spawnOrigin = caster:GetAbsOrigin()
end
local ____try = pcall(function()
local attachId = caster:ScriptLookupAttachment("attach_attack1")
if attachId ~= nil and attachId >= 0 then
spawnOrigin = caster:GetAttachmentOrigin(attachId)
else
spawnOrigin = caster:GetAbsOrigin()
end
end)
if not ____try then
____catch()
end
end
local projectileSpeed = self:GetSpecialValueFor("projectile_speed")
local direction = targetPoint - spawnOrigin
direction.z = 0
local directionLength = math.sqrt(direction.x * direction.x + direction.y * direction.y)
if directionLength < 0.01 then
return
end
direction = direction:Normalized()
local distance = directionLength
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_abaddon/abaddon_death_coil.vpcf", PATTACH_CUSTOMORIGIN, nil)
ParticleManager:SetParticleControl(particle, 0, spawnOrigin)
ParticleManager:SetParticleControl(particle, 1, targetPoint)
ParticleManager:SetParticleControl(
particle,
2,
Vector(projectileSpeed, 0, 0)
)
ParticleManager:SetParticleControl(
particle,
3,
Vector(distance, 0, 0)
)
ParticleManager:SetParticleControl(
particle,
4,
Vector(0, 0, 0)
)
ParticleManager:SetParticleControl(particle, 9, spawnOrigin)
ParticleManager:SetParticleControl(particle, 13, direction)
self.projectile_particle = particle
self.projectile_start_pos = spawnOrigin
self.projectile_target_pos = targetPoint
self.projectile_direction = direction
self.projectile_speed = projectileSpeed
self.projectile_distance = distance
local info = {
Ability = self,
EffectName = "",
vSpawnOrigin = spawnOrigin,
fDistance = distance,
fStartRadius = 0,
fEndRadius = 0,
Source = caster,
bHasFrontalCone = false,
bReplaceExisting = false,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
fExpireTime = GameRules:GetGameTime() + 10,
bDeleteOnHit = true,
vVelocity = direction * projectileSpeed,
iMoveSpeed = projectileSpeed,
bProvidesVision = true,
iVisionRadius = 200,
iVisionTeamNumber = caster:GetTeamNumber()
}
ProjectileManager:CreateLinearProjectile(info)
Timers:CreateTimer(
distance / projectileSpeed + 0.1,
function()
if self.projectile_particle ~= nil then
ParticleManager:DestroyParticle(self.projectile_particle, false)
ParticleManager:ReleaseParticleIndex(self.projectile_particle)
self.projectile_particle = nil
end
return nil
end
)
self.target_point = targetPoint
local travelTime = distance / projectileSpeed
Timers:CreateTimer(
travelTime,
function()
if not self.projectile_hit then
self:OnProjectileHit(nil, targetPoint)
end
return nil
end
)
local effectCast = ParticleManager:CreateParticle("particles/units/heroes/hero_abaddon/abaddon_death_coil_abaddon.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:ReleaseParticleIndex(effectCast)
EmitSoundOn("Hero_Abaddon.DeathCoil.Cast", caster)
end
function sheep_coil.prototype.OnProjectileThink(self, location)
if self.projectile_particle ~= nil then
local currentPos = GetGroundPosition(location, nil)
ParticleManager:SetParticleControl(self.projectile_particle, 0, currentPos)
ParticleManager:SetParticleControl(self.projectile_particle, 9, currentPos)
local startPos = self.projectile_start_pos
local targetPos = self.projectile_target_pos
local totalDist = self.projectile_distance
local currentDist = math.sqrt((currentPos.x - startPos.x) * (currentPos.x - startPos.x) + (currentPos.y - startPos.y) * (currentPos.y - startPos.y))
local progress = math.min(currentDist / totalDist, 1)
ParticleManager:SetParticleControl(
self.projectile_particle,
3,
Vector(totalDist * (1 - progress), 0, 0)
)
end
end
function sheep_coil.prototype.OnProjectileHit(self, target, location)
self.projectile_hit = true
if self.projectile_particle ~= nil then
ParticleManager:DestroyParticle(self.projectile_particle, false)
ParticleManager:ReleaseParticleIndex(self.projectile_particle)
self.projectile_particle = nil
end
local caster = self:GetCaster()
local slow_duration = self:GetSpecialValueFor("slow_duration")
local radius = self:GetSpecialValueFor("radius")
local hitPoint = self.target_point or location
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
hitPoint,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, unit in ipairs(units) do
ApplyDamage({
victim = unit,
attacker = caster,
damage = caster:GetAttackDamage(),
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local existingModifier = unit:FindModifierByName("modifier_sheep_coil_slow")
if existingModifier then
existingModifier:IncrementStackCount()
existingModifier:SetDuration(slow_duration, true)
else
local modifier = unit:AddNewModifier(caster, self, "modifier_sheep_coil_slow", {duration = slow_duration})
if modifier ~= nil then
modifier:SetStackCount(1)
end
end
EmitSoundOn("Hero_Abaddon.DeathCoil.Target", unit)
end
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_abaddon/abaddon_death_coil_explosion.vpcf", PATTACH_CUSTOMORIGIN, nil)
ParticleManager:SetParticleControl(particle, 0, hitPoint)
ParticleManager:SetParticleControl(
particle,
1,
Vector(radius, 0, 0)
)
ParticleManager:ReleaseParticleIndex(particle)
return true
end
function sheep_coil.prototype.GetAbilityTextureName(self)
return "abaddon_death_coil"
end
sheep_coil = __TS__Decorate(
sheep_coil,
sheep_coil,
{registerAbility(nil)},
{kind = "class", name = "sheep_coil"}
)
____exports.sheep_coil = sheep_coil
____exports.modifier_sheep_coil_slow = __TS__Class()
local modifier_sheep_coil_slow = ____exports.modifier_sheep_coil_slow
modifier_sheep_coil_slow.name = "modifier_sheep_coil_slow"
modifier_sheep_coil_slow.____file_path = "scripts/vscripts/abilities/creep/sheep_coil.lua"
__TS__ClassExtends(modifier_sheep_coil_slow, BaseModifier)
function modifier_sheep_coil_slow.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_sheep_coil_slow.prototype.GetModifierMoveSpeedBonus_Percentage(self)
local ability = self:GetAbility()
if not ability then
return 0
end
return ability:GetSpecialValueFor("movement_slow") * self:GetStackCount()
end
function modifier_sheep_coil_slow.prototype.OnCreated(self)
if not IsServer() then
return
end
end
function modifier_sheep_coil_slow.prototype.GetEffectName(self)
return "particles/items4_fx/nullifier_slow.vpcf"
end
function modifier_sheep_coil_slow.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_sheep_coil_slow.prototype.RemoveOnDeath(self)
return true
end
function modifier_sheep_coil_slow.prototype.IsPurgable(self)
return true
end
modifier_sheep_coil_slow = __TS__Decorate(
modifier_sheep_coil_slow,
modifier_sheep_coil_slow,
{registerModifier(nil)},
{kind = "class", name = "modifier_sheep_coil_slow"}
)
____exports.modifier_sheep_coil_slow = modifier_sheep_coil_slow
return ____exports
@@ -0,0 +1,91 @@
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 registerModifier = ____dota_ts_adapter.registerModifier
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
local registerAbility = ____dota_ts_adapter.registerAbility
____exports.skeleton_archer_fire_arrow = __TS__Class()
local skeleton_archer_fire_arrow = ____exports.skeleton_archer_fire_arrow
skeleton_archer_fire_arrow.name = "skeleton_archer_fire_arrow"
skeleton_archer_fire_arrow.____file_path = "scripts/vscripts/abilities/creep/skeleton_archer.lua"
__TS__ClassExtends(skeleton_archer_fire_arrow, BaseAbility)
function skeleton_archer_fire_arrow.prototype.GetIntrinsicModifierName(self)
return "modifier_skeleton_archer_fire_arrow"
end
skeleton_archer_fire_arrow = __TS__Decorate(
skeleton_archer_fire_arrow,
skeleton_archer_fire_arrow,
{registerAbility(nil)},
{kind = "class", name = "skeleton_archer_fire_arrow"}
)
____exports.skeleton_archer_fire_arrow = skeleton_archer_fire_arrow
____exports.modifier_skeleton_archer_fire_arrow = __TS__Class()
local modifier_skeleton_archer_fire_arrow = ____exports.modifier_skeleton_archer_fire_arrow
modifier_skeleton_archer_fire_arrow.name = "modifier_skeleton_archer_fire_arrow"
modifier_skeleton_archer_fire_arrow.____file_path = "scripts/vscripts/abilities/creep/skeleton_archer.lua"
__TS__ClassExtends(modifier_skeleton_archer_fire_arrow, BaseModifier)
function modifier_skeleton_archer_fire_arrow.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.bonusDamage = 0
end
function modifier_skeleton_archer_fire_arrow.prototype.IsHidden(self)
return true
end
function modifier_skeleton_archer_fire_arrow.prototype.IsPurgable(self)
return false
end
function modifier_skeleton_archer_fire_arrow.prototype.OnCreated(self, params)
if not IsServer() then
return
end
if not self:GetAbility() then
return
end
self.bonusDamage = self:GetAbility():GetSpecialValueFor("bonus_damage")
end
function modifier_skeleton_archer_fire_arrow.prototype.OnRefresh(self, params)
if not IsServer() then
return
end
if not self:GetAbility() then
return
end
self.bonusDamage = self:GetAbility():GetSpecialValueFor("bonus_damage")
end
function modifier_skeleton_archer_fire_arrow.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_skeleton_archer_fire_arrow.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
if event.attacker ~= self:GetParent() then
return
end
if not event.target then
return
end
if not event.target:IsAlive() then
return
end
ApplyDamage({
victim = event.target,
attacker = event.attacker,
damage = self.bonusDamage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self:GetAbility()
})
end
modifier_skeleton_archer_fire_arrow = __TS__Decorate(
modifier_skeleton_archer_fire_arrow,
modifier_skeleton_archer_fire_arrow,
{registerModifier(nil)},
{kind = "class", name = "modifier_skeleton_archer_fire_arrow"}
)
____exports.modifier_skeleton_archer_fire_arrow = modifier_skeleton_archer_fire_arrow
return ____exports
@@ -0,0 +1,123 @@
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 registerAbility = ____dota_ts_adapter.registerAbility
____exports.thief_arrow = __TS__Class()
local thief_arrow = ____exports.thief_arrow
thief_arrow.name = "thief_arrow"
thief_arrow.____file_path = "scripts/vscripts/abilities/creep/thief_arrow.lua"
__TS__ClassExtends(thief_arrow, BaseAbility)
function thief_arrow.prototype.Precache(self, context)
PrecacheResource("soundfile", "sounds/units/heroes/mirana/arrow.vsnd", context)
PrecacheResource("soundfile", "sounds/units/heroes/mirana/arrow_target.vsnd", context)
PrecacheResource("particle", "particles/units/heroes/hero_phantom_assassin/phantom_assassin_crit_impact.vpcf", context)
end
function thief_arrow.prototype.OnAbilityPhaseStart(self)
if IsServer() then
self:GetCaster():StartGestureWithPlaybackRate(ACT_DOTA_ATTACK, 0.5)
self.preParticle = ParticleManager:CreateParticle(
"particles/darkmoon_creep_warning.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetCaster()
)
ParticleManager:SetParticleControlEnt(
self.preParticle,
0,
self:GetCaster(),
PATTACH_ABSORIGIN_FOLLOW,
"",
self:GetCaster():GetOrigin(),
true
)
ParticleManager:SetParticleControl(
self.preParticle,
1,
Vector(100, 100, 100)
)
end
return true
end
function thief_arrow.prototype.OnAbilityPhaseInterrupted(self)
if IsClient() or not self.preParticle then
return
end
self:GetCaster():FadeGesture(ACT_DOTA_ATTACK)
ParticleManager:DestroyParticle(self.preParticle, false)
end
function thief_arrow.prototype.OnSpellStart(self)
if self.preParticle then
ParticleManager:DestroyParticle(self.preParticle, false)
end
self:GetCaster():FadeGesture(ACT_DOTA_ATTACK)
local caster = self:GetCaster()
local origin = caster:GetOrigin()
local point = self:GetCursorPosition()
local projectile_speed = self:GetSpecialValueFor("arrow_speed")
local projectile_distance = self:GetSpecialValueFor("arrow_range")
local projectile_start_radius = self:GetSpecialValueFor("arrow_width")
local projectile_end_radius = self:GetSpecialValueFor("arrow_width")
local projectile_direction = Vector(point.x - origin.x, point.y - origin.y, 0):Normalized()
ProjectileManager:CreateLinearProjectile({
Source = caster,
Ability = self,
vSpawnOrigin = caster:GetOrigin(),
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
EffectName = "particles/units/heroes/hero_mirana/mirana_spell_arrow.vpcf",
fDistance = projectile_distance,
fStartRadius = projectile_start_radius,
fEndRadius = projectile_end_radius,
vVelocity = projectile_direction * projectile_speed,
bHasFrontalCone = false,
fExpireTime = GameRules:GetGameTime() + 10
})
self:EmitSound("Hero_Mirana.ArrowCast")
end
function thief_arrow.prototype.OnProjectileHit_ExtraData(self, target, location)
if not target then
return
end
local effect_cast = ParticleManager:CreateParticle("particles/units/heroes/hero_phantom_assassin/phantom_assassin_crit_impact.vpcf", PATTACH_POINT_FOLLOW, target)
ParticleManager:SetParticleControlEnt(
effect_cast,
0,
target,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
target:GetOrigin(),
true
)
ParticleManager:SetParticleControl(
effect_cast,
1,
target:GetAbsOrigin()
)
ParticleManager:SetParticleControlForward(
effect_cast,
1,
(self:GetCaster():GetOrigin() - target:GetOrigin()):Normalized()
)
ParticleManager:ReleaseParticleIndex(effect_cast)
ApplyDamage({
victim = target,
attacker = self:GetCaster(),
damage = self:GetCaster():GetAttackDamage(),
damage_type = DAMAGE_TYPE_PHYSICAL,
ability = self
})
EmitSoundOn("Hero_Mirana.ArrowImpact", target)
return true
end
thief_arrow = __TS__Decorate(
thief_arrow,
thief_arrow,
{registerAbility(nil)},
{kind = "class", name = "thief_arrow"}
)
____exports.thief_arrow = thief_arrow
return ____exports
+844
View File
@@ -0,0 +1,844 @@
local ____lualib = require("lualib_bundle")
local __TS__NumberIsFinite = ____lualib.__TS__NumberIsFinite
local __TS__ArraySort = ____lualib.__TS__ArraySort
local Map = ____lualib.Map
local __TS__New = ____lualib.__TS__New
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local ____exports = {}
local clampToxinPoolRadius, toxinIsValidUnit, isToxinPoolThinker, toxinIsValidAbility, toxinPoolsOverlap, getToxinPoolRadiusForThinker, getToxinPoolMergeStackForThinker, getToxinDamagePerTickForThinker, getToxinPoolRemainingDuration, toxinDistSqHoriz, buildToxinOverlapCluster, computeMergedPoolStats, toxinSortDedupeEntIndices, toxinEnqueuePoolMergeForThinker, toxinDrainToxinMergeQueueFrame, toxinTryResolvePoolMergeForThinkerIndex, TOXIN_POOL_MODIFIER_NAME, TOXIN_MERGE_SCAN_RADIUS, TOXIN_MERGE_OVERLAP_EPSILON, TOXIN_THINKER_CLASS, TOXIN_POOL_MAX_RADIUS, TOXIN_MAX_MERGE_SCAN_THINKERS, toxinMergeQueue, toxinMergeDrainScheduled, toxinIsDrainingMerge
local ____difficulty_manager = require("difficulty_manager")
local Difficulty = ____difficulty_manager.Difficulty
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 ____creep_render_color = require("utils.creep_render_color")
local trySetIntrinsicCreepRenderColor = ____creep_render_color.trySetIntrinsicCreepRenderColor
local ____entity_radius = require("utils.entity_radius")
local findAllByClassnameInRadius = ____entity_radius.findAllByClassnameInRadius
function clampToxinPoolRadius(self, r)
return math.max(
1,
math.min(r, TOXIN_POOL_MAX_RADIUS)
)
end
function toxinIsValidUnit(self, unit)
return unit ~= nil and unit ~= nil and not unit:IsNull() and IsValidEntity(unit)
end
function isToxinPoolThinker(self, unit)
return toxinIsValidUnit(nil, unit) and unit:GetClassname() == TOXIN_THINKER_CLASS
end
function toxinIsValidAbility(self, ab)
return ab ~= nil and ab ~= nil and not ab:IsNull() and IsValidEntity(ab)
end
function toxinPoolsOverlap(self, centerA, radiusA, centerB, radiusB)
local dx = centerA.x - centerB.x
local dy = centerA.y - centerB.y
local dist = math.sqrt(dx * dx + dy * dy)
return dist <= radiusA + radiusB + TOXIN_MERGE_OVERLAP_EPSILON
end
function getToxinPoolRadiusForThinker(self, thinker, poolMod, ability)
if not toxinIsValidAbility(nil, ability) then
return 0
end
local raw
if poolMod and poolMod.effectiveRadius > 0 then
raw = poolMod.effectiveRadius
else
raw = ability:GetSpecialValueFor("radius")
end
return clampToxinPoolRadius(nil, raw)
end
function getToxinPoolMergeStackForThinker(self, poolMod, _ability)
if poolMod ~= nil and poolMod.poolMergeStackCount > 0 then
return math.floor(poolMod.poolMergeStackCount)
end
return 1
end
function getToxinDamagePerTickForThinker(self, poolMod, ability)
if not toxinIsValidAbility(nil, ability) then
return 0
end
if poolMod and poolMod.damagePerTick > 0 then
return poolMod.damagePerTick
end
return ability:GetSpecialValueFor("damage") * 0.33
end
function getToxinPoolRemainingDuration(self, poolMod, fallbackDuration)
local getter = poolMod.GetRemainingTime
if getter ~= nil then
local v = getter(poolMod)
if type(v) == "number" and __TS__NumberIsFinite(v) then
return math.max(0, v)
end
end
return math.max(0, fallbackDuration)
end
function toxinDistSqHoriz(self, ax, bx)
local dx = ax.x - bx.x
local dy = ax.y - bx.y
return dx * dx + dy * dy
end
function buildToxinOverlapCluster(self, seed, ability)
if not toxinIsValidUnit(nil, seed) or not toxinIsValidAbility(nil, ability) then
return {}
end
local seedTeam = seed:GetTeamNumber()
local origin = seed:GetAbsOrigin()
local raw = findAllByClassnameInRadius("npc_dota_thinker", origin, TOXIN_MERGE_SCAN_RADIUS)
local toxinThinkers = {}
for ____, ent in ipairs(raw) do
do
local npc = ent
if not toxinIsValidUnit(nil, npc) then
goto __continue22
end
if npc:GetTeamNumber() ~= seedTeam then
goto __continue22
end
if not npc:FindModifierByName(TOXIN_POOL_MODIFIER_NAME) then
goto __continue22
end
toxinThinkers[#toxinThinkers + 1] = npc
end
::__continue22::
end
if #toxinThinkers > TOXIN_MAX_MERGE_SCAN_THINKERS then
__TS__ArraySort(
toxinThinkers,
function(____, a, b) return toxinDistSqHoriz(
nil,
a:GetAbsOrigin(),
origin
) - toxinDistSqHoriz(
nil,
b:GetAbsOrigin(),
origin
) end
)
while #toxinThinkers > TOXIN_MAX_MERGE_SCAN_THINKERS do
table.remove(toxinThinkers)
end
end
local cluster = {}
local visited = __TS__New(Map)
local queue = {seed}
while #queue > 0 do
do
local cur = table.remove(queue)
if not toxinIsValidUnit(nil, cur) then
goto __continue30
end
local idx = cur:GetEntityIndex()
if visited:get(idx) then
goto __continue30
end
visited:set(idx, true)
cluster[#cluster + 1] = cur
local curMod = cur:FindModifierByName(TOXIN_POOL_MODIFIER_NAME)
local rCur = getToxinPoolRadiusForThinker(nil, cur, curMod, ability)
local pCur = cur:GetAbsOrigin()
for ____, other in ipairs(toxinThinkers) do
do
if not toxinIsValidUnit(nil, other) then
goto __continue33
end
local oIdx = other:GetEntityIndex()
if visited:get(oIdx) then
goto __continue33
end
local oMod = other:FindModifierByName(TOXIN_POOL_MODIFIER_NAME)
local rO = getToxinPoolRadiusForThinker(nil, other, oMod, ability)
if toxinPoolsOverlap(
nil,
pCur,
rCur,
other:GetAbsOrigin(),
rO
) then
queue[#queue + 1] = other
end
end
::__continue33::
end
end
::__continue30::
end
return cluster
end
function computeMergedPoolStats(self, cluster, ability)
if not toxinIsValidAbility(nil, ability) then
return {
centroid = Vector(0, 0, 0),
damagePerTick = 0,
radius = 1,
duration = 0.05,
mergeStackCount = 1
}
end
local valid = __TS__ArrayFilter(
cluster,
function(____, t) return toxinIsValidUnit(nil, t) end
)
local n = #valid
if n <= 0 then
local baseRadius = ability:GetSpecialValueFor("radius")
local baseDur = ability:GetSpecialValueFor("duration")
return {
centroid = Vector(0, 0, 0),
damagePerTick = ability:GetSpecialValueFor("damage") * 0.33,
radius = clampToxinPoolRadius(nil, baseRadius),
duration = math.max(0.05, baseDur),
mergeStackCount = 1
}
end
local baseDuration = ability:GetSpecialValueFor("duration")
local radiusBonusPerMerge = math.max(
0,
ability:GetSpecialValueFor("merge_radius_bonus")
)
local durationBonusPerMerge = math.max(
0,
ability:GetSpecialValueFor("merge_duration_bonus")
)
local sumR2 = 0
local sumDmg = 0
local sumStacks = 0
local maxRem = 0
local sx = 0
local sy = 0
local sz = 0
for ____, t in ipairs(valid) do
local mod = t:FindModifierByName(TOXIN_POOL_MODIFIER_NAME)
local r = getToxinPoolRadiusForThinker(nil, t, mod, ability)
sumR2 = sumR2 + r * r
sumDmg = sumDmg + getToxinDamagePerTickForThinker(nil, mod, ability)
sumStacks = sumStacks + getToxinPoolMergeStackForThinker(nil, mod, ability)
local p = t:GetAbsOrigin()
sx = sx + p.x
sy = sy + p.y
sz = sz + p.z
if mod then
maxRem = math.max(
maxRem,
getToxinPoolRemainingDuration(nil, mod, baseDuration)
)
else
maxRem = math.max(maxRem, baseDuration)
end
end
local mergedRadiusUncapped = math.max(
1,
math.sqrt(sumR2) + math.max(0, n - 1) * radiusBonusPerMerge
)
local mergedRadius = clampToxinPoolRadius(nil, mergedRadiusUncapped)
local mergedDuration = math.max(
0.05,
maxRem + math.max(0, n - 1) * durationBonusPerMerge
)
return {
centroid = Vector(sx / n, sy / n, sz / n),
damagePerTick = sumDmg,
radius = mergedRadius,
duration = mergedDuration,
mergeStackCount = math.max(1, sumStacks)
}
end
function toxinSortDedupeEntIndices(self, arr)
if #arr <= 1 then
return arr
end
local sorted = {unpack(arr)}
__TS__ArraySort(
sorted,
function(____, a, b) return a - b end
)
local out = {}
local prev = -2147483648
for ____, x in ipairs(sorted) do
local n = x
if n ~= prev then
out[#out + 1] = x
prev = n
end
end
return out
end
function toxinEnqueuePoolMergeForThinker(self, entIndex)
if not IsServer() then
return
end
toxinMergeQueue[#toxinMergeQueue + 1] = entIndex
if toxinMergeDrainScheduled or toxinIsDrainingMerge then
return
end
toxinMergeDrainScheduled = true
Timers:CreateTimer(0, toxinDrainToxinMergeQueueFrame)
end
function toxinDrainToxinMergeQueueFrame(self)
if not IsServer() then
return
end
toxinIsDrainingMerge = true
toxinMergeDrainScheduled = false
local batch = toxinMergeQueue
toxinMergeQueue = {}
local uniq = toxinSortDedupeEntIndices(nil, batch)
for ____, idx in ipairs(uniq) do
toxinTryResolvePoolMergeForThinkerIndex(nil, idx)
end
toxinIsDrainingMerge = false
if #toxinMergeQueue > 0 then
toxinMergeDrainScheduled = true
Timers:CreateTimer(0, toxinDrainToxinMergeQueueFrame)
end
end
function toxinTryResolvePoolMergeForThinkerIndex(self, entIndex)
if not IsServer() then
return
end
local npc = EntIndexToHScript(entIndex)
if not isToxinPoolThinker(nil, npc) then
return
end
local buff = npc:FindModifierByName(TOXIN_POOL_MODIFIER_NAME)
if not buff then
return
end
local poolMod = buff
local abilityRaw = buff:GetAbility()
if not toxinIsValidAbility(nil, abilityRaw) then
return
end
local ability = abilityRaw
local caster = buff:GetCaster()
if not toxinIsValidUnit(nil, caster) then
return
end
local cluster = buildToxinOverlapCluster(nil, npc, ability)
if #cluster < 2 then
poolMod:initializeSinglePoolFromAbility()
return
end
local mergeLeader
local minIdx = 2147483647
for ____, t in ipairs(cluster) do
do
if not toxinIsValidUnit(nil, t) then
goto __continue141
end
local ei = t:GetEntityIndex()
if ei < minIdx then
minIdx = ei
mergeLeader = t
end
end
::__continue141::
end
if not mergeLeader or not toxinIsValidUnit(nil, mergeLeader) then
return
end
if npc:GetEntityIndex() ~= mergeLeader:GetEntityIndex() then
toxinEnqueuePoolMergeForThinker(
nil,
mergeLeader:GetEntityIndex()
)
return
end
local merged = computeMergedPoolStats(nil, cluster, ability)
local spawnParams = {duration = merged.duration, merged_damage_per_tick = merged.damagePerTick, merged_radius = merged.radius, merged_stack_count = merged.mergeStackCount}
for ____, t in ipairs(cluster) do
if toxinIsValidUnit(nil, t) then
UTIL_Remove(t)
end
end
if not toxinIsValidAbility(nil, ability) or not toxinIsValidUnit(nil, caster) then
return
end
CreateModifierThinker(
caster,
ability,
TOXIN_POOL_MODIFIER_NAME,
spawnParams,
merged.centroid,
caster:GetTeamNumber(),
false
)
end
TOXIN_POOL_MODIFIER_NAME = "modifier_spider_nethertoxin_lua"
TOXIN_MERGE_SCAN_RADIUS = 2400
TOXIN_MERGE_OVERLAP_EPSILON = 12
TOXIN_THINKER_CLASS = "npc_dota_thinker"
TOXIN_POOL_MAX_RADIUS = 900
TOXIN_MAX_MERGE_SCAN_THINKERS = 220
toxinMergeQueue = {}
toxinMergeDrainScheduled = false
toxinIsDrainingMerge = false
____exports.toxin = __TS__Class()
local toxin = ____exports.toxin
toxin.name = "toxin"
toxin.____file_path = "scripts/vscripts/abilities/creep/toxin.lua"
__TS__ClassExtends(toxin, BaseAbility)
function toxin.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_alchemist/alchemist_acid_spray.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_viper/viper_nethertoxin.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_viper/viper_nethertoxin_debuff.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_broodmother.vsndevts", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_viper.vsndevts", context)
end
function toxin.prototype.GetIntrinsicModifierName(self)
return "modifier_spider_toxin_death_listener"
end
toxin = __TS__Decorate(
toxin,
toxin,
{registerAbility(nil)},
{kind = "class", name = "toxin"}
)
____exports.toxin = toxin
____exports.modifier_spider_toxin_death_listener = __TS__Class()
local modifier_spider_toxin_death_listener = ____exports.modifier_spider_toxin_death_listener
modifier_spider_toxin_death_listener.name = "modifier_spider_toxin_death_listener"
modifier_spider_toxin_death_listener.____file_path = "scripts/vscripts/abilities/creep/toxin.lua"
__TS__ClassExtends(modifier_spider_toxin_death_listener, BaseModifier)
function modifier_spider_toxin_death_listener.prototype.IsHidden(self)
return true
end
function modifier_spider_toxin_death_listener.prototype.IsPurgable(self)
return false
end
function modifier_spider_toxin_death_listener.prototype.OnCreated(self, _params)
if not IsServer() then
return
end
local parent = self:GetParent()
if not toxinIsValidUnit(nil, parent) then
return
end
trySetIntrinsicCreepRenderColor(
nil,
parent,
51,
102,
0
)
end
function modifier_spider_toxin_death_listener.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_DEATH}
end
function modifier_spider_toxin_death_listener.prototype.OnDeath(self, event)
if not IsServer() then
return
end
if event.unit ~= self:GetParent() then
return
end
local ability = self:GetAbility()
if not toxinIsValidAbility(nil, ability) then
return
end
local caster = self:GetCaster()
if not toxinIsValidUnit(nil, caster) then
return
end
local parent = self:GetParent()
local spawnOrigin = parent:GetAbsOrigin()
local duration = ability:GetSpecialValueFor("duration")
local radius = clampToxinPoolRadius(
nil,
ability:GetSpecialValueFor("radius")
)
local splashPfx = ParticleManager:CreateParticle("particles/units/heroes/hero_alchemist/alchemist_acid_spray.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(splashPfx, 0, spawnOrigin)
ParticleManager:SetParticleControl(
splashPfx,
1,
Vector(radius, 1, 1)
)
ParticleManager:SetParticleControl(
splashPfx,
15,
Vector(255, 153, 102)
)
ParticleManager:SetParticleControl(
splashPfx,
16,
Vector(1, 0, 0)
)
Timers:CreateTimer(
4,
function()
if not IsServer() then
return
end
ParticleManager:DestroyParticle(splashPfx, false)
ParticleManager:ReleaseParticleIndex(splashPfx)
end
)
EmitSoundOn("Hero_Broodmother.SpawnSpiderlings", parent)
CreateModifierThinker(
caster,
ability,
TOXIN_POOL_MODIFIER_NAME,
{duration = duration},
spawnOrigin,
caster:GetTeamNumber(),
false
)
end
modifier_spider_toxin_death_listener = __TS__Decorate(
modifier_spider_toxin_death_listener,
modifier_spider_toxin_death_listener,
{registerModifier(nil)},
{kind = "class", name = "modifier_spider_toxin_death_listener"}
)
____exports.modifier_spider_toxin_death_listener = modifier_spider_toxin_death_listener
____exports.modifier_spider_nethertoxin_lua = __TS__Class()
local modifier_spider_nethertoxin_lua = ____exports.modifier_spider_nethertoxin_lua
modifier_spider_nethertoxin_lua.name = "modifier_spider_nethertoxin_lua"
modifier_spider_nethertoxin_lua.____file_path = "scripts/vscripts/abilities/creep/toxin.lua"
__TS__ClassExtends(modifier_spider_nethertoxin_lua, BaseModifier)
function modifier_spider_nethertoxin_lua.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.effectiveRadius = 0
self.damagePerTick = 0
self.poolMergeStackCount = 0
self.auraPenaltyStack = 1
self.damageTable = {}
end
function modifier_spider_nethertoxin_lua.prototype.GetTexture(self)
return "viper_nethertoxin"
end
function modifier_spider_nethertoxin_lua.prototype.IsHidden(self)
return false
end
function modifier_spider_nethertoxin_lua.prototype.IsDebuff(self)
return true
end
function modifier_spider_nethertoxin_lua.prototype.IsStunDebuff(self)
return false
end
function modifier_spider_nethertoxin_lua.prototype.IsPurgable(self)
return false
end
function modifier_spider_nethertoxin_lua.prototype.initializeAuraVictimDebuff(self)
local ability = self:GetAbility()
if toxinIsValidAbility(nil, ability) then
self:SetDuration(
math.max(
0.05,
self:GetAuraDuration()
),
true
)
end
self.effectiveRadius = 0
self.damagePerTick = 0
self.poolMergeStackCount = 0
if IsServer() then
self:syncAuraPenaltyFromCasterThinker()
self:SetStackCount(math.max(
1,
math.floor(self.auraPenaltyStack)
))
end
end
function modifier_spider_nethertoxin_lua.prototype.syncAuraPenaltyFromCasterThinker(self)
local parent = self:GetParent()
if isToxinPoolThinker(nil, parent) then
return
end
local source = self:GetCaster()
if not toxinIsValidUnit(nil, source) then
return
end
local srcMod = source:FindModifierByName(TOXIN_POOL_MODIFIER_NAME)
if srcMod ~= nil and srcMod.poolMergeStackCount > 0 then
self.auraPenaltyStack = math.floor(srcMod.poolMergeStackCount)
else
self.auraPenaltyStack = math.max(1, self.auraPenaltyStack)
end
end
function modifier_spider_nethertoxin_lua.prototype.initializeSinglePoolFromAbility(self)
local ability = self:GetAbility()
local caster = self:GetCaster()
local parent = self:GetParent()
if not toxinIsValidAbility(nil, ability) or not toxinIsValidUnit(nil, caster) or not toxinIsValidUnit(nil, parent) then
return
end
local baseDamage = ability:GetSpecialValueFor("damage")
local baseRadius = ability:GetSpecialValueFor("radius")
local baseDuration = ability:GetSpecialValueFor("duration")
self.damagePerTick = (baseDamage + self:GetCaster():GetAttackDamage() * 0.15) * 0.33
local totaldamage = self:GetParent():IsRangedAttacker() and self.damagePerTick or self.damagePerTick * 0.25
self.effectiveRadius = clampToxinPoolRadius(nil, baseRadius)
self.poolMergeStackCount = 1
self:SetDuration(
math.max(0.05, baseDuration),
true
)
self.damageTable = {
victim = caster,
attacker = caster,
damage = totaldamage,
damage_type = ability:GetAbilityDamageType(),
ability = ability
}
self:StartIntervalThink(0.33)
self:PlayEffects()
end
function modifier_spider_nethertoxin_lua.prototype.initializeMergedPoolFromParams(self, params)
local ability = self:GetAbility()
local caster = self:GetCaster()
local parent = self:GetParent()
if not toxinIsValidAbility(nil, ability) or not toxinIsValidUnit(nil, caster) or not toxinIsValidUnit(nil, parent) then
return
end
self.damagePerTick = params.merged_damage_per_tick
self.effectiveRadius = clampToxinPoolRadius(nil, params.merged_radius)
self.poolMergeStackCount = math.max(
1,
math.floor(params.merged_stack_count or 1)
)
self:SetDuration(
math.max(0.05, params.duration),
true
)
self.damageTable = {
victim = caster,
attacker = caster,
damage = self.damagePerTick,
damage_type = ability:GetAbilityDamageType(),
ability = ability
}
self:StartIntervalThink(0.33)
self:PlayEffects()
end
function modifier_spider_nethertoxin_lua.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
if not isToxinPoolThinker(nil, parent) then
self:initializeAuraVictimDebuff()
return
end
local p = params
if p.merged_damage_per_tick ~= nil and p.merged_radius ~= nil and p.duration ~= nil then
self:initializeMergedPoolFromParams(p)
return
end
toxinEnqueuePoolMergeForThinker(
nil,
parent:GetEntityIndex()
)
end
function modifier_spider_nethertoxin_lua.prototype.OnRefresh(self, _params)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not toxinIsValidAbility(nil, ability) then
return
end
if not isToxinPoolThinker(
nil,
self:GetParent()
) then
self:syncAuraPenaltyFromCasterThinker()
self:SetStackCount(math.max(
1,
math.floor(self.auraPenaltyStack)
))
return
end
self.damageTable.damage = self.damagePerTick
self.damageTable.damage_type = ability:GetAbilityDamageType()
end
function modifier_spider_nethertoxin_lua.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS, MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS}
end
function modifier_spider_nethertoxin_lua.prototype.GetModifierPhysicalArmorBonus(self)
local parent = self:GetParent()
if isToxinPoolThinker(nil, parent) then
return 0
end
local ability = self:GetAbility()
if not toxinIsValidAbility(nil, ability) then
return 0
end
local per = math.max(
0,
ability:GetSpecialValueFor("armor_magic_reduce_per_stack")
)
local scale = Difficulty:getNpcStatScale()
return -per * math.max(
1,
math.floor(self.auraPenaltyStack)
) * scale
end
function modifier_spider_nethertoxin_lua.prototype.GetModifierMagicalResistanceBonus(self)
local parent = self:GetParent()
if isToxinPoolThinker(nil, parent) then
return 0
end
local ability = self:GetAbility()
if not toxinIsValidAbility(nil, ability) then
return 0
end
local per = math.max(
0,
ability:GetSpecialValueFor("armor_magic_reduce_per_stack")
)
local scale = Difficulty:getNpcStatScale()
return -per * math.max(
1,
math.floor(self.auraPenaltyStack)
) * scale
end
function modifier_spider_nethertoxin_lua.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if not isToxinPoolThinker(nil, parent) then
return
end
local entIndex = parent:GetEntityIndex()
Timers:CreateTimer(
0,
function()
if not IsServer() then
return
end
local npc = EntIndexToHScript(entIndex)
if not toxinIsValidUnit(nil, npc) then
return
end
if npc:GetClassname() ~= TOXIN_THINKER_CLASS then
return
end
UTIL_Remove(npc)
end
)
end
function modifier_spider_nethertoxin_lua.prototype.CheckState(self)
return {[MODIFIER_STATE_PASSIVES_DISABLED] = true}
end
function modifier_spider_nethertoxin_lua.prototype.OnIntervalThink(self)
local parent = self:GetParent()
if not isToxinPoolThinker(nil, parent) then
return
end
local caster = self:GetCaster()
local ability = self:GetAbility()
if not toxinIsValidUnit(nil, caster) or not toxinIsValidAbility(nil, ability) then
return
end
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
self.effectiveRadius,
self:GetAuraSearchTeam(),
self:GetAuraSearchType(),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
self.damageTable.attacker = caster
self.damageTable.ability = ability
self.damageTable.damage_type = ability:GetAbilityDamageType()
local damagedAny = false
for ____, unit in ipairs(units) do
do
if not toxinIsValidUnit(nil, unit) or not unit:IsAlive() then
goto __continue104
end
self.damageTable.victim = unit
ApplyDamage(self.damageTable)
damagedAny = true
end
::__continue104::
end
if damagedAny then
EmitSoundOn("Hero_Viper.NetherToxin.Damage", parent)
end
end
function modifier_spider_nethertoxin_lua.prototype.IsAura(self)
return isToxinPoolThinker(
nil,
self:GetParent()
)
end
function modifier_spider_nethertoxin_lua.prototype.GetModifierAura(self)
return TOXIN_POOL_MODIFIER_NAME
end
function modifier_spider_nethertoxin_lua.prototype.GetAuraRadius(self)
local ability = self:GetAbility()
if self.effectiveRadius > 0 then
return self.effectiveRadius
end
if toxinIsValidAbility(nil, ability) then
return clampToxinPoolRadius(
nil,
ability:GetSpecialValueFor("radius")
)
end
return 0
end
function modifier_spider_nethertoxin_lua.prototype.GetAuraDuration(self)
return 0.25
end
function modifier_spider_nethertoxin_lua.prototype.GetAuraSearchTeam(self)
return DOTA_UNIT_TARGET_TEAM_ENEMY
end
function modifier_spider_nethertoxin_lua.prototype.GetAuraSearchType(self)
return DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC
end
function modifier_spider_nethertoxin_lua.prototype.GetEffectName(self)
return "particles/units/heroes/hero_viper/viper_nethertoxin_debuff.vpcf"
end
function modifier_spider_nethertoxin_lua.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_spider_nethertoxin_lua.prototype.PlayEffects(self)
local parent = self:GetParent()
if not toxinIsValidUnit(nil, parent) then
return
end
local particle_cast = "particles/units/heroes/hero_viper/viper_nethertoxin.vpcf"
local sound_cast = "Hero_Viper.NetherToxin"
local effect_cast = ParticleManager:CreateParticle(particle_cast, PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(
effect_cast,
0,
parent:GetOrigin()
)
ParticleManager:SetParticleControl(
effect_cast,
1,
Vector(self.effectiveRadius, 1, 1)
)
self:AddParticle(
effect_cast,
false,
false,
-1,
false,
false
)
EmitSoundOn(sound_cast, parent)
end
modifier_spider_nethertoxin_lua = __TS__Decorate(
modifier_spider_nethertoxin_lua,
modifier_spider_nethertoxin_lua,
{registerModifier(nil)},
{kind = "class", name = "modifier_spider_nethertoxin_lua"}
)
____exports.modifier_spider_nethertoxin_lua = modifier_spider_nethertoxin_lua
return ____exports
@@ -0,0 +1,94 @@
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 ____difficulty_manager = require("difficulty_manager")
local Difficulty = ____difficulty_manager.Difficulty
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
--- Пассивка для волновых крипов: при здоровье ниже порога атаки лечат на долю нанесённого урона.
____exports.wave_desperate_vampirism = __TS__Class()
local wave_desperate_vampirism = ____exports.wave_desperate_vampirism
wave_desperate_vampirism.name = "wave_desperate_vampirism"
wave_desperate_vampirism.____file_path = "scripts/vscripts/abilities/creep/wave_desperate_vampirism.lua"
__TS__ClassExtends(wave_desperate_vampirism, BaseAbility)
function wave_desperate_vampirism.prototype.GetIntrinsicModifierName(self)
return "modifier_wave_desperate_vampirism"
end
function wave_desperate_vampirism.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_bloodseeker/bloodseeker_bloodbath.vpcf", context)
end
wave_desperate_vampirism = __TS__Decorate(
wave_desperate_vampirism,
wave_desperate_vampirism,
{registerAbility(nil)},
{kind = "class", name = "wave_desperate_vampirism"}
)
____exports.wave_desperate_vampirism = wave_desperate_vampirism
____exports.modifier_wave_desperate_vampirism = __TS__Class()
local modifier_wave_desperate_vampirism = ____exports.modifier_wave_desperate_vampirism
modifier_wave_desperate_vampirism.name = "modifier_wave_desperate_vampirism"
modifier_wave_desperate_vampirism.____file_path = "scripts/vscripts/abilities/creep/wave_desperate_vampirism.lua"
__TS__ClassExtends(modifier_wave_desperate_vampirism, BaseModifier)
function modifier_wave_desperate_vampirism.prototype.IsHidden(self)
return true
end
function modifier_wave_desperate_vampirism.prototype.IsDebuff(self)
return false
end
function modifier_wave_desperate_vampirism.prototype.IsPurgable(self)
return false
end
function modifier_wave_desperate_vampirism.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_wave_desperate_vampirism.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability or not parent or event.attacker ~= parent then
return
end
local target = event.target
if not target or not target:IsAlive() or target:IsBuilding() or target:IsOther() then
return
end
local thresholdPct = ability:GetSpecialValueFor("hp_threshold_pct")
if parent:GetHealthPercent() >= thresholdPct then
return
end
local vampPct = ability:GetSpecialValueFor("vamp_pct")
local damage = event.damage or 0
if damage <= 0 then
damage = parent:GetAverageTrueAttackDamage(target)
end
if damage <= 0 then
return
end
local heal = damage * vampPct / 100 * Difficulty:getNpcStatScale()
if heal <= 0 then
return
end
parent:Heal(heal, ability)
local p = ParticleManager:CreateParticle("particles/units/heroes/hero_bloodseeker/bloodseeker_bloodbath.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:SetParticleControl(
p,
0,
parent:GetAbsOrigin()
)
ParticleManager:ReleaseParticleIndex(p)
end
modifier_wave_desperate_vampirism = __TS__Decorate(
modifier_wave_desperate_vampirism,
modifier_wave_desperate_vampirism,
{registerModifier(nil)},
{kind = "class", name = "modifier_wave_desperate_vampirism"}
)
____exports.modifier_wave_desperate_vampirism = modifier_wave_desperate_vampirism
return ____exports
@@ -0,0 +1,139 @@
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 ____creep_render_color = require("utils.creep_render_color")
local trySetIntrinsicCreepRenderColor = ____creep_render_color.trySetIntrinsicCreepRenderColor
--- Пассив: усиливает юнита на bonus_pct процентов (по умолчанию 100 = удвоение по смыслу «+100%»).
-- HP/мана — плоский бонус от базового макс.; урон/IAS/мувспид/спелламп/реген HP% — через модификаторы.
____exports.wave_full_brutality = __TS__Class()
local wave_full_brutality = ____exports.wave_full_brutality
wave_full_brutality.name = "wave_full_brutality"
wave_full_brutality.____file_path = "scripts/vscripts/abilities/creep/wave_full_brutality.lua"
__TS__ClassExtends(wave_full_brutality, BaseAbility)
function wave_full_brutality.prototype.GetIntrinsicModifierName(self)
return "modifier_wave_full_brutality_passive"
end
wave_full_brutality = __TS__Decorate(
wave_full_brutality,
wave_full_brutality,
{registerAbility(nil)},
{kind = "class", name = "wave_full_brutality"}
)
____exports.wave_full_brutality = wave_full_brutality
____exports.modifier_wave_full_brutality_passive = __TS__Class()
local modifier_wave_full_brutality_passive = ____exports.modifier_wave_full_brutality_passive
modifier_wave_full_brutality_passive.name = "modifier_wave_full_brutality_passive"
modifier_wave_full_brutality_passive.____file_path = "scripts/vscripts/abilities/creep/wave_full_brutality.lua"
__TS__ClassExtends(modifier_wave_full_brutality_passive, BaseModifier)
function modifier_wave_full_brutality_passive.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.bonusPct = 100
self.effectiveBonusPct = 100
self.healthBonusFlat = 0
self.manaBonusFlat = 0
end
function modifier_wave_full_brutality_passive.prototype.IsHidden(self)
return false
end
function modifier_wave_full_brutality_passive.prototype.IsDebuff(self)
return false
end
function modifier_wave_full_brutality_passive.prototype.IsPurgable(self)
return false
end
function modifier_wave_full_brutality_passive.prototype.OnCreated(self)
local ability = self:GetAbility()
local parent = self:GetParent()
if not parent then
return
end
if IsServer() then
trySetIntrinsicCreepRenderColor(
nil,
self:GetParent(),
52,
0,
0
)
end
self.bonusPct = ability and ability:GetSpecialValueFor("bonus_pct") or 100
if self.bonusPct < 0 then
self.bonusPct = 0
end
self.effectiveBonusPct = self.bonusPct
local baseHp = math.max(
1,
parent:GetMaxHealth()
)
local baseMana = math.max(
0,
parent:GetMaxMana()
)
self.healthBonusFlat = math.floor(baseHp * (self.effectiveBonusPct / 100))
self.manaBonusFlat = math.floor(baseMana * (self.effectiveBonusPct / 100))
if IsServer() then
Timers:CreateTimer(
0,
function()
local p = self:GetParent()
if not p or not IsValidEntity(p) or not p:IsAlive() then
return nil
end
p:SetHealth(p:GetMaxHealth() * 2)
if p:GetMaxMana() > 0 then
p:SetMana(p:GetMaxMana() * 2)
end
return nil
end
)
end
end
function modifier_wave_full_brutality_passive.prototype.DeclareFunctions(self)
return {
MODIFIER_PROPERTY_HEALTH_BONUS,
MODIFIER_PROPERTY_MANA_BONUS,
MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE,
MODIFIER_PROPERTY_ATTACKSPEED_PERCENTAGE,
MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE,
MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE
}
end
function modifier_wave_full_brutality_passive.prototype.GetModifierHealthBonus(self)
return self.healthBonusFlat
end
function modifier_wave_full_brutality_passive.prototype.GetModifierManaBonus(self)
return self.manaBonusFlat
end
function modifier_wave_full_brutality_passive.prototype.GetModifierDamageOutgoing_Percentage(self, _event)
return self.effectiveBonusPct
end
function modifier_wave_full_brutality_passive.prototype.GetModifierAttackSpeedPercentage(self)
return self.effectiveBonusPct
end
function modifier_wave_full_brutality_passive.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self.effectiveBonusPct
end
function modifier_wave_full_brutality_passive.prototype.GetModifierSpellAmplify_Percentage(self, _event)
return self.effectiveBonusPct
end
function modifier_wave_full_brutality_passive.prototype.GetEffectName(self)
return "particles/items2_fx/mask_of_madness.vpcf"
end
function modifier_wave_full_brutality_passive.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_wave_full_brutality_passive = __TS__Decorate(
modifier_wave_full_brutality_passive,
modifier_wave_full_brutality_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_wave_full_brutality_passive"}
)
____exports.modifier_wave_full_brutality_passive = modifier_wave_full_brutality_passive
return ____exports
@@ -0,0 +1,63 @@
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 ____difficulty_manager = require("difficulty_manager")
local Difficulty = ____difficulty_manager.Difficulty
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
--- Пассив волны: проход сквозь юнитов и бонус к скорости передвижения.
____exports.wave_phasing_march = __TS__Class()
local wave_phasing_march = ____exports.wave_phasing_march
wave_phasing_march.name = "wave_phasing_march"
wave_phasing_march.____file_path = "scripts/vscripts/abilities/creep/wave_phasing_march.lua"
__TS__ClassExtends(wave_phasing_march, BaseAbility)
function wave_phasing_march.prototype.GetIntrinsicModifierName(self)
return "modifier_wave_phasing_march_passive"
end
wave_phasing_march = __TS__Decorate(
wave_phasing_march,
wave_phasing_march,
{registerAbility(nil)},
{kind = "class", name = "wave_phasing_march"}
)
____exports.wave_phasing_march = wave_phasing_march
____exports.modifier_wave_phasing_march_passive = __TS__Class()
local modifier_wave_phasing_march_passive = ____exports.modifier_wave_phasing_march_passive
modifier_wave_phasing_march_passive.name = "modifier_wave_phasing_march_passive"
modifier_wave_phasing_march_passive.____file_path = "scripts/vscripts/abilities/creep/wave_phasing_march.lua"
__TS__ClassExtends(modifier_wave_phasing_march_passive, BaseModifier)
function modifier_wave_phasing_march_passive.prototype.IsHidden(self)
return true
end
function modifier_wave_phasing_march_passive.prototype.IsDebuff(self)
return false
end
function modifier_wave_phasing_march_passive.prototype.IsPurgable(self)
return false
end
function modifier_wave_phasing_march_passive.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT}
end
function modifier_wave_phasing_march_passive.prototype.GetModifierMoveSpeedBonus_Constant(self)
local ab = self:GetAbility()
if not ab then
return 0
end
return ab:GetSpecialValueFor("bonus_movement_speed") * Difficulty:getNpcStatScale()
end
function modifier_wave_phasing_march_passive.prototype.CheckState(self)
return {[MODIFIER_STATE_NO_UNIT_COLLISION] = true}
end
modifier_wave_phasing_march_passive = __TS__Decorate(
modifier_wave_phasing_march_passive,
modifier_wave_phasing_march_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_wave_phasing_march_passive"}
)
____exports.modifier_wave_phasing_march_passive = modifier_wave_phasing_march_passive
return ____exports
@@ -0,0 +1,137 @@
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
____exports.weaking_impetus = __TS__Class()
local weaking_impetus = ____exports.weaking_impetus
weaking_impetus.name = "weaking_impetus"
weaking_impetus.____file_path = "scripts/vscripts/abilities/creep/weaking_impetus.lua"
__TS__ClassExtends(weaking_impetus, BaseAbility)
function weaking_impetus.prototype.GetIntrinsicModifierName(self)
return "modifier_weaking_impetus_passive"
end
weaking_impetus = __TS__Decorate(
weaking_impetus,
weaking_impetus,
{registerAbility(nil)},
{kind = "class", name = "weaking_impetus"}
)
____exports.weaking_impetus = weaking_impetus
____exports.modifier_weaking_impetus_passive = __TS__Class()
local modifier_weaking_impetus_passive = ____exports.modifier_weaking_impetus_passive
modifier_weaking_impetus_passive.name = "modifier_weaking_impetus_passive"
modifier_weaking_impetus_passive.____file_path = "scripts/vscripts/abilities/creep/weaking_impetus.lua"
__TS__ClassExtends(modifier_weaking_impetus_passive, BaseModifier)
function modifier_weaking_impetus_passive.prototype.IsHidden(self)
return true
end
function modifier_weaking_impetus_passive.prototype.IsDebuff(self)
return false
end
function modifier_weaking_impetus_passive.prototype.IsPurgable(self)
return false
end
function modifier_weaking_impetus_passive.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_abaddon_borrowed_time.vpcf"
end
function modifier_weaking_impetus_passive.prototype.GetEffectName(self)
return "particles/units/heroes/hero_abaddon/abaddon_borrowed_time.vpcf"
end
function modifier_weaking_impetus_passive.prototype.StatusEffectPriority(self)
return 10
end
function modifier_weaking_impetus_passive.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_weaking_impetus_passive.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
if event.attacker ~= self:GetParent() then
return
end
local target = event.target
if not target then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if parent:GetMana() < self:GetAbility():GetSpecialValueFor("mana_hit") then
return
end
parent:SpendMana(
self:GetAbility():GetSpecialValueFor("mana_hit"),
ability
)
local duration = ability:GetSpecialValueFor("debuff_duration")
local modifier = target:FindModifierByName("modifier_weaking_impetus_debuff")
if modifier then
modifier:SetDuration(duration, true)
if modifier:GetStackCount() < self:GetAbility():GetSpecialValueFor("max_stacks") then
modifier:IncrementStackCount()
end
else
modifier = target:AddNewModifier(
self:GetParent(),
ability,
"modifier_weaking_impetus_debuff",
{duration = duration}
)
modifier:SetStackCount(1)
end
end
modifier_weaking_impetus_passive = __TS__Decorate(
modifier_weaking_impetus_passive,
modifier_weaking_impetus_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_weaking_impetus_passive"}
)
____exports.modifier_weaking_impetus_passive = modifier_weaking_impetus_passive
____exports.modifier_weaking_impetus_debuff = __TS__Class()
local modifier_weaking_impetus_debuff = ____exports.modifier_weaking_impetus_debuff
modifier_weaking_impetus_debuff.name = "modifier_weaking_impetus_debuff"
modifier_weaking_impetus_debuff.____file_path = "scripts/vscripts/abilities/creep/weaking_impetus.lua"
__TS__ClassExtends(modifier_weaking_impetus_debuff, BaseModifier)
function modifier_weaking_impetus_debuff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.damage_reduction = 0
end
function modifier_weaking_impetus_debuff.prototype.IsHidden(self)
return false
end
function modifier_weaking_impetus_debuff.prototype.IsDebuff(self)
return true
end
function modifier_weaking_impetus_debuff.prototype.IsPurgable(self)
return true
end
function modifier_weaking_impetus_debuff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.damage_reduction = ability:GetSpecialValueFor("damage_reduction")
end
function modifier_weaking_impetus_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE, MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE}
end
function modifier_weaking_impetus_debuff.prototype.GetModifierDamageOutgoing_Percentage(self, event)
return -self.damage_reduction * self:GetStackCount()
end
function modifier_weaking_impetus_debuff.prototype.GetModifierSpellAmplify_Percentage(self, event)
return -self.damage_reduction * self:GetStackCount()
end
modifier_weaking_impetus_debuff = __TS__Decorate(
modifier_weaking_impetus_debuff,
modifier_weaking_impetus_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_weaking_impetus_debuff"}
)
____exports.modifier_weaking_impetus_debuff = modifier_weaking_impetus_debuff
return ____exports
@@ -0,0 +1,72 @@
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 ____difficulty_manager = require("difficulty_manager")
local Difficulty = ____difficulty_manager.Difficulty
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
____exports.witch_base = __TS__Class()
local witch_base = ____exports.witch_base
witch_base.name = "witch_base"
witch_base.____file_path = "scripts/vscripts/abilities/creep/witch_base.lua"
__TS__ClassExtends(witch_base, BaseAbility)
function witch_base.prototype.GetIntrinsicModifierName(self)
return "modifier_witch_base"
end
witch_base = __TS__Decorate(
witch_base,
witch_base,
{registerAbility(nil)},
{kind = "class", name = "witch_base"}
)
____exports.witch_base = witch_base
____exports.modifier_witch_base = __TS__Class()
local modifier_witch_base = ____exports.modifier_witch_base
modifier_witch_base.name = "modifier_witch_base"
modifier_witch_base.____file_path = "scripts/vscripts/abilities/creep/witch_base.lua"
__TS__ClassExtends(modifier_witch_base, BaseModifier)
function modifier_witch_base.prototype.IsHidden(self)
return true
end
function modifier_witch_base.prototype.OnCreated(self, params)
local difficulty = Difficulty:getNpcStatScale()
local gameTime = GameRules:GetGameTime() / 60
self:SetStackCount(math.floor(gameTime))
end
function modifier_witch_base.prototype.OnRefresh(self, params)
self:OnCreated(params)
end
function modifier_witch_base.prototype.DeclareFunctions(self)
return {
MODIFIER_EVENT_ON_DEATH,
MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE,
MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE,
MODIFIER_PROPERTY_EXTRA_HEALTH_BONUS,
MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS
}
end
function modifier_witch_base.prototype.GetModifierSpellAmplify_Percentage(self, event)
return self:GetStackCount() * self:GetAbility():GetSpecialValueFor("amp_death_bonus") * Difficulty:getNpcStatScale()
end
function modifier_witch_base.prototype.GetModifierPreAttack_BonusDamage(self)
return self:GetStackCount() * self:GetAbility():GetSpecialValueFor("attack_death_bonus") * Difficulty:getNpcStatScale()
end
function modifier_witch_base.prototype.GetModifierExtraHealthBonus(self)
return self:GetStackCount() * self:GetAbility():GetSpecialValueFor("health_death_bonus") * Difficulty:getNpcStatScale()
end
function modifier_witch_base.prototype.GetModifierPhysicalArmorBonus(self, event)
return self:GetStackCount() * self:GetAbility():GetSpecialValueFor("armor_death_bonus") * Difficulty:getNpcStatScale()
end
modifier_witch_base = __TS__Decorate(
modifier_witch_base,
modifier_witch_base,
{registerModifier(nil)},
{kind = "class", name = "modifier_witch_base"}
)
____exports.modifier_witch_base = modifier_witch_base
return ____exports
@@ -0,0 +1,115 @@
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 ____difficulty_manager = require("difficulty_manager")
local Difficulty = ____difficulty_manager.Difficulty
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
____exports.zombie_armor_decress = __TS__Class()
local zombie_armor_decress = ____exports.zombie_armor_decress
zombie_armor_decress.name = "zombie_armor_decress"
zombie_armor_decress.____file_path = "scripts/vscripts/abilities/creep/zombie_armor_decress.lua"
__TS__ClassExtends(zombie_armor_decress, BaseAbility)
function zombie_armor_decress.prototype.GetIntrinsicModifierName(self)
return "modifier_zombie_armor_decress"
end
zombie_armor_decress = __TS__Decorate(
zombie_armor_decress,
zombie_armor_decress,
{registerAbility(nil)},
{kind = "class", name = "zombie_armor_decress"}
)
____exports.zombie_armor_decress = zombie_armor_decress
____exports.modifier_zombie_armor_decress = __TS__Class()
local modifier_zombie_armor_decress = ____exports.modifier_zombie_armor_decress
modifier_zombie_armor_decress.name = "modifier_zombie_armor_decress"
modifier_zombie_armor_decress.____file_path = "scripts/vscripts/abilities/creep/zombie_armor_decress.lua"
__TS__ClassExtends(modifier_zombie_armor_decress, BaseModifier)
function modifier_zombie_armor_decress.prototype.IsHidden(self)
return true
end
function modifier_zombie_armor_decress.prototype.IsPurgable(self)
return false
end
function modifier_zombie_armor_decress.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_zombie_armor_decress.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
if event.attacker ~= self:GetParent() then
return
end
if not event.target or not event.target:IsAlive() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
local duration = ability:GetSpecialValueFor("corruption_duration")
event.target:AddNewModifier(
self:GetParent(),
ability,
____exports.modifier_zombie_armor_decress_debuff.name,
{duration = duration}
)
end
modifier_zombie_armor_decress = __TS__Decorate(
modifier_zombie_armor_decress,
modifier_zombie_armor_decress,
{registerModifier(nil)},
{kind = "class", name = "modifier_zombie_armor_decress"}
)
____exports.modifier_zombie_armor_decress = modifier_zombie_armor_decress
____exports.modifier_zombie_armor_decress_debuff = __TS__Class()
local modifier_zombie_armor_decress_debuff = ____exports.modifier_zombie_armor_decress_debuff
modifier_zombie_armor_decress_debuff.name = "modifier_zombie_armor_decress_debuff"
modifier_zombie_armor_decress_debuff.____file_path = "scripts/vscripts/abilities/creep/zombie_armor_decress.lua"
__TS__ClassExtends(modifier_zombie_armor_decress_debuff, BaseModifier)
function modifier_zombie_armor_decress_debuff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.armorDebuffBase = 0
end
function modifier_zombie_armor_decress_debuff.prototype.IsHidden(self)
return true
end
function modifier_zombie_armor_decress_debuff.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_zombie_armor_decress_debuff.prototype.IsDebuff(self)
return true
end
function modifier_zombie_armor_decress_debuff.prototype.IsPurgable(self)
return true
end
function modifier_zombie_armor_decress_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
end
function modifier_zombie_armor_decress_debuff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.armorDebuffBase = ability:GetSpecialValueFor("armor_debuff")
end
function modifier_zombie_armor_decress_debuff.prototype.OnRefresh(self)
self:OnCreated()
end
function modifier_zombie_armor_decress_debuff.prototype.GetModifierPhysicalArmorBonus(self)
return self.armorDebuffBase * Difficulty:getNpcStatScale()
end
modifier_zombie_armor_decress_debuff = __TS__Decorate(
modifier_zombie_armor_decress_debuff,
modifier_zombie_armor_decress_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_zombie_armor_decress_debuff"}
)
____exports.modifier_zombie_armor_decress_debuff = modifier_zombie_armor_decress_debuff
return ____exports
@@ -0,0 +1,123 @@
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 ____creep_render_color = require("utils.creep_render_color")
local trySetIntrinsicCreepRenderColor = ____creep_render_color.trySetIntrinsicCreepRenderColor
--- Пассив: при смерти взрыв по радиусу — урон и союзникам, и врагам (герои и крипы).
____exports.zombie_death_explosion = __TS__Class()
local zombie_death_explosion = ____exports.zombie_death_explosion
zombie_death_explosion.name = "zombie_death_explosion"
zombie_death_explosion.____file_path = "scripts/vscripts/abilities/creep/zombie_death_explosion.lua"
__TS__ClassExtends(zombie_death_explosion, BaseAbility)
function zombie_death_explosion.prototype.GetIntrinsicModifierName(self)
return "modifier_zombie_death_explosion_listener"
end
function zombie_death_explosion.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_techies/techies_remote_mines_detonate.vpcf", context)
end
zombie_death_explosion = __TS__Decorate(
zombie_death_explosion,
zombie_death_explosion,
{registerAbility(nil)},
{kind = "class", name = "zombie_death_explosion"}
)
____exports.zombie_death_explosion = zombie_death_explosion
____exports.modifier_zombie_death_explosion_listener = __TS__Class()
local modifier_zombie_death_explosion_listener = ____exports.modifier_zombie_death_explosion_listener
modifier_zombie_death_explosion_listener.name = "modifier_zombie_death_explosion_listener"
modifier_zombie_death_explosion_listener.____file_path = "scripts/vscripts/abilities/creep/zombie_death_explosion.lua"
__TS__ClassExtends(modifier_zombie_death_explosion_listener, BaseModifier)
function modifier_zombie_death_explosion_listener.prototype.IsHidden(self)
return true
end
function modifier_zombie_death_explosion_listener.prototype.IsPurgable(self)
return false
end
function modifier_zombie_death_explosion_listener.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_DEATH}
end
function modifier_zombie_death_explosion_listener.prototype.OnCreated(self, params)
if IsServer() then
trySetIntrinsicCreepRenderColor(
nil,
self:GetParent(),
255,
0,
0
)
end
end
function modifier_zombie_death_explosion_listener.prototype.OnDeath(self, event)
if not IsServer() then
return
end
local parent = self:GetParent()
if event.unit ~= parent then
return
end
local ability = self:GetAbility()
if not ability then
return
end
local radius = ability:GetSpecialValueFor("radius")
local baseDamage = ability:GetSpecialValueFor("explosion_damage") + self:GetCaster():GetAttackDamage() * 0.35
local origin = parent:GetAbsOrigin()
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_techies/techies_remote_mines_detonate.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particle, 0, origin)
ParticleManager:SetParticleControl(
particle,
1,
Vector(radius, radius, radius)
)
ParticleManager:ReleaseParticleIndex(particle)
EmitSoundOn("Hero_Techies.RemoteMine.Detonate", parent)
local units = FindUnitsInRadius(
parent:GetTeamNumber(),
origin,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_BOTH,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local deadIndex = parent:entindex()
for ____, target in ipairs(units) do
do
if not target or not IsValidEntity(target) or not target:IsAlive() then
goto __continue13
end
if target:entindex() == deadIndex then
goto __continue13
end
local damage = target:IsRangedAttacker() and baseDamage or baseDamage * 0.25
if target:GetTeamNumber() == parent:GetTeamNumber() then
damage = damage * 0.5
end
ApplyDamage({
victim = target,
attacker = parent,
damage = damage,
damage_type = DAMAGE_TYPE_PHYSICAL,
ability = ability
})
end
::__continue13::
end
end
modifier_zombie_death_explosion_listener = __TS__Decorate(
modifier_zombie_death_explosion_listener,
modifier_zombie_death_explosion_listener,
{registerModifier(nil)},
{kind = "class", name = "modifier_zombie_death_explosion_listener"}
)
____exports.modifier_zombie_death_explosion_listener = modifier_zombie_death_explosion_listener
return ____exports
@@ -0,0 +1,227 @@
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 ____difficulty_manager = require("difficulty_manager")
local Difficulty = ____difficulty_manager.Difficulty
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 ZOMBIE_VIRUS_DEBUFF_NAME = "modifier_zombie_virus_debuff"
local ZOMBIE_VIRUS_MAX_INSTANCES = 9
local function countZombieVirusDebuffInstances(self, unit)
local n = 0
do
local i = 0
while i < unit:GetModifierCount() do
if unit:GetModifierNameByIndex(i) == ZOMBIE_VIRUS_DEBUFF_NAME then
n = n + 1
end
i = i + 1
end
end
return n
end
____exports.zombie_virus = __TS__Class()
local zombie_virus = ____exports.zombie_virus
zombie_virus.name = "zombie_virus"
zombie_virus.____file_path = "scripts/vscripts/abilities/creep/zombie_virus.lua"
__TS__ClassExtends(zombie_virus, BaseAbility)
function zombie_virus.prototype.GetIntrinsicModifierName(self)
return "modifier_zombie_virus_intrinsic"
end
zombie_virus = __TS__Decorate(
zombie_virus,
zombie_virus,
{registerAbility(nil)},
{kind = "class", name = "zombie_virus"}
)
____exports.zombie_virus = zombie_virus
____exports.modifier_zombie_virus_intrinsic = __TS__Class()
local modifier_zombie_virus_intrinsic = ____exports.modifier_zombie_virus_intrinsic
modifier_zombie_virus_intrinsic.name = "modifier_zombie_virus_intrinsic"
modifier_zombie_virus_intrinsic.____file_path = "scripts/vscripts/abilities/creep/zombie_virus.lua"
__TS__ClassExtends(modifier_zombie_virus_intrinsic, BaseModifier)
function modifier_zombie_virus_intrinsic.prototype.IsHidden(self)
return true
end
function modifier_zombie_virus_intrinsic.prototype.IsDebuff(self)
return false
end
function modifier_zombie_virus_intrinsic.prototype.IsPurgable(self)
return false
end
function modifier_zombie_virus_intrinsic.prototype.OnCreated(self)
if not IsServer() then
return
end
end
function modifier_zombie_virus_intrinsic.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_zombie_virus_intrinsic.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
if event.attacker ~= self:GetParent() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
local primaryZombieVirus = event.attacker:FindAbilityByName("zombie_virus")
if not primaryZombieVirus or ability ~= primaryZombieVirus then
return
end
local target = event.target
if not target or target:GetUnitName() == "npc_homer" then
return
end
local duration = ability:GetSpecialValueFor("duration")
if RandomInt(1, 100) > ability:GetSpecialValueFor("chance") then
return
end
if countZombieVirusDebuffInstances(nil, target) >= ZOMBIE_VIRUS_MAX_INSTANCES then
return
end
target:AddNewModifier(
self:GetParent(),
ability,
ZOMBIE_VIRUS_DEBUFF_NAME,
{duration = duration}
)
end
modifier_zombie_virus_intrinsic = __TS__Decorate(
modifier_zombie_virus_intrinsic,
modifier_zombie_virus_intrinsic,
{registerModifier(nil)},
{kind = "class", name = "modifier_zombie_virus_intrinsic"}
)
____exports.modifier_zombie_virus_intrinsic = modifier_zombie_virus_intrinsic
____exports.modifier_zombie_virus_debuff = __TS__Class()
local modifier_zombie_virus_debuff = ____exports.modifier_zombie_virus_debuff
modifier_zombie_virus_debuff.name = "modifier_zombie_virus_debuff"
modifier_zombie_virus_debuff.____file_path = "scripts/vscripts/abilities/creep/zombie_virus.lua"
__TS__ClassExtends(modifier_zombie_virus_debuff, BaseModifier)
function modifier_zombie_virus_debuff.prototype.IsHidden(self)
return true
end
function modifier_zombie_virus_debuff.prototype.IsDebuff(self)
return true
end
function modifier_zombie_virus_debuff.prototype.IsPurgable(self)
return true
end
function modifier_zombie_virus_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
end
function modifier_zombie_virus_debuff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
local ability = self:GetAbility()
if not ability then
return 0
end
return -ability:GetSpecialValueFor("slow_movespeed") * Difficulty:getNpcStatScale()
end
function modifier_zombie_virus_debuff.prototype.GetModifierPhysicalArmorBonus(self)
local ability = self:GetAbility()
if not ability then
return 0
end
return -ability:GetSpecialValueFor("armor") * Difficulty:getNpcStatScale()
end
function modifier_zombie_virus_debuff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.damage = ability:GetSpecialValueFor("damage")
self.tickInterval = ability:GetSpecialValueFor("tick_interval")
if IsServer() then
local caster = self:GetCaster()
if not caster or caster:IsNull() or not IsValidEntity(caster) or not caster:IsAlive() then
self:Destroy()
return
end
self:StartIntervalThink(self.tickInterval)
self.particleId = ParticleManager:CreateParticle(
"particles/econ/items/viper/viper_ti7_immortal/viper_poison_debuff_ti7.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
self.particleId,
0,
self:GetParent():GetAbsOrigin()
)
ParticleManager:SetParticleControl(
self.particleId,
1,
self:GetParent():GetAbsOrigin()
)
end
end
function modifier_zombie_virus_debuff.prototype.OnRefresh(self, params)
if self.particleId then
ParticleManager:DestroyParticle(self.particleId, false)
ParticleManager:ReleaseParticleIndex(self.particleId)
end
end
function modifier_zombie_virus_debuff.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
local caster = self:GetCaster()
local target = self:GetParent()
if not ability or ability:IsNull() or not caster or caster:IsNull() or not IsValidEntity(caster) or not caster:IsAlive() then
self:Destroy()
return
end
local tickDamage = self.damage * self.tickInterval * Difficulty:getNpcStatScale()
if target and target:IsAlive() then
ApplyDamage({
victim = target,
attacker = caster,
damage = tickDamage,
damage_type = DAMAGE_TYPE_PHYSICAL,
ability = ability
})
SendOverheadEventMessage(
nil,
OVERHEAD_ALERT_DAMAGE,
target,
tickDamage,
nil
)
end
end
function modifier_zombie_virus_debuff.prototype.OnDestroy(self)
if IsClient() then
return
end
if self.particleId then
ParticleManager:DestroyParticle(self.particleId, false)
ParticleManager:ReleaseParticleIndex(self.particleId)
end
end
function modifier_zombie_virus_debuff.prototype.GetEffectName(self)
return "particles/econ/items/void_spirit/void_spirit_immortal_2021/void_spirit_immortal_2021_astral_step_debuff.vpcf"
end
function modifier_zombie_virus_debuff.prototype.GetTexture(self)
return "life_stealer_open_wounds"
end
function modifier_zombie_virus_debuff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_zombie_virus_debuff = __TS__Decorate(
modifier_zombie_virus_debuff,
modifier_zombie_virus_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_zombie_virus_debuff"}
)
____exports.modifier_zombie_virus_debuff = modifier_zombie_virus_debuff
return ____exports
+56
View File
@@ -0,0 +1,56 @@
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
____exports.fish_basic = __TS__Class()
local fish_basic = ____exports.fish_basic
fish_basic.name = "fish_basic"
fish_basic.____file_path = "scripts/vscripts/abilities/fish_basic.lua"
__TS__ClassExtends(fish_basic, BaseAbility)
function fish_basic.prototype.GetIntrinsicModifierName(self)
return "modifier_fish_basic"
end
fish_basic = __TS__Decorate(
fish_basic,
fish_basic,
{registerAbility(nil)},
{kind = "class", name = "fish_basic"}
)
____exports.fish_basic = fish_basic
____exports.modifier_fish_basic = __TS__Class()
local modifier_fish_basic = ____exports.modifier_fish_basic
modifier_fish_basic.name = "modifier_fish_basic"
modifier_fish_basic.____file_path = "scripts/vscripts/abilities/fish_basic.lua"
__TS__ClassExtends(modifier_fish_basic, BaseModifier)
function modifier_fish_basic.prototype.IsHidden(self)
return true
end
function modifier_fish_basic.prototype.IsPurgable(self)
return false
end
function modifier_fish_basic.prototype.IsDebuff(self)
return false
end
function modifier_fish_basic.prototype.CheckState(self)
return {[MODIFIER_STATE_NO_HEALTH_BAR] = true, [MODIFIER_STATE_UNSELECTABLE] = true, [MODIFIER_STATE_UNTARGETABLE] = true}
end
function modifier_fish_basic.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MIN_HEALTH}
end
function modifier_fish_basic.prototype.GetMinHealth(self)
return self:GetParent():GetHealth()
end
modifier_fish_basic = __TS__Decorate(
modifier_fish_basic,
modifier_fish_basic,
{registerModifier(nil)},
{kind = "class", name = "modifier_fish_basic"}
)
____exports.modifier_fish_basic = modifier_fish_basic
return ____exports
@@ -0,0 +1,39 @@
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
local ____exports = {}
local ____hero_rage_whitelist = require("abilities.hero_rage.hero_rage_whitelist")
local isUnitNameAllowedForHeroRage = ____hero_rage_whitelist.isUnitNameAllowedForHeroRage
--- Параметры в духе infinity_levels / hero_rage.
local DEFAULT_HERO_RAGE = {
max_rage = 100,
rage_per_attack = 3,
rage_per_damage = 1,
time_decrase_rage = 4,
tick_decrase_rage = 0.5
}
local MOD_NAME = "modifier_hero_rage"
--- Вешает систему «ярости» (мана = ярость) на героя, если ещё не висит.
-- Нужна любая способность-носитель для AddNewModifier (у всех наших героев есть ability_stacking_crit).
-- **Только** герои из `hero_rage_whitelist.ts`.
function ____exports.tryApplyDefaultHeroRage(self, hero)
if not IsServer() then
return
end
if not hero:IsRealHero() or hero:IsIllusion() then
return
end
if not isUnitNameAllowedForHeroRage(
nil,
hero:GetUnitName()
) then
return
end
if hero:HasModifier(MOD_NAME) then
return
end
local host = hero:FindAbilityByName("ability_stacking_crit")
if not host then
return
end
hero:AddNewModifier(hero, host, MOD_NAME, DEFAULT_HERO_RAGE)
end
return ____exports
@@ -0,0 +1,222 @@
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 BaseModifier = ____dota_ts_adapter.BaseModifier
local registerModifier = ____dota_ts_adapter.registerModifier
local ____hero_rage_nettable = require("abilities.hero_rage.hero_rage_nettable")
local clearHeroRageNetTable = ____hero_rage_nettable.clearHeroRageNetTable
local syncHeroRageNetTable = ____hero_rage_nettable.syncHeroRageNetTable
local DEFAULT_MAX = 100
local DEFAULT_RAGE_PER_ATTACK = 3
local DEFAULT_RAGE_WHEN_HIT = 1
local DEFAULT_OUT_OF_COMBAT = 4
--- Как у infinity: шаг, с которым списывается 1 ед. ярости после тайм-аута «без прироста».
local DEFAULT_DECAY_COOLDOWN = 0.5
--- Реже тик — меньше нагрузка (раньше 0.05 сильно лагало).
local MANA_SYNC = 0.12
local function readParam(self, params, key, def)
if params == nil then
return def
end
local t = params
local v = t[key]
if v == nil or v == nil then
return def
end
local n = tonumber(v)
return n ~= nil and n ~= nil and n or def
end
--- Максимальная и текущая «мана» героя = шкала ярости; списание маны при кастах = ярость.
-- Накопление: удары и получение автоатак, затухание после простоя.
____exports.modifier_hero_rage = __TS__Class()
local modifier_hero_rage = ____exports.modifier_hero_rage
modifier_hero_rage.name = "modifier_hero_rage"
modifier_hero_rage.____file_path = "scripts/vscripts/abilities/hero_rage/hero_rage_modifiers.lua"
__TS__ClassExtends(modifier_hero_rage, BaseModifier)
function modifier_hero_rage.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.maxRage = DEFAULT_MAX
self.ragePerAttack = DEFAULT_RAGE_PER_ATTACK
self.rageWhenHit = DEFAULT_RAGE_WHEN_HIT
self.timeOutForDecay = DEFAULT_OUT_OF_COMBAT
self.decayStep = DEFAULT_DECAY_COOLDOWN
self.manaDelta = 0
self.timeSinceRageGain = 0
self.decayAcc = 0
self.lastNetCur = -1
self.lastNetMax = -1
self.intellectReadLock = false
end
function modifier_hero_rage.prototype.IsHidden(self)
return true
end
function modifier_hero_rage.prototype.IsDebuff(self)
return false
end
function modifier_hero_rage.prototype.IsPurgable(self)
return false
end
function modifier_hero_rage.prototype.RemoveOnDeath(self)
return false
end
function modifier_hero_rage.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MANA_BONUS, MODIFIER_PROPERTY_STATS_INTELLECT_BONUS, MODIFIER_EVENT_ON_ATTACK_LANDED, MODIFIER_EVENT_ON_DEATH}
end
function modifier_hero_rage.prototype.OnCreated(self, params)
self.parentHero = self:GetParent()
self.maxRage = readParam(nil, params, "max_rage", DEFAULT_MAX)
self.ragePerAttack = readParam(nil, params, "rage_per_attack", DEFAULT_RAGE_PER_ATTACK)
self.rageWhenHit = readParam(nil, params, "rage_per_damage", DEFAULT_RAGE_WHEN_HIT)
self.timeOutForDecay = readParam(nil, params, "time_decrase_rage", DEFAULT_OUT_OF_COMBAT)
self.decayStep = readParam(nil, params, "tick_decrase_rage", DEFAULT_DECAY_COOLDOWN)
self.timeSinceRageGain = 0
self.decayAcc = 0
self.manaDelta = 0
if IsServer() then
self:StartIntervalThink(MANA_SYNC)
self.parentHero:SetMana(0)
self.lastNetCur = -1
self.lastNetMax = -1
self.parentHero:CalculateStatBonus(true)
syncHeroRageNetTable(
nil,
self.parentHero,
0,
self.maxRage,
true
)
end
end
function modifier_hero_rage.prototype.OnRefresh(self, params)
self.maxRage = readParam(nil, params, "max_rage", self.maxRage)
end
function modifier_hero_rage.prototype.GetModifierManaBonus(self)
return self.manaDelta
end
function modifier_hero_rage.prototype.GetModifierBonusStats_Intellect(self)
if self.intellectReadLock then
return 0
end
local p = self:GetParent()
if not p or p:IsNull() then
return 0
end
self.intellectReadLock = true
local int = p:GetIntellect(true)
self.intellectReadLock = false
return int * -1
end
function modifier_hero_rage.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
local p = self.parentHero
if event.attacker == p then
self:bumpRage(self.ragePerAttack)
elseif event.target == p then
self:bumpRage(self.rageWhenHit)
end
end
function modifier_hero_rage.prototype.OnDeath(self, event)
if not IsServer() then
return
end
if event.unit ~= self:GetParent() then
return
end
self.parentHero:SetMana(0)
self:pushNet(0, self.maxRage, true)
end
function modifier_hero_rage.prototype.bumpRage(self, amt)
if amt <= 0 then
return
end
self.timeSinceRageGain = 0
self.decayAcc = 0
local p = self.parentHero
local m = p:GetMaxMana()
p:SetMana(math.min(
m,
p:GetMana() + amt
))
end
function modifier_hero_rage.prototype.stripPassiveManaRegen(self, p)
if not p or p:IsNull() then
return
end
local regenPerSec = p:GetManaRegen()
if regenPerSec > 0 then
p:SetMana(math.max(
0,
p:GetMana() - regenPerSec * MANA_SYNC
))
end
end
function modifier_hero_rage.prototype.pushNet(self, cur, max, force)
if force == nil then
force = false
end
if not force and self.lastNetCur == cur and self.lastNetMax == max then
return
end
self.lastNetCur = cur
self.lastNetMax = max
syncHeroRageNetTable(
nil,
self.parentHero,
cur,
max,
true
)
end
function modifier_hero_rage.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local p = self.parentHero
if not p or p:IsNull() or not p:IsAlive() then
return
end
self.manaDelta = self.maxRage - p:GetMaxMana() + (self.manaDelta or 0)
p:CalculateStatBonus(true)
p:SetMana(math.min(
p:GetMana(),
p:GetMaxMana()
))
self:stripPassiveManaRegen(p)
self.timeSinceRageGain = self.timeSinceRageGain + MANA_SYNC
if self.timeSinceRageGain >= self.timeOutForDecay then
self.decayAcc = self.decayAcc + MANA_SYNC
if self.decayAcc >= self.decayStep then
p:SetMana(math.max(
0,
p:GetMana() - 1
))
self.decayAcc = self.decayAcc - self.decayStep
end
end
self:pushNet(
p:GetMana(),
math.min(
p:GetMaxMana(),
self.maxRage
),
false
)
end
function modifier_hero_rage.prototype.OnDestroy(self)
if IsServer() then
clearHeroRageNetTable(nil, self.parentHero)
end
end
modifier_hero_rage = __TS__Decorate(
modifier_hero_rage,
modifier_hero_rage,
{registerModifier(nil)},
{kind = "class", name = "modifier_hero_rage"}
)
____exports.modifier_hero_rage = modifier_hero_rage
return ____exports
@@ -0,0 +1,41 @@
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
local ____exports = {}
--- Синхронизация «ярости» (игровая мана) с клиентом для кастомного HUD.
local TABLE = "hero_rage"
function ____exports.syncHeroRageNetTable(self, hero, current, max, active)
if not IsServer() then
return
end
local pid = hero:GetPlayerOwnerID()
if pid < 0 then
return
end
local row = {
current = math.floor(current + 0.5),
max = math.max(
0,
math.floor(max + 0.5)
),
active = active and 1 or 0
}
CustomNetTables:SetTableValue(
TABLE,
tostring(pid),
row
)
end
function ____exports.clearHeroRageNetTable(self, hero)
if not IsServer() then
return
end
local pid = hero:GetPlayerOwnerID()
if pid < 0 then
return
end
CustomNetTables:SetTableValue(
TABLE,
tostring(pid),
{current = 0, max = 0, active = 0}
)
end
return ____exports
@@ -0,0 +1,13 @@
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
local ____exports = {}
--- Ярость выдаётся **только** героям, чьё `GetUnitName()` есть в этой таблице.
-- Имена — как в KV/npc: `npc_dota_hero_*`, кастомы — `npc_из_твоей_таверны_hero_...` если так заведено.
local HERO_RAGE_UNIT_NAMES = {npc_dota_hero_axe = true, npc_dota_hero_sven = true, npc_dota_hero_juggernaut = true}
--- Проверка, входит ли юнит в белый список ярости.
function ____exports.isUnitNameAllowedForHeroRage(self, unitName)
if unitName == nil or unitName == nil or unitName == "" then
return false
end
return HERO_RAGE_UNIT_NAMES[unitName] == true
end
return ____exports
@@ -0,0 +1,352 @@
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 ____heal_tracker = require("utils.heal_tracker")
local HealWithBattlePass = ____heal_tracker.HealWithBattlePass
____exports.AXE_BATTLE_HUNGER_CUSTOM = "axe_battle_hunger_custom"
--- Вызывается из Berserker's Call (шард): вешает голод даже без клика, если способность прокачана.
function ____exports.axeApplyBattleHungerFromCall(self, caster, target, duration)
if not IsServer() then
return
end
local hunger = caster:FindAbilityByName(____exports.AXE_BATTLE_HUNGER_CUSTOM)
if not hunger or hunger:GetLevel() <= 0 then
return
end
if target:GetTeamNumber() == caster:GetTeamNumber() then
target:AddNewModifier(caster, hunger, ____exports.modifier_axe_battle_hunger_ally_buff.name, {duration = duration})
else
target:AddNewModifier(caster, hunger, ____exports.modifier_axe_battle_hunger_debuff.name, {duration = duration})
end
end
____exports.axe_battle_hunger_custom = __TS__Class()
local axe_battle_hunger_custom = ____exports.axe_battle_hunger_custom
axe_battle_hunger_custom.name = "axe_battle_hunger_custom"
axe_battle_hunger_custom.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_battle_hunger_custom.lua"
__TS__ClassExtends(axe_battle_hunger_custom, BaseAbility)
function axe_battle_hunger_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_axe/axe_battle_hunger.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_axe.vsndevts", context)
end
function axe_battle_hunger_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not target then
return
end
local duration = self:GetSpecialValueFor("duration")
if target:GetTeamNumber() == caster:GetTeamNumber() then
target:AddNewModifier(caster, self, ____exports.modifier_axe_battle_hunger_ally_buff.name, {duration = duration})
else
target:AddNewModifier(caster, self, ____exports.modifier_axe_battle_hunger_debuff.name, {duration = duration})
end
EmitSoundOn("Hero_Axe.Battle_Hunger", target)
end
function axe_battle_hunger_custom.prototype.GetCastRange(self)
return self:GetSpecialValueFor("AbilityCastRange")
end
function axe_battle_hunger_custom.prototype.CastFilterResultTarget(self, target)
if target:IsInvulnerable() then
return UF_FAIL_CUSTOM
end
return UF_SUCCESS
end
function axe_battle_hunger_custom.prototype.GetAbilityTargetTeam(self)
return DOTA_UNIT_TARGET_TEAM_BOTH
end
axe_battle_hunger_custom.ALLY_HUNGER_STACKS_PER_SECOND = 5
axe_battle_hunger_custom.ALLY_HEAL_PCT_PER_SECOND = 1.5
axe_battle_hunger_custom = __TS__Decorate(
axe_battle_hunger_custom,
axe_battle_hunger_custom,
{registerAbility(nil)},
{kind = "class", name = "axe_battle_hunger_custom"}
)
____exports.axe_battle_hunger_custom = axe_battle_hunger_custom
--- На Аксе: +% скорости за каждого врага с Battle Hunger.
____exports.modifier_axe_battle_hunger_owner_counter = __TS__Class()
local modifier_axe_battle_hunger_owner_counter = ____exports.modifier_axe_battle_hunger_owner_counter
modifier_axe_battle_hunger_owner_counter.name = "modifier_axe_battle_hunger_owner_counter"
modifier_axe_battle_hunger_owner_counter.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_battle_hunger_custom.lua"
__TS__ClassExtends(modifier_axe_battle_hunger_owner_counter, BaseModifier)
function modifier_axe_battle_hunger_owner_counter.prototype.IsHidden(self)
return true
end
function modifier_axe_battle_hunger_owner_counter.prototype.IsPurgable(self)
return false
end
function modifier_axe_battle_hunger_owner_counter.changeStacksOnCaster(self, caster, delta)
local ab = caster:FindAbilityByName(____exports.AXE_BATTLE_HUNGER_CUSTOM)
if ab then
local m = caster:FindModifierByName(____exports.modifier_axe_battle_hunger_owner_counter.name)
if not m and delta > 0 then
m = caster:AddNewModifier(caster, ab, ____exports.modifier_axe_battle_hunger_owner_counter.name, {})
end
if m and not m:IsNull() then
local next = math.max(
0,
m:GetStackCount() + delta
)
m:SetStackCount(next)
if next <= 0 then
m:Destroy()
end
end
end
end
function modifier_axe_battle_hunger_owner_counter.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_axe_battle_hunger_owner_counter.prototype.GetModifierMoveSpeedBonus_Percentage(self)
local ab = self:GetAbility()
if not ab then
return 0
end
local pct = ab:GetSpecialValueFor("speed_per_enemy_pct")
return self:GetStackCount() * pct
end
modifier_axe_battle_hunger_owner_counter = __TS__Decorate(
modifier_axe_battle_hunger_owner_counter,
modifier_axe_battle_hunger_owner_counter,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_battle_hunger_owner_counter"}
)
____exports.modifier_axe_battle_hunger_owner_counter = modifier_axe_battle_hunger_owner_counter
____exports.modifier_axe_battle_hunger_debuff = __TS__Class()
local modifier_axe_battle_hunger_debuff = ____exports.modifier_axe_battle_hunger_debuff
modifier_axe_battle_hunger_debuff.name = "modifier_axe_battle_hunger_debuff"
modifier_axe_battle_hunger_debuff.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_battle_hunger_custom.lua"
__TS__ClassExtends(modifier_axe_battle_hunger_debuff, BaseModifier)
function modifier_axe_battle_hunger_debuff.prototype.IsHidden(self)
return false
end
function modifier_axe_battle_hunger_debuff.prototype.IsDebuff(self)
return true
end
function modifier_axe_battle_hunger_debuff.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_axe_battle_hunger_debuff.prototype.IsPurgable(self)
return true
end
function modifier_axe_battle_hunger_debuff.prototype.GetTexture(self)
return "axe_battle_hunger"
end
function modifier_axe_battle_hunger_debuff.prototype.OnCreated(self)
if not IsServer() then
return
end
self:StartIntervalThink(1)
____exports.modifier_axe_battle_hunger_owner_counter:changeStacksOnCaster(
self:GetCaster(),
1
)
local parent = self:GetParent()
self.killListener = ListenToGameEvent(
"entity_killed",
function(event)
if not parent or not parent:IsAlive() then
return
end
local attacker = EntIndexToHScript(event.entindex_attacker)
if attacker == parent then
self:Destroy()
end
end,
nil
)
end
function modifier_axe_battle_hunger_debuff.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not parent or not caster or not ability then
return
end
local basePerSec = ability:GetSpecialValueFor("damage_per_second")
local armorMult = ability:GetSpecialValueFor("armor_mult") * 0.01
local armorBonus = caster:GetPhysicalArmorBaseValue() * armorMult
local dmg = math.max(1, basePerSec + armorBonus)
local dealtDamage = ApplyDamage({
victim = parent,
attacker = caster,
damage = dmg,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
SendOverheadEventMessage(
nil,
OVERHEAD_ALERT_BONUS_SPELL_DAMAGE,
parent,
dealtDamage,
caster:GetPlayerOwner()
)
end
function modifier_axe_battle_hunger_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_axe_battle_hunger_debuff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
local ability = self:GetAbility()
if not ability then
return 0
end
local slow = ability:GetSpecialValueFor("slow")
local parent = self:GetParent()
local caster = self:GetCaster()
if not parent or not caster then
return 0
end
local toAxe = caster:GetAbsOrigin():__sub(parent:GetAbsOrigin()):Normalized()
local fwd = parent:GetForwardVector()
local facingAxe = fwd:Dot(toAxe)
if facingAxe < 0.25 then
return -slow
end
return 0
end
function modifier_axe_battle_hunger_debuff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_axe/axe_battle_hunger.vpcf"
end
function modifier_axe_battle_hunger_debuff.prototype.GetEffectAttachType(self)
return PATTACH_OVERHEAD_FOLLOW
end
function modifier_axe_battle_hunger_debuff.prototype.OnRefresh(self)
if IsServer() then
self:SetDuration(
self:GetAbility():GetSpecialValueFor("duration"),
true
)
end
end
function modifier_axe_battle_hunger_debuff.prototype.OnDestroy(self)
if IsServer() then
local caster = self:GetCaster()
if caster then
____exports.modifier_axe_battle_hunger_owner_counter:changeStacksOnCaster(caster, -1)
end
if self.killListener ~= nil then
StopListeningToGameEvent(self.killListener)
self.killListener = nil
end
end
end
modifier_axe_battle_hunger_debuff = __TS__Decorate(
modifier_axe_battle_hunger_debuff,
modifier_axe_battle_hunger_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_battle_hunger_debuff"}
)
____exports.modifier_axe_battle_hunger_debuff = modifier_axe_battle_hunger_debuff
____exports.modifier_axe_battle_hunger_ally_buff = __TS__Class()
local modifier_axe_battle_hunger_ally_buff = ____exports.modifier_axe_battle_hunger_ally_buff
modifier_axe_battle_hunger_ally_buff.name = "modifier_axe_battle_hunger_ally_buff"
modifier_axe_battle_hunger_ally_buff.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_battle_hunger_custom.lua"
__TS__ClassExtends(modifier_axe_battle_hunger_ally_buff, BaseModifier)
function modifier_axe_battle_hunger_ally_buff.prototype.IsHidden(self)
return false
end
function modifier_axe_battle_hunger_ally_buff.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_axe_battle_hunger_ally_buff.prototype.IsDebuff(self)
return false
end
function modifier_axe_battle_hunger_ally_buff.prototype.IsPurgable(self)
return true
end
function modifier_axe_battle_hunger_ally_buff.prototype.GetTexture(self)
return "axe_battle_hunger"
end
function modifier_axe_battle_hunger_ally_buff.prototype.OnCreated(self)
if not IsServer() then
return
end
self:StartIntervalThink(1)
end
function modifier_axe_battle_hunger_ally_buff.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not parent or not caster or not ability then
return
end
local hunger = parent:FindModifierByName(modifier_general_hunger.name)
if not hunger then
hunger = parent:AddNewModifier(caster, ability, modifier_general_hunger.name, {})
end
if hunger and not hunger:IsNull() then
do
local i = 0
while i < ____exports.axe_battle_hunger_custom.ALLY_HUNGER_STACKS_PER_SECOND do
hunger:IncrementStackCount()
i = i + 1
end
end
end
local heal = parent:GetMaxHealth() * (____exports.axe_battle_hunger_custom.ALLY_HEAL_PCT_PER_SECOND * 0.01)
if heal > 0 then
HealWithBattlePass(
nil,
parent,
heal,
ability,
caster
)
SendOverheadEventMessage(
nil,
OVERHEAD_ALERT_HEAL,
parent,
heal,
parent:GetPlayerOwner()
)
end
end
function modifier_axe_battle_hunger_ally_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_BASEDAMAGEOUTGOING_PERCENTAGE, MODIFIER_PROPERTY_TOOLTIP}
end
function modifier_axe_battle_hunger_ally_buff.prototype.GetModifierBaseDamageOutgoing_Percentage(self)
local ability = self:GetAbility()
if not ability then
return 0
end
return ability:GetSpecialValueFor("speed_bonus")
end
function modifier_axe_battle_hunger_ally_buff.prototype.GetModifierTooltip(self)
local parent = self:GetParent()
if not parent then
return 0
end
return math.floor(parent:GetMaxHealth() * (____exports.axe_battle_hunger_custom.ALLY_HEAL_PCT_PER_SECOND * 0.01) + 0.5)
end
function modifier_axe_battle_hunger_ally_buff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_axe/axe_battle_hunger.vpcf"
end
function modifier_axe_battle_hunger_ally_buff.prototype.GetEffectAttachType(self)
return PATTACH_OVERHEAD_FOLLOW
end
modifier_axe_battle_hunger_ally_buff = __TS__Decorate(
modifier_axe_battle_hunger_ally_buff,
modifier_axe_battle_hunger_ally_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_battle_hunger_ally_buff"}
)
____exports.modifier_axe_battle_hunger_ally_buff = modifier_axe_battle_hunger_ally_buff
return ____exports
@@ -0,0 +1,257 @@
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
@@ -0,0 +1,158 @@
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
____exports.axe_counter_helix_custom = __TS__Class()
local axe_counter_helix_custom = ____exports.axe_counter_helix_custom
axe_counter_helix_custom.name = "axe_counter_helix_custom"
axe_counter_helix_custom.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_counter_helix_custom.lua"
__TS__ClassExtends(axe_counter_helix_custom, BaseAbility)
function axe_counter_helix_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_axe/axe_counterhelix.vpcf", context)
PrecacheResource("particle", "particles/econ/items/axe/axe_weapon_bloodchaser/axe_attack_blur_counterhelix_bloodchaser.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_axe.vsndevts", context)
end
function axe_counter_helix_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_axe_counter_helix_passive.name
end
axe_counter_helix_custom = __TS__Decorate(
axe_counter_helix_custom,
axe_counter_helix_custom,
{registerAbility(nil)},
{kind = "class", name = "axe_counter_helix_custom"}
)
____exports.axe_counter_helix_custom = axe_counter_helix_custom
____exports.modifier_axe_counter_helix_passive = __TS__Class()
local modifier_axe_counter_helix_passive = ____exports.modifier_axe_counter_helix_passive
modifier_axe_counter_helix_passive.name = "modifier_axe_counter_helix_passive"
modifier_axe_counter_helix_passive.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_counter_helix_custom.lua"
__TS__ClassExtends(modifier_axe_counter_helix_passive, BaseModifier)
function modifier_axe_counter_helix_passive.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.lastHelixGameTime = 0
self.scepterLandCounter = 0
end
function modifier_axe_counter_helix_passive.prototype.IsHidden(self)
return true
end
function modifier_axe_counter_helix_passive.prototype.IsPurgable(self)
return false
end
function modifier_axe_counter_helix_passive.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_TAKEDAMAGE}
end
function modifier_axe_counter_helix_passive.prototype.OnTakeDamage(self, event)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if parent:PassivesDisabled() then
return
end
if not ability or event.unit ~= parent then
return
end
local attacker = event.attacker
if not attacker or attacker == parent or not attacker:IsAlive() then
return
end
if attacker:GetTeamNumber() == parent:GetTeamNumber() then
return
end
local cd = ability:GetSpecialValueFor("duration")
local now = GameRules:GetGameTime()
if now < self.lastHelixGameTime + cd then
return
end
local chance = ability:GetSpecialValueFor("trigger_chance")
local needScepter = parent:HasScepter()
local attacksForProc = needScepter and ability:GetSpecialValueFor("scepter_attacks") or 0
local helixed = false
if attacksForProc > 0 then
self.scepterLandCounter = self.scepterLandCounter + 1
if self.scepterLandCounter >= attacksForProc then
self.scepterLandCounter = 0
self:triggerHelix(ability)
helixed = true
end
end
if not helixed and RollPercentage(chance) then
self:triggerHelix(ability)
helixed = true
end
if helixed then
self.lastHelixGameTime = now
end
end
function modifier_axe_counter_helix_passive.prototype.triggerHelix(self, ability)
if self:GetParent():PassivesDisabled() then
return
end
local parent = self:GetParent()
local radius = ability:GetSpecialValueFor("radius")
local damage = ability:GetSpecialValueFor("damage")
parent:StartGestureWithPlaybackRate(ACT_DOTA_CAST_ABILITY_3, 1)
local helix_pfx = ParticleManager:CreateParticle("particles/econ/items/axe/axe_weapon_bloodchaser/axe_attack_blur_counterhelix_bloodchaser.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
EmitSoundOn("Hero_Axe.CounterHelix", parent)
ParticleManager:SetParticleControl(
helix_pfx,
0,
parent:GetAbsOrigin()
)
ParticleManager:ReleaseParticleIndex(helix_pfx)
local enemies = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
do
if not enemy or not enemy:IsAlive() then
goto __continue20
end
ApplyDamage({
victim = enemy,
attacker = parent,
damage = damage,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
parent:PerformAttack(
enemy,
false,
true,
true,
true,
false,
false,
true
)
end
::__continue20::
end
local icd = ability:GetSpecialValueFor("duration")
if icd > 0 then
ability:StartCooldown(icd)
end
end
modifier_axe_counter_helix_passive = __TS__Decorate(
modifier_axe_counter_helix_passive,
modifier_axe_counter_helix_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_counter_helix_passive"}
)
____exports.modifier_axe_counter_helix_passive = modifier_axe_counter_helix_passive
return ____exports
@@ -0,0 +1,334 @@
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
--- Навсегда броня: стаки × armor_per_creep_kill (крип +0.1, герой — через armor_per_stack).
local function axeCullingAddPermanentArmor(self, caster, ability, flatArmor)
if flatArmor <= 0 then
return
end
local step = ability:GetSpecialValueFor("armor_per_creep_kill")
if step <= 0 then
return
end
local addStacks = math.floor(flatArmor / step + 0.5)
if addStacks < 1 then
addStacks = 1
end
local m = caster:FindModifierByName(____exports.modifier_axe_culling_blade_armor_stack.name)
if not m then
m = caster:AddNewModifier(caster, ability, ____exports.modifier_axe_culling_blade_armor_stack.name, {})
end
if m ~= nil then
m:SetStackCount(m:GetStackCount() + addStacks)
end
end
local function axeReduceAllAbilityCooldowns(self, caster, seconds)
if seconds <= 0 then
return
end
do
local i = 0
while i < 24 do
do
local ab = caster:GetAbilityByIndex(i)
if not ab or ab:IsNull() then
goto __continue10
end
local remaining = ab:GetCooldownTimeRemaining()
if remaining <= 0 then
goto __continue10
end
ab:EndCooldown()
local next = math.max(0, remaining - seconds)
if next > 0 then
ab:StartCooldown(next)
end
end
::__continue10::
i = i + 1
end
end
end
____exports.axe_culling_blade_custom = __TS__Class()
local axe_culling_blade_custom = ____exports.axe_culling_blade_custom
axe_culling_blade_custom.name = "axe_culling_blade_custom"
axe_culling_blade_custom.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_culling_blade_custom.lua"
__TS__ClassExtends(axe_culling_blade_custom, BaseAbility)
function axe_culling_blade_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_axe_culling_blade_shard_cdr.name
end
function axe_culling_blade_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_axe/axe_culling_blade.vpcf", context)
PrecacheResource("particle", "particles/econ/items/axe/ti9_jungle_axe/ti9_jungle_axe_culling_blade_sprint_fire.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_axe.vsndevts", context)
end
function axe_culling_blade_custom.prototype.GetCastRange(self, location, target)
return self:GetSpecialValueFor("AbilityCastRange")
end
function axe_culling_blade_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("cull_radius")
end
function axe_culling_blade_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local cullRadius = self:GetSpecialValueFor("cull_radius")
local buffRadius = self:GetSpecialValueFor("speed_aoe")
local creepArmor = self:GetSpecialValueFor("armor_per_creep_kill")
local heroArmor = self:GetSpecialValueFor("armor_per_stack")
EmitSoundOn("Hero_Axe.Culling_Blade", caster)
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
point,
nil,
cullRadius,
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 anyExecuted = false
for ____, target in ipairs(enemies) do
do
if not target or not target:IsAlive() or target:IsInvulnerable() then
goto __continue20
end
self:playCullingBladeParticle(caster, target)
EmitSoundOn("Hero_Axe.Culling_Blade", target)
local wasHero = target:IsHero()
local bonusAttackDamage = caster:GetAverageTrueAttackDamage(target)
ApplyDamage({
victim = target,
attacker = caster,
damage = bonusAttackDamage,
damage_type = self:GetAbilityDamageType(),
ability = self
})
if target:IsAlive() then
caster:PerformAttack(
target,
false,
true,
true,
true,
false,
false,
true
)
end
if not target:IsAlive() then
anyExecuted = true
EmitSoundOn("Hero_Axe.Culling_Blade_Success", target)
if not wasHero and creepArmor > 0 then
axeCullingAddPermanentArmor(nil, caster, self, creepArmor)
elseif wasHero and heroArmor > 0 then
axeCullingAddPermanentArmor(nil, caster, self, heroArmor)
end
end
end
::__continue20::
end
if anyExecuted then
local durBase = self:GetSpecialValueFor("speed_duration")
local dur = caster:HasScepter() and self:GetSpecialValueFor("scepter_speed_duration") or durBase
local tm = caster:GetTeamNumber()
local unitList = FindUnitsInRadius(
tm,
caster:GetAbsOrigin(),
nil,
buffRadius,
DOTA_UNIT_TARGET_TEAM_FRIENDLY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, unit in ipairs(unitList) do
do
if not unit or not unit:IsAlive() then
goto __continue28
end
unit:AddNewModifier(caster, self, ____exports.modifier_axe_culling_blade_movespeed.name, {duration = dur})
end
::__continue28::
end
end
end
function axe_culling_blade_custom.prototype.playCullingBladeParticle(self, caster, target)
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_axe/axe_culling_blade.vpcf", PATTACH_ABSORIGIN_FOLLOW, target)
ParticleManager:SetParticleControl(
particle,
0,
caster:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
particle,
1,
target:GetAbsOrigin()
)
ParticleManager:SetParticleControlEnt(
particle,
2,
target,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
target:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(particle)
end
axe_culling_blade_custom = __TS__Decorate(
axe_culling_blade_custom,
axe_culling_blade_custom,
{registerAbility(nil)},
{kind = "class", name = "axe_culling_blade_custom"}
)
____exports.axe_culling_blade_custom = axe_culling_blade_custom
____exports.modifier_axe_culling_blade_shard_cdr = __TS__Class()
local modifier_axe_culling_blade_shard_cdr = ____exports.modifier_axe_culling_blade_shard_cdr
modifier_axe_culling_blade_shard_cdr.name = "modifier_axe_culling_blade_shard_cdr"
modifier_axe_culling_blade_shard_cdr.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_culling_blade_custom.lua"
__TS__ClassExtends(modifier_axe_culling_blade_shard_cdr, BaseModifier)
function modifier_axe_culling_blade_shard_cdr.prototype.IsHidden(self)
return true
end
function modifier_axe_culling_blade_shard_cdr.prototype.IsPurgable(self)
return false
end
function modifier_axe_culling_blade_shard_cdr.prototype.RemoveOnDeath(self)
return false
end
function modifier_axe_culling_blade_shard_cdr.prototype.OnCreated(self)
if not IsServer() then
return
end
local parent = self:GetParent()
self.killListener = ListenToGameEvent(
"entity_killed",
function(event)
local attacker = EntIndexToHScript(event.entindex_attacker)
local killed = EntIndexToHScript(event.entindex_killed)
local ____temp_0
if event.entindex_inflictor ~= nil and event.entindex_inflictor ~= 0 then
____temp_0 = EntIndexToHScript(event.entindex_inflictor)
else
____temp_0 = nil
end
local inflictor = ____temp_0
if not attacker or not killed then
return
end
if attacker ~= parent then
return
end
if inflictor and not inflictor:IsNull() then
return
end
if not parent:IsRealHero() or parent:IsIllusion() then
return
end
if parent:PassivesDisabled() then
return
end
if not parent:HasScepter() then
return
end
if not killed:IsCreep() then
return
end
axeReduceAllAbilityCooldowns(nil, parent, 1)
end,
nil
)
end
function modifier_axe_culling_blade_shard_cdr.prototype.OnDestroy(self)
if self.killListener ~= nil then
StopListeningToGameEvent(self.killListener)
self.killListener = nil
end
end
modifier_axe_culling_blade_shard_cdr = __TS__Decorate(
modifier_axe_culling_blade_shard_cdr,
modifier_axe_culling_blade_shard_cdr,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_culling_blade_shard_cdr"}
)
____exports.modifier_axe_culling_blade_shard_cdr = modifier_axe_culling_blade_shard_cdr
____exports.modifier_axe_culling_blade_armor_stack = __TS__Class()
local modifier_axe_culling_blade_armor_stack = ____exports.modifier_axe_culling_blade_armor_stack
modifier_axe_culling_blade_armor_stack.name = "modifier_axe_culling_blade_armor_stack"
modifier_axe_culling_blade_armor_stack.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_culling_blade_custom.lua"
__TS__ClassExtends(modifier_axe_culling_blade_armor_stack, BaseModifier)
function modifier_axe_culling_blade_armor_stack.prototype.IsHidden(self)
return false
end
function modifier_axe_culling_blade_armor_stack.prototype.IsPurgable(self)
return false
end
function modifier_axe_culling_blade_armor_stack.prototype.IsDebuff(self)
return false
end
function modifier_axe_culling_blade_armor_stack.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
end
function modifier_axe_culling_blade_armor_stack.prototype.GetModifierPhysicalArmorBonus(self)
local ab = self:GetAbility()
if not ab then
return 0
end
return self:GetStackCount() * ab:GetSpecialValueFor("armor_per_creep_kill")
end
modifier_axe_culling_blade_armor_stack = __TS__Decorate(
modifier_axe_culling_blade_armor_stack,
modifier_axe_culling_blade_armor_stack,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_culling_blade_armor_stack"}
)
____exports.modifier_axe_culling_blade_armor_stack = modifier_axe_culling_blade_armor_stack
____exports.modifier_axe_culling_blade_movespeed = __TS__Class()
local modifier_axe_culling_blade_movespeed = ____exports.modifier_axe_culling_blade_movespeed
modifier_axe_culling_blade_movespeed.name = "modifier_axe_culling_blade_movespeed"
modifier_axe_culling_blade_movespeed.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_culling_blade_custom.lua"
__TS__ClassExtends(modifier_axe_culling_blade_movespeed, BaseModifier)
function modifier_axe_culling_blade_movespeed.prototype.IsHidden(self)
return false
end
function modifier_axe_culling_blade_movespeed.prototype.IsPurgable(self)
return true
end
function modifier_axe_culling_blade_movespeed.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT}
end
function modifier_axe_culling_blade_movespeed.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self:GetAbility():GetSpecialValueFor("speed_bonus")
end
function modifier_axe_culling_blade_movespeed.prototype.CheckState(self)
return {[MODIFIER_STATE_DEBUFF_IMMUNE] = true}
end
function modifier_axe_culling_blade_movespeed.prototype.GetModifierAttackSpeedBonus_Constant(self)
return self:GetAbility():GetSpecialValueFor("attack_speed_bonus")
end
function modifier_axe_culling_blade_movespeed.prototype.GetEffectName(self)
return "particles/econ/items/axe/ti9_jungle_axe/ti9_jungle_axe_culling_blade_sprint_fire.vpcf"
end
function modifier_axe_culling_blade_movespeed.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_axe_culling_blade_movespeed = __TS__Decorate(
modifier_axe_culling_blade_movespeed,
modifier_axe_culling_blade_movespeed,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_culling_blade_movespeed"}
)
____exports.modifier_axe_culling_blade_movespeed = modifier_axe_culling_blade_movespeed
return ____exports
@@ -0,0 +1,83 @@
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
____exports.axe_one_man_army_custom = __TS__Class()
local axe_one_man_army_custom = ____exports.axe_one_man_army_custom
axe_one_man_army_custom.name = "axe_one_man_army_custom"
axe_one_man_army_custom.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_one_man_army_custom.lua"
__TS__ClassExtends(axe_one_man_army_custom, BaseAbility)
function axe_one_man_army_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_axe_one_man_army_custom.name
end
axe_one_man_army_custom = __TS__Decorate(
axe_one_man_army_custom,
axe_one_man_army_custom,
{registerAbility(nil)},
{kind = "class", name = "axe_one_man_army_custom"}
)
____exports.axe_one_man_army_custom = axe_one_man_army_custom
____exports.modifier_axe_one_man_army_custom = __TS__Class()
local modifier_axe_one_man_army_custom = ____exports.modifier_axe_one_man_army_custom
modifier_axe_one_man_army_custom.name = "modifier_axe_one_man_army_custom"
modifier_axe_one_man_army_custom.____file_path = "scripts/vscripts/abilities/heroes/axe/axe_one_man_army_custom.lua"
__TS__ClassExtends(modifier_axe_one_man_army_custom, BaseModifier)
function modifier_axe_one_man_army_custom.prototype.IsHidden(self)
return true
end
function modifier_axe_one_man_army_custom.prototype.IsPurgable(self)
return false
end
function modifier_axe_one_man_army_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_STATS_STRENGTH_BONUS}
end
function modifier_axe_one_man_army_custom.prototype.GetModifierBonusStats_Strength(self)
local parent = self:GetParent()
if parent:PassivesDisabled() then
return 0
end
local ability = self:GetAbility()
if not ability or parent:IsIllusion() then
return 0
end
local factor = ability:GetSpecialValueFor("armor_to_str")
local allies = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
ability:GetSpecialValueFor("radius"),
DOTA_UNIT_TARGET_TEAM_FRIENDLY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, u in ipairs(allies) do
do
if u == parent then
goto __continue9
end
if not u:IsRealHero() or u:IsIllusion() then
goto __continue9
end
return 0
end
::__continue9::
end
local armor = parent:GetPhysicalArmorValue(false)
return math.floor(armor * factor)
end
modifier_axe_one_man_army_custom = __TS__Decorate(
modifier_axe_one_man_army_custom,
modifier_axe_one_man_army_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_axe_one_man_army_custom"}
)
____exports.modifier_axe_one_man_army_custom = modifier_axe_one_man_army_custom
return ____exports
@@ -0,0 +1,221 @@
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 ____vampirism = require("utils.vampirism")
local addPhysicalVampirism = ____vampirism.addPhysicalVampirism
local reducePhysicalVampirism = ____vampirism.reducePhysicalVampirism
____exports.ability_bloodrage = __TS__Class()
local ability_bloodrage = ____exports.ability_bloodrage
ability_bloodrage.name = "ability_bloodrage"
ability_bloodrage.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_bloodrage.lua"
__TS__ClassExtends(ability_bloodrage, BaseAbility)
function ability_bloodrage.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
caster:AddNewModifier(
caster,
self,
____exports.modifier_bloodrage_buff.name,
{duration = self:GetSpecialValueFor("duration")}
)
EmitSoundOn("hero_bloodseeker.bloodRage", caster)
end
ability_bloodrage = __TS__Decorate(
ability_bloodrage,
ability_bloodrage,
{registerAbility(nil)},
{kind = "class", name = "ability_bloodrage"}
)
____exports.ability_bloodrage = ability_bloodrage
____exports.modifier_bloodrage_buff = __TS__Class()
local modifier_bloodrage_buff = ____exports.modifier_bloodrage_buff
modifier_bloodrage_buff.name = "modifier_bloodrage_buff"
modifier_bloodrage_buff.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_bloodrage.lua"
__TS__ClassExtends(modifier_bloodrage_buff, BaseModifier)
function modifier_bloodrage_buff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.bonusDamage = 0
self.bonusAttackSpeed = 0
self.stackDamage = 0
self.stackAttackspeed = 0
self.physicalVampirism = 0
self.stackPhysicalVampirism = 0
end
function modifier_bloodrage_buff.prototype.IsHidden(self)
return false
end
function modifier_bloodrage_buff.prototype.IsPurgable(self)
return false
end
function modifier_bloodrage_buff.prototype.IsDebuff(self)
return false
end
function modifier_bloodrage_buff.prototype.IsBuff(self)
return true
end
function modifier_bloodrage_buff.prototype.RemoveOnDeath(self)
return true
end
function modifier_bloodrage_buff.prototype.GetEffectName(self)
return "particles/econ/items/bloodseeker/bloodseeker_eztzhok_weapon/bloodseeker_bloodrage_eztzhok.vpcf"
end
function modifier_bloodrage_buff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_bloodrage_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE, MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT, MODIFIER_PROPERTY_PROCATTACK_FEEDBACK}
end
function modifier_bloodrage_buff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.bonusDamage = ability:GetSpecialValueFor("bonus_damage")
self.bonusAttackSpeed = ability:GetSpecialValueFor("bonus_attack_speed")
self.stackDamage = ability:GetSpecialValueFor("stack_damage")
self.stackAttackspeed = ability:GetSpecialValueFor("stack_attackspeed")
self.physicalVampirism = ability:GetSpecialValueFor("physical_vampirism")
self.stackPhysicalVampirism = 0
local parent = self:GetParent()
if parent:IsRealHero() then
addPhysicalVampirism(nil, parent, self.physicalVampirism)
end
self:StartIntervalThink(0.25)
self:OnIntervalThink()
end
function modifier_bloodrage_buff.prototype.OnRefresh(self)
local ability = self:GetAbility()
if not ability then
return
end
self.bonusDamage = ability:GetSpecialValueFor("bonus_damage")
self.bonusAttackSpeed = ability:GetSpecialValueFor("bonus_attack_speed")
self.stackDamage = ability:GetSpecialValueFor("stack_damage")
self.stackAttackspeed = ability:GetSpecialValueFor("stack_attackspeed")
self.physicalVampirism = ability:GetSpecialValueFor("physical_vampirism")
self.stackPhysicalVampirism = 0
self:StartIntervalThink(0.25)
self:OnIntervalThink()
end
function modifier_bloodrage_buff.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local currentHealth = parent:GetHealth()
local damage = 100 * 0.1
parent:SetHealth(math.max(currentHealth - damage, 1))
end
function modifier_bloodrage_buff.prototype.GetModifierProcAttack_Feedback(self, event)
if not IsServer() then
return 0
end
local parent = self:GetParent()
if parent:HasScepter() then
self:AddStack(40, 5)
else
self:AddStack(20, 2)
end
parent:CalculateStatBonus(true)
return 0
end
function modifier_bloodrage_buff.prototype.GetModifierPreAttack_BonusDamage(self)
return self.bonusDamage + self:GetStackCount() * self.stackDamage
end
function modifier_bloodrage_buff.prototype.GetModifierAttackSpeedBonus_Constant(self)
return self.bonusAttackSpeed + self:GetStackCount() * self.stackAttackspeed
end
function modifier_bloodrage_buff.prototype.AddStack(self, duration, count)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
local mod = parent:AddNewModifier(parent, ability, ____exports.modifier_bloodrage_count.name, {duration = duration})
if mod then
mod.modifier = self
mod.bonus = count
end
self:SetStackCount(self:GetStackCount() + count)
if parent:IsRealHero() then
addPhysicalVampirism(nil, parent, self.stackPhysicalVampirism)
end
end
function modifier_bloodrage_buff.prototype.RemoveStack(self, value)
if not IsServer() then
return
end
self:SetStackCount(self:GetStackCount() - value)
local parent = self:GetParent()
if parent:IsRealHero() then
reducePhysicalVampirism(nil, parent, self.stackPhysicalVampirism)
end
end
function modifier_bloodrage_buff.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if parent:IsRealHero() then
local totalPhysical = self.physicalVampirism + self:GetStackCount() * self.stackPhysicalVampirism
reducePhysicalVampirism(nil, parent, totalPhysical)
end
end
modifier_bloodrage_buff = __TS__Decorate(
modifier_bloodrage_buff,
modifier_bloodrage_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_bloodrage_buff"}
)
____exports.modifier_bloodrage_buff = modifier_bloodrage_buff
____exports.modifier_bloodrage_count = __TS__Class()
local modifier_bloodrage_count = ____exports.modifier_bloodrage_count
modifier_bloodrage_count.name = "modifier_bloodrage_count"
modifier_bloodrage_count.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_bloodrage.lua"
__TS__ClassExtends(modifier_bloodrage_count, BaseModifier)
function modifier_bloodrage_count.prototype.IsHidden(self)
return true
end
function modifier_bloodrage_count.prototype.IsPurgable(self)
return false
end
function modifier_bloodrage_count.prototype.IsDebuff(self)
return false
end
function modifier_bloodrage_count.prototype.IsBuff(self)
return true
end
function modifier_bloodrage_count.prototype.RemoveOnDeath(self)
return false
end
function modifier_bloodrage_count.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_bloodrage_count.prototype.OnRemoved(self)
if not IsServer() then
return
end
if self.modifier and self.bonus ~= nil then
self.modifier:RemoveStack(self.bonus)
end
end
modifier_bloodrage_count = __TS__Decorate(
modifier_bloodrage_count,
modifier_bloodrage_count,
{registerModifier(nil)},
{kind = "class", name = "modifier_bloodrage_count"}
)
____exports.modifier_bloodrage_count = modifier_bloodrage_count
return ____exports
@@ -0,0 +1,106 @@
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 ____ability_bloodrage = require("abilities.heroes.bloodhunter.ability_bloodrage")
local modifier_bloodrage_buff = ____ability_bloodrage.modifier_bloodrage_buff
____exports.ability_bloodstained_memory = __TS__Class()
local ability_bloodstained_memory = ____exports.ability_bloodstained_memory
ability_bloodstained_memory.name = "ability_bloodstained_memory"
ability_bloodstained_memory.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_bloodstained_memory.lua"
__TS__ClassExtends(ability_bloodstained_memory, BaseAbility)
function ability_bloodstained_memory.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_bloodstained_memory.name
end
ability_bloodstained_memory = __TS__Decorate(
ability_bloodstained_memory,
ability_bloodstained_memory,
{registerAbility(nil)},
{kind = "class", name = "ability_bloodstained_memory"}
)
____exports.ability_bloodstained_memory = ability_bloodstained_memory
____exports.modifier_bloodstained_memory = __TS__Class()
local modifier_bloodstained_memory = ____exports.modifier_bloodstained_memory
modifier_bloodstained_memory.name = "modifier_bloodstained_memory"
modifier_bloodstained_memory.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_bloodstained_memory.lua"
__TS__ClassExtends(modifier_bloodstained_memory, BaseModifier)
function modifier_bloodstained_memory.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.healthbonus = 0
self.movespeed = 0
end
function modifier_bloodstained_memory.prototype.IsHidden(self)
return false
end
function modifier_bloodstained_memory.prototype.IsPurgable(self)
return false
end
function modifier_bloodstained_memory.prototype.IsDebuff(self)
return false
end
function modifier_bloodstained_memory.prototype.RemoveOnDeath(self)
return true
end
function modifier_bloodstained_memory.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_HEALTH_BONUS, MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT, MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT}
end
function modifier_bloodstained_memory.prototype.OnCreated(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
self.healthbonus = ability:GetSpecialValueFor("healthbonus")
self.movespeed = ability:GetSpecialValueFor("movespeed")
self:StartIntervalThink(0.1)
end
function modifier_bloodstained_memory.prototype.OnIntervalThink(self)
self:OnCreated()
end
function modifier_bloodstained_memory.prototype.OnRefresh(self)
self:OnCreated()
end
function modifier_bloodstained_memory.prototype.GetModifierIgnoreMovespeedLimit(self)
if self:GetParent():PassivesDisabled() then
return 0
end
return 1
end
function modifier_bloodstained_memory.prototype.GetModifierHealthBonus(self)
local parent = self:GetParent()
if parent:PassivesDisabled() then
return 0
end
local bloodrageMod = parent:FindModifierByName(modifier_bloodrage_buff.name)
if not bloodrageMod then
return 0
end
return self.healthbonus * bloodrageMod:GetStackCount()
end
function modifier_bloodstained_memory.prototype.GetModifierMoveSpeedBonus_Constant(self)
local parent = self:GetParent()
if parent:PassivesDisabled() then
return 0
end
local bloodrageMod = parent:FindModifierByName(modifier_bloodrage_buff.name)
if not bloodrageMod then
return 0
end
return self.movespeed * bloodrageMod:GetStackCount()
end
modifier_bloodstained_memory = __TS__Decorate(
modifier_bloodstained_memory,
modifier_bloodstained_memory,
{registerModifier(nil)},
{kind = "class", name = "modifier_bloodstained_memory"}
)
____exports.modifier_bloodstained_memory = modifier_bloodstained_memory
return ____exports
@@ -0,0 +1,291 @@
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 ____ability_bloodrage = require("abilities.heroes.bloodhunter.ability_bloodrage")
local modifier_bloodrage_buff = ____ability_bloodrage.modifier_bloodrage_buff
local modifier_bloodrage_count = ____ability_bloodrage.modifier_bloodrage_count
____exports.ability_illusion_of_blood = __TS__Class()
local ability_illusion_of_blood = ____exports.ability_illusion_of_blood
ability_illusion_of_blood.name = "ability_illusion_of_blood"
ability_illusion_of_blood.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_illusion_of_blood.lua"
__TS__ClassExtends(ability_illusion_of_blood, BaseAbility)
function ability_illusion_of_blood.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.illusions = {}
end
function ability_illusion_of_blood.prototype.GetHealthCost(self, level)
return 0
end
function ability_illusion_of_blood.prototype.CastFilterResult(self)
local caster = self:GetCaster()
if not caster:HasModifier(modifier_bloodrage_buff.name) then
return UF_FAIL_CUSTOM
end
local modif = caster:FindModifierByName(modifier_bloodrage_buff.name)
if not modif then
return UF_FAIL_CUSTOM
end
local healthCost = self:GetHealthCost(self:GetLevel())
if modif:GetStackCount() < healthCost then
return UF_FAIL_CUSTOM
end
return UF_SUCCESS
end
function ability_illusion_of_blood.prototype.GetCustomCastError(self)
local caster = self:GetCaster()
if not caster:HasModifier(modifier_bloodrage_buff.name) then
return "#dota_hud_error_havent_charges"
end
local modif = caster:FindModifierByName(modifier_bloodrage_buff.name)
if not modif then
return "#dota_hud_error_havent_charges"
end
local healthCost = self:GetHealthCost(self:GetLevel())
if modif:GetStackCount() < healthCost then
return "#dota_hud_error_havent_charges"
end
return ""
end
function ability_illusion_of_blood.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local healthCost = self:GetHealthCost(self:GetLevel())
local modif = caster:FindModifierByName(modifier_bloodrage_buff.name)
if modif then
modif:SetStackCount(modif:GetStackCount() - healthCost)
end
local invDuration = self:GetSpecialValueFor("invuln_duration")
caster:AddNewModifier(caster, self, ____exports.modifier_illusion_of_blood.name, {duration = 0.5})
end
ability_illusion_of_blood = __TS__Decorate(
ability_illusion_of_blood,
ability_illusion_of_blood,
{registerAbility(nil)},
{kind = "class", name = "ability_illusion_of_blood"}
)
____exports.ability_illusion_of_blood = ability_illusion_of_blood
____exports.modifier_illusion_of_blood = __TS__Class()
local modifier_illusion_of_blood = ____exports.modifier_illusion_of_blood
modifier_illusion_of_blood.name = "modifier_illusion_of_blood"
modifier_illusion_of_blood.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_illusion_of_blood.lua"
__TS__ClassExtends(modifier_illusion_of_blood, BaseModifier)
function modifier_illusion_of_blood.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.imageCount = 0
self.imageDuration = 0
self.incomingDamage = 0
self.outgoingDamage = 0
self.magicResistance = 0
self.illusions = {}
self.spawnLoc = {}
self.spawnedUnits = 0
end
function modifier_illusion_of_blood.prototype.IsHidden(self)
return true
end
function modifier_illusion_of_blood.prototype.IsPurgable(self)
return true
end
function modifier_illusion_of_blood.prototype.IsDebuff(self)
return false
end
function modifier_illusion_of_blood.prototype.IsBuff(self)
return true
end
function modifier_illusion_of_blood.prototype.RemoveOnDeath(self)
return true
end
function modifier_illusion_of_blood.prototype.AllowIllusionDuplicate(self)
return false
end
function modifier_illusion_of_blood.prototype.CheckState(self)
return {
[MODIFIER_STATE_INVULNERABLE] = true,
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
[MODIFIER_STATE_UNSELECTABLE] = true,
[MODIFIER_STATE_OUT_OF_GAME] = true,
[MODIFIER_STATE_ROOTED] = true,
[MODIFIER_STATE_UNTARGETABLE] = true
}
end
function modifier_illusion_of_blood.prototype.OnCreated(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
self.imageCount = ability:GetSpecialValueFor("images_count")
self.imageDuration = ability:GetSpecialValueFor("illusion_duration")
self.incomingDamage = ability:GetSpecialValueFor("incoming_damage")
self.outgoingDamage = ability:GetSpecialValueFor("outgoing_damage")
self.magicResistance = ability:GetSpecialValueFor("magic_resistance")
local caster = self:GetParent()
self.illusions = {}
caster:Purge(
false,
true,
false,
false,
false
)
caster:Stop()
local abilityInstance = ability
if abilityInstance ~= nil and abilityInstance ~= nil and abilityInstance.illusions ~= nil and abilityInstance.illusions ~= nil then
for ____, illusion in ipairs(abilityInstance.illusions) do
if IsValidEntity(illusion) and illusion:IsAlive() then
illusion:ForceKill(false)
end
end
abilityInstance.illusions = {}
end
local distance = 135
local spawn = {}
spawn[1] = caster:GetAbsOrigin()
local rightVector = caster:GetRightVector():Normalized()
local forwardVector = caster:GetForwardVector():Normalized()
spawn[2] = spawn[1] + rightVector * distance
spawn[3] = spawn[1] + rightVector * -distance
spawn[4] = spawn[1] + forwardVector * -distance
spawn[5] = spawn[1] + forwardVector * distance
local realPos = RandomInt(0, #spawn - 1)
self.spawnSelf = spawn[realPos + 1]
self.spawnLoc = {}
do
local i = 0
while i < self.imageCount do
local sp = i
if sp == realPos then
sp = self.imageCount + 1
end
self.spawnLoc[i + 1] = spawn[sp + 1]
i = i + 1
end
end
self.spawnedUnits = 0
self.effectCast = ParticleManager:CreateParticle("particles/units/heroes/hero_chaos_knight/chaos_knight_phantasm.vpcf", PATTACH_ABSORIGIN, caster)
ParticleManager:SetParticleControl(self.effectCast, 0, spawn[1])
self:AddParticle(
self.effectCast,
false,
false,
-1,
false,
false
)
EmitSoundOn("Hero_ChaosKnight.Phantasm", caster)
end
function modifier_illusion_of_blood.prototype.CreateIllusionAndAdd(self, caster, location)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
local function modifyIllusion(____, illusion)
if not illusion:IsRealHero() then
return
end
local heroIllusion = illusion
local heroCaster = caster
heroIllusion:SetForwardVector(heroCaster:GetForwardVector())
while heroIllusion:GetLevel() < heroCaster:GetLevel() do
heroIllusion:HeroLevelUp(false)
end
heroIllusion:SetAbilityPoints(0)
do
local i = 0
while i < 24 do
local casterAbility = heroCaster:GetAbilityByIndex(i)
local illusionAbility = heroIllusion:GetAbilityByIndex(i)
if casterAbility and illusionAbility then
illusionAbility:SetLevel(casterAbility:GetLevel())
end
i = i + 1
end
end
do
local slot = 0
while slot <= 5 do
local item = heroCaster:GetItemInSlot(slot)
if item then
heroIllusion:AddItemByName(item:GetName())
end
slot = slot + 1
end
end
heroIllusion:MakeIllusion()
heroIllusion:SetControllableByPlayer(
heroCaster:GetPlayerID(),
false
)
heroIllusion:SetOwner(heroCaster)
illusion:AddNewModifier(caster, ability, "modifier_illusion", {duration = self.imageDuration, outgoing_damage = self.outgoingDamage, incoming_damage = self.incomingDamage})
illusion:AddNewModifier(caster, ability, modifier_bloodrage_buff.name, {duration = 100})
illusion:AddNewModifier(caster, ability, modifier_bloodrage_count.name, {duration = 100})
illusion:SetBaseMagicalResistanceValue(self.magicResistance)
local abilityInstance = ability
if abilityInstance ~= nil and abilityInstance ~= nil then
if abilityInstance.illusions == nil or abilityInstance.illusions == nil then
abilityInstance.illusions = {}
end
local ____abilityInstance_illusions_0 = abilityInstance.illusions
____abilityInstance_illusions_0[#____abilityInstance_illusions_0 + 1] = illusion
end
end
CreateUnitByNameAsync(
caster:GetUnitName(),
location,
false,
caster,
caster,
caster:GetTeamNumber(),
function(illusion) return modifyIllusion(nil, illusion) end
)
end
function modifier_illusion_of_blood.prototype.OnDestroy(self)
if not IsServer() then
return
end
if self.spawnSelf then
FindClearSpaceForUnit(
self:GetParent(),
self.spawnSelf,
true
)
end
local loop = true
while loop do
if self.spawnedUnits < #self.spawnLoc then
self:CreateIllusionAndAdd(
self:GetParent(),
self.spawnLoc[self.spawnedUnits + 1]
)
self.spawnedUnits = self.spawnedUnits + 1
if self.spawnedUnits >= self.imageCount then
loop = false
end
else
loop = false
end
end
end
modifier_illusion_of_blood = __TS__Decorate(
modifier_illusion_of_blood,
modifier_illusion_of_blood,
{registerModifier(nil)},
{kind = "class", name = "modifier_illusion_of_blood"}
)
____exports.modifier_illusion_of_blood = modifier_illusion_of_blood
return ____exports
@@ -0,0 +1,227 @@
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
____exports.ability_ring_of_corrosive = __TS__Class()
local ability_ring_of_corrosive = ____exports.ability_ring_of_corrosive
ability_ring_of_corrosive.name = "ability_ring_of_corrosive"
ability_ring_of_corrosive.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_ring_of_corrosive.lua"
__TS__ClassExtends(ability_ring_of_corrosive, BaseAbility)
function ability_ring_of_corrosive.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function ability_ring_of_corrosive.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local duration = self:GetSpecialValueFor("duration")
CreateModifierThinker(
caster,
self,
____exports.modifier_ring_of_corrosive.name,
{duration = duration},
point,
caster:GetTeamNumber(),
false
)
end
ability_ring_of_corrosive = __TS__Decorate(
ability_ring_of_corrosive,
ability_ring_of_corrosive,
{registerAbility(nil)},
{kind = "class", name = "ability_ring_of_corrosive"}
)
____exports.ability_ring_of_corrosive = ability_ring_of_corrosive
____exports.modifier_ring_of_corrosive = __TS__Class()
local modifier_ring_of_corrosive = ____exports.modifier_ring_of_corrosive
modifier_ring_of_corrosive.name = "modifier_ring_of_corrosive"
modifier_ring_of_corrosive.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_ring_of_corrosive.lua"
__TS__ClassExtends(modifier_ring_of_corrosive, BaseModifier)
function modifier_ring_of_corrosive.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.interval = 0
self.damage = 0
self.radius = 0
self.thinker = false
end
function modifier_ring_of_corrosive.prototype.IsHidden(self)
return false
end
function modifier_ring_of_corrosive.prototype.IsDebuff(self)
return true
end
function modifier_ring_of_corrosive.prototype.IsStunDebuff(self)
return false
end
function modifier_ring_of_corrosive.prototype.IsPurgable(self)
return false
end
function modifier_ring_of_corrosive.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
self.interval = ability:GetSpecialValueFor("tick_rate")
self.damage = ability:GetSpecialValueFor("damage")
self.radius = ability:GetSpecialValueFor("radius")
self.thinker = params.isProvidedByAura ~= 1
if not self.thinker then
return
end
self.soundCast = "Hero_Warlock.Upheaval"
EmitSoundOn(
self.soundCast,
self:GetParent()
)
self:StartIntervalThink(self.interval)
self:OnIntervalThink()
self:PlayEffects()
end
function modifier_ring_of_corrosive.prototype.OnRefresh(self)
end
function modifier_ring_of_corrosive.prototype.OnRemoved(self)
end
function modifier_ring_of_corrosive.prototype.OnDestroy(self)
if not IsServer() then
return
end
if not self.thinker then
return
end
if self.soundCast then
StopSoundOn(
self.soundCast,
self:GetParent()
)
end
local parent = self:GetParent()
if IsValidEntity(parent) then
UTIL_Remove(parent)
end
end
function modifier_ring_of_corrosive.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local ability = self:GetAbility()
if not caster or not ability then
return
end
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
self:GetParent():GetAbsOrigin(),
nil,
self.radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
do
if not enemy or not enemy:IsAlive() then
goto __continue23
end
local baseDamage = self:GetParent():GetBaseDamageMax() * 3
local damageTick = self.damage * baseDamage * self.interval
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damageTick,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
end
::__continue23::
end
end
function modifier_ring_of_corrosive.prototype.DeclareFunctions(self)
return {}
end
function modifier_ring_of_corrosive.prototype.IsAura(self)
return self.thinker
end
function modifier_ring_of_corrosive.prototype.GetModifierAura(self)
return ____exports.modifier_ring_of_corrosive.name
end
function modifier_ring_of_corrosive.prototype.GetAuraRadius(self)
return self.radius
end
function modifier_ring_of_corrosive.prototype.GetAuraDuration(self)
return 0.5
end
function modifier_ring_of_corrosive.prototype.GetAuraSearchTeam(self)
return DOTA_UNIT_TARGET_TEAM_ENEMY
end
function modifier_ring_of_corrosive.prototype.GetAuraSearchType(self)
return bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC)
end
function modifier_ring_of_corrosive.prototype.GetAuraSearchFlags(self)
return DOTA_UNIT_TARGET_FLAG_NONE
end
function modifier_ring_of_corrosive.prototype.PlayEffects(self)
if not IsServer() then
return
end
local particleCast = "particles/units/heroes/hero_bloodseeker/bloodseeker_bloodritual_ring_lv.vpcf"
local effectCast = ParticleManager:CreateParticle(
particleCast,
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
effectCast,
0,
self:GetParent():GetAbsOrigin()
)
ParticleManager:SetParticleControl(
effectCast,
1,
Vector(self.radius, 1, 1)
)
local particleCast2 = "particles/units/heroes/hero_bloodseeker/bloodseeker_spell_bloodbath_bubbles_.vpcf"
local effectCast2 = ParticleManager:CreateParticle(
particleCast2,
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
effectCast2,
0,
self:GetParent():GetAbsOrigin()
)
ParticleManager:SetParticleControl(
effectCast2,
1,
Vector(self.radius, 1, 1)
)
self:AddParticle(
effectCast2,
false,
false,
-1,
false,
false
)
end
modifier_ring_of_corrosive = __TS__Decorate(
modifier_ring_of_corrosive,
modifier_ring_of_corrosive,
{registerModifier(nil)},
{kind = "class", name = "modifier_ring_of_corrosive"}
)
____exports.modifier_ring_of_corrosive = modifier_ring_of_corrosive
return ____exports
@@ -0,0 +1,205 @@
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 ____ability_bloodrage = require("abilities.heroes.bloodhunter.ability_bloodrage")
local modifier_bloodrage_buff = ____ability_bloodrage.modifier_bloodrage_buff
____exports.ability_sacrifice_revenge = __TS__Class()
local ability_sacrifice_revenge = ____exports.ability_sacrifice_revenge
ability_sacrifice_revenge.name = "ability_sacrifice_revenge"
ability_sacrifice_revenge.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_sacrifice_revenge.lua"
__TS__ClassExtends(ability_sacrifice_revenge, BaseAbility)
function ability_sacrifice_revenge.prototype.GetHealthCost(self, level)
return 0
end
function ability_sacrifice_revenge.prototype.CastFilterResult(self)
local caster = self:GetCaster()
if not caster:HasModifier(modifier_bloodrage_buff.name) then
return UF_FAIL_CUSTOM
end
local modif = caster:FindModifierByName(modifier_bloodrage_buff.name)
if not modif then
return UF_FAIL_CUSTOM
end
local healthCost = self:GetHealthCost(self:GetLevel())
if modif:GetStackCount() < healthCost then
return UF_FAIL_CUSTOM
end
return UF_SUCCESS
end
function ability_sacrifice_revenge.prototype.GetCustomCastError(self)
local caster = self:GetCaster()
if not caster:HasModifier(modifier_bloodrage_buff.name) then
return "#dota_hud_error_havent_charges"
end
local modif = caster:FindModifierByName(modifier_bloodrage_buff.name)
if not modif then
return "#dota_hud_error_havent_charges"
end
local healthCost = self:GetHealthCost(self:GetLevel())
if modif:GetStackCount() < healthCost then
return "#dota_hud_error_havent_charges"
end
return ""
end
function ability_sacrifice_revenge.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local healthCost = self:GetHealthCost(self:GetLevel())
local modif = caster:FindModifierByName(modifier_bloodrage_buff.name)
if modif then
modif:SetStackCount(modif:GetStackCount() - healthCost)
end
caster:Purge(
false,
true,
false,
false,
false
)
caster:AddNewModifier(
caster,
self,
____exports.modifier_sacrifice_revenge.name,
{duration = self:GetSpecialValueFor("transformation_time")}
)
EmitSoundOn("hero_bloodseeker.rupture", caster)
end
ability_sacrifice_revenge = __TS__Decorate(
ability_sacrifice_revenge,
ability_sacrifice_revenge,
{registerAbility(nil)},
{kind = "class", name = "ability_sacrifice_revenge"}
)
____exports.ability_sacrifice_revenge = ability_sacrifice_revenge
____exports.modifier_sacrifice_revenge = __TS__Class()
local modifier_sacrifice_revenge = ____exports.modifier_sacrifice_revenge
modifier_sacrifice_revenge.name = "modifier_sacrifice_revenge"
modifier_sacrifice_revenge.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_sacrifice_revenge.lua"
__TS__ClassExtends(modifier_sacrifice_revenge, BaseModifier)
function modifier_sacrifice_revenge.prototype.IsHidden(self)
return true
end
function modifier_sacrifice_revenge.prototype.GetEffectName(self)
return "particles/econ/items/lifestealer/ls_ti10_immortal/ls_ti10_immortal_infest_gold.vpcf"
end
function modifier_sacrifice_revenge.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN
end
function modifier_sacrifice_revenge.prototype.OnCreated(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if parent:GetUnitName() == "npc_dota_hero_bloodseeker" then
parent:StartGesture(ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_START)
end
end
function modifier_sacrifice_revenge.prototype.OnDestroy(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local ability = self:GetAbility()
if not caster or not ability then
return
end
caster:AddNewModifier(
caster,
ability,
____exports.modifier_sacrifice_revenge_buff.name,
{duration = ability:GetSpecialValueFor("duration")}
)
end
modifier_sacrifice_revenge = __TS__Decorate(
modifier_sacrifice_revenge,
modifier_sacrifice_revenge,
{registerModifier(nil)},
{kind = "class", name = "modifier_sacrifice_revenge"}
)
____exports.modifier_sacrifice_revenge = modifier_sacrifice_revenge
____exports.modifier_sacrifice_revenge_buff = __TS__Class()
local modifier_sacrifice_revenge_buff = ____exports.modifier_sacrifice_revenge_buff
modifier_sacrifice_revenge_buff.name = "modifier_sacrifice_revenge_buff"
modifier_sacrifice_revenge_buff.____file_path = "scripts/vscripts/abilities/heroes/bloodhunter/ability_sacrifice_revenge.lua"
__TS__ClassExtends(modifier_sacrifice_revenge_buff, BaseModifier)
function modifier_sacrifice_revenge_buff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.bonusArmor = 0
self.baseAttackTime = 0
self.pureDamage = 0
end
function modifier_sacrifice_revenge_buff.prototype.IsHidden(self)
return false
end
function modifier_sacrifice_revenge_buff.prototype.IsPurgable(self)
return false
end
function modifier_sacrifice_revenge_buff.prototype.IsDebuff(self)
return false
end
function modifier_sacrifice_revenge_buff.prototype.IsBuff(self)
return true
end
function modifier_sacrifice_revenge_buff.prototype.AllowIllusionDuplicate(self)
return true
end
function modifier_sacrifice_revenge_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS, MODIFIER_PROPERTY_BASE_ATTACK_TIME_CONSTANT, MODIFIER_PROPERTY_PROCATTACK_BONUS_DAMAGE_PURE}
end
function modifier_sacrifice_revenge_buff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_ursa/ursa_enrage_buff_2.vpcf"
end
function modifier_sacrifice_revenge_buff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_sacrifice_revenge_buff.prototype.StatusEffectPriority(self)
return 10
end
function modifier_sacrifice_revenge_buff.prototype.HeroEffectPriority(self)
return 10
end
function modifier_sacrifice_revenge_buff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.bonusArmor = ability:GetSpecialValueFor("bonus_armor")
self.baseAttackTime = ability:GetSpecialValueFor("base_attack_time")
self.pureDamage = ability:GetSpecialValueFor("pure_damage")
end
function modifier_sacrifice_revenge_buff.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if parent:GetUnitName() == "npc_dota_hero_bloodseeker" then
parent:StartGesture(ACT_DOTA_ALCHEMIST_CHEMICAL_RAGE_END)
end
end
function modifier_sacrifice_revenge_buff.prototype.GetModifierPhysicalArmorBonus(self)
return self:GetParent():GetPhysicalArmorBaseValue() * 2
end
function modifier_sacrifice_revenge_buff.prototype.GetModifierProcAttack_BonusDamage_Pure(self, event)
local damage = self:GetParent():GetAverageTrueAttackDamage(event.target) * (self.pureDamage / 100)
return damage
end
function modifier_sacrifice_revenge_buff.prototype.GetModifierBaseAttackTimeConstant(self)
return self.baseAttackTime
end
modifier_sacrifice_revenge_buff = __TS__Decorate(
modifier_sacrifice_revenge_buff,
modifier_sacrifice_revenge_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_sacrifice_revenge_buff"}
)
____exports.modifier_sacrifice_revenge_buff = modifier_sacrifice_revenge_buff
return ____exports
@@ -0,0 +1,303 @@
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 ____incoming_damage_reduction_combine = require("utils.incoming_damage_reduction_combine")
local removeIncomingDamageReductionSource = ____incoming_damage_reduction_combine.removeIncomingDamageReductionSource
local setIncomingDamageReductionEventSource = ____incoming_damage_reduction_combine.setIncomingDamageReductionEventSource
local BRISTLEBACK_INCOMING_SOURCE = "modifier_bristleback_bristleback_custom"
____exports.bristleback_bristleback_custom = __TS__Class()
local bristleback_bristleback_custom = ____exports.bristleback_bristleback_custom
bristleback_bristleback_custom.name = "bristleback_bristleback_custom"
bristleback_bristleback_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_bristleback_custom.lua"
__TS__ClassExtends(bristleback_bristleback_custom, BaseAbility)
function bristleback_bristleback_custom.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.caster = self:GetCaster()
end
function bristleback_bristleback_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_bristleback_bristleback_custom.name
end
function bristleback_bristleback_custom.prototype.IsFacingBack(self, attacker)
local convert_attacker = EntIndexToHScript(attacker)
local forwardVector = self.caster:GetForwardVector()
local forwardAngle = math.deg(math.atan2(forwardVector.x, forwardVector.y))
local reverseEnemyVector = (self.caster:GetAbsOrigin() - convert_attacker:GetAbsOrigin()):Normalized()
local reverseEnemyAngle = math.deg(math.atan2(reverseEnemyVector.x, reverseEnemyVector.y))
local back_angle = self:GetSpecialValueFor("back_angle")
local difference = math.abs(forwardAngle - reverseEnemyAngle)
if difference <= back_angle / 1 or difference >= 360 - back_angle / 1 then
return true
end
return false
end
function bristleback_bristleback_custom.prototype.IncStacks(self, add_stack)
local stack = add_stack
local mod = self.caster:FindModifierByName(____exports.modifier_bristleback_bristleback_custom.name)
local quill_release_threshold = self:GetSpecialValueFor("quill_release_threshold")
if mod == nil then
return
end
local all_stack = mod:GetStackCount() + stack
if self.caster:HasScepter() then
local scepter_thresholds = {
self:GetSpecialValueFor("quill_release_threshold"),
self:GetSpecialValueFor("quill_release_threshold_scepter1"),
self:GetSpecialValueFor("quill_release_threshold_scepter2"),
self:GetSpecialValueFor("quill_release_threshold_scepter3"),
self:GetSpecialValueFor("quill_release_threshold_scepter4")
}
local spray_count = 0
if all_stack >= scepter_thresholds[5] then
spray_count = 5
elseif all_stack >= scepter_thresholds[4] and all_stack < scepter_thresholds[5] then
spray_count = 4
elseif all_stack >= scepter_thresholds[3] and all_stack < scepter_thresholds[4] then
spray_count = 3
elseif all_stack >= scepter_thresholds[2] and all_stack < scepter_thresholds[3] then
spray_count = 2
elseif all_stack >= scepter_thresholds[1] and all_stack < scepter_thresholds[2] then
spray_count = 1
end
if spray_count >= 1 then
do
local i = 0
while i < spray_count do
____exports.modifier_bristleback_bristleback_custom_make_spray:apply(self.caster, self.caster, self, {})
i = i + 1
end
end
mod:SetStackCount(all_stack - spray_count * quill_release_threshold)
return
end
end
if all_stack >= quill_release_threshold then
local count = math.floor(all_stack / quill_release_threshold)
do
local i = 0
while i < count do
____exports.modifier_bristleback_bristleback_custom_make_spray:apply(self.caster, self.caster, self, {})
i = i + 1
end
end
mod:SetStackCount(all_stack - count * quill_release_threshold)
else
mod:SetStackCount(all_stack)
end
end
bristleback_bristleback_custom = __TS__Decorate(
bristleback_bristleback_custom,
bristleback_bristleback_custom,
{registerAbility(nil)},
{kind = "class", name = "bristleback_bristleback_custom"}
)
____exports.bristleback_bristleback_custom = bristleback_bristleback_custom
____exports.modifier_bristleback_bristleback_custom = __TS__Class()
local modifier_bristleback_bristleback_custom = ____exports.modifier_bristleback_bristleback_custom
modifier_bristleback_bristleback_custom.name = "modifier_bristleback_bristleback_custom"
modifier_bristleback_bristleback_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_bristleback_custom.lua"
__TS__ClassExtends(modifier_bristleback_bristleback_custom, BaseModifier)
function modifier_bristleback_bristleback_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.ability = self:GetAbility()
self.parent = self:GetParent()
self.side_angle = 0
self.back_angle = 0
end
function modifier_bristleback_bristleback_custom.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_bristleback_custom.prototype.IsPurgeException(self)
return false
end
function modifier_bristleback_bristleback_custom.prototype.IsHidden(self)
return true
end
function modifier_bristleback_bristleback_custom.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_TAKEDAMAGE}
end
function modifier_bristleback_bristleback_custom.prototype.OnCreated(self)
self.side_angle = self.ability:GetSpecialValueFor("side_angle")
self.back_angle = self.ability:GetSpecialValueFor("back_angle")
if not IsServer() then
return
end
setIncomingDamageReductionEventSource(
nil,
self.parent,
BRISTLEBACK_INCOMING_SOURCE,
function(____, event)
if self.parent:PassivesDisabled() then
return 0
end
if bit.band(event.damage_flags, DOTA_DAMAGE_FLAG_REFLECTION) == DOTA_DAMAGE_FLAG_REFLECTION then
return 0
end
if bit.band(event.damage_flags, DOTA_DAMAGE_FLAG_HPLOSS) == DOTA_DAMAGE_FLAG_HPLOSS then
return 0
end
local forwardVector = self.parent:GetForwardVector()
local forwardAngle = math.deg(math.atan2(forwardVector.x, forwardVector.y))
local reverseEnemyVector = (self.parent:GetAbsOrigin() - event.attacker:GetAbsOrigin()):Normalized()
local reverseEnemyAngle = math.deg(math.atan2(reverseEnemyVector.x, reverseEnemyVector.y))
local difference = math.abs(forwardAngle - reverseEnemyAngle)
local sideDamageReduction = self.ability:GetSpecialValueFor("side_damage_reduction")
local backDamageReduction = self.ability:GetSpecialValueFor("back_damage_reduction")
if difference <= self.back_angle / 1 or difference >= 360 - self.back_angle / 1 then
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_bristleback/bristleback_back_dmg.vpcf", PATTACH_ABSORIGIN_FOLLOW, self.parent)
ParticleManager:SetParticleControl(
particle,
1,
self.parent:GetAbsOrigin()
)
ParticleManager:SetParticleControlEnt(
particle,
1,
self.parent,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
self.parent:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(particle)
local particle2 = ParticleManager:CreateParticle("particles/units/heroes/hero_bristleback/bristleback_back_lrg_dmg.vpcf", PATTACH_ABSORIGIN_FOLLOW, self.parent)
ParticleManager:SetParticleControlEnt(
particle2,
1,
self.parent,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
self.parent:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(particle2)
EmitSoundOn("Hero_Bristleback.Bristleback", self.parent)
return math.max(0, backDamageReduction)
end
if difference <= self.side_angle or difference >= 360 - self.side_angle then
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_bristleback/bristleback_back_dmg.vpcf", PATTACH_ABSORIGIN_FOLLOW, self.parent)
ParticleManager:SetParticleControl(
particle,
1,
self.parent:GetAbsOrigin()
)
ParticleManager:SetParticleControlEnt(
particle,
1,
self.parent,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
self.parent:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(particle)
return math.max(0, sideDamageReduction)
end
return 0
end
)
end
function modifier_bristleback_bristleback_custom.prototype.OnRefresh(self)
self:OnCreated()
end
function modifier_bristleback_bristleback_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
removeIncomingDamageReductionSource(nil, self.parent, BRISTLEBACK_INCOMING_SOURCE)
end
function modifier_bristleback_bristleback_custom.prototype.OnTakeDamage(self, event)
if event.attacker == nil then
return
end
if event.unit ~= self.parent then
return
end
if self.parent:PassivesDisabled() then
return
end
if bit.band(event.damage_flags, DOTA_DAMAGE_FLAG_REFLECTION) == DOTA_DAMAGE_FLAG_REFLECTION then
return
end
if bit.band(event.damage_flags, DOTA_DAMAGE_FLAG_HPLOSS) == DOTA_DAMAGE_FLAG_HPLOSS then
return
end
if not self.parent:HasAbility("bristleback_quill_spray_custom") then
return
end
if not self.parent:FindAbilityByName("bristleback_quill_spray_custom"):IsTrained() then
return
end
if self.ability:IsFacingBack(event.attacker:GetEntityIndex()) then
self.ability:IncStacks(event.damage)
end
end
modifier_bristleback_bristleback_custom = __TS__Decorate(
modifier_bristleback_bristleback_custom,
modifier_bristleback_bristleback_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_bristleback_custom"}
)
____exports.modifier_bristleback_bristleback_custom = modifier_bristleback_bristleback_custom
____exports.modifier_bristleback_bristleback_custom_make_spray = __TS__Class()
local modifier_bristleback_bristleback_custom_make_spray = ____exports.modifier_bristleback_bristleback_custom_make_spray
modifier_bristleback_bristleback_custom_make_spray.name = "modifier_bristleback_bristleback_custom_make_spray"
modifier_bristleback_bristleback_custom_make_spray.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_bristleback_custom.lua"
__TS__ClassExtends(modifier_bristleback_bristleback_custom_make_spray, BaseModifier)
function modifier_bristleback_bristleback_custom_make_spray.prototype.IsHidden(self)
return true
end
function modifier_bristleback_bristleback_custom_make_spray.prototype.OnCreated(self, params)
if not IsServer() then
return
end
self:SetStackCount(1)
self:Active()
self:StartIntervalThink(self:GetAbility():GetSpecialValueFor("quill_release_interval"))
end
function modifier_bristleback_bristleback_custom_make_spray.prototype.OnRefresh(self, params)
if not IsServer() then
return
end
self:IncrementStackCount()
end
function modifier_bristleback_bristleback_custom_make_spray.prototype.Active(self)
if not IsServer() then
return
end
if self:GetStackCount() <= 0 then
return
end
self:DecrementStackCount()
local ability_quill = self:GetParent():FindAbilityByName("bristleback_quill_spray_custom")
if not ability_quill then
return
end
if ability_quill:GetLevel() <= 0 then
return
end
ability_quill:MakeSpray(nil, true)
end
function modifier_bristleback_bristleback_custom_make_spray.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
self:Active()
if self:GetStackCount() <= 0 then
self:Destroy()
end
end
modifier_bristleback_bristleback_custom_make_spray = __TS__Decorate(
modifier_bristleback_bristleback_custom_make_spray,
modifier_bristleback_bristleback_custom_make_spray,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_bristleback_custom_make_spray"}
)
____exports.modifier_bristleback_bristleback_custom_make_spray = modifier_bristleback_bristleback_custom_make_spray
return ____exports
@@ -0,0 +1,87 @@
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 registerAbility = ____dota_ts_adapter.registerAbility
____exports.bristleback_hairball_custom = __TS__Class()
local bristleback_hairball_custom = ____exports.bristleback_hairball_custom
bristleback_hairball_custom.name = "bristleback_hairball_custom"
bristleback_hairball_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_hairball_custom.lua"
__TS__ClassExtends(bristleback_hairball_custom, BaseAbility)
function bristleback_hairball_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_hairball.vpcf", context)
PrecacheResource("model", "models/heroes/lanaya/lanaya_trap_crystal_invis.vmdl", context)
end
function bristleback_hairball_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
EmitSoundOn("Hero_Bristleback.Hairball.Cast", caster)
local projectile = {
Ability = self,
EffectName = "particles/units/heroes/hero_bristleback/bristleback_hairball.vpcf",
vSpawnOrigin = caster:GetAttachmentOrigin(caster:ScriptLookupAttachment("attach_hitloc")),
fDistance = (self:GetCursorPosition() - caster:GetAbsOrigin()):Length2D(),
fStartRadius = 0,
fEndRadius = 0,
Source = caster,
bHasFrontalCone = false,
bReplaceExisting = false,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_NONE,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = DOTA_UNIT_TARGET_NONE,
fExpireTime = GameRules:GetGameTime() + 5,
bDeleteOnHit = false,
vVelocity = (self:GetCursorPosition() - self:GetCaster():GetAbsOrigin()):Normalized() * self:GetSpecialValueFor("projectile_speed") * Vector(1, 1, 0),
bProvidesVision = false
}
ProjectileManager:CreateLinearProjectile(projectile)
end
function bristleback_hairball_custom.prototype.OnProjectileHit(self, target, vLocation)
if not IsServer() then
return
end
local caster = self:GetCaster()
local spray = caster:FindAbilityByName("bristleback_quill_spray_custom")
AddFOWViewer(
caster:GetTeamNumber(),
vLocation,
self:GetSpecialValueFor("radius"),
2,
false
)
self:AddGoo(vLocation, caster)
Timers:CreateTimer(
0.15,
function()
self:AddGoo(vLocation, caster)
end
)
if spray and spray:GetLevel() > 0 then
do
local i = 0
while i < self:GetSpecialValueFor("quill_stacks") do
spray:MakeSpray(
GetGroundPosition(vLocation, nil),
nil
)
i = i + 1
end
end
end
end
function bristleback_hairball_custom.prototype.AddGoo(self, vLocation, caster)
local goo = caster:FindAbilityByName("bristleback_viscous_nasal_goo_custom")
if goo and goo:GetLevel() > 0 then
goo:OnCustomSpellStart(nil, vLocation)
end
end
bristleback_hairball_custom = __TS__Decorate(
bristleback_hairball_custom,
bristleback_hairball_custom,
{registerAbility(nil)},
{kind = "class", name = "bristleback_hairball_custom"}
)
____exports.bristleback_hairball_custom = bristleback_hairball_custom
return ____exports
@@ -0,0 +1,330 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
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
____exports.bristleback_quill_spray_custom = __TS__Class()
local bristleback_quill_spray_custom = ____exports.bristleback_quill_spray_custom
bristleback_quill_spray_custom.name = "bristleback_quill_spray_custom"
bristleback_quill_spray_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_quill_spray_custom.lua"
__TS__ClassExtends(bristleback_quill_spray_custom, BaseAbility)
function bristleback_quill_spray_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_quill_spray.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_quill_spray_impact.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_quill_spray_hit.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_quill_spray_hit_creep.vpcf", context)
end
function bristleback_quill_spray_custom.prototype.GetCastRange(self, location, target)
return self:GetSpecialValueFor("radius")
end
function bristleback_quill_spray_custom.prototype.OnSpellStart(self)
self:MakeSpray(nil, nil)
end
function bristleback_quill_spray_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_bristleback_quill_spray_autocast_custom.name
end
function bristleback_quill_spray_custom.prototype.MakeSpray(self, location, isPassive)
if not IsServer() then
return
end
local caster = self:GetCaster()
local projectile_speed = self:GetSpecialValueFor("projectile_speed")
local radius = self:GetSpecialValueFor("radius")
local duration = radius / projectile_speed
if location == nil then
caster:FadeGesture(ACT_DOTA_CAST_ABILITY_2)
caster:StartGesture(ACT_DOTA_CAST_ABILITY_2)
end
local x = nil
local y = nil
if location ~= nil then
x = location.x
y = location.y
end
____exports.modifier_bristleback_quillspray_custom_thinker:apply(caster, caster, self, {x = x, y = y, duration = duration, passive = isPassive})
EmitSoundOn("Hero_Bristleback.QuillSpray.Cast", caster)
end
bristleback_quill_spray_custom = __TS__Decorate(
bristleback_quill_spray_custom,
bristleback_quill_spray_custom,
{registerAbility(nil)},
{kind = "class", name = "bristleback_quill_spray_custom"}
)
____exports.bristleback_quill_spray_custom = bristleback_quill_spray_custom
____exports.modifier_bristleback_quill_spray_autocast_custom = __TS__Class()
local modifier_bristleback_quill_spray_autocast_custom = ____exports.modifier_bristleback_quill_spray_autocast_custom
modifier_bristleback_quill_spray_autocast_custom.name = "modifier_bristleback_quill_spray_autocast_custom"
modifier_bristleback_quill_spray_autocast_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_quill_spray_custom.lua"
__TS__ClassExtends(modifier_bristleback_quill_spray_autocast_custom, BaseModifier)
function modifier_bristleback_quill_spray_autocast_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.ability = self:GetAbility()
end
function modifier_bristleback_quill_spray_autocast_custom.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_quill_spray_autocast_custom.prototype.IsPurgeException(self)
return false
end
function modifier_bristleback_quill_spray_autocast_custom.prototype.IsHidden(self)
return true
end
function modifier_bristleback_quill_spray_autocast_custom.prototype.OnCreated(self, params)
self:StartIntervalThink(0.1)
end
function modifier_bristleback_quill_spray_autocast_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if self.ability:GetAutoCastState() == true and self.ability:IsFullyCastable() and not parent:IsChanneling() and not self.ability:IsHidden() then
parent:CastAbilityNoTarget(
self.ability,
parent:GetPlayerID()
)
end
end
modifier_bristleback_quill_spray_autocast_custom = __TS__Decorate(
modifier_bristleback_quill_spray_autocast_custom,
modifier_bristleback_quill_spray_autocast_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_quill_spray_autocast_custom"}
)
____exports.modifier_bristleback_quill_spray_autocast_custom = modifier_bristleback_quill_spray_autocast_custom
____exports.modifier_bristleback_quillspray_custom_thinker = __TS__Class()
local modifier_bristleback_quillspray_custom_thinker = ____exports.modifier_bristleback_quillspray_custom_thinker
modifier_bristleback_quillspray_custom_thinker.name = "modifier_bristleback_quillspray_custom_thinker"
modifier_bristleback_quillspray_custom_thinker.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_quill_spray_custom.lua"
__TS__ClassExtends(modifier_bristleback_quillspray_custom_thinker, BaseModifier)
function modifier_bristleback_quillspray_custom_thinker.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.caster = self:GetCaster()
self.parent = self:GetParent()
self.ability = self:GetAbility()
self.radius = 0
self.quill_base_damage = 0
self.quill_stack_damage = 0
self.quill_stack_duration = 0
self.max_damage = 0
self.attack_damage_bonus_pct = 0
self.hit_enemies = {}
self.cast_point = Vector(0, 0, 0)
self.passive = false
end
function modifier_bristleback_quillspray_custom_thinker.prototype.IsHidden(self)
return true
end
function modifier_bristleback_quillspray_custom_thinker.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_quillspray_custom_thinker.prototype.RemoveOnDeath(self)
return false
end
function modifier_bristleback_quillspray_custom_thinker.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_bristleback_quillspray_custom_thinker.prototype.OnCreated(self, params)
self.radius = self.ability:GetSpecialValueFor("radius")
self.quill_base_damage = self.ability:GetSpecialValueFor("quill_base_damage")
self.quill_stack_damage = self.ability:GetSpecialValueFor("quill_stack_damage")
self.quill_stack_duration = self.ability:GetSpecialValueFor("quill_stack_duration")
self.max_damage = self.ability:GetSpecialValueFor("max_damage")
self.attack_damage_bonus_pct = self.ability:GetSpecialValueFor("attack_damage_bonus_pct")
self.passive = params.passive
if not IsServer() then
return
end
self.cast_point = self.parent:GetAbsOrigin()
if params.x ~= nil and params.y ~= nil then
self.cast_point = GetGroundPosition(
Vector(params.x, params.y, 0),
nil
)
end
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_bristleback/bristleback_quill_spray.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particle, 0, self.cast_point)
self:AddParticle(
particle,
false,
false,
-1,
false,
false
)
self.hit_enemies = {}
self:StartIntervalThink(FrameTime())
end
function modifier_bristleback_quillspray_custom_thinker.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local radius_pct = math.min(
(self:GetDuration() - self:GetRemainingTime()) / self:GetDuration(),
1
)
local origin = self.cast_point
local enemies = FindUnitsInRadius(
self.parent:GetTeamNumber(),
origin,
nil,
self.radius * radius_pct,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_CREEP,
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES,
FIND_ANY_ORDER,
false
)
__TS__ArrayForEach(
enemies,
function(____, enemy)
if not (self.hit_enemies[enemy:GetEntityIndex()] ~= nil) then
self.hit_enemies[enemy:GetEntityIndex()] = true
local quill_spray_stacks = 0
local quill_spray_modifier = enemy:FindModifierByName("modifier_bristleback_quill_spray_custom")
if quill_spray_modifier ~= nil then
quill_spray_stacks = quill_spray_modifier:GetStackCount()
end
local attackBonus = self.caster:GetAverageTrueAttackDamage(enemy) * self.attack_damage_bonus_pct / 100
local damage_flags = DOTA_DAMAGE_FLAG_BYPASSES_BLOCK
ApplyDamage({
victim = enemy,
damage = math.min(self.quill_base_damage + self.quill_stack_damage * quill_spray_stacks + attackBonus, self.max_damage),
damage_type = DAMAGE_TYPE_PHYSICAL,
damage_flags = damage_flags,
attacker = self.caster,
ability = self.ability
})
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_bristleback/bristleback_quill_spray_impact.vpcf", PATTACH_ABSORIGIN_FOLLOW, enemy)
ParticleManager:SetParticleControlEnt(
particle,
1,
enemy,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
enemy:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(particle)
EmitSoundOn("Hero_Bristleback.QuillSpray.Target", enemy)
____exports.modifier_bristleback_quill_spray_custom:apply(
enemy,
self.caster,
self.ability,
{duration = self.quill_stack_duration * (1 - enemy:GetStatusResistance())}
)
____exports.modifier_bristleback_quill_spray_custom_count:apply(
enemy,
self.caster,
self.ability,
{duration = self.quill_stack_duration * (1 - enemy:GetStatusResistance())}
)
end
end
)
end
modifier_bristleback_quillspray_custom_thinker = __TS__Decorate(
modifier_bristleback_quillspray_custom_thinker,
modifier_bristleback_quillspray_custom_thinker,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_quillspray_custom_thinker"}
)
____exports.modifier_bristleback_quillspray_custom_thinker = modifier_bristleback_quillspray_custom_thinker
____exports.modifier_bristleback_quill_spray_custom = __TS__Class()
local modifier_bristleback_quill_spray_custom = ____exports.modifier_bristleback_quill_spray_custom
modifier_bristleback_quill_spray_custom.name = "modifier_bristleback_quill_spray_custom"
modifier_bristleback_quill_spray_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_quill_spray_custom.lua"
__TS__ClassExtends(modifier_bristleback_quill_spray_custom, BaseModifier)
function modifier_bristleback_quill_spray_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.parent = self:GetParent()
end
function modifier_bristleback_quill_spray_custom.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_quill_spray_custom.prototype.OnCreated(self, params)
if not IsServer() then
return
end
self:IncrementStackCount()
local particle_name = "particles/units/heroes/hero_bristleback/bristleback_quill_spray_hit.vpcf"
if self.parent:IsCreep() then
particle_name = "particles/units/heroes/hero_bristleback/bristleback_quill_spray_hit_creep.vpcf"
end
local particle = ParticleManager:CreateParticle(particle_name, PATTACH_ABSORIGIN_FOLLOW, self.parent)
ParticleManager:SetParticleControlEnt(
particle,
0,
self.parent,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
self.parent:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
particle,
1,
self.parent,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
self.parent:GetAbsOrigin(),
true
)
self:AddParticle(
particle,
false,
false,
-1,
false,
false
)
end
function modifier_bristleback_quill_spray_custom.prototype.OnRefresh(self, params)
if not IsServer() then
return
end
self:IncrementStackCount()
end
modifier_bristleback_quill_spray_custom = __TS__Decorate(
modifier_bristleback_quill_spray_custom,
modifier_bristleback_quill_spray_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_quill_spray_custom"}
)
____exports.modifier_bristleback_quill_spray_custom = modifier_bristleback_quill_spray_custom
____exports.modifier_bristleback_quill_spray_custom_count = __TS__Class()
local modifier_bristleback_quill_spray_custom_count = ____exports.modifier_bristleback_quill_spray_custom_count
modifier_bristleback_quill_spray_custom_count.name = "modifier_bristleback_quill_spray_custom_count"
modifier_bristleback_quill_spray_custom_count.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_quill_spray_custom.lua"
__TS__ClassExtends(modifier_bristleback_quill_spray_custom_count, BaseModifier)
function modifier_bristleback_quill_spray_custom_count.prototype.IsHidden(self)
return true
end
function modifier_bristleback_quill_spray_custom_count.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_quill_spray_custom_count.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_bristleback_quill_spray_custom_count.prototype.OnDestroy(self)
if not IsServer() then
return
end
local modifier = self:GetParent():FindModifierByName("modifier_bristleback_quill_spray_custom")
if modifier ~= nil then
modifier:DecrementStackCount()
end
end
modifier_bristleback_quill_spray_custom_count = __TS__Decorate(
modifier_bristleback_quill_spray_custom_count,
modifier_bristleback_quill_spray_custom_count,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_quill_spray_custom_count"}
)
____exports.modifier_bristleback_quill_spray_custom_count = modifier_bristleback_quill_spray_custom_count
return ____exports
@@ -0,0 +1,127 @@
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 ____hero_rage = require("abilities.system.hero_rage")
local heroRageGetCurrent = ____hero_rage.heroRageGetCurrent
local WARPATH_ACTIVE_PARTICLE = "particles/units/heroes/hero_bristleback/bristleback_warpath_active.vpcf"
____exports.bristleback_rage_fortitude_custom = __TS__Class()
local bristleback_rage_fortitude_custom = ____exports.bristleback_rage_fortitude_custom
bristleback_rage_fortitude_custom.name = "bristleback_rage_fortitude_custom"
bristleback_rage_fortitude_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_rage_fortitude_custom.lua"
__TS__ClassExtends(bristleback_rage_fortitude_custom, BaseAbility)
function bristleback_rage_fortitude_custom.prototype.Precache(self, context)
PrecacheResource("particle", WARPATH_ACTIVE_PARTICLE, context)
end
function bristleback_rage_fortitude_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_bristleback_rage_fortitude_custom.name
end
bristleback_rage_fortitude_custom = __TS__Decorate(
bristleback_rage_fortitude_custom,
bristleback_rage_fortitude_custom,
{registerAbility(nil)},
{kind = "class", name = "bristleback_rage_fortitude_custom"}
)
____exports.bristleback_rage_fortitude_custom = bristleback_rage_fortitude_custom
--- Следит за яростью и включает защитный бафф выше порога.
____exports.modifier_bristleback_rage_fortitude_custom = __TS__Class()
local modifier_bristleback_rage_fortitude_custom = ____exports.modifier_bristleback_rage_fortitude_custom
modifier_bristleback_rage_fortitude_custom.name = "modifier_bristleback_rage_fortitude_custom"
modifier_bristleback_rage_fortitude_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_rage_fortitude_custom.lua"
__TS__ClassExtends(modifier_bristleback_rage_fortitude_custom, BaseModifier)
function modifier_bristleback_rage_fortitude_custom.prototype.IsHidden(self)
return true
end
function modifier_bristleback_rage_fortitude_custom.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_rage_fortitude_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
self:StartIntervalThink(0.1)
self:OnIntervalThink()
end
function modifier_bristleback_rage_fortitude_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability or parent:PassivesDisabled() then
parent:RemoveModifierByName(____exports.modifier_bristleback_rage_fortitude_buff.name)
return
end
local threshold = ability:GetSpecialValueFor("rage_threshold")
local rage = heroRageGetCurrent(nil, parent)
local buffName = ____exports.modifier_bristleback_rage_fortitude_buff.name
if rage > threshold then
if not parent:HasModifier(buffName) then
parent:AddNewModifier(parent, ability, buffName, {})
end
else
parent:RemoveModifierByName(buffName)
end
end
function modifier_bristleback_rage_fortitude_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
self:GetParent():RemoveModifierByName(____exports.modifier_bristleback_rage_fortitude_buff.name)
end
modifier_bristleback_rage_fortitude_custom = __TS__Decorate(
modifier_bristleback_rage_fortitude_custom,
modifier_bristleback_rage_fortitude_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_rage_fortitude_custom"}
)
____exports.modifier_bristleback_rage_fortitude_custom = modifier_bristleback_rage_fortitude_custom
____exports.modifier_bristleback_rage_fortitude_buff = __TS__Class()
local modifier_bristleback_rage_fortitude_buff = ____exports.modifier_bristleback_rage_fortitude_buff
modifier_bristleback_rage_fortitude_buff.name = "modifier_bristleback_rage_fortitude_buff"
modifier_bristleback_rage_fortitude_buff.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_rage_fortitude_custom.lua"
__TS__ClassExtends(modifier_bristleback_rage_fortitude_buff, BaseModifier)
function modifier_bristleback_rage_fortitude_buff.prototype.IsHidden(self)
return false
end
function modifier_bristleback_rage_fortitude_buff.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_rage_fortitude_buff.prototype.IsDebuff(self)
return false
end
function modifier_bristleback_rage_fortitude_buff.prototype.GetTexture(self)
return "bristleback_warpath"
end
function modifier_bristleback_rage_fortitude_buff.prototype.CheckState(self)
return {[MODIFIER_STATE_DEBUFF_IMMUNE] = true}
end
function modifier_bristleback_rage_fortitude_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS, MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
end
function modifier_bristleback_rage_fortitude_buff.prototype.GetModifierMagicalResistanceBonus(self)
return self:GetAbility():GetSpecialValueFor("bonus_magic_resist")
end
function modifier_bristleback_rage_fortitude_buff.prototype.GetModifierPhysicalArmorBonus(self)
return self:GetAbility():GetSpecialValueFor("bonus_armor")
end
function modifier_bristleback_rage_fortitude_buff.prototype.GetEffectName(self)
return WARPATH_ACTIVE_PARTICLE
end
function modifier_bristleback_rage_fortitude_buff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_bristleback_rage_fortitude_buff = __TS__Decorate(
modifier_bristleback_rage_fortitude_buff,
modifier_bristleback_rage_fortitude_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_rage_fortitude_buff"}
)
____exports.modifier_bristleback_rage_fortitude_buff = modifier_bristleback_rage_fortitude_buff
return ____exports
@@ -0,0 +1,289 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ObjectAssign = ____lualib.__TS__ObjectAssign
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
____exports.bristleback_viscous_nasal_goo_custom = __TS__Class()
local bristleback_viscous_nasal_goo_custom = ____exports.bristleback_viscous_nasal_goo_custom
bristleback_viscous_nasal_goo_custom.name = "bristleback_viscous_nasal_goo_custom"
bristleback_viscous_nasal_goo_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_viscous_nasal_goo_custom.lua"
__TS__ClassExtends(bristleback_viscous_nasal_goo_custom, BaseAbility)
function bristleback_viscous_nasal_goo_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_viscous_nasal_goo.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_viscous_nasal_goo_debuff.vpcf", context)
PrecacheResource("particle", "particles/status_fx/status_effect_goo.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_bristleback/bristleback_viscous_nasal_stack.vpcf", context)
end
function bristleback_viscous_nasal_goo_custom.prototype.GetCastRange(self, location, target)
return self:GetSpecialValueFor("AbilityCastRange")
end
function bristleback_viscous_nasal_goo_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function bristleback_viscous_nasal_goo_custom.prototype.OnSpellStart(self)
local target = self:GetCursorTarget()
if not target then
return
end
self:OnCustomSpellStart(
target:entindex(),
nil
)
end
function bristleback_viscous_nasal_goo_custom.prototype.OnCustomSpellStart(self, target, location)
local caster = self:GetCaster()
local sourceCaster = caster
local sourceLocation = caster:GetAbsOrigin()
local shardAbility = caster:FindAbilityByName("bristleback_hairball_custom")
local shardRadius = shardAbility and shardAbility:GetSpecialValueFor("radius") or 0
local isShard = 0
if location ~= nil then
local shardUnit = CreateUnitByName(
"npc_dota_templar_assassin_psionic_trap",
location,
false,
caster,
caster,
caster:GetTeamNumber()
)
____exports.modifier_bristleback_viscous_nasal_goo_shard_unit:apply(shardUnit, nil, self, {duration = 1})
sourceLocation = shardUnit:GetAbsOrigin()
sourceCaster = shardUnit
isShard = 1
EmitSoundOn("Hero_Bristleback.ViscousGoo.Cast", shardUnit)
self:LaunchGooAtRadius(
caster,
sourceCaster,
sourceLocation,
shardRadius,
isShard
)
return
end
if target == nil then
return
end
local cursorTarget = EntIndexToHScript(target)
if not cursorTarget or cursorTarget:IsNull() then
return
end
EmitSoundOn("Hero_Bristleback.ViscousGoo.Cast", caster)
local radius = self:GetSpecialValueFor("radius")
self:LaunchGooAtRadius(
caster,
caster,
caster:GetAbsOrigin(),
radius,
isShard,
cursorTarget:GetAbsOrigin()
)
end
function bristleback_viscous_nasal_goo_custom.prototype.LaunchGooAtRadius(self, caster, sourceCaster, sourceLocation, radius, isShard, impactLocation)
local origin = impactLocation or sourceLocation
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
origin,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
if #enemies == 0 then
return
end
local projectile = {
Source = sourceCaster,
Ability = self,
iSourceAttachment = DOTA_PROJECTILE_ATTACHMENT_HITLOCATION,
EffectName = "particles/units/heroes/hero_bristleback/bristleback_viscous_nasal_goo.vpcf",
iMoveSpeed = self:GetSpecialValueFor("goo_speed"),
vSourceLoc = sourceLocation,
bDrawsOnMinimap = false,
bDodgeable = true,
bIsAttack = false,
bVisibleToEnemies = true,
bReplaceExisting = false,
flExpireTime = GameRules:GetGameTime() + 10,
bProvidesVision = false,
ExtraData = {is_shard = isShard}
}
for ____, enemy in ipairs(enemies) do
ProjectileManager:CreateTrackingProjectile(__TS__ObjectAssign({}, projectile, {Target = enemy}))
end
if caster:GetUnitName() == "npc_dota_hero_bristleback" then
EmitSoundOn(
"bristleback_bristle_nasal_goo_0" .. tostring(math.random(1, 7)),
caster
)
end
end
function bristleback_viscous_nasal_goo_custom.prototype.OnProjectileHit_ExtraData(self, target, location, ExtraData)
if target == nil or not target:IsAlive() or target:IsMagicImmune() then
return
end
if ExtraData.is_shard and ExtraData.is_shard == 0 then
if target:TriggerSpellAbsorb(self) then
return
end
end
local duration = self:GetSpecialValueFor("goo_duration")
local modifier = target:FindModifierByName(____exports.modifier_bristleback_viscous_nasal_goo_custom.name)
____exports.modifier_bristleback_viscous_nasal_goo_custom:apply(
target,
self:GetCaster(),
self,
{duration = duration * (1 - target:GetStatusResistance())}
):SetStackCount((modifier and modifier:GetStackCount() or 0) + 1)
EmitSoundOn("Hero_Bristleback.ViscousGoo.Target", target)
end
bristleback_viscous_nasal_goo_custom = __TS__Decorate(
bristleback_viscous_nasal_goo_custom,
bristleback_viscous_nasal_goo_custom,
{registerAbility(nil)},
{kind = "class", name = "bristleback_viscous_nasal_goo_custom"}
)
____exports.bristleback_viscous_nasal_goo_custom = bristleback_viscous_nasal_goo_custom
____exports.modifier_bristleback_viscous_nasal_goo_custom = __TS__Class()
local modifier_bristleback_viscous_nasal_goo_custom = ____exports.modifier_bristleback_viscous_nasal_goo_custom
modifier_bristleback_viscous_nasal_goo_custom.name = "modifier_bristleback_viscous_nasal_goo_custom"
modifier_bristleback_viscous_nasal_goo_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_viscous_nasal_goo_custom.lua"
__TS__ClassExtends(modifier_bristleback_viscous_nasal_goo_custom, BaseModifier)
function modifier_bristleback_viscous_nasal_goo_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.parent = self:GetParent()
self.movespeed_slow = 0
self.armor_reduce_pct = 0
self.armor_reduce_pct_per_stack = 0
self.movespeed_slow_per_stack = 0
self.ability = self:GetAbility()
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.IsHidden(self)
return false
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.IsPurgable(self)
return true
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.GetEffectName(self)
return "particles/units/heroes/hero_bristleback/bristleback_viscous_nasal_goo_debuff.vpcf"
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_goo.vpcf"
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.StatusEffectPriority(self)
return MODIFIER_PRIORITY_NORMAL
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.OnCreated(self, params)
self.movespeed_slow = self.ability:GetSpecialValueFor("base_move_slow")
self.armor_reduce_pct = self.ability:GetSpecialValueFor("base_armor_pct")
self.armor_reduce_pct_per_stack = self.ability:GetSpecialValueFor("armor_per_stack_pct")
self.movespeed_slow_per_stack = self.ability:GetSpecialValueFor("move_slow_per_stack")
self.particle = ParticleManager:CreateParticle("particles/units/heroes/hero_bristleback/bristleback_viscous_nasal_stack.vpcf", PATTACH_OVERHEAD_FOLLOW, self.parent)
ParticleManager:SetParticleControl(
self.particle,
1,
Vector(
0,
self:GetStackCount(),
0
)
)
self:AddParticle(
self.particle,
false,
false,
-1,
false,
false
)
self.isBoss = self.parent:IsBossCreature()
self:SetHasCustomTransmitterData(true)
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.AddCustomTransmitterData(self)
return {isBoss = self.isBoss, movespeed_total = self.movespeed_total}
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.HandleCustomTransmitterData(self, data)
self.isBoss = data.isBoss
self.movespeed_total = data.movespeed_total
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.OnStackCountChanged(self, stackCount)
if self.isBoss then
self.movespeed_total = 0
else
self.movespeed_total = (self.movespeed_slow + self.movespeed_slow_per_stack * self:GetStackCount()) * -1
end
if self.particle ~= nil then
ParticleManager:SetParticleControl(
self.particle,
1,
Vector(
0,
self:GetStackCount(),
0
)
)
end
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self.movespeed_total
end
function modifier_bristleback_viscous_nasal_goo_custom.prototype.GetModifierPhysicalArmorBonus(self, event)
local baseArmor = self.parent:GetPhysicalArmorBaseValue()
if baseArmor <= 0 then
return 0
end
local totalPct = (self.armor_reduce_pct + self.armor_reduce_pct_per_stack * self:GetStackCount()) / 100
return -baseArmor * totalPct
end
modifier_bristleback_viscous_nasal_goo_custom = __TS__Decorate(
modifier_bristleback_viscous_nasal_goo_custom,
modifier_bristleback_viscous_nasal_goo_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_viscous_nasal_goo_custom"}
)
____exports.modifier_bristleback_viscous_nasal_goo_custom = modifier_bristleback_viscous_nasal_goo_custom
____exports.modifier_bristleback_viscous_nasal_goo_shard_unit = __TS__Class()
local modifier_bristleback_viscous_nasal_goo_shard_unit = ____exports.modifier_bristleback_viscous_nasal_goo_shard_unit
modifier_bristleback_viscous_nasal_goo_shard_unit.name = "modifier_bristleback_viscous_nasal_goo_shard_unit"
modifier_bristleback_viscous_nasal_goo_shard_unit.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_viscous_nasal_goo_custom.lua"
__TS__ClassExtends(modifier_bristleback_viscous_nasal_goo_shard_unit, BaseModifier)
function modifier_bristleback_viscous_nasal_goo_shard_unit.prototype.IsHidden(self)
return true
end
function modifier_bristleback_viscous_nasal_goo_shard_unit.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_viscous_nasal_goo_shard_unit.prototype.CheckState(self)
return {
[MODIFIER_STATE_INVULNERABLE] = true,
[MODIFIER_STATE_OUT_OF_GAME] = true,
[MODIFIER_STATE_STUNNED] = true,
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
[MODIFIER_STATE_NO_UNIT_COLLISION] = true
}
end
function modifier_bristleback_viscous_nasal_goo_shard_unit.prototype.OnCreated(self, params)
self:GetParent():AddNoDraw()
end
function modifier_bristleback_viscous_nasal_goo_shard_unit.prototype.OnDestroy(self)
UTIL_Remove(self:GetParent())
end
modifier_bristleback_viscous_nasal_goo_shard_unit = __TS__Decorate(
modifier_bristleback_viscous_nasal_goo_shard_unit,
modifier_bristleback_viscous_nasal_goo_shard_unit,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_viscous_nasal_goo_shard_unit"}
)
____exports.modifier_bristleback_viscous_nasal_goo_shard_unit = modifier_bristleback_viscous_nasal_goo_shard_unit
return ____exports
@@ -0,0 +1,181 @@
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
--- Значения Warpath от уровня героя (не от уровня способности).
local function getWarpathLevel(self, hero)
return math.max(
1,
hero:GetLevel()
)
end
local function getWarpathDamagePerStack(self, ability, hero)
local level = getWarpathLevel(nil, hero)
return ability:GetSpecialValueFor("damage_per_stack_base") + level * ability:GetSpecialValueFor("damage_per_stack_per_hero_level") + ability:GetSpecialValueFor("damage_per_stack")
end
local function getWarpathMoveSpeedPerStack(self, ability, hero)
local level = getWarpathLevel(nil, hero)
return ability:GetSpecialValueFor("move_speed_per_stack_base") + level * ability:GetSpecialValueFor("move_speed_per_stack_per_hero_level")
end
local function getWarpathMaxStacks(self, ability, hero)
local level = getWarpathLevel(nil, hero)
return math.floor(ability:GetSpecialValueFor("max_stacks_base") + level * ability:GetSpecialValueFor("max_stacks_per_hero_level"))
end
local function getWarpathStackDuration(self, ability, hero)
local level = getWarpathLevel(nil, hero)
return ability:GetSpecialValueFor("stack_duration_base") + level * ability:GetSpecialValueFor("stack_duration_per_hero_level")
end
____exports.bristleback_warpath = __TS__Class()
local bristleback_warpath = ____exports.bristleback_warpath
bristleback_warpath.name = "bristleback_warpath"
bristleback_warpath.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_warpath_custom.lua"
__TS__ClassExtends(bristleback_warpath, BaseAbility)
function bristleback_warpath.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_bristleback_warpath_custom.name
end
bristleback_warpath = __TS__Decorate(
bristleback_warpath,
bristleback_warpath,
{registerAbility(nil)},
{kind = "class", name = "bristleback_warpath"}
)
____exports.bristleback_warpath = bristleback_warpath
____exports.modifier_bristleback_warpath_custom = __TS__Class()
local modifier_bristleback_warpath_custom = ____exports.modifier_bristleback_warpath_custom
modifier_bristleback_warpath_custom.name = "modifier_bristleback_warpath_custom"
modifier_bristleback_warpath_custom.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_warpath_custom.lua"
__TS__ClassExtends(modifier_bristleback_warpath_custom, BaseModifier)
function modifier_bristleback_warpath_custom.prototype.IsHidden(self)
return true
end
function modifier_bristleback_warpath_custom.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_warpath_custom.prototype.RemoveOnDeath(self)
return false
end
function modifier_bristleback_warpath_custom.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_TAKEDAMAGE}
end
function modifier_bristleback_warpath_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
self.parentHero = self:GetParent()
end
function modifier_bristleback_warpath_custom.prototype.OnTakeDamage(self, event)
if not IsServer() then
return
end
if event.unit ~= self.parentHero then
return
end
if event.damage <= 0 then
return
end
if self.parentHero:PassivesDisabled() then
return
end
local ability = self:GetAbility()
if not ability or ability:IsNull() then
return
end
local stacksMod = self.parentHero:FindModifierByName(____exports.modifier_bristleback_warpath_stacks.name)
local maxStacks = getWarpathMaxStacks(nil, ability, self.parentHero)
local duration = getWarpathStackDuration(nil, ability, self.parentHero)
if not stacksMod then
self.parentHero:AddNewModifier(self.parentHero, ability, ____exports.modifier_bristleback_warpath_stacks.name, {duration = duration})
return
end
local nextStacks = math.min(
maxStacks,
stacksMod:GetStackCount() + 1
)
stacksMod:SetStackCount(nextStacks)
stacksMod:SetDuration(duration, true)
stacksMod:ForceRefresh()
end
modifier_bristleback_warpath_custom = __TS__Decorate(
modifier_bristleback_warpath_custom,
modifier_bristleback_warpath_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_warpath_custom"}
)
____exports.modifier_bristleback_warpath_custom = modifier_bristleback_warpath_custom
____exports.modifier_bristleback_warpath_stacks = __TS__Class()
local modifier_bristleback_warpath_stacks = ____exports.modifier_bristleback_warpath_stacks
modifier_bristleback_warpath_stacks.name = "modifier_bristleback_warpath_stacks"
modifier_bristleback_warpath_stacks.____file_path = "scripts/vscripts/abilities/heroes/bristleback/bristleback_warpath_custom.lua"
__TS__ClassExtends(modifier_bristleback_warpath_stacks, BaseModifier)
function modifier_bristleback_warpath_stacks.prototype.IsHidden(self)
return false
end
function modifier_bristleback_warpath_stacks.prototype.IsPurgable(self)
return false
end
function modifier_bristleback_warpath_stacks.prototype.IsDebuff(self)
return false
end
function modifier_bristleback_warpath_stacks.prototype.GetTexture(self)
return "bristleback_warpath"
end
function modifier_bristleback_warpath_stacks.prototype.OnCreated(self)
if not IsServer() then
return
end
self:SetStackCount(1)
end
function modifier_bristleback_warpath_stacks.prototype.OnRefresh(self)
if not IsServer() then
return
end
self:SetStackCount(math.max(
1,
self:GetStackCount()
))
end
function modifier_bristleback_warpath_stacks.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE, MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT}
end
function modifier_bristleback_warpath_stacks.prototype.GetModifierPreAttack_BonusDamage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
local ability = self:GetAbility()
if not ability then
return 0
end
return self:GetStackCount() * getWarpathDamagePerStack(
nil,
ability,
self:GetParent()
)
end
function modifier_bristleback_warpath_stacks.prototype.GetModifierMoveSpeedBonus_Constant(self)
if self:GetParent():PassivesDisabled() then
return 0
end
local ability = self:GetAbility()
if not ability then
return 0
end
return self:GetStackCount() * getWarpathMoveSpeedPerStack(
nil,
ability,
self:GetParent()
)
end
modifier_bristleback_warpath_stacks = __TS__Decorate(
modifier_bristleback_warpath_stacks,
modifier_bristleback_warpath_stacks,
{registerModifier(nil)},
{kind = "class", name = "modifier_bristleback_warpath_stacks"}
)
____exports.modifier_bristleback_warpath_stacks = modifier_bristleback_warpath_stacks
return ____exports
@@ -0,0 +1,687 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
local Set = ____lualib.Set
local __TS__New = ____lualib.__TS__New
local __TS__ArraySplice = ____lualib.__TS__ArraySplice
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_froze = require("abilities.modifiers.modifier_general_froze")
local modifier_general_froze = ____modifier_general_froze.modifier_general_froze
____exports.ability_crystal_maiden_brilliance_aura_custom = __TS__Class()
local ability_crystal_maiden_brilliance_aura_custom = ____exports.ability_crystal_maiden_brilliance_aura_custom
ability_crystal_maiden_brilliance_aura_custom.name = "ability_crystal_maiden_brilliance_aura_custom"
ability_crystal_maiden_brilliance_aura_custom.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_brilliance_aura_custom.lua"
__TS__ClassExtends(ability_crystal_maiden_brilliance_aura_custom, BaseAbility)
function ability_crystal_maiden_brilliance_aura_custom.prototype.GetIntrinsicModifierName(self)
return "modifier_crystal_maiden_brilliance_aura_custom"
end
function ability_crystal_maiden_brilliance_aura_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("active_radius")
end
function ability_crystal_maiden_brilliance_aura_custom.prototype.GetManaCost(self, level)
local ____opt_0 = self:GetCaster()
return (____opt_0 and ____opt_0:GetMana()) * (0.01 * self:GetSpecialValueFor("mana_cost_pct"))
end
function ability_crystal_maiden_brilliance_aura_custom.prototype.GetCastRange(self, location, target)
if self:IsAltCastAbility() then
return self:GetSpecialValueFor("teleport_range")
end
return 0
end
function ability_crystal_maiden_brilliance_aura_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local isAltCast = self:IsAltCastAbility()
if isAltCast then
local teleportRange = self:GetSpecialValueFor("teleport_range")
local casterPos = caster:GetAbsOrigin()
local dx = point.x - casterPos.x
local dy = point.y - casterPos.y
local distance = math.sqrt(dx * dx + dy * dy)
local targetPos
if distance > teleportRange then
local normalizedX = dx / distance
local normalizedY = dy / distance
targetPos = Vector(casterPos.x + normalizedX * teleportRange, casterPos.y + normalizedY * teleportRange, casterPos.z)
else
targetPos = point
end
caster:Stop()
caster:StartGesture(ACT_DOTA_CAST_ABILITY_5)
FindClearSpaceForUnit(caster, targetPos, false)
local activeModifier = caster:FindModifierByName("modifier_crystal_maiden_brilliance_active")
if activeModifier then
activeModifier:SetDuration(
self:GetSpecialValueFor("duration"),
true
)
else
caster:AddNewModifier(
caster,
self,
"modifier_crystal_maiden_brilliance_active",
{duration = self:GetSpecialValueFor("duration")}
)
end
else
local activeModifier = caster:FindModifierByName("modifier_crystal_maiden_brilliance_active")
if activeModifier then
activeModifier:SetDuration(
self:GetSpecialValueFor("duration"),
true
)
else
caster:AddNewModifier(
caster,
self,
"modifier_crystal_maiden_brilliance_active",
{duration = self:GetSpecialValueFor("duration")}
)
end
end
end
ability_crystal_maiden_brilliance_aura_custom = __TS__Decorate(
ability_crystal_maiden_brilliance_aura_custom,
ability_crystal_maiden_brilliance_aura_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_crystal_maiden_brilliance_aura_custom"}
)
____exports.ability_crystal_maiden_brilliance_aura_custom = ability_crystal_maiden_brilliance_aura_custom
____exports.modifier_crystal_maiden_brilliance_active = __TS__Class()
local modifier_crystal_maiden_brilliance_active = ____exports.modifier_crystal_maiden_brilliance_active
modifier_crystal_maiden_brilliance_active.name = "modifier_crystal_maiden_brilliance_active"
modifier_crystal_maiden_brilliance_active.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_brilliance_aura_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_brilliance_active, BaseModifier)
function modifier_crystal_maiden_brilliance_active.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_brilliance_active.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ABILITY_FULLY_CAST}
end
function modifier_crystal_maiden_brilliance_active.prototype.OnAbilityFullyCast(self, event)
if not IsServer() then
return
end
if event.unit ~= self:GetParent() then
return
end
if event.ability:IsItem() then
return
end
local caster = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
local hasCrystalAspect = ability:GetSpecialValueFor("crystal_aspect_enabled") > 0
if hasCrystalAspect then
local crystalDuration = ability:GetSpecialValueFor("crystal_duration")
local crystalModifier = caster:FindModifierByName("modifier_crystal_maiden_brilliance_crystals")
if crystalModifier then
local currentStacks = crystalModifier:GetStackCount()
local maxStacks = 5
if currentStacks < maxStacks then
crystalModifier:IncrementStackCount()
crystalModifier:SyncCrystalsWithStacks()
end
crystalModifier:SetDuration(crystalDuration, true)
else
crystalModifier = caster:AddNewModifier(caster, ability, "modifier_crystal_maiden_brilliance_crystals", {duration = crystalDuration})
if crystalModifier then
crystalModifier:IncrementStackCount()
crystalModifier:SyncCrystalsWithStacks()
end
end
end
local radius = ability:GetSpecialValueFor("active_radius")
local damage = ability:GetSpecialValueFor("damage")
local frost_stacks = ability:GetSpecialValueFor("frost_stacks_per_level")
local intellect_per_damage = ability:GetSpecialValueFor("intellect_per_damage")
EmitSoundOn("Hero_Crystal.CrystalNova", caster)
local particleEffect = ParticleManager:CreateParticle("particles/econ/items/queen_of_pain/qop_2022_immortal/queen_2022_scream_of_pain_owner_blue.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(
particleEffect,
0,
caster:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
particleEffect,
1,
Vector(radius, 1, 1)
)
ParticleManager:SetParticleControl(
particleEffect,
2,
caster:GetAbsOrigin()
)
ParticleManager:ReleaseParticleIndex(particleEffect)
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
caster:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
__TS__ArrayForEach(
enemies,
function(____, enemy)
if not enemy or enemy:IsNull() or not enemy:IsAlive() then
return
end
local ____ApplyDamage_8 = ApplyDamage
local ____enemy_7 = enemy
local ____opt_2 = self:GetCaster()
local ____temp_6 = ____opt_2 and ____opt_2:GetMaxMana()
local ____opt_4 = self:GetCaster()
____ApplyDamage_8({
victim = ____enemy_7,
attacker = caster,
damage = damage + (____temp_6 - (____opt_4 and ____opt_4:GetMana())),
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
local frostModifier = enemy:AddNewModifier(caster, ability, modifier_general_froze.name, {})
if frostModifier then
frostModifier:SetDuration(
ability:GetSpecialValueFor("slow_duration"),
true
)
local stacksToAdd = frost_stacks + getLuck(nil, caster) * 0.1
do
local i = 0
while i < stacksToAdd do
frostModifier:IncrementStackCount()
i = i + 1
end
end
end
end
)
end
modifier_crystal_maiden_brilliance_active = __TS__Decorate(
modifier_crystal_maiden_brilliance_active,
modifier_crystal_maiden_brilliance_active,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_brilliance_active"}
)
____exports.modifier_crystal_maiden_brilliance_active = modifier_crystal_maiden_brilliance_active
____exports.modifier_crystal_maiden_brilliance_crystals = __TS__Class()
local modifier_crystal_maiden_brilliance_crystals = ____exports.modifier_crystal_maiden_brilliance_crystals
modifier_crystal_maiden_brilliance_crystals.name = "modifier_crystal_maiden_brilliance_crystals"
modifier_crystal_maiden_brilliance_crystals.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_brilliance_aura_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_brilliance_crystals, BaseModifier)
function modifier_crystal_maiden_brilliance_crystals.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.crystals = {}
self.maxCrystals = self:GetAbility():GetSpecialValueFor("max_crystals")
self.rotationRadius = 150
self.rotationSpeed = 12000
end
function modifier_crystal_maiden_brilliance_crystals.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_brilliance_crystals.prototype.IsPurgable(self)
return false
end
function modifier_crystal_maiden_brilliance_crystals.prototype.OnCreated(self)
if not IsServer() then
return
end
self:StartRotation()
local initialStacks = self:GetStackCount()
if initialStacks > 0 then
do
local i = 0
while i < initialStacks do
self:AddCrystal()
i = i + 1
end
end
end
end
function modifier_crystal_maiden_brilliance_crystals.prototype.SyncCrystalsWithStacks(self)
if not IsServer() then
return
end
local currentStacks = self:GetStackCount()
while #self.crystals < currentStacks and #self.crystals < self.maxCrystals do
self:AddCrystal()
end
while #self.crystals > currentStacks do
self:RemoveCrystal(#self.crystals - 1)
end
self:RecalculateCrystalAngles()
end
function modifier_crystal_maiden_brilliance_crystals.prototype.OnRefresh(self)
if not IsServer() then
return
end
self:SyncCrystalsWithStacks()
end
function modifier_crystal_maiden_brilliance_crystals.prototype.OnDestroy(self)
if IsServer() then
self:StopRotation()
__TS__ArrayForEach(
self.crystals,
function(____, crystal)
if crystal.particle ~= nil then
ParticleManager:DestroyParticle(crystal.particle, false)
ParticleManager:ReleaseParticleIndex(crystal.particle)
end
if crystal.radiusParticle ~= nil then
ParticleManager:DestroyParticle(crystal.radiusParticle, false)
ParticleManager:ReleaseParticleIndex(crystal.radiusParticle)
end
end
)
self.crystals = {}
if self.lastDamageTime then
self.lastDamageTime:clear()
end
end
end
function modifier_crystal_maiden_brilliance_crystals.prototype.RecalculateCrystalAngles(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if not parent or parent:IsNull() then
return
end
local parentPos = parent:GetAbsOrigin()
local totalCrystals = #self.crystals
if totalCrystals == 0 then
return
end
local angleStep = 360 / totalCrystals
__TS__ArrayForEach(
self.crystals,
function(____, crystal, index)
local newAngle = index * angleStep
crystal.angle = newAngle
local radians = newAngle * math.pi / 180
local newPos = Vector(
parentPos.x + math.cos(radians) * self.rotationRadius,
parentPos.y + math.sin(radians) * self.rotationRadius,
parentPos.z + 50
)
crystal.position = newPos
if crystal.particle ~= nil then
ParticleManager:SetParticleControl(crystal.particle, 0, newPos)
end
if crystal.radiusParticle ~= nil then
local radiusPos = Vector(newPos.x, newPos.y, newPos.z - 10)
ParticleManager:SetParticleControl(crystal.radiusParticle, 0, radiusPos)
end
end
)
end
function modifier_crystal_maiden_brilliance_crystals.prototype.AddCrystal(self)
if not IsServer() then
return
end
if #self.crystals >= self.maxCrystals then
return
end
local parent = self:GetParent()
if not parent or parent:IsNull() then
return
end
local parentPos = parent:GetAbsOrigin()
local totalCrystals = #self.crystals + 1
local angleStep = 360 / totalCrystals
__TS__ArrayForEach(
self.crystals,
function(____, crystal, index)
local newAngle = index * angleStep
crystal.angle = newAngle
local radians = newAngle * math.pi / 180
local newPos = Vector(
parentPos.x + math.cos(radians) * self.rotationRadius,
parentPos.y + math.sin(radians) * self.rotationRadius,
parentPos.z + 50
)
crystal.position = newPos
if crystal.particle ~= nil then
ParticleManager:SetParticleControl(crystal.particle, 0, newPos)
end
end
)
local newCrystalIndex = #self.crystals
local startAngle = newCrystalIndex * angleStep
local radians = startAngle * math.pi / 180
local initialPos = Vector(
parentPos.x + math.cos(radians) * self.rotationRadius,
parentPos.y + math.sin(radians) * self.rotationRadius,
parentPos.z + 50
)
local particle = ParticleManager:CreateParticle("particles/crystal_maiden_aspect_3.vpcf", PATTACH_CUSTOMORIGIN, nil)
if not particle then
return
end
ParticleManager:SetParticleControl(particle, 0, initialPos)
ParticleManager:SetParticleControl(
particle,
3,
Vector(100, 0, 0)
)
self:AddParticle(
particle,
false,
false,
-1,
false,
false
)
local ability = self:GetAbility()
local damageRadius = ability and (ability:GetSpecialValueFor("crystal_explosion_radius") or 100) or 100
local radiusParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_crystalmaiden/maiden_crystal_nova.vpcf", PATTACH_CUSTOMORIGIN, nil)
if radiusParticle ~= nil then
local radiusPos = Vector(initialPos.x, initialPos.y, initialPos.z - 10)
ParticleManager:SetParticleControl(radiusParticle, 0, radiusPos)
ParticleManager:SetParticleControl(
radiusParticle,
1,
Vector(damageRadius, 1, damageRadius)
)
self:AddParticle(
radiusParticle,
false,
false,
-1,
false,
false
)
end
local ____self_crystals_9 = self.crystals
____self_crystals_9[#____self_crystals_9 + 1] = {
particle = particle,
radiusParticle = radiusParticle,
angle = startAngle,
position = initialPos,
hitEnemies = __TS__New(Set)
}
EmitSoundOn("Hero_Crystal.FreezingField.Explosion", parent)
end
function modifier_crystal_maiden_brilliance_crystals.prototype.StartRotation(self)
if not IsServer() then
return
end
if self.rotationTimer then
return
end
local modifier = self
local parent = self:GetParent()
local updateRotation
updateRotation = function()
if not modifier or not parent or parent:IsNull() then
modifier.rotationTimer = nil
return
end
if not modifier.crystals or #modifier.crystals == 0 then
modifier.rotationTimer = nil
return
end
local parentPos = parent:GetAbsOrigin()
local deltaTime = 0.00033
local angleDelta = modifier.rotationSpeed * deltaTime
local ability = modifier:GetAbility()
local caster = modifier:GetCaster()
if not ability or not caster then
modifier.rotationTimer = nil
return
end
local damageRadius = ability:GetSpecialValueFor("crystal_explosion_radius")
local crystalDamage = ability:GetSpecialValueFor("crystal_damage")
local crystalFrostStacks = ability:GetSpecialValueFor("crystal_frost_stacks")
local touchRadius = 90
__TS__ArrayForEach(
modifier.crystals,
function(____, crystal, index)
crystal.angle = crystal.angle + angleDelta
if crystal.angle >= 360 then
crystal.angle = crystal.angle - 360
end
local radians = crystal.angle * math.pi / 180
local newPos = Vector(
parentPos.x + math.cos(radians) * modifier.rotationRadius,
parentPos.y + math.sin(radians) * modifier.rotationRadius,
parentPos.z + 50
)
crystal.position = newPos
if crystal.particle ~= nil then
ParticleManager:SetParticleControl(crystal.particle, 0, newPos)
else
return
end
if crystal.radiusParticle ~= nil then
local radiusPos = Vector(newPos.x, newPos.y, newPos.z - 10)
ParticleManager:SetParticleControl(crystal.radiusParticle, 0, radiusPos)
end
local enemiesInRadius = FindUnitsInRadius(
caster:GetTeamNumber(),
newPos,
nil,
touchRadius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local currentEnemiesInRadius = __TS__New(Set)
__TS__ArrayForEach(
enemiesInRadius,
function(____, enemy)
if not enemy or enemy:IsNull() or not enemy:IsAlive() then
return
end
local enemyPos = enemy:GetAbsOrigin()
local distance = (newPos - enemyPos):Length2D()
if distance > touchRadius then
return
end
local enemyIndex = enemy:GetEntityIndex()
currentEnemiesInRadius:add(enemyIndex)
if not crystal.hitEnemies:has(enemyIndex) then
local ____ApplyDamage_17 = ApplyDamage
local ____enemy_16 = enemy
local ____temp_15 = modifier:GetAbility():GetSpecialValueFor("pct_25_mana_damage") * 0.01
local ____opt_10 = modifier:GetParent()
local ____temp_14 = ____opt_10 and ____opt_10:GetMaxMana()
local ____opt_12 = modifier:GetParent()
____ApplyDamage_17({
victim = ____enemy_16,
attacker = caster,
damage = crystalDamage + ____temp_15 * (____temp_14 - (____opt_12 and ____opt_12:GetMana())),
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
local frostModifier = enemy:FindModifierByName(modifier_general_froze.name)
if not frostModifier then
frostModifier = enemy:AddNewModifier(caster, ability, modifier_general_froze.name, {})
end
if frostModifier then
frostModifier:SetDuration(1, true)
do
local i = 0
while i < crystalFrostStacks do
frostModifier:IncrementStackCount()
i = i + 1
end
end
end
crystal.hitEnemies:add(enemyIndex)
end
end
)
crystal.hitEnemies:forEach(function(____, enemyIndex)
if not currentEnemiesInRadius:has(enemyIndex) then
crystal.hitEnemies:delete(enemyIndex)
end
end)
end
)
Timers:CreateTimer(deltaTime, updateRotation)
end
modifier.rotationTimer = Timers:CreateTimer(0.00033, updateRotation)
end
function modifier_crystal_maiden_brilliance_crystals.prototype.StopRotation(self)
if not IsServer() then
return
end
if self.rotationTimer ~= nil and self.rotationTimer ~= nil then
do
pcall(function()
Timers:RemoveTimer(self.rotationTimer)
end)
end
self.rotationTimer = nil
end
end
function modifier_crystal_maiden_brilliance_crystals.prototype.RemoveCrystal(self, index)
if not IsServer() then
return
end
if index < 0 or index >= #self.crystals then
return
end
local crystal = self.crystals[index + 1]
if crystal.particle ~= nil then
ParticleManager:DestroyParticle(crystal.particle, false)
ParticleManager:ReleaseParticleIndex(crystal.particle)
end
if crystal.radiusParticle ~= nil then
ParticleManager:DestroyParticle(crystal.radiusParticle, false)
ParticleManager:ReleaseParticleIndex(crystal.radiusParticle)
end
__TS__ArraySplice(self.crystals, index, 1)
local parent = self:GetParent()
if parent and not parent:IsNull() and #self.crystals > 0 then
local parentPos = parent:GetAbsOrigin()
local totalCrystals = #self.crystals
local angleStep = 360 / totalCrystals
__TS__ArrayForEach(
self.crystals,
function(____, crystal, newIndex)
local newAngle = newIndex * angleStep
crystal.angle = newAngle
local radians = newAngle * math.pi / 180
local newPos = Vector(
parentPos.x + math.cos(radians) * self.rotationRadius,
parentPos.y + math.sin(radians) * self.rotationRadius,
parentPos.z + 50
)
crystal.position = newPos
if crystal.particle ~= nil then
ParticleManager:SetParticleControl(crystal.particle, 0, newPos)
end
if crystal.radiusParticle ~= nil then
local radiusPos = Vector(newPos.x, newPos.y, newPos.z - 10)
ParticleManager:SetParticleControl(crystal.radiusParticle, 0, radiusPos)
end
end
)
end
end
function modifier_crystal_maiden_brilliance_crystals.prototype.GetCrystalCount(self)
return #self.crystals
end
modifier_crystal_maiden_brilliance_crystals = __TS__Decorate(
modifier_crystal_maiden_brilliance_crystals,
modifier_crystal_maiden_brilliance_crystals,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_brilliance_crystals"}
)
____exports.modifier_crystal_maiden_brilliance_crystals = modifier_crystal_maiden_brilliance_crystals
____exports.modifier_crystal_maiden_brilliance_aura_custom = __TS__Class()
local modifier_crystal_maiden_brilliance_aura_custom = ____exports.modifier_crystal_maiden_brilliance_aura_custom
modifier_crystal_maiden_brilliance_aura_custom.name = "modifier_crystal_maiden_brilliance_aura_custom"
modifier_crystal_maiden_brilliance_aura_custom.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_brilliance_aura_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_brilliance_aura_custom, BaseModifier)
function modifier_crystal_maiden_brilliance_aura_custom.prototype.IsHidden(self)
return true
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.IsPurgable(self)
return false
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.IsAura(self)
return true
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.GetAuraRadius(self)
return self:GetAbility():GetSpecialValueFor("aura_radius")
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.GetAuraSearchTeam(self)
return DOTA_UNIT_TARGET_TEAM_FRIENDLY
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.GetAuraSearchType(self)
return bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC)
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.GetAuraSearchFlags(self)
return DOTA_UNIT_TARGET_FLAG_NONE
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.GetModifierAura(self)
return "modifier_crystal_maiden_brilliance_aura_buff"
end
function modifier_crystal_maiden_brilliance_aura_custom.prototype.GetAuraEntityReject(self, _hTarget)
return self:GetParent():PassivesDisabled()
end
modifier_crystal_maiden_brilliance_aura_custom = __TS__Decorate(
modifier_crystal_maiden_brilliance_aura_custom,
modifier_crystal_maiden_brilliance_aura_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_brilliance_aura_custom"}
)
____exports.modifier_crystal_maiden_brilliance_aura_custom = modifier_crystal_maiden_brilliance_aura_custom
____exports.modifier_crystal_maiden_brilliance_aura_buff = __TS__Class()
local modifier_crystal_maiden_brilliance_aura_buff = ____exports.modifier_crystal_maiden_brilliance_aura_buff
modifier_crystal_maiden_brilliance_aura_buff.name = "modifier_crystal_maiden_brilliance_aura_buff"
modifier_crystal_maiden_brilliance_aura_buff.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_brilliance_aura_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_brilliance_aura_buff, BaseModifier)
function modifier_crystal_maiden_brilliance_aura_buff.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_brilliance_aura_buff.prototype.IsDebuff(self)
return false
end
function modifier_crystal_maiden_brilliance_aura_buff.prototype.IsPurgable(self)
return false
end
function modifier_crystal_maiden_brilliance_aura_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MANA_REGEN_TOTAL_PERCENTAGE}
end
function modifier_crystal_maiden_brilliance_aura_buff.prototype.GetModifierTotalPercentageManaRegen(self)
local caster = self:GetCaster()
if caster and caster:PassivesDisabled() then
return 0
end
return self:GetAbility():GetSpecialValueFor("mana_regen_pct")
end
function modifier_crystal_maiden_brilliance_aura_buff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_crystalmaiden/maiden_brilliance_aura.vpcf"
end
function modifier_crystal_maiden_brilliance_aura_buff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_crystal_maiden_brilliance_aura_buff = __TS__Decorate(
modifier_crystal_maiden_brilliance_aura_buff,
modifier_crystal_maiden_brilliance_aura_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_brilliance_aura_buff"}
)
____exports.modifier_crystal_maiden_brilliance_aura_buff = modifier_crystal_maiden_brilliance_aura_buff
return ____exports
@@ -0,0 +1,211 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
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_froze = require("abilities.modifiers.modifier_general_froze")
local modifier_general_froze = ____modifier_general_froze.modifier_general_froze
local ____heal_tracker = require("utils.heal_tracker")
local HealWithBattlePass = ____heal_tracker.HealWithBattlePass
____exports.ability_crystal_maiden_crystal_nova_custom = __TS__Class()
local ability_crystal_maiden_crystal_nova_custom = ____exports.ability_crystal_maiden_crystal_nova_custom
ability_crystal_maiden_crystal_nova_custom.name = "ability_crystal_maiden_crystal_nova_custom"
ability_crystal_maiden_crystal_nova_custom.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_crystal_nova_custom.lua"
__TS__ClassExtends(ability_crystal_maiden_crystal_nova_custom, BaseAbility)
function ability_crystal_maiden_crystal_nova_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function ability_crystal_maiden_crystal_nova_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local radius = self:GetSpecialValueFor("radius")
local damage = self:GetSpecialValueFor("damage")
local slow_duration = self:GetSpecialValueFor("slow_duration")
local frost_stacks = self:GetSpecialValueFor("frost_stacks_per_level")
local intellect_per_damage = self:GetSpecialValueFor("intellect_per_damage")
EmitSoundOnLocationWithCaster(point, "Hero_Crystal.CrystalNova", caster)
local particleEffect = ParticleManager:CreateParticle("particles/units/heroes/hero_crystalmaiden/maiden_crystal_nova.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particleEffect, 0, point)
ParticleManager:SetParticleControl(
particleEffect,
1,
Vector(radius, 1, radius)
)
ParticleManager:SetParticleControl(
particleEffect,
2,
self:GetCursorPosition()
)
ParticleManager:ReleaseParticleIndex(particleEffect)
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
point,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_BOTH,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local healAmount = self:GetSpecialValueFor("heal") or damage
__TS__ArrayForEach(
units,
function(____, unit)
if not unit or unit:IsNull() or not unit:IsAlive() then
return
end
if unit == caster then
return
end
local isAlly = unit:GetTeamNumber() == caster:GetTeamNumber()
if isAlly then
local healValue = healAmount + self:GetCaster():GetIntellect(true) * intellect_per_damage
local maxShieldPctValue = self:GetSpecialValueFor("max_shield_pct")
local hasShieldFromOverheal = maxShieldPctValue > 0
if hasShieldFromOverheal then
local healthBefore = unit:GetHealth()
local maxHealth = unit:GetMaxHealth()
local potentialHealthAfter = healthBefore + healValue
local potentialOverheal = potentialHealthAfter - maxHealth
HealWithBattlePass(
nil,
unit,
healValue,
self,
caster
)
local healthAfter = unit:GetHealth()
local actualOverheal = healthAfter - maxHealth
local overheal = actualOverheal > 0 and actualOverheal or (potentialOverheal > 0 and potentialOverheal or 0)
if overheal > 0 then
local shieldModifier = unit:FindModifierByName("modifier_crystal_maiden_crystal_nova_shield")
local maxShieldPct = self:GetSpecialValueFor("max_shield_pct")
local maxShield = unit:GetMaxHealth() * (maxShieldPct / 100)
local shieldDuration = self:GetSpecialValueFor("shield_duration")
if shieldModifier then
local currentShield = shieldModifier:GetStackCount()
local newShield = math.min(currentShield + overheal, maxShield)
shieldModifier:SetDuration(shieldDuration, true)
shieldModifier:SetStackCount(newShield)
else
local newShieldModifier = unit:AddNewModifier(caster, self, "modifier_crystal_maiden_crystal_nova_shield", {duration = shieldDuration})
if newShieldModifier ~= nil and newShieldModifier ~= nil then
newShieldModifier:SetStackCount(overheal)
end
end
end
else
HealWithBattlePass(
nil,
unit,
healValue,
self,
caster
)
end
else
local damageValue = damage + self:GetCaster():GetIntellect(true) * intellect_per_damage
ApplyDamage({
victim = unit,
attacker = caster,
damage = damageValue,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local modifier = unit:AddNewModifier(caster, self, modifier_general_froze.name, {})
if modifier then
modifier:SetDuration(slow_duration, true)
do
local i = 0
while i < frost_stacks + getLuck(
nil,
self:GetCaster()
) * 0.1 do
modifier:IncrementStackCount()
i = i + 1
end
end
end
end
end
)
end
ability_crystal_maiden_crystal_nova_custom = __TS__Decorate(
ability_crystal_maiden_crystal_nova_custom,
ability_crystal_maiden_crystal_nova_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_crystal_maiden_crystal_nova_custom"}
)
____exports.ability_crystal_maiden_crystal_nova_custom = ability_crystal_maiden_crystal_nova_custom
____exports.modifier_crystal_maiden_crystal_nova_shield = __TS__Class()
local modifier_crystal_maiden_crystal_nova_shield = ____exports.modifier_crystal_maiden_crystal_nova_shield
modifier_crystal_maiden_crystal_nova_shield.name = "modifier_crystal_maiden_crystal_nova_shield"
modifier_crystal_maiden_crystal_nova_shield.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_crystal_nova_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_crystal_nova_shield, BaseModifier)
function modifier_crystal_maiden_crystal_nova_shield.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.IsPurgable(self)
return true
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.GetEffectName(self)
return "particles/crystal_scepter_shield.vpcf"
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.OnCreated(self)
if not IsServer() then
return
end
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.OnRefresh(self)
if not IsServer() then
return
end
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_INCOMING_DAMAGE_CONSTANT}
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.GetModifierIncomingDamageConstant(self, event)
if IsClient() then
return self:GetStackCount()
end
if not IsServer() then
return 0
end
if event.inflictor and event.inflictor == self:GetAbility() then
return 0
end
local currentShield = self:GetStackCount()
if currentShield > event.damage then
self:SetStackCount(currentShield - event.damage)
return -event.damage
else
local absorbedDamage = currentShield
self:SetStackCount(0)
self:Destroy()
return -absorbedDamage
end
end
function modifier_crystal_maiden_crystal_nova_shield.prototype.GetTexture(self)
return "crystal_maiden_crystal_nova"
end
modifier_crystal_maiden_crystal_nova_shield = __TS__Decorate(
modifier_crystal_maiden_crystal_nova_shield,
modifier_crystal_maiden_crystal_nova_shield,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_crystal_nova_shield"}
)
____exports.modifier_crystal_maiden_crystal_nova_shield = modifier_crystal_maiden_crystal_nova_shield
return ____exports
@@ -0,0 +1,432 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__NumberToFixed = ____lualib.__TS__NumberToFixed
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
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_froze = require("abilities.modifiers.modifier_general_froze")
local modifier_general_froze = ____modifier_general_froze.modifier_general_froze
local ____ability_alt_cast_manager = require("ability_alt_cast_manager")
local AbilityAltCastManager = ____ability_alt_cast_manager.AbilityAltCastManager
local ____heal_tracker = require("utils.heal_tracker")
local HealWithBattlePass = ____heal_tracker.HealWithBattlePass
____exports.ability_crystal_maiden_freezing_field_custom = __TS__Class()
local ability_crystal_maiden_freezing_field_custom = ____exports.ability_crystal_maiden_freezing_field_custom
ability_crystal_maiden_freezing_field_custom.name = "ability_crystal_maiden_freezing_field_custom"
ability_crystal_maiden_freezing_field_custom.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_freezing_field_custom.lua"
__TS__ClassExtends(ability_crystal_maiden_freezing_field_custom, BaseAbility)
function ability_crystal_maiden_freezing_field_custom.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.modifier = nil
end
function ability_crystal_maiden_freezing_field_custom.prototype.GetBehavior(self)
if self:GetCaster():HasScepter() then
return bit.bor(
bit.bor(DOTA_ABILITY_BEHAVIOR_NO_TARGET, DOTA_ABILITY_BEHAVIOR_CHANNELLED),
DOTA_ABILITY_BEHAVIOR_IMMEDIATE
)
end
return bit.bor(DOTA_ABILITY_BEHAVIOR_NO_TARGET, DOTA_ABILITY_BEHAVIOR_CHANNELLED)
end
function ability_crystal_maiden_freezing_field_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local duration = self:GetChannelTime()
print("[FreezingField] OnSpellStart called, duration: " .. tostring(duration))
self.modifier = caster:AddNewModifier(caster, self, ____exports.modifier_crystal_maiden_freezing_field_custom.name, {duration = duration})
if not self.modifier or self.modifier:IsNull() then
print("[FreezingField] ERROR: Failed to apply modifier!")
else
print("[FreezingField] Modifier applied successfully")
end
end
function ability_crystal_maiden_freezing_field_custom.prototype.OnChannelFinish(self, interrupted)
if not IsServer() then
return
end
local caster = self:GetCaster()
if self.modifier and not self.modifier:IsNull() then
self.modifier:Destroy()
end
StopSoundOn("hero_Crystal.freezingField.wind", caster)
end
ability_crystal_maiden_freezing_field_custom = __TS__Decorate(
ability_crystal_maiden_freezing_field_custom,
ability_crystal_maiden_freezing_field_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_crystal_maiden_freezing_field_custom"}
)
____exports.ability_crystal_maiden_freezing_field_custom = ability_crystal_maiden_freezing_field_custom
____exports.modifier_crystal_maiden_freezing_field_custom = __TS__Class()
local modifier_crystal_maiden_freezing_field_custom = ____exports.modifier_crystal_maiden_freezing_field_custom
modifier_crystal_maiden_freezing_field_custom.name = "modifier_crystal_maiden_freezing_field_custom"
modifier_crystal_maiden_freezing_field_custom.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_freezing_field_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_freezing_field_custom, BaseModifier)
function modifier_crystal_maiden_freezing_field_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.explosionInterval = 0.1
self.radius = 0
self.explosionRadius = 0
self.explosionDamage = 0
self.frostStacksPerExplosion = 0
self.slowDuration = 0
self.intellectPerDamage = 0
self.lastCrystalNovaTime = 0
self.crystalNovaChance = 0.5
self.crystalNovaCheckInterval = 0.5
end
function modifier_crystal_maiden_freezing_field_custom.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_freezing_field_custom.prototype.IsDebuff(self)
return false
end
function modifier_crystal_maiden_freezing_field_custom.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_crystal_maiden_freezing_field_custom.prototype.IsPurgable(self)
return false
end
function modifier_crystal_maiden_freezing_field_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
print("[FreezingField] Modifier OnCreated called")
local ability = self:GetAbility()
if not ability then
print("[FreezingField] ERROR: Ability is null!")
self:Destroy()
return
end
self.radius = ability:GetSpecialValueFor("radius")
self.explosionRadius = ability:GetSpecialValueFor("explosion_radius")
self.explosionDamage = ability:GetSpecialValueFor("explosion_damage")
self.frostStacksPerExplosion = ability:GetSpecialValueFor("frost_stacks_per_explosion")
self.slowDuration = ability:GetSpecialValueFor("slow_duration")
self.explosionInterval = ability:GetSpecialValueFor("explosion_interval")
self.intellectPerDamage = ability:GetSpecialValueFor("intellect_per_damage")
print((((("[FreezingField] Values loaded - radius: " .. tostring(self.radius)) .. ", interval: ") .. tostring(self.explosionInterval)) .. ", damage: ") .. tostring(self.explosionDamage))
local parent = self:GetParent()
self.mainParticleId = ParticleManager:CreateParticle("particles/units/heroes/hero_crystalmaiden/maiden_freezing_field_snow.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:SetParticleControl(
self.mainParticleId,
0,
parent:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
self.mainParticleId,
1,
Vector(self.radius, 0, 0)
)
self:AddParticle(
self.mainParticleId,
false,
false,
-1,
false,
false
)
local caster = self:GetCaster()
if caster then
EmitSoundOn("hero_Crystal.freezingField.wind", caster)
end
self.lastCrystalNovaTime = GameRules:GetGameTime()
self:StartIntervalThink(self.explosionInterval)
end
function modifier_crystal_maiden_freezing_field_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local parent = self:GetParent()
local ability = self:GetAbility()
if caster and (caster:IsStunned() or caster:IsHexed() or caster:IsSilenced()) then
return
end
if not caster or caster:IsNull() or not parent or parent:IsNull() or not ability then
return
end
local roll = math.random()
print((("[FreezingField] Checking for mini Crystal Nova - roll: " .. __TS__NumberToFixed(roll, 3)) .. ", chance: ") .. tostring(self.crystalNovaChance))
print("[FreezingField] Casting mini Crystal Nova!")
if self:GetCaster():HasScepter() then
self:CastMiniCrystalNova(caster, parent)
end
local casterPos = parent:GetAbsOrigin()
local angle = RandomFloat(0, 360)
local minDistance = 120
local distance = RandomFloat(minDistance, self.radius)
local radians = angle * math.pi / 180
local explosionPos = Vector(
casterPos.x + math.cos(radians) * distance,
casterPos.y + math.sin(radians) * distance,
casterPos.z
)
local particleEffect = ParticleManager:CreateParticle("particles/units/heroes/hero_crystalmaiden/maiden_freezing_field_explosion.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particleEffect, 0, explosionPos)
ParticleManager:SetParticleControl(
particleEffect,
1,
Vector(self.explosionRadius, 0, 0)
)
ParticleManager:ReleaseParticleIndex(particleEffect)
EmitSoundOnLocationWithCaster(explosionPos, "Hero_Crystal.FreezingField.Explosion", caster)
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
explosionPos,
nil,
self.explosionRadius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
print(((((("[FreezingField] Explosion at (" .. __TS__NumberToFixed(explosionPos.x, 1)) .. ", ") .. __TS__NumberToFixed(explosionPos.y, 1)) .. ") - found ") .. tostring(#enemies)) .. " enemies")
__TS__ArrayForEach(
enemies,
function(____, enemy)
if not enemy or enemy:IsNull() or not enemy:IsAlive() then
return
end
local damageValue = self.explosionDamage + caster:GetIntellect(true) * self.intellectPerDamage
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damageValue,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
print(((("[FreezingField] Explosion hit enemy " .. enemy:GetUnitName()) .. " for ") .. __TS__NumberToFixed(damageValue, 1)) .. " damage")
local frostModifier = enemy:FindModifierByName(modifier_general_froze.name)
if not frostModifier then
frostModifier = enemy:AddNewModifier(caster, ability, modifier_general_froze.name, {})
end
if frostModifier then
frostModifier:SetDuration(self.slowDuration, true)
local stacksToAdd = self.frostStacksPerExplosion + getLuck(nil, caster) * 0.1
do
local i = 0
while i < stacksToAdd do
frostModifier:IncrementStackCount()
i = i + 1
end
end
print((("[FreezingField] Applied " .. __TS__NumberToFixed(stacksToAdd, 1)) .. " frost stacks to ") .. enemy:GetUnitName())
end
end
)
end
function modifier_crystal_maiden_freezing_field_custom.prototype.CastMiniCrystalNova(self, caster, parent)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not ability then
print("[FreezingField] CastMiniCrystalNova - ability is null!")
return
end
local crystalNovaAbility = parent:FindAbilityByName("ability_crystal_maiden_crystal_nova_custom")
if not crystalNovaAbility or crystalNovaAbility:GetLevel() == 0 then
print("[FreezingField] CastMiniCrystalNova - Crystal Nova not learned or level 0")
return
end
print("[FreezingField] CastMiniCrystalNova - Crystal Nova level: " .. tostring(crystalNovaAbility:GetLevel()))
local casterPos = parent:GetAbsOrigin()
local angle = RandomFloat(0, 360)
local minDistance = 200
local maxDistance = self.radius
local distance = RandomFloat(minDistance, maxDistance)
local radians = angle * math.pi / 180
local novaPos = Vector(
casterPos.x + math.cos(radians) * distance,
casterPos.y + math.sin(radians) * distance,
casterPos.z
)
local novaRadius = crystalNovaAbility:GetSpecialValueFor("radius") * (self:GetAbility():GetSpecialValueFor("mini_nova_pct") * 0.01)
local novaDamage = crystalNovaAbility:GetSpecialValueFor("damage") * (self:GetAbility():GetSpecialValueFor("mini_nova_pct") * 0.01)
local novaHeal = crystalNovaAbility:GetSpecialValueFor("heal") * (self:GetAbility():GetSpecialValueFor("mini_nova_pct") * 0.01)
local novaSlowDuration = crystalNovaAbility:GetSpecialValueFor("slow_duration")
local novaFrostStacks = math.floor(crystalNovaAbility:GetSpecialValueFor("frost_stacks_per_level") * (self:GetAbility():GetSpecialValueFor("mini_nova_pct") * 0.01))
local novaIntellectPerDamage = crystalNovaAbility:GetSpecialValueFor("intellect_per_damage")
EmitSoundOnLocationWithCaster(novaPos, "Hero_Crystal.CrystalNova", caster)
local particleEffect = ParticleManager:CreateParticle("particles/units/heroes/hero_crystalmaiden/maiden_crystal_nova.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particleEffect, 0, novaPos)
ParticleManager:SetParticleControl(
particleEffect,
1,
Vector(novaRadius, 1, novaRadius)
)
ParticleManager:ReleaseParticleIndex(particleEffect)
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
novaPos,
nil,
novaRadius,
DOTA_UNIT_TARGET_TEAM_BOTH,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local frostbiteAbility = parent:FindAbilityByName("ability_crystal_maiden_frostbite_custom")
local brillianceAbility = parent:FindAbilityByName("ability_crystal_maiden_brilliance_aura_custom")
print(((((((("[FreezingField] CastMiniCrystalNova - Nova at (" .. __TS__NumberToFixed(novaPos.x, 1)) .. ", ") .. __TS__NumberToFixed(novaPos.y, 1)) .. "), radius: ") .. tostring(novaRadius)) .. ", found ") .. tostring(#units)) .. " units")
print((("[FreezingField] CastMiniCrystalNova - Frostbite level: " .. tostring(frostbiteAbility and frostbiteAbility:GetLevel() or 0)) .. ", Brilliance level: ") .. tostring(brillianceAbility and brillianceAbility:GetLevel() or 0))
__TS__ArrayForEach(
units,
function(____, unit)
if not unit or unit:IsNull() or not unit:IsAlive() then
return
end
if unit == parent then
return
end
local isAlly = unit:GetTeamNumber() == caster:GetTeamNumber()
if isAlly then
local healValue = novaHeal + caster:GetIntellect(true) * novaIntellectPerDamage
HealWithBattlePass(
nil,
unit,
healValue,
ability,
caster
)
print((("[FreezingField] CastMiniCrystalNova - Healed ally " .. unit:GetUnitName()) .. " for ") .. __TS__NumberToFixed(healValue, 1))
if frostbiteAbility and frostbiteAbility:GetLevel() > 0 then
local playerId = caster:GetPlayerOwnerID()
if playerId == -1 or playerId == nil then
playerId = caster:GetPlayerID()
end
local isFrostbiteAltCast = false
if playerId ~= -1 and playerId ~= nil then
local altCastManager = AbilityAltCastManager:getInstance()
isFrostbiteAltCast = altCastManager:getAltCastState(playerId, "ability_crystal_maiden_frostbite_custom")
end
if not isFrostbiteAltCast then
local frostbiteDuration = frostbiteAbility:GetSpecialValueFor("duration") * 0.5
unit:AddNewModifier(caster, ability, "modifier_crystal_maiden_frostbite_ally", {duration = frostbiteDuration})
print(((("[FreezingField] CastMiniCrystalNova - Applied Frostbite (ally) to " .. unit:GetUnitName()) .. " for ") .. tostring(frostbiteDuration)) .. "s")
else
print(("[FreezingField] CastMiniCrystalNova - Skipped Frostbite (ally) for " .. unit:GetUnitName()) .. " because alt cast is enabled")
end
end
if brillianceAbility and brillianceAbility:GetLevel() > 0 then
unit:AddNewModifier(caster, ability, "modifier_crystal_maiden_brilliance_aura_buff", {duration = 3})
print("[FreezingField] CastMiniCrystalNova - Applied Brilliance Aura buff to " .. unit:GetUnitName())
end
else
local damageValue = novaDamage + caster:GetIntellect(true) * novaIntellectPerDamage
ApplyDamage({
victim = unit,
attacker = caster,
damage = damageValue,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
print((("[FreezingField] CastMiniCrystalNova - Damaged enemy " .. unit:GetUnitName()) .. " for ") .. __TS__NumberToFixed(damageValue, 1))
local modifier = unit:AddNewModifier(caster, ability, modifier_general_froze.name, {})
if modifier then
modifier:SetDuration(novaSlowDuration, true)
do
local i = 0
while i < novaFrostStacks do
modifier:IncrementStackCount()
i = i + 1
end
end
print((("[FreezingField] CastMiniCrystalNova - Applied " .. tostring(novaFrostStacks)) .. " frost stacks to ") .. unit:GetUnitName())
end
if frostbiteAbility and frostbiteAbility:GetLevel() > 0 then
local frostbiteDuration = frostbiteAbility:GetSpecialValueFor("duration") * 0.5
local frostbiteDamage = frostbiteAbility:GetSpecialValueFor("damage") * 0.5
unit:AddNewModifier(caster, ability, "modifier_crystal_maiden_frostbite_enemy", {duration = frostbiteDuration, isAltCast = 0})
ApplyDamage({
victim = unit,
attacker = caster,
damage = frostbiteDamage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
print((((("[FreezingField] CastMiniCrystalNova - Applied Frostbite (enemy) to " .. unit:GetUnitName()) .. " for ") .. tostring(frostbiteDuration)) .. "s, damage: ") .. __TS__NumberToFixed(frostbiteDamage, 1))
end
if brillianceAbility and brillianceAbility:GetLevel() > 0 then
local brillianceRadius = brillianceAbility:GetSpecialValueFor("active_radius") * 0.5
local brillianceDamage = brillianceAbility:GetSpecialValueFor("damage") * 0.5
local brillianceFrostStacks = math.floor(brillianceAbility:GetSpecialValueFor("frost_stacks_per_level") * 0.5)
local nearbyEnemies = FindUnitsInRadius(
caster:GetTeamNumber(),
unit:GetAbsOrigin(),
nil,
brillianceRadius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
print(((("[FreezingField] CastMiniCrystalNova - Brilliance Aura effect from " .. unit:GetUnitName()) .. ", found ") .. tostring(#nearbyEnemies)) .. " nearby enemies")
__TS__ArrayForEach(
nearbyEnemies,
function(____, enemy)
if not enemy or enemy:IsNull() or not enemy:IsAlive() or enemy == unit then
return
end
ApplyDamage({
victim = enemy,
attacker = caster,
damage = brillianceDamage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
local frostMod = enemy:FindModifierByName(modifier_general_froze.name)
if not frostMod then
frostMod = enemy:AddNewModifier(caster, ability, modifier_general_froze.name, {})
end
if frostMod then
frostMod:SetDuration(1, true)
do
local i = 0
while i < brillianceFrostStacks do
frostMod:IncrementStackCount()
i = i + 1
end
end
end
end
)
end
end
end
)
end
function modifier_crystal_maiden_freezing_field_custom.prototype.OnDestroy(self)
if IsClient() then
return
end
print("[FreezingField] Modifier OnDestroy called")
if self.mainParticleId then
ParticleManager:DestroyParticle(self.mainParticleId, false)
ParticleManager:ReleaseParticleIndex(self.mainParticleId)
end
StopSoundOn(
"hero_Crystal.freezingField.wind",
self:GetParent()
)
end
modifier_crystal_maiden_freezing_field_custom = __TS__Decorate(
modifier_crystal_maiden_freezing_field_custom,
modifier_crystal_maiden_freezing_field_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_freezing_field_custom"}
)
____exports.modifier_crystal_maiden_freezing_field_custom = modifier_crystal_maiden_freezing_field_custom
return ____exports
@@ -0,0 +1,910 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__StringIncludes = ____lualib.__TS__StringIncludes
local __TS__ArrayFind = ____lualib.__TS__ArrayFind
local __TS__ArraySome = ____lualib.__TS__ArraySome
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_froze = require("abilities.modifiers.modifier_general_froze")
local modifier_general_froze = ____modifier_general_froze.modifier_general_froze
local ____modifier_general_knockback = require("abilities.modifiers.modifier_general_knockback")
local modifier_general_knockback = ____modifier_general_knockback.modifier_general_knockback
local ____heal_tracker = require("utils.heal_tracker")
local HealWithBattlePass = ____heal_tracker.HealWithBattlePass
local ____incoming_damage_reduction_combine = require("utils.incoming_damage_reduction_combine")
local removeIncomingDamageReductionSource = ____incoming_damage_reduction_combine.removeIncomingDamageReductionSource
local setIncomingDamageReductionSource = ____incoming_damage_reduction_combine.setIncomingDamageReductionSource
local FROSTBITE_ALLY_INCOMING_SOURCE = "modifier_crystal_maiden_frostbite_ally"
____exports.ability_crystal_maiden_frostbite_custom = __TS__Class()
local ability_crystal_maiden_frostbite_custom = ____exports.ability_crystal_maiden_frostbite_custom
ability_crystal_maiden_frostbite_custom.name = "ability_crystal_maiden_frostbite_custom"
ability_crystal_maiden_frostbite_custom.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_frostbite_custom.lua"
__TS__ClassExtends(ability_crystal_maiden_frostbite_custom, BaseAbility)
function ability_crystal_maiden_frostbite_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function ability_crystal_maiden_frostbite_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local radius = self:GetSpecialValueFor("radius")
local duration = self:GetSpecialValueFor("duration")
local damage = self:GetSpecialValueFor("damage")
local heal_per_second = self:GetSpecialValueFor("heal_per_second")
local isAltCast = self:IsAltCastAbility()
print(isAltCast)
EmitSoundOnLocationWithCaster(point, "Hero_Crystal.Frostbite", caster)
local ____isAltCast_0
if isAltCast then
____isAltCast_0 = DOTA_UNIT_TARGET_TEAM_ENEMY
else
____isAltCast_0 = DOTA_UNIT_TARGET_TEAM_BOTH
end
local targetTeam = ____isAltCast_0
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
point,
nil,
radius,
targetTeam,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
__TS__ArrayForEach(
units,
function(____, unit)
if not unit or unit:IsNull() or not unit:IsAlive() then
return
end
local isAlly = unit:GetTeamNumber() == caster:GetTeamNumber()
if isAltCast and isAlly then
return
end
if isAlly then
unit:AddNewModifier(caster, self, "modifier_crystal_maiden_frostbite_ally", {duration = duration})
else
unit:AddNewModifier(caster, self, "modifier_crystal_maiden_frostbite_enemy", {duration = duration, isAltCast = isAltCast and 1 or 0})
local initialDamage = isAltCast and damage * 2 or damage
ApplyDamage({
victim = unit,
attacker = caster,
damage = initialDamage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
end
end
)
end
function ability_crystal_maiden_frostbite_custom.prototype.GetCastRange(self, location, target)
return self:GetSpecialValueFor("cast_range")
end
function ability_crystal_maiden_frostbite_custom.prototype.OnProjectileHit(self, target, location)
if not IsServer() then
return false
end
if not target then
return false
end
local caster = self:GetCaster()
if not caster then
return false
end
local damage = 100
ApplyDamage({
victim = target,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local frostModifier = target:AddNewModifier(caster, self, modifier_general_froze.name, {})
if frostModifier then
do
local i = 0
while i < 10 do
frostModifier:IncrementStackCount()
i = i + 1
end
end
frostModifier:SetDuration(2, true)
end
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_crystalmaiden/crystal_maiden_frostbite.vpcf", PATTACH_ABSORIGIN_FOLLOW, target)
ParticleManager:ReleaseParticleIndex(particle)
EmitSoundOn("Hero_Crystal.Frostbite", target)
return true
end
ability_crystal_maiden_frostbite_custom = __TS__Decorate(
ability_crystal_maiden_frostbite_custom,
ability_crystal_maiden_frostbite_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_crystal_maiden_frostbite_custom"}
)
____exports.ability_crystal_maiden_frostbite_custom = ability_crystal_maiden_frostbite_custom
____exports.modifier_crystal_maiden_frostbite_ally = __TS__Class()
local modifier_crystal_maiden_frostbite_ally = ____exports.modifier_crystal_maiden_frostbite_ally
modifier_crystal_maiden_frostbite_ally.name = "modifier_crystal_maiden_frostbite_ally"
modifier_crystal_maiden_frostbite_ally.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_frostbite_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_frostbite_ally, BaseModifier)
function modifier_crystal_maiden_frostbite_ally.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.healPerSecond = 0
end
function modifier_crystal_maiden_frostbite_ally.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_frostbite_ally.prototype.IsDebuff(self)
return false
end
function modifier_crystal_maiden_frostbite_ally.prototype.IsPurgable(self)
return true
end
function modifier_crystal_maiden_frostbite_ally.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_crystal_maiden_frostbite_ally.prototype.OnCreated(self)
if IsServer() then
local ability = self:GetAbility()
if ability then
self.healPerSecond = ability:GetSpecialValueFor("heal_per_second")
end
setIncomingDamageReductionSource(
nil,
self:GetParent(),
FROSTBITE_ALLY_INCOMING_SOURCE,
function()
local frostAbility = self:GetAbility()
if not frostAbility then
return 0
end
return math.max(
0,
frostAbility:GetSpecialValueFor("incoming_damage_pct")
)
end
)
self:StartIntervalThink(0.5)
self:OnIntervalThink()
end
end
function modifier_crystal_maiden_frostbite_ally.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if not parent or parent:IsNull() or not parent:IsAlive() then
return
end
HealWithBattlePass(
nil,
parent,
self.healPerSecond * 0.5,
self:GetAbility(),
self:GetCaster()
)
end
function modifier_crystal_maiden_frostbite_ally.prototype.CheckState(self)
return {[MODIFIER_STATE_ROOTED] = true, [MODIFIER_STATE_DISARMED] = false}
end
function modifier_crystal_maiden_frostbite_ally.prototype.GetEffectName(self)
return "particles/econ/items/crystal_maiden/ti7_immortal_shoulder/cm_ti7_immortal_frostbite.vpcf"
end
function modifier_crystal_maiden_frostbite_ally.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_crystal_maiden_frostbite_ally.prototype.OnDestroy(self)
if IsClient() then
return
end
removeIncomingDamageReductionSource(
nil,
self:GetParent(),
FROSTBITE_ALLY_INCOMING_SOURCE
)
StopSoundOn(
"Hero_Crystal.Frostbite",
self:GetParent()
)
end
modifier_crystal_maiden_frostbite_ally = __TS__Decorate(
modifier_crystal_maiden_frostbite_ally,
modifier_crystal_maiden_frostbite_ally,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_frostbite_ally"}
)
____exports.modifier_crystal_maiden_frostbite_ally = modifier_crystal_maiden_frostbite_ally
____exports.modifier_crystal_maiden_frostbite_enemy = __TS__Class()
local modifier_crystal_maiden_frostbite_enemy = ____exports.modifier_crystal_maiden_frostbite_enemy
modifier_crystal_maiden_frostbite_enemy.name = "modifier_crystal_maiden_frostbite_enemy"
modifier_crystal_maiden_frostbite_enemy.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_frostbite_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_frostbite_enemy, BaseModifier)
function modifier_crystal_maiden_frostbite_enemy.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.damage = 0
self.frostStacksPerLevel = 0
self.isAltCast = false
self.executeThresholdPct = 0
self.executeAllowed = false
self.hasCreatedCopy = false
end
function modifier_crystal_maiden_frostbite_enemy.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_frostbite_enemy.prototype.IsDebuff(self)
return true
end
function modifier_crystal_maiden_frostbite_enemy.prototype.IsPurgable(self)
return true
end
function modifier_crystal_maiden_frostbite_enemy.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_crystal_maiden_frostbite_enemy.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_DEATH}
end
function modifier_crystal_maiden_frostbite_enemy.prototype.OnCreated(self, params)
if IsServer() then
local ability = self:GetAbility()
if ability then
self.damage = ability:GetSpecialValueFor("damage")
self.frostStacksPerLevel = ability:GetSpecialValueFor("frost_stacks_per_level")
self.executeThresholdPct = ability:GetSpecialValueFor("execute_threshold_pct") or 0
end
self.executeAllowed = self:canUseExecuteOnTarget(self:GetParent())
self.isAltCast = params.isAltCast == 1
self:StartIntervalThink(0.5)
end
end
function modifier_crystal_maiden_frostbite_enemy.prototype.canUseExecuteOnTarget(self, target)
local unitName = target:GetUnitName()
if not unitName then
return true
end
local lowerCaseName = string.lower(unitName)
local denyNames = {
"boss",
"npc_fish_1",
"npc_fish_2",
"npc_bomb",
"npc_wisps"
}
for ____, deny in ipairs(denyNames) do
if __TS__StringIncludes(lowerCaseName, deny) then
return false
end
end
return true
end
function modifier_crystal_maiden_frostbite_enemy.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not parent or parent:IsNull() or not parent:IsAlive() or not caster or not ability then
return
end
if self.executeThresholdPct > 0 and self.executeAllowed then
local currentHealth = parent:GetHealth()
local maxHealth = parent:GetMaxHealth()
local healthPct = currentHealth / maxHealth * 100
if healthPct < self.executeThresholdPct and not self.hasCreatedCopy then
local killPosition = parent:GetAbsOrigin()
local killForward = parent:GetForwardVector()
local unitName = parent:GetUnitName()
self.hasCreatedCopy = true
parent:Kill(
self:GetAbility(),
self:GetCaster()
)
parent:RemoveSelf()
Timers:CreateTimer(
0.1,
function()
if not parent or parent:IsNull() or not parent:IsAlive() then
local frozenCopy = CreateUnitByName(
unitName,
killPosition,
true,
caster,
caster,
DOTA_TEAM_NEUTRALS
)
if IsServer() then
frozenCopy:SetRenderColor(60, 120, 255)
end
if frozenCopy and IsValidEntity(frozenCopy) then
frozenCopy:SetForwardVector(killForward)
FindClearSpaceForUnit(frozenCopy, killPosition, true)
frozenCopy:SetMinimumGoldBounty(0)
frozenCopy:SetMaximumGoldBounty(0)
frozenCopy:SetDeathXP(0)
frozenCopy:SetMoveCapability(DOTA_UNIT_CAP_MOVE_NONE)
frozenCopy:SetAttackCapability(DOTA_UNIT_CAP_NO_ATTACK)
local frozenModifier = frozenCopy:AddNewModifier(caster, ability, modifier_general_froze.name, {})
if frozenModifier then
do
local i = 0
while i < 150 do
frozenModifier:IncrementStackCount()
i = i + 1
end
end
frozenModifier:SetDuration(-1, true)
end
frozenCopy:AddNewModifier(caster, ability, "modifier_crystal_maiden_frostbite_execute", {duration = 6})
EmitSoundOn("Hero_Ancient_Apparition.ColdFeetCast", frozenCopy)
end
end
end
)
return
end
end
local damageToDeal = self.isAltCast and self.damage * 2 or self.damage
ApplyDamage({
victim = parent,
attacker = caster,
damage = damageToDeal * 0.5,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
local frostModifier = parent:FindModifierByName(modifier_general_froze.name)
if not frostModifier then
frostModifier = parent:AddNewModifier(caster, ability, modifier_general_froze.name, {})
end
if frostModifier then
do
local i = 0
while i < self.frostStacksPerLevel * 0.5 do
frostModifier:IncrementStackCount()
i = i + 1
end
end
frostModifier:SetDuration(1.01, true)
end
end
function modifier_crystal_maiden_frostbite_enemy.prototype.CheckState(self)
return {[MODIFIER_STATE_ROOTED] = true}
end
function modifier_crystal_maiden_frostbite_enemy.prototype.GetEffectName(self)
return "particles/units/heroes/hero_crystalmaiden/maiden_frostbite_buff.vpcf"
end
function modifier_crystal_maiden_frostbite_enemy.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_crystal_maiden_frostbite_enemy.prototype.OnDeath(self, event)
if not IsServer() then
return
end
if event.unit ~= self:GetParent() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not parent or parent:IsNull() or not caster or not ability then
return
end
if self.executeThresholdPct > 0 and self.executeAllowed and not self.hasCreatedCopy then
self.hasCreatedCopy = true
local deathPosition = parent:GetAbsOrigin()
local deathForward = parent:GetForwardVector()
local unitName = parent:GetUnitName()
Timers:CreateTimer(
0.1,
function()
local frozenCopy = CreateUnitByName(
unitName,
deathPosition,
true,
caster,
caster,
DOTA_TEAM_NEUTRALS
)
if IsServer() then
frozenCopy:SetRenderColor(60, 120, 255)
end
if frozenCopy and IsValidEntity(frozenCopy) then
frozenCopy:SetForwardVector(deathForward)
FindClearSpaceForUnit(frozenCopy, deathPosition, true)
frozenCopy:SetMinimumGoldBounty(0)
frozenCopy:SetMaximumGoldBounty(0)
frozenCopy:SetDeathXP(0)
frozenCopy:SetMoveCapability(DOTA_UNIT_CAP_MOVE_NONE)
frozenCopy:SetAttackCapability(DOTA_UNIT_CAP_NO_ATTACK)
local frozenModifier = frozenCopy:AddNewModifier(caster, ability, modifier_general_froze.name, {})
if frozenModifier then
do
local i = 0
while i < 150 do
frozenModifier:IncrementStackCount()
i = i + 1
end
end
frozenModifier:SetDuration(-1, true)
end
frozenCopy:AddNewModifier(caster, ability, "modifier_crystal_maiden_frostbite_execute", {duration = 6})
EmitSoundOn("Hero_Ancient_Apparition.ColdFeetCast", frozenCopy)
end
end
)
end
end
function modifier_crystal_maiden_frostbite_enemy.prototype.OnDestroy(self)
if IsClient() then
return
end
StopSoundOn(
"Hero_Crystal.Frostbite",
self:GetParent()
)
end
modifier_crystal_maiden_frostbite_enemy = __TS__Decorate(
modifier_crystal_maiden_frostbite_enemy,
modifier_crystal_maiden_frostbite_enemy,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_frostbite_enemy"}
)
____exports.modifier_crystal_maiden_frostbite_enemy = modifier_crystal_maiden_frostbite_enemy
____exports.modifier_crystal_maiden_frostbite_execute = __TS__Class()
local modifier_crystal_maiden_frostbite_execute = ____exports.modifier_crystal_maiden_frostbite_execute
modifier_crystal_maiden_frostbite_execute.name = "modifier_crystal_maiden_frostbite_execute"
modifier_crystal_maiden_frostbite_execute.____file_path = "scripts/vscripts/abilities/heroes/crystal_maiden/ability_crystal_maiden_frostbite_custom.lua"
__TS__ClassExtends(modifier_crystal_maiden_frostbite_execute, BaseModifier)
function modifier_crystal_maiden_frostbite_execute.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.isFlying = false
self.lastPosition = Vector(0, 0, 0)
end
function modifier_crystal_maiden_frostbite_execute.prototype.IsHidden(self)
return false
end
function modifier_crystal_maiden_frostbite_execute.prototype.IsDebuff(self)
return true
end
function modifier_crystal_maiden_frostbite_execute.prototype.IsPurgable(self)
return false
end
function modifier_crystal_maiden_frostbite_execute.prototype.GetEffectName(self)
return "particles/events/crownfall/survivors/abilities/crystal_maiden/crystal_maiden_frostbite.vpcf"
end
function modifier_crystal_maiden_frostbite_execute.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_crystal_maiden_frostbite_execute.prototype.OnCreated(self)
if IsServer() then
self.lastPosition = self:GetParent():GetAbsOrigin()
self:GetParent():RemoveAbility("ability_unit_less_laggy")
end
end
function modifier_crystal_maiden_frostbite_execute.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACKED, MODIFIER_PROPERTY_MIN_HEALTH}
end
function modifier_crystal_maiden_frostbite_execute.prototype.GetMinHealth(self)
return 1
end
function modifier_crystal_maiden_frostbite_execute.prototype.CheckState(self)
return {
[MODIFIER_STATE_FROZEN] = true,
[MODIFIER_STATE_ROOTED] = true,
[MODIFIER_STATE_DISARMED] = true,
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
[MODIFIER_STATE_SILENCED] = true
}
end
function modifier_crystal_maiden_frostbite_execute.prototype.OnAttacked(self, event)
if not IsServer() then
return
end
if event.target ~= self:GetParent() then
return
end
if self.isFlying then
return
end
local parent = self:GetParent()
local attacker = event.attacker
if not parent or parent:IsNull() or not attacker or attacker:IsNull() then
return
end
local direction = parent:GetAbsOrigin() - attacker:GetAbsOrigin()
direction.z = 0
local normalizedDirection = direction:Normalized()
parent:SetMoveCapability(DOTA_UNIT_CAP_MOVE_GROUND)
local capturedModifier = self
local capturedParent = parent
self.explosionTimer = Timers:CreateTimer(
0.5,
function()
if not IsServer() then
return
end
if not capturedModifier or capturedModifier:IsNull() then
return
end
if not capturedParent or capturedParent:IsNull() or not IsValidEntity(capturedParent) then
return
end
capturedModifier:Explode()
capturedParent:RemoveSelf()
end
)
self.isFlying = true
self.lastPosition = parent:GetAbsOrigin()
modifier_general_knockback:apply(
parent,
attacker,
self:GetAbility(),
{
duration = 0.5,
distance = 600,
height = 0,
direction_x = normalizedDirection.x,
direction_y = normalizedDirection.y
}
)
self:StartCollisionCheck()
self:StartIntervalThink(0.1)
self.knockbackEndTimer = Timers:CreateTimer(
0.6,
function()
if not IsServer() then
return
end
if not capturedModifier or capturedModifier:IsNull() then
return
end
if not capturedParent or capturedParent:IsNull() or not IsValidEntity(capturedParent) then
return
end
if capturedModifier.isFlying then
capturedModifier.isFlying = false
capturedModifier:Explode()
capturedParent:RemoveSelf()
end
end
)
end
function modifier_crystal_maiden_frostbite_execute.prototype.OnDestroy(self)
if IsServer() then
if self.collisionCheckTimer then
Timers:RemoveTimer(self.collisionCheckTimer)
self.collisionCheckTimer = nil
end
if self.explosionTimer then
Timers:RemoveTimer(self.explosionTimer)
self.explosionTimer = nil
end
if self.knockbackEndTimer then
Timers:RemoveTimer(self.knockbackEndTimer)
self.knockbackEndTimer = nil
end
self:Explode()
local parent = self:GetParent()
if parent and not parent:IsNull() and IsValidEntity(parent) then
parent:RemoveSelf()
end
end
end
function modifier_crystal_maiden_frostbite_execute.prototype.StartCollisionCheck(self)
if not IsServer() then
return
end
local checkInterval = 0.05
local checkCount = 0
local checkCollision
checkCollision = function()
if not self or self:IsNull() then
self.collisionCheckTimer = nil
return
end
local parent = self:GetParent()
if not parent or parent:IsNull() or not IsValidEntity(parent) or not self.isFlying then
if self and not self:IsNull() then
self.collisionCheckTimer = nil
end
return
end
local currentPos = parent:GetAbsOrigin()
local lastPos = self.lastPosition
checkCount = checkCount + 1
local caster = self:GetCaster()
local searchTeam = caster and caster:GetTeamNumber() or parent:GetTeamNumber()
local nearbyUnits = FindUnitsInRadius(
searchTeam,
currentPos,
nil,
100,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local allNearbyUnits = FindUnitsInRadius(
DOTA_TEAM_NEUTRALS,
currentPos,
nil,
100,
DOTA_UNIT_TARGET_TEAM_BOTH,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local otherFrozenCopy = __TS__ArrayFind(
allNearbyUnits,
function(____, unit) return unit ~= parent and unit:IsAlive() and unit:HasModifier("modifier_crystal_maiden_frostbite_execute") end
)
if otherFrozenCopy then
local pushDirection = otherFrozenCopy:GetAbsOrigin() - currentPos
pushDirection.z = 0
local normalizedPushDirection = pushDirection:Normalized()
local otherModifier = otherFrozenCopy:FindModifierByName("modifier_crystal_maiden_frostbite_execute")
if otherModifier and not otherModifier.isFlying then
otherFrozenCopy:SetMoveCapability(DOTA_UNIT_CAP_MOVE_GROUND)
modifier_general_knockback:apply(
otherFrozenCopy,
parent,
self:GetAbility(),
{
duration = 0.5,
distance = 400,
height = 0,
direction_x = normalizedPushDirection.x,
direction_y = normalizedPushDirection.y
}
)
otherModifier.isFlying = true
otherModifier.lastPosition = otherFrozenCopy:GetAbsOrigin()
otherModifier:StartCollisionCheck()
otherModifier:StartIntervalThink(0.1)
local capturedModifier = otherModifier
local capturedUnit = otherFrozenCopy
otherModifier.knockbackEndTimer = Timers:CreateTimer(
0.6,
function()
if not IsServer() then
return
end
if not capturedModifier or capturedModifier:IsNull() then
return
end
if not capturedUnit or capturedUnit:IsNull() or not IsValidEntity(capturedUnit) then
return
end
if capturedModifier.isFlying then
capturedModifier.isFlying = false
capturedModifier:Explode()
capturedUnit:RemoveSelf()
end
end
)
otherModifier.explosionTimer = Timers:CreateTimer(
0.5,
function()
if not IsServer() then
return
end
if not capturedModifier or capturedModifier:IsNull() then
return
end
if not capturedUnit or capturedUnit:IsNull() or not IsValidEntity(capturedUnit) then
return
end
capturedModifier:Explode()
capturedUnit:RemoveSelf()
end
)
end
end
local hasUnitCollision = __TS__ArraySome(
nearbyUnits,
function(____, unit) return unit ~= parent and unit:IsAlive() end
)
local isBlocked = not GridNav:CanFindPath(currentPos, currentPos)
local isStuck = false
if checkCount > 5 then
local distanceMoved = (currentPos - lastPos):Length2D()
isStuck = distanceMoved < 10 and self.isFlying
end
if hasUnitCollision or isBlocked or isStuck then
self:Explode()
return
end
self.lastPosition = currentPos
self.collisionCheckTimer = Timers:CreateTimer(checkInterval, checkCollision)
end
self.collisionCheckTimer = Timers:CreateTimer(0.1, checkCollision)
end
function modifier_crystal_maiden_frostbite_execute.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
if not self or self:IsNull() then
return
end
if not self.isFlying then
return
end
local parent = self:GetParent()
if not parent or parent:IsNull() or not IsValidEntity(parent) then
self:Destroy()
return
end
local knockbackModifier = parent:FindModifierByName("modifier_general_knockback")
if not knockbackModifier and self.isFlying then
self.isFlying = false
Timers:CreateTimer(
0.1,
function()
if self and not self:IsNull() then
local checkParent = self:GetParent()
if checkParent and not checkParent:IsNull() and IsValidEntity(checkParent) then
self:CheckFinalCollision()
end
end
end
)
end
end
function modifier_crystal_maiden_frostbite_execute.prototype.CheckFinalCollision(self)
if not IsServer() then
return
end
if self:IsNull() then
return
end
local parent = self:GetParent()
if not parent or parent:IsNull() or not IsValidEntity(parent) then
return
end
if not self.isFlying then
return
end
local currentPos = parent:GetAbsOrigin()
local caster = self:GetCaster()
local searchTeam = caster and caster:GetTeamNumber() or parent:GetTeamNumber()
local nearbyUnits = FindUnitsInRadius(
searchTeam,
currentPos,
nil,
100,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local hasCollision = __TS__ArraySome(
nearbyUnits,
function(____, unit) return unit ~= parent and unit:IsAlive() end
)
if hasCollision then
self:Explode()
local parent = self:GetParent()
if parent and not parent:IsNull() and IsValidEntity(parent) then
parent:RemoveSelf()
end
else
self:Explode()
local parent = self:GetParent()
if parent and not parent:IsNull() and IsValidEntity(parent) then
parent:RemoveSelf()
end
end
end
function modifier_crystal_maiden_frostbite_execute.prototype.Explode(self)
if not IsServer() then
return
end
if self.collisionCheckTimer then
Timers:RemoveTimer(self.collisionCheckTimer)
self.collisionCheckTimer = nil
end
if self.explosionTimer then
Timers:RemoveTimer(self.explosionTimer)
self.explosionTimer = nil
end
if self.knockbackEndTimer then
Timers:RemoveTimer(self.knockbackEndTimer)
self.knockbackEndTimer = nil
end
local parent = self:GetParent()
if not parent or parent:IsNull() then
return
end
local explosionPos = parent:GetAbsOrigin()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not caster or not ability then
return
end
local knockbackModifier = parent:FindModifierByName("modifier_general_knockback")
if knockbackModifier then
knockbackModifier:Destroy()
end
local explosionParticle = ParticleManager:CreateParticle("particles/econ/items/effigies/status_fx_effigies/frosty_base_statue_destruction_dire.vpcf", PATTACH_CUSTOMORIGIN, nil)
ParticleManager:SetParticleControl(explosionParticle, 0, explosionPos)
ParticleManager:ReleaseParticleIndex(explosionParticle)
EmitSoundOnLocationWithCaster(explosionPos, "Hero_Ancient_Apparition.IceBlast.Target", caster)
local modifierAbility = self:GetAbility()
self:ExplodeInRadius(explosionPos, caster, modifierAbility or ability)
Timers:CreateTimer(
0.1,
function()
if IsServer() and parent and not parent:IsNull() and IsValidEntity(parent) then
parent:RemoveSelf()
end
end
)
self:Destroy()
end
function modifier_crystal_maiden_frostbite_execute.prototype.ExplodeInRadius(self, position, caster, ability)
if not IsServer() then
return
end
local explosionRadius = ability:GetSpecialValueFor("explosion_radius")
local damage = ability:GetCaster():GetMana() * (0.01 * ability:GetSpecialValueFor("damage_per_mana"))
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
position,
nil,
explosionRadius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
__TS__ArrayForEach(
enemies,
function(____, enemy)
if not enemy or enemy:IsNull() or not enemy:IsAlive() then
return
end
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
local frostModifier = enemy:AddNewModifier(caster, ability, modifier_general_froze.name, {})
if frostModifier then
do
local i = 0
while i < 15 do
frostModifier:IncrementStackCount()
i = i + 1
end
end
frostModifier:SetDuration(3, true)
end
local particle = ParticleManager:CreateParticle("particles/econ/items/crystal_maiden/crystal_maiden_maiden_of_icewrack/maiden_freezing_field_explosion_c_arcana1.vpcf", PATTACH_ABSORIGIN_FOLLOW, enemy)
ParticleManager:ReleaseParticleIndex(particle)
EmitSoundOn("Hero_Crystal.Frostbite", enemy)
end
)
end
modifier_crystal_maiden_frostbite_execute = __TS__Decorate(
modifier_crystal_maiden_frostbite_execute,
modifier_crystal_maiden_frostbite_execute,
{registerModifier(nil)},
{kind = "class", name = "modifier_crystal_maiden_frostbite_execute"}
)
____exports.modifier_crystal_maiden_frostbite_execute = modifier_crystal_maiden_frostbite_execute
return ____exports
@@ -0,0 +1,293 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayFind = ____lualib.__TS__ArrayFind
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__Delete = ____lualib.__TS__Delete
local ____exports = {}
local modifier_ability_drow_ranger_frost_arrows
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_froze = require("abilities.modifiers.modifier_general_froze")
local modifier_general_froze = ____modifier_general_froze.modifier_general_froze
____exports.ability_drow_ranger_frost_arrows_custom = __TS__Class()
local ability_drow_ranger_frost_arrows_custom = ____exports.ability_drow_ranger_frost_arrows_custom
ability_drow_ranger_frost_arrows_custom.name = "ability_drow_ranger_frost_arrows_custom"
ability_drow_ranger_frost_arrows_custom.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_frost_arrows_custom.lua"
__TS__ClassExtends(ability_drow_ranger_frost_arrows_custom, BaseAbility)
function ability_drow_ranger_frost_arrows_custom.prototype.GetIntrinsicModifierName(self)
return modifier_ability_drow_ranger_frost_arrows.name
end
function ability_drow_ranger_frost_arrows_custom.prototype.OnOrbFire(self, params)
local sound_cast = "Hero_DrowRanger.FrostArrows"
EmitSoundOn(
sound_cast,
self:GetCaster()
)
end
function ability_drow_ranger_frost_arrows_custom.prototype.OnOrbImpact(self, params)
local target = params.target
if not target then
return
end
local modifier = target:AddNewModifier(
self:GetCaster(),
self,
modifier_general_froze.name,
{}
)
if modifier then
local stacksPerLevel = self:GetSpecialValueFor("frost_stacks_per_level")
do
local i = 0
while i < stacksPerLevel do
modifier:IncrementStackCount()
i = i + 1
end
end
end
if not self:GetCaster():HasScepter() then
return
end
local ricochetChance = self:GetSpecialValueFor("ricochet_chance")
if RandomInt(1, 100) > ricochetChance then
return
end
local ricochetRadius = 500
local enemies = FindUnitsInRadius(
self:GetCaster():GetTeamNumber(),
target:GetAbsOrigin(),
nil,
ricochetRadius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_CLOSEST,
false
)
local nearestEnemy = __TS__ArrayFind(
enemies,
function(____, enemy) return enemy ~= target end
)
if nearestEnemy then
local particlePath = "particles/units/heroes/hero_drow/drow_frost_arrow.vpcf"
ProjectileManager:CreateTrackingProjectile({
Source = target,
Target = nearestEnemy,
Ability = self,
EffectName = particlePath,
iMoveSpeed = 1250,
bDodgeable = true,
bVisibleToEnemies = true,
bReplaceExisting = false,
bProvidesVision = false
})
Timers:CreateTimer(
0.2,
function()
if nearestEnemy and nearestEnemy:IsAlive() then
local ricochetModifier = nearestEnemy:AddNewModifier(
self:GetCaster(),
self,
modifier_general_froze.name,
{}
)
if ricochetModifier ~= nil then
local stacksPerLevel = self:GetSpecialValueFor("frost_stacks_per_level")
do
local i = 0
while i < stacksPerLevel do
ricochetModifier:IncrementStackCount()
i = i + 1
end
end
end
self:GetCaster():PerformAttack(
nearestEnemy,
true,
false,
true,
false,
false,
false,
false
)
EmitSoundOn("Hero_DrowRanger.FrostArrows.Impact", nearestEnemy)
end
end
)
end
end
ability_drow_ranger_frost_arrows_custom = __TS__Decorate(
ability_drow_ranger_frost_arrows_custom,
ability_drow_ranger_frost_arrows_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_drow_ranger_frost_arrows_custom"}
)
____exports.ability_drow_ranger_frost_arrows_custom = ability_drow_ranger_frost_arrows_custom
modifier_ability_drow_ranger_frost_arrows = __TS__Class()
modifier_ability_drow_ranger_frost_arrows.name = "modifier_ability_drow_ranger_frost_arrows"
modifier_ability_drow_ranger_frost_arrows.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_frost_arrows_custom.lua"
__TS__ClassExtends(modifier_ability_drow_ranger_frost_arrows, BaseModifier)
function modifier_ability_drow_ranger_frost_arrows.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.cast = false
self.records = {}
end
function modifier_ability_drow_ranger_frost_arrows.prototype.IsHidden(self)
return false
end
function modifier_ability_drow_ranger_frost_arrows.prototype.IsPurgable(self)
return false
end
function modifier_ability_drow_ranger_frost_arrows.prototype.IsPurgeException(self)
return false
end
function modifier_ability_drow_ranger_frost_arrows.prototype.IsDebuff(self)
return false
end
function modifier_ability_drow_ranger_frost_arrows.prototype.IsBuff(self)
return true
end
function modifier_ability_drow_ranger_frost_arrows.prototype.RemoveOnDeath(self)
return false
end
function modifier_ability_drow_ranger_frost_arrows.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_PERMANENT
end
function modifier_ability_drow_ranger_frost_arrows.prototype.DeclareFunctions(self)
return {
MODIFIER_EVENT_ON_ATTACK,
MODIFIER_EVENT_ON_ATTACK_FAIL,
MODIFIER_EVENT_ON_ATTACK_LANDED,
MODIFIER_PROPERTY_PROCATTACK_FEEDBACK,
MODIFIER_EVENT_ON_ATTACK_RECORD_DESTROY,
MODIFIER_EVENT_ON_ORDER,
MODIFIER_PROPERTY_PROJECTILE_NAME,
MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE
}
end
function modifier_ability_drow_ranger_frost_arrows.prototype.OnCreated(self)
self.ability = self:GetAbility()
self.cast = false
self.records = {}
end
function modifier_ability_drow_ranger_frost_arrows.prototype.GetModifierPreAttack_BonusDamage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
if self:GetParent():IsIllusion() then
return 0
end
if IsServer() then
local target = self:GetParent():GetAggroTarget()
if self:ShouldLaunch(target) then
return self:GetParent():GetAttackDamage() * (self:GetAbility():GetSpecialValueFor("damage_pct") * 0.01)
end
end
return 0
end
function modifier_ability_drow_ranger_frost_arrows.prototype.OnAttack(self, params)
if params.attacker ~= self:GetParent() then
return
end
if self:GetParent():PassivesDisabled() then
return
end
if self:GetParent():IsIllusion() then
return
end
if self:ShouldLaunch(params.target) then
self.ability:UseResources(true, false, true, true)
self.records[params.record] = true
if self.ability.OnOrbFire ~= nil then
self.ability:OnOrbFire(params)
end
end
self.cast = false
end
function modifier_ability_drow_ranger_frost_arrows.prototype.OnAttackLanded(self, event)
if event.attacker ~= self:GetParent() then
return
end
if self:GetParent():PassivesDisabled() then
return
end
if self:GetParent():IsIllusion() then
return
end
if self:GetAbility():GetSpecialValueFor("crit_multiplier") > 0 then
self:IncrementStackCount()
if self:GetStackCount() > 3 then
if not IsServer() then
return
end
local mult = self:GetAbility():GetSpecialValueFor("crit_multiplier")
local stackingCritMod = self:GetCaster():FindModifierByName("modifier_stacking_crit")
if stackingCritMod then
local ability = self
stackingCritMod:AddCustomCrit(100, mult, "drow_ranger_frost_arrows")
end
if self:GetStackCount() > 4 then
self:SetStackCount(1)
if stackingCritMod then
stackingCritMod:RemoveCrit("drow_ranger_frost_arrows")
end
end
end
end
end
function modifier_ability_drow_ranger_frost_arrows.prototype.GetModifierProcAttack_Feedback(self, params)
if self:GetParent():PassivesDisabled() then
return 0
end
if self:GetParent():IsIllusion() then
return 0
end
if self.records[params.record] then
if self.ability.OnOrbImpact ~= nil then
self.ability:OnOrbImpact(params)
end
end
return 0
end
function modifier_ability_drow_ranger_frost_arrows.prototype.OnAttackFail(self, params)
if self.records[params.record] then
__TS__Delete(self.records, params.record)
end
end
function modifier_ability_drow_ranger_frost_arrows.prototype.OnAttackRecordDestroy(self, params)
self.records[params.record] = false
end
function modifier_ability_drow_ranger_frost_arrows.prototype.OnOrder(self, params)
return
end
function modifier_ability_drow_ranger_frost_arrows.prototype.ShouldLaunch(self, target)
if not target then
return false
end
return self.ability:GetCooldownTimeRemaining() == 0
end
function modifier_ability_drow_ranger_frost_arrows.prototype.GetModifierProjectileName(self)
if self:GetParent():PassivesDisabled() then
return ""
end
local target = self:GetParent():GetAggroTarget()
if not target then
return ""
end
if self:ShouldLaunch(target) then
return "particles/units/heroes/hero_drow/drow_frost_arrow.vpcf"
end
return ""
end
modifier_ability_drow_ranger_frost_arrows = __TS__Decorate(
modifier_ability_drow_ranger_frost_arrows,
modifier_ability_drow_ranger_frost_arrows,
{registerModifier(nil)},
{kind = "class", name = "modifier_ability_drow_ranger_frost_arrows"}
)
return ____exports
@@ -0,0 +1,151 @@
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_froze = require("abilities.modifiers.modifier_general_froze")
local modifier_general_froze = ____modifier_general_froze.modifier_general_froze
local ____modifier_general_knockback = require("abilities.modifiers.modifier_general_knockback")
local modifier_general_knockback = ____modifier_general_knockback.modifier_general_knockback
____exports.ability_drow_ranger_gust_custom = __TS__Class()
local ability_drow_ranger_gust_custom = ____exports.ability_drow_ranger_gust_custom
ability_drow_ranger_gust_custom.name = "ability_drow_ranger_gust_custom"
ability_drow_ranger_gust_custom.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_gust_custom.lua"
__TS__ClassExtends(ability_drow_ranger_gust_custom, BaseAbility)
function ability_drow_ranger_gust_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local casterPos = caster:GetAbsOrigin()
local speed = self:GetSpecialValueFor("gust_speed")
local width = self:GetSpecialValueFor("gust_width")
local distance = self:GetSpecialValueFor("gust_distance")
local direction = point - casterPos
direction.z = 0
direction = direction:Normalized()
local projectileInfo = {
Source = caster,
Ability = self,
vSpawnOrigin = casterPos,
bDeleteOnHit = false,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
EffectName = "particles/units/heroes/hero_drow/drow_silence_wave.vpcf",
fDistance = distance,
fStartRadius = width,
fEndRadius = width,
vVelocity = direction * speed,
ExtraData = {x = casterPos.x, y = casterPos.y}
}
ProjectileManager:CreateLinearProjectile(projectileInfo)
EmitSoundOn("Hero_DrowRanger.Silence", caster)
end
function ability_drow_ranger_gust_custom.prototype.OnProjectileHit_ExtraData(self, target, location, extraData)
if not target then
return false
end
if target:GetTeamNumber() == self:GetCaster():GetTeamNumber() then
return false
end
local caster = self:GetCaster()
local knockback_duration = self:GetSpecialValueFor("knockback_duration")
local knockback_distance = self:GetSpecialValueFor("knockback_distance")
local damage = self:GetSpecialValueFor("damage")
local modifier = target:AddNewModifier(
self:GetCaster(),
self,
modifier_general_froze.name,
{}
)
local stacksPerLevel = self:GetSpecialValueFor("frost_stacks_per_level")
do
local i = 0
while i < stacksPerLevel do
modifier:IncrementStackCount()
i = i + 1
end
end
if self:GetSpecialValueFor("frozen_son_duration") > 0 then
target:AddNewModifier(
self:GetCaster(),
self,
____exports.modifier_general_frozen_son.name,
{duration = self:GetSpecialValueFor("frozen_son_duration")}
)
end
ApplyDamage({
victim = target,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local knockbackDirection = target:GetAbsOrigin() - Vector(extraData.x, extraData.y, 0)
knockbackDirection.z = 0
knockbackDirection = knockbackDirection:Normalized()
modifier_general_knockback:apply(target, caster, self, {duration = knockback_duration, distance = knockback_distance, direction_x = knockbackDirection.x, direction_y = knockbackDirection.y})
local effect_cast = ParticleManager:CreateParticle("particles/units/heroes/hero_drow/drow_silence.vpcf", PATTACH_ABSORIGIN_FOLLOW, target)
ParticleManager:ReleaseParticleIndex(effect_cast)
return false
end
ability_drow_ranger_gust_custom = __TS__Decorate(
ability_drow_ranger_gust_custom,
ability_drow_ranger_gust_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_drow_ranger_gust_custom"}
)
____exports.ability_drow_ranger_gust_custom = ability_drow_ranger_gust_custom
____exports.modifier_general_frozen_son = __TS__Class()
local modifier_general_frozen_son = ____exports.modifier_general_frozen_son
modifier_general_frozen_son.name = "modifier_general_frozen_son"
modifier_general_frozen_son.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_gust_custom.lua"
__TS__ClassExtends(modifier_general_frozen_son, BaseModifier)
function modifier_general_frozen_son.prototype.IsHidden(self)
return false
end
function modifier_general_frozen_son.prototype.IsDebuff(self)
return true
end
function modifier_general_frozen_son.prototype.IsPurgable(self)
return true
end
function modifier_general_frozen_son.prototype.GetEffectName(self)
return "particles/units/heroes/hero_crystalmaiden/maiden_frostbite_buff.vpcf"
end
function modifier_general_frozen_son.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_general_frozen_son.prototype.CheckState(self)
return {[MODIFIER_STATE_ROOTED] = true, [MODIFIER_STATE_DISARMED] = true}
end
function modifier_general_frozen_son.prototype.OnCreated(self, params)
if IsClient() then
return
end
EmitSoundOn(
"Hero_Crystal.Frostbite",
self:GetParent()
)
end
function modifier_general_frozen_son.prototype.OnDestroy(self)
if IsClient() then
return
end
StopSoundOn(
"Hero_Crystal.Frostbite",
self:GetParent()
)
end
modifier_general_frozen_son = __TS__Decorate(
modifier_general_frozen_son,
modifier_general_frozen_son,
{registerModifier(nil)},
{kind = "class", name = "modifier_general_frozen_son"}
)
____exports.modifier_general_frozen_son = modifier_general_frozen_son
return ____exports
@@ -0,0 +1,194 @@
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
____exports.ability_drow_ranger_marksmanship_custom = __TS__Class()
local ability_drow_ranger_marksmanship_custom = ____exports.ability_drow_ranger_marksmanship_custom
ability_drow_ranger_marksmanship_custom.name = "ability_drow_ranger_marksmanship_custom"
ability_drow_ranger_marksmanship_custom.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_marksmanship_custom.lua"
__TS__ClassExtends(ability_drow_ranger_marksmanship_custom, BaseAbility)
function ability_drow_ranger_marksmanship_custom.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.modifier = "modifier_drow_ranger_marksmanship_custom"
end
function ability_drow_ranger_marksmanship_custom.prototype.GetIntrinsicModifierName(self)
return self.modifier
end
ability_drow_ranger_marksmanship_custom = __TS__Decorate(
ability_drow_ranger_marksmanship_custom,
ability_drow_ranger_marksmanship_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_drow_ranger_marksmanship_custom"}
)
____exports.ability_drow_ranger_marksmanship_custom = ability_drow_ranger_marksmanship_custom
____exports.modifier_drow_ranger_marksmanship_custom = __TS__Class()
local modifier_drow_ranger_marksmanship_custom = ____exports.modifier_drow_ranger_marksmanship_custom
modifier_drow_ranger_marksmanship_custom.name = "modifier_drow_ranger_marksmanship_custom"
modifier_drow_ranger_marksmanship_custom.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_marksmanship_custom.lua"
__TS__ClassExtends(modifier_drow_ranger_marksmanship_custom, BaseModifier)
function modifier_drow_ranger_marksmanship_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.hits = 0
self.bonusDamage = 0
self.isActive = true
self.checkRadius = self:GetAbility():GetSpecialValueFor("disable_range")
end
function modifier_drow_ranger_marksmanship_custom.prototype.IsHidden(self)
return false
end
function modifier_drow_ranger_marksmanship_custom.prototype.IsDebuff(self)
return false
end
function modifier_drow_ranger_marksmanship_custom.prototype.IsPurgable(self)
return false
end
function modifier_drow_ranger_marksmanship_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
self.hits = ability:GetSpecialValueFor("hits")
self.bonusDamage = ability:GetSpecialValueFor("bonus_damage")
self.checkRadius = ability:GetSpecialValueFor("disable_range")
self:SetStackCount(self.hits)
self:StartIntervalThink(0.1)
end
function modifier_drow_ranger_marksmanship_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
if self:GetParent():PassivesDisabled() then
self.isActive = false
return
end
local parent = self:GetParent()
local enemies = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
self.checkRadius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
self.isActive = #enemies == 0
end
function modifier_drow_ranger_marksmanship_custom.prototype.OnDestroy(self)
if IsClient() then
return
end
end
function modifier_drow_ranger_marksmanship_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PROJECTILE_NAME, MODIFIER_EVENT_ON_ATTACK, MODIFIER_PROPERTY_BASEATTACK_BONUSDAMAGE}
end
function modifier_drow_ranger_marksmanship_custom.prototype.OnAttack(self, event)
if not IsServer() then
return
end
if self:GetParent():PassivesDisabled() then
return
end
if not self.isActive then
return
end
if self:GetParent():IsIllusion() then
return
end
local parent = self:GetParent()
if event.attacker ~= parent then
return
end
if self:GetStackCount() == 1 then
self:SetStackCount(self.hits)
EmitSoundOn("Hero_DrowRanger.Marksmanship.Target", event.target)
if self:GetAbility():GetSpecialValueFor("marksmanship_master") > 0 then
event.target:AddNewModifier(
parent,
self:GetAbility(),
"modifier_drow_ranger_marksmanship_custom_armor",
{duration = 0.5}
)
end
return
end
self:DecrementStackCount()
end
function modifier_drow_ranger_marksmanship_custom.prototype.GetPriority(self)
local ____temp_0
if self:GetStackCount() == 1 then
____temp_0 = MODIFIER_PRIORITY_ULTRA
else
____temp_0 = MODIFIER_PRIORITY_NORMAL
end
return ____temp_0
end
function modifier_drow_ranger_marksmanship_custom.prototype.GetModifierProjectileName(self)
if self:GetParent():PassivesDisabled() then
return ""
end
if self:GetParent():IsIllusion() then
return ""
end
if not self.isActive then
return ""
end
return self:GetStackCount() == 1 and "particles/units/heroes/hero_drow/drow_marksmanship_attack.vpcf" or ""
end
function modifier_drow_ranger_marksmanship_custom.prototype.GetModifierBaseAttack_BonusDamage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
if self:GetParent():IsIllusion() then
return 0
end
if not self.isActive then
return 0
end
return self:GetStackCount() == 1 and self.bonusDamage or 0
end
modifier_drow_ranger_marksmanship_custom = __TS__Decorate(
modifier_drow_ranger_marksmanship_custom,
modifier_drow_ranger_marksmanship_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_drow_ranger_marksmanship_custom"}
)
____exports.modifier_drow_ranger_marksmanship_custom = modifier_drow_ranger_marksmanship_custom
____exports.modifier_drow_ranger_marksmanship_custom_armor = __TS__Class()
local modifier_drow_ranger_marksmanship_custom_armor = ____exports.modifier_drow_ranger_marksmanship_custom_armor
modifier_drow_ranger_marksmanship_custom_armor.name = "modifier_drow_ranger_marksmanship_custom_armor"
modifier_drow_ranger_marksmanship_custom_armor.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_marksmanship_custom.lua"
__TS__ClassExtends(modifier_drow_ranger_marksmanship_custom_armor, BaseModifier)
function modifier_drow_ranger_marksmanship_custom_armor.prototype.IsHidden(self)
return true
end
function modifier_drow_ranger_marksmanship_custom_armor.prototype.IsDebuff(self)
return true
end
function modifier_drow_ranger_marksmanship_custom_armor.prototype.IsPurgable(self)
return false
end
function modifier_drow_ranger_marksmanship_custom_armor.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_IGNORE_PHYSICAL_ARMOR}
end
function modifier_drow_ranger_marksmanship_custom_armor.prototype.GetModifierIgnorePhysicalArmor(self)
return 1
end
function modifier_drow_ranger_marksmanship_custom_armor.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_IGNORE_INVULNERABLE
end
modifier_drow_ranger_marksmanship_custom_armor = __TS__Decorate(
modifier_drow_ranger_marksmanship_custom_armor,
modifier_drow_ranger_marksmanship_custom_armor,
{registerModifier(nil)},
{kind = "class", name = "modifier_drow_ranger_marksmanship_custom_armor"}
)
____exports.modifier_drow_ranger_marksmanship_custom_armor = modifier_drow_ranger_marksmanship_custom_armor
return ____exports
@@ -0,0 +1,201 @@
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_froze = require("abilities.modifiers.modifier_general_froze")
local modifier_general_froze = ____modifier_general_froze.modifier_general_froze
____exports.ability_drow_ranger_multishot_custom = __TS__Class()
local ability_drow_ranger_multishot_custom = ____exports.ability_drow_ranger_multishot_custom
ability_drow_ranger_multishot_custom.name = "ability_drow_ranger_multishot_custom"
ability_drow_ranger_multishot_custom.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_multishot_custom.lua"
__TS__ClassExtends(ability_drow_ranger_multishot_custom, BaseAbility)
function ability_drow_ranger_multishot_custom.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.modifier = nil
end
function ability_drow_ranger_multishot_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local duration = self:GetChannelTime()
caster:AddNewModifier(caster, self, ____exports.modifier_drow_ranger_multishot_damage_custom.name, {duration = 1.75})
self.modifier = ____exports.modifier_drow_ranger_multishot_custom:apply(caster, caster, self, {duration = duration, x = point.x, y = point.y, z = point.z})
EmitSoundOn("Hero_DrowRanger.Multishot.Channel", caster)
end
function ability_drow_ranger_multishot_custom.prototype.OnChannelFinish(self)
if self.modifier ~= nil then
self.modifier:Destroy()
end
self:GetCaster():RemoveModifierByName(____exports.modifier_drow_ranger_multishot_damage_custom.name)
end
function ability_drow_ranger_multishot_custom.prototype.OnProjectileHit_ExtraData(self, target)
if not target then
return
end
local caster = self:GetCaster()
local modifier = target:AddNewModifier(
self:GetCaster(),
self,
modifier_general_froze.name,
{}
)
local stacksPerLevel = self:GetSpecialValueFor("frost_stacks_per_level")
do
local i = 0
while i < stacksPerLevel do
modifier:IncrementStackCount()
i = i + 1
end
end
caster:PerformAttack(
target,
true,
true,
true,
false,
false,
false,
false
)
EmitSoundOn("Hero_DrowRanger.ProjectileImpact", target)
if self:GetSpecialValueFor("piercing_arrows") > 0 then
return false
end
return true
end
ability_drow_ranger_multishot_custom = __TS__Decorate(
ability_drow_ranger_multishot_custom,
ability_drow_ranger_multishot_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_drow_ranger_multishot_custom"}
)
____exports.ability_drow_ranger_multishot_custom = ability_drow_ranger_multishot_custom
____exports.modifier_drow_ranger_multishot_custom = __TS__Class()
local modifier_drow_ranger_multishot_custom = ____exports.modifier_drow_ranger_multishot_custom
modifier_drow_ranger_multishot_custom.name = "modifier_drow_ranger_multishot_custom"
modifier_drow_ranger_multishot_custom.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_multishot_custom.lua"
__TS__ClassExtends(modifier_drow_ranger_multishot_custom, BaseModifier)
function modifier_drow_ranger_multishot_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.arrowDelay = 0.01
self.direction = Vector(0, 0, 0)
self.currentArrows = 0
self.currentWave = 0
self.arrowsPerWave = 0
self.waveCount = 0
self.waveDelay = 0
self.speed = 0
self.angle = 0
end
function modifier_drow_ranger_multishot_custom.prototype.OnCreated(self, params)
local caster = self:GetParent()
local ability = self:GetAbility()
local range = ability:GetSpecialValueFor("arrow_range_multiplier")
local width = ability:GetSpecialValueFor("arrow_width")
self.speed = ability:GetSpecialValueFor("arrow_speed")
if IsClient() then
return
end
local vision = 100
local delay = 0.1
local wave = ability:GetSpecialValueFor("wave_count")
local waveInterval = 0.4375
self.arrowsPerWave = ability:GetSpecialValueFor("arrow_count_per_wave")
self.waveCount = wave
self.waveDelay = waveInterval - self.arrowDelay * (self.arrowsPerWave - 1)
self.angle = 30
local point = Vector(params.x, params.y, params.z)
self.direction = point - caster:GetOrigin()
self.direction.z = 0
self.direction = self.direction:Normalized()
self.info = {
Source = caster,
Ability = ability,
vSpawnOrigin = caster:GetAttachmentOrigin(caster:ScriptLookupAttachment("attach_attack1")),
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES,
EffectName = "particles/units/heroes/hero_drow/drow_multishot_proj_linear_proj.vpcf",
fDistance = caster:Script_GetAttackRange() * range,
fStartRadius = width,
fEndRadius = width,
bProvidesVision = true,
iVisionRadius = vision,
iVisionTeamNumber = caster:GetTeamNumber()
}
self:StartIntervalThink(delay)
end
function modifier_drow_ranger_multishot_custom.prototype.OnDestroy(self)
if IsClient() then
return
end
StopSoundOn(
"Hero_DrowRanger.Multishot.Channel",
self:GetParent()
)
end
function modifier_drow_ranger_multishot_custom.prototype.OnIntervalThink(self)
if self.currentWave >= 3 then
return
end
if self.currentArrows < self.arrowsPerWave then
self:StartIntervalThink(self.arrowDelay)
else
self.currentArrows = 0
self.currentWave = self.currentWave + 1
if self.currentWave < 3 then
self:StartIntervalThink(self.waveDelay)
end
return
end
local step = self.angle / (self.arrowsPerWave - 1)
local angle = -self.angle / 2 + self.currentArrows * step
local projectileDirection = rotatePositionYaw(
nil,
Vector(0, 0, 0),
angle,
self.direction
)
self.info.vVelocity = projectileDirection * self.speed
ProjectileManager:CreateLinearProjectile(self.info)
EmitSoundOn(
"Hero_DrowRanger.Multishot.Attack",
self:GetParent()
)
self.currentArrows = self.currentArrows + 1
end
modifier_drow_ranger_multishot_custom = __TS__Decorate(
modifier_drow_ranger_multishot_custom,
modifier_drow_ranger_multishot_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_drow_ranger_multishot_custom"}
)
____exports.modifier_drow_ranger_multishot_custom = modifier_drow_ranger_multishot_custom
____exports.modifier_drow_ranger_multishot_damage_custom = __TS__Class()
local modifier_drow_ranger_multishot_damage_custom = ____exports.modifier_drow_ranger_multishot_damage_custom
modifier_drow_ranger_multishot_damage_custom.name = "modifier_drow_ranger_multishot_damage_custom"
modifier_drow_ranger_multishot_damage_custom.____file_path = "scripts/vscripts/abilities/heroes/drow_ranger/ability_drow_ranger_multishot_custom.lua"
__TS__ClassExtends(modifier_drow_ranger_multishot_damage_custom, BaseModifier)
function modifier_drow_ranger_multishot_damage_custom.prototype.IsHidden(self)
return true
end
function modifier_drow_ranger_multishot_damage_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE}
end
function modifier_drow_ranger_multishot_damage_custom.prototype.GetModifierDamageOutgoing_Percentage(self, event)
local damage = self:GetAbility():GetSpecialValueFor("arrow_damage_pct") - 100
return damage
end
modifier_drow_ranger_multishot_damage_custom = __TS__Decorate(
modifier_drow_ranger_multishot_damage_custom,
modifier_drow_ranger_multishot_damage_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_drow_ranger_multishot_damage_custom"}
)
____exports.modifier_drow_ranger_multishot_damage_custom = modifier_drow_ranger_multishot_damage_custom
return ____exports
@@ -0,0 +1,95 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
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
____exports.grimstroke_dark_portrait_custom = __TS__Class()
local grimstroke_dark_portrait_custom = ____exports.grimstroke_dark_portrait_custom
grimstroke_dark_portrait_custom.name = "grimstroke_dark_portrait_custom"
grimstroke_dark_portrait_custom.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_dark_portrait_custom.lua"
__TS__ClassExtends(grimstroke_dark_portrait_custom, BaseAbility)
function grimstroke_dark_portrait_custom.prototype.Precache(self, context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_terrorblade.vsndevts", context)
PrecacheResource("particle", "particles/units/heroes/hero_terrorblade/terrorblade_mirror_image.vpcf", context)
end
function grimstroke_dark_portrait_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not target or not target:IsInstance(CDOTA_BaseNPC_Hero) then
return
end
local duration = self:GetSpecialValueFor("illusion_duration")
local outgoing = self:GetSpecialValueFor("illusion_outgoing_damage")
local incoming = self:GetSpecialValueFor("illusion_incoming_damage")
local illusion = CreateIllusions(
caster,
target,
{incoming_damage = incoming, outgoing_damage = outgoing, duration = duration},
1,
caster:GetHullRadius(),
false,
true
)
__TS__ArrayForEach(
target:FindAllModifiers(),
function(____, modifier)
illusion[1]:AddNewModifier(
caster,
self,
modifier:GetName(),
{}
)
end
)
EmitSoundOn("Hero_Terrorblade.ConjureImage", illusion[1])
end
grimstroke_dark_portrait_custom = __TS__Decorate(
grimstroke_dark_portrait_custom,
grimstroke_dark_portrait_custom,
{registerAbility(nil)},
{kind = "class", name = "grimstroke_dark_portrait_custom"}
)
____exports.grimstroke_dark_portrait_custom = grimstroke_dark_portrait_custom
____exports.modifier_grimstroke_dark_portrait_custom = __TS__Class()
local modifier_grimstroke_dark_portrait_custom = ____exports.modifier_grimstroke_dark_portrait_custom
modifier_grimstroke_dark_portrait_custom.name = "modifier_grimstroke_dark_portrait_custom"
modifier_grimstroke_dark_portrait_custom.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_dark_portrait_custom.lua"
__TS__ClassExtends(modifier_grimstroke_dark_portrait_custom, BaseModifier)
function modifier_grimstroke_dark_portrait_custom.prototype.IsHidden(self)
return true
end
function modifier_grimstroke_dark_portrait_custom.prototype.IsDebuff(self)
return false
end
function modifier_grimstroke_dark_portrait_custom.prototype.IsStunDebuff(self)
return false
end
function modifier_grimstroke_dark_portrait_custom.prototype.IsPurgable(self)
return false
end
function modifier_grimstroke_dark_portrait_custom.prototype.GetEffectName(self)
return "particles/units/heroes/hero_terrorblade/terrorblade_mirror_image.vpcf"
end
function modifier_grimstroke_dark_portrait_custom.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_grimstroke_dark_portrait_custom.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_terrorblade_reflection.vpcf"
end
function modifier_grimstroke_dark_portrait_custom.prototype.StatusEffectPriority(self)
return MODIFIER_PRIORITY_SUPER_ULTRA
end
modifier_grimstroke_dark_portrait_custom = __TS__Decorate(
modifier_grimstroke_dark_portrait_custom,
modifier_grimstroke_dark_portrait_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_grimstroke_dark_portrait_custom"}
)
____exports.modifier_grimstroke_dark_portrait_custom = modifier_grimstroke_dark_portrait_custom
return ____exports
@@ -0,0 +1,231 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
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
____exports.grimstroke_ink_swell_custom = __TS__Class()
local grimstroke_ink_swell_custom = ____exports.grimstroke_ink_swell_custom
grimstroke_ink_swell_custom.name = "grimstroke_ink_swell_custom"
grimstroke_ink_swell_custom.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_ink_swell_custom.lua"
__TS__ClassExtends(grimstroke_ink_swell_custom, BaseAbility)
function grimstroke_ink_swell_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not target then
return
end
local duration = self:GetSpecialValueFor("buff_duration")
target:AddNewModifier(caster, self, ____exports.modifier_grimstroke_ink_swell.name, {duration = duration})
local effectCast = ParticleManager:CreateParticle("particles/units/heroes/hero_grimstroke/grimstroke_cast_ink_swell.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:ReleaseParticleIndex(effectCast)
EmitSoundOn("Hero_Grimstroke.InkSwell.Cast", caster)
end
grimstroke_ink_swell_custom = __TS__Decorate(
grimstroke_ink_swell_custom,
grimstroke_ink_swell_custom,
{registerAbility(nil)},
{kind = "class", name = "grimstroke_ink_swell_custom"}
)
____exports.grimstroke_ink_swell_custom = grimstroke_ink_swell_custom
____exports.modifier_grimstroke_ink_swell = __TS__Class()
local modifier_grimstroke_ink_swell = ____exports.modifier_grimstroke_ink_swell
modifier_grimstroke_ink_swell.name = "modifier_grimstroke_ink_swell"
modifier_grimstroke_ink_swell.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_ink_swell_custom.lua"
__TS__ClassExtends(modifier_grimstroke_ink_swell, BaseModifier)
function modifier_grimstroke_ink_swell.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.counter = 0
end
function modifier_grimstroke_ink_swell.prototype.IsHidden(self)
return false
end
function modifier_grimstroke_ink_swell.prototype.IsDebuff(self)
return false
end
function modifier_grimstroke_ink_swell.prototype.IsPurgable(self)
return true
end
function modifier_grimstroke_ink_swell.prototype.OnCreated(self)
if IsClient() then
return
end
local interval = self:GetAbility():GetSpecialValueFor("tick_rate")
local radius = self:GetAbility():GetSpecialValueFor("radius")
self:StartIntervalThink(interval)
local effectCast = ParticleManager:CreateParticle(
"particles/units/heroes/hero_grimstroke/grimstroke_ink_swell_buff.vpcf",
PATTACH_OVERHEAD_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
effectCast,
2,
Vector(radius, radius, radius)
)
ParticleManager:SetParticleControlEnt(
effectCast,
3,
self:GetParent(),
PATTACH_ABSORIGIN_FOLLOW,
"attach_attack1",
self:GetParent():GetOrigin(),
true
)
self:AddParticle(
effectCast,
false,
false,
-1,
false,
true
)
EmitSoundOn(
"Hero_Grimstroke.InkSwell.Target",
self:GetParent()
)
end
function modifier_grimstroke_ink_swell.prototype.OnDestroy(self)
if IsClient() then
return
end
local radius = self:GetAbility():GetSpecialValueFor("radius")
local enemies = FindUnitsInRadius(
self:GetParent():GetTeamNumber(),
self:GetParent():GetOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_HERO),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local baseStun = self:GetAbility():GetSpecialValueFor("debuff_duration")
local maxMultiplier = self:GetAbility():GetSpecialValueFor("max_bonus_multiplier")
local baseDamage = self:GetAbility():GetSpecialValueFor("damage")
local maxCounter = self:GetAbility():GetSpecialValueFor("max_counter")
local multiplier = self.counter / maxCounter * maxMultiplier
local finalMultiplier = math.min(maxMultiplier, multiplier + 1)
local stun = baseStun * finalMultiplier
local damage = baseDamage * finalMultiplier
__TS__ArrayForEach(
enemies,
function(____, enemy)
ApplyDamage({
victim = enemy,
attacker = self:GetParent(),
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self:GetAbility()
})
enemy:AddNewModifier(
self:GetParent(),
self:GetAbility(),
"modifier_stunned",
{duration = stun}
)
end
)
StopSoundOn(
"Hero_Grimstroke.InkSwell.Target",
self:GetParent()
)
local effectCast = ParticleManager:CreateParticle(
"particles/units/heroes/hero_grimstroke/grimstroke_ink_swell_aoe.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
effectCast,
2,
Vector(radius, radius, radius)
)
ParticleManager:ReleaseParticleIndex(effectCast)
EmitSoundOn(
"Hero_Grimstroke.InkSwell.Stun",
self:GetParent()
)
end
function modifier_grimstroke_ink_swell.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_grimstroke_ink_swell.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self:GetAbility():GetSpecialValueFor("movespeed_bonus_pct")
end
function modifier_grimstroke_ink_swell.prototype.CheckState(self)
return {[MODIFIER_STATE_ATTACK_IMMUNE] = true, [MODIFIER_STATE_DISARMED] = true, [MODIFIER_STATE_SILENCED] = true}
end
function modifier_grimstroke_ink_swell.prototype.OnIntervalThink(self)
if IsClient() then
return
end
local maxCounter = self:GetAbility():GetSpecialValueFor("max_counter")
local radius = self:GetAbility():GetSpecialValueFor("radius")
local maxMultiplier = self:GetAbility():GetSpecialValueFor("max_bonus_multiplier")
local multiplier = self.counter / maxCounter * maxMultiplier
local damagePerTick = self:GetAbility():GetSpecialValueFor("tick_dps_tooltip") * self:GetAbility():GetSpecialValueFor("tick_rate")
local damage = damagePerTick * math.min(maxMultiplier, multiplier + 1)
local enemies = FindUnitsInRadius(
self:GetParent():GetTeamNumber(),
self:GetParent():GetOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_ALL,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
__TS__ArrayForEach(
enemies,
function(____, enemy)
ApplyDamage({
victim = enemy,
attacker = self:GetParent(),
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self:GetAbility()
})
self.counter = self.counter + 1
local effectCast = ParticleManager:CreateParticle(
"particles/units/heroes/hero_grimstroke/grimstroke_ink_swell_tick_damage.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControlEnt(
effectCast,
0,
self:GetParent(),
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
Vector(0, 0, 0),
true
)
ParticleManager:SetParticleControlEnt(
effectCast,
1,
enemy,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
Vector(0, 0, 0),
true
)
ParticleManager:ReleaseParticleIndex(effectCast)
EmitSoundOn("Hero_Grimstroke.InkSwell.Damage", enemy)
end
)
end
modifier_grimstroke_ink_swell = __TS__Decorate(
modifier_grimstroke_ink_swell,
modifier_grimstroke_ink_swell,
{registerModifier(nil)},
{kind = "class", name = "modifier_grimstroke_ink_swell"}
)
____exports.modifier_grimstroke_ink_swell = modifier_grimstroke_ink_swell
return ____exports
@@ -0,0 +1,316 @@
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 BaseModifierMotionHorizontal = ____dota_ts_adapter.BaseModifierMotionHorizontal
local registerAbility = ____dota_ts_adapter.registerAbility
local registerModifier = ____dota_ts_adapter.registerModifier
____exports.grimstroke_phantoms_embrace_custom = __TS__Class()
local grimstroke_phantoms_embrace_custom = ____exports.grimstroke_phantoms_embrace_custom
grimstroke_phantoms_embrace_custom.name = "grimstroke_phantoms_embrace_custom"
grimstroke_phantoms_embrace_custom.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_phantoms_embrace_custom.lua"
__TS__ClassExtends(grimstroke_phantoms_embrace_custom, BaseAbility)
function grimstroke_phantoms_embrace_custom.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.returned = false
end
function grimstroke_phantoms_embrace_custom.prototype.OnSpellStart(self)
local target = self:GetCursorTarget()
if not target then
return
end
local caster = self:GetCaster()
local spawnPos = caster:GetOrigin() + caster:GetForwardVector() * 150
self.returned = false
local phantom = CreateUnitByName(
"npc_dota_grimstroke_ink_creature",
spawnPos,
true,
nil,
nil,
caster:GetTeamNumber()
)
phantom:AddNewModifier(
caster,
self,
____exports.modifier_grimstroke_phantoms_embrace_custom_thinker.name,
{target = target:entindex()}
)
local effectCast = ParticleManager:CreateParticle("particles/units/heroes/hero_grimstroke/grimstroke_cast_phantom.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:ReleaseParticleIndex(effectCast)
self:SetActivated(false)
EmitSoundOn("Hero_Grimstroke.InkCreature.Cast", caster)
end
function grimstroke_phantoms_embrace_custom.prototype.OnProjectileHit(self, _target)
local caster = self:GetCaster()
self:EndCooldown()
self:SetActivated(true)
self.returned = true
Timers:CreateTimer(
self:GetSpecialValueFor("return_time_free"),
function()
self.returned = false
return nil
end
)
EmitSoundOn("Hero_Grimstroke.InkCreature.Returned", caster)
end
grimstroke_phantoms_embrace_custom = __TS__Decorate(
grimstroke_phantoms_embrace_custom,
grimstroke_phantoms_embrace_custom,
{registerAbility(nil)},
{kind = "class", name = "grimstroke_phantoms_embrace_custom"}
)
____exports.grimstroke_phantoms_embrace_custom = grimstroke_phantoms_embrace_custom
____exports.modifier_grimstroke_phantoms_embrace_custom_thinker = __TS__Class()
local modifier_grimstroke_phantoms_embrace_custom_thinker = ____exports.modifier_grimstroke_phantoms_embrace_custom_thinker
modifier_grimstroke_phantoms_embrace_custom_thinker.name = "modifier_grimstroke_phantoms_embrace_custom_thinker"
modifier_grimstroke_phantoms_embrace_custom_thinker.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_phantoms_embrace_custom.lua"
__TS__ClassExtends(modifier_grimstroke_phantoms_embrace_custom_thinker, BaseModifierMotionHorizontal)
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.____constructor(self, ...)
BaseModifierMotionHorizontal.prototype.____constructor(self, ...)
self.latchOffset = 80
self.latchDuration = 0
self.speed = 0
self.tick = 0
self.latching = false
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.OnCreated(self, params)
if IsClient() then
return
end
local ability = self:GetAbility()
self.target = EntIndexToHScript(params.target)
self.speed = ability:GetSpecialValueFor("speed")
self.latchDuration = ability:GetSpecialValueFor("latch_duration")
self.tick = ability:GetSpecialValueFor("tick")
if not self:ApplyHorizontalMotionController() then
self:Destroy()
end
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.OnDestroy(self)
if IsClient() then
return
end
local parent = self:GetParent()
parent:InterruptMotionControllers(true)
self.target:RemoveModifierByName(____exports.modifier_grimstroke_phantoms_embrace_custom_debuff.name)
local effectCast = ParticleManager:CreateParticle("particles/units/heroes/hero_grimstroke/grimstroke_phantom_death.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:ReleaseParticleIndex(effectCast)
EmitSoundOn("Hero_Grimstroke.InkCreature.Death", parent)
if not self.latching then
local ____opt_0 = self:GetAbility()
if ____opt_0 ~= nil then
____opt_0:SetActivated(true)
end
end
parent:ForceKill(false)
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.CheckState(self)
return {[MODIFIER_STATE_INVULNERABLE] = true, [MODIFIER_STATE_NO_HEALTH_BAR] = true}
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_OVERRIDE_ANIMATION}
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.GetOverrideAnimation(self)
local ____table_latching_2
if self.latching then
____table_latching_2 = ACT_DOTA_CAPTURE
else
____table_latching_2 = ACT_DOTA_RUN
end
return ____table_latching_2
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.UpdateHorizontalMotion(self, me, dt)
if self.latching then
self:latch(me, dt)
return
end
if (self.target:GetOrigin() - self:GetParent():GetOrigin()):Length2D() < self.latchOffset then
self:setLatching()
return
end
self:charge(me, dt)
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.OnHorizontalMotionInterrupted(self)
if IsServer() then
self:Destroy()
end
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.charge(self, _me, dt)
local parent = self:GetParent()
local point = parent:GetOrigin()
local targetPoint = self.target:GetOrigin()
local direction = targetPoint - point
direction.z = 0
local target = point + direction:Normalized() * (self.speed * dt)
parent:SetOrigin(target)
parent:FaceTowards(targetPoint)
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.latch(self, _me, _dt)
local parent = self:GetParent()
local target = self.target:GetOrigin() + self.target:GetForwardVector() * self.latchOffset
parent:SetOrigin(target)
parent:FaceTowards(self.target:GetOrigin())
end
function modifier_grimstroke_phantoms_embrace_custom_thinker.prototype.setLatching(self)
if not self.target:IsAlive() then
self:Destroy()
return
end
self.latching = true
self:SetStackCount(1)
self:SetDuration(self.latchDuration, false)
____exports.modifier_grimstroke_phantoms_embrace_custom_debuff:apply(
self.target,
self:GetCaster(),
self:GetAbility(),
{phantom = self:GetParent():entindex()}
)
EmitSoundOn(
"Hero_Grimstroke.InkCreature.Attach",
self:GetParent()
)
end
modifier_grimstroke_phantoms_embrace_custom_thinker = __TS__Decorate(
modifier_grimstroke_phantoms_embrace_custom_thinker,
modifier_grimstroke_phantoms_embrace_custom_thinker,
{registerModifier(nil)},
{kind = "class", name = "modifier_grimstroke_phantoms_embrace_custom_thinker"}
)
____exports.modifier_grimstroke_phantoms_embrace_custom_thinker = modifier_grimstroke_phantoms_embrace_custom_thinker
____exports.modifier_grimstroke_phantoms_embrace_custom_debuff = __TS__Class()
local modifier_grimstroke_phantoms_embrace_custom_debuff = ____exports.modifier_grimstroke_phantoms_embrace_custom_debuff
modifier_grimstroke_phantoms_embrace_custom_debuff.name = "modifier_grimstroke_phantoms_embrace_custom_debuff"
modifier_grimstroke_phantoms_embrace_custom_debuff.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_phantoms_embrace_custom.lua"
__TS__ClassExtends(modifier_grimstroke_phantoms_embrace_custom_debuff, BaseModifier)
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.tick = 0
self.damage = 0
self.radiusFind = 0
self.damageIncoming = 0
end
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.IsPurgable(self)
return false
end
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.RemoveOnDeath(self)
return true
end
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE}
end
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.GetModifierIncomingDamage_Percentage(self, event)
if event.target == self:GetParent() and event.attacker == self:GetCaster() then
return self.damageIncoming
end
return 0
end
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.OnCreated(self, params)
local ability = self:GetAbility()
self.tick = ability:GetSpecialValueFor("tick")
self.damage = ability:GetSpecialValueFor("damage")
self.radiusFind = ability:GetSpecialValueFor("radius_find")
self.damageIncoming = ability:GetSpecialValueFor("damage_incoming")
if IsClient() then
return
end
self.phantom = EntIndexToHScript(params.phantom)
local parent = self:GetParent()
local effectCast = ParticleManager:CreateParticle("particles/units/heroes/hero_grimstroke/grimstroke_phantom_ambient.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:SetParticleControlEnt(
effectCast,
0,
parent,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
Vector(0, 0, 0),
true
)
self:AddParticle(
effectCast,
false,
false,
-1,
false,
false
)
EmitSoundOn("Hero_Grimstroke.InkCreature.Spawn", parent)
self:StartIntervalThink(self.tick)
end
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.OnDestroy(self)
if IsClient() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
self.phantom:ForceKill(false)
if parent:IsAlive() then
ability:SetActivated(true)
return
end
local caster = self:GetCaster()
local enemy = FindUnitsInRadius(
caster:GetTeamNumber(),
parent:GetOrigin(),
nil,
self.radiusFind,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_CLOSEST,
false
)[1]
if enemy then
UTIL_Remove(self.phantom)
local spawnPos = parent:GetOrigin() + parent:GetForwardVector() * 150
local phantom = CreateUnitByName(
"npc_dota_grimstroke_ink_creature",
spawnPos,
true,
nil,
nil,
caster:GetTeamNumber()
)
phantom:AddNewModifier(
caster,
ability,
____exports.modifier_grimstroke_phantoms_embrace_custom_thinker.name,
{target = enemy:entindex()}
)
return
end
ProjectileManager:CreateTrackingProjectile({
Target = caster,
Source = parent,
Ability = ability,
EffectName = "particles/units/heroes/hero_grimstroke/grimstroke_phantom_return.vpcf",
iMoveSpeed = ability:GetSpecialValueFor("speed"),
bDodgeable = true
})
end
function modifier_grimstroke_phantoms_embrace_custom_debuff.prototype.OnIntervalThink(self)
if IsClient() then
return
end
local ability = self:GetAbility()
ApplyDamage({
victim = self:GetParent(),
attacker = self:GetCaster(),
damage = self.damage * self.tick,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
end
modifier_grimstroke_phantoms_embrace_custom_debuff = __TS__Decorate(
modifier_grimstroke_phantoms_embrace_custom_debuff,
modifier_grimstroke_phantoms_embrace_custom_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_grimstroke_phantoms_embrace_custom_debuff"}
)
____exports.modifier_grimstroke_phantoms_embrace_custom_debuff = modifier_grimstroke_phantoms_embrace_custom_debuff
return ____exports
@@ -0,0 +1,315 @@
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
____exports.grimstroke_stroke_of_fate_custom = __TS__Class()
local grimstroke_stroke_of_fate_custom = ____exports.grimstroke_stroke_of_fate_custom
grimstroke_stroke_of_fate_custom.name = "grimstroke_stroke_of_fate_custom"
grimstroke_stroke_of_fate_custom.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_stroke_of_fate_custom.lua"
__TS__ClassExtends(grimstroke_stroke_of_fate_custom, BaseAbility)
function grimstroke_stroke_of_fate_custom.prototype.____constructor(self, ...)
BaseAbility.prototype.____constructor(self, ...)
self.activeProj = {}
self.bentWaveId = 0
self.projectileWaveId = {}
self.waveState = {}
end
function grimstroke_stroke_of_fate_custom.prototype.GetVectorTargetRange(self)
return self:GetCastRange(
self:GetCaster():GetAbsOrigin(),
nil
)
end
function grimstroke_stroke_of_fate_custom.prototype.GetVectorTargetStartRadius(self)
return self:GetSpecialValueFor("start_radius")
end
function grimstroke_stroke_of_fate_custom.prototype.GetVectorTargetEndRadius(self)
return self:GetSpecialValueFor("end_radius")
end
function grimstroke_stroke_of_fate_custom.prototype.GetVectorPosition(self)
local ____self_vectorTargetPosition_0 = self.vectorTargetPosition
if ____self_vectorTargetPosition_0 == nil then
____self_vectorTargetPosition_0 = self:GetCursorPosition()
end
return ____self_vectorTargetPosition_0
end
function grimstroke_stroke_of_fate_custom.prototype.GetVector2Position(self)
local ____self_vectorTargetPosition2_1 = self.vectorTargetPosition2
if ____self_vectorTargetPosition2_1 == nil then
____self_vectorTargetPosition2_1 = self:GetCursorPosition()
end
return ____self_vectorTargetPosition2_1
end
function grimstroke_stroke_of_fate_custom.prototype.GetVectorDirection(self)
local ____self_vectorTargetDirection_2 = self.vectorTargetDirection
if ____self_vectorTargetDirection_2 == nil then
____self_vectorTargetDirection_2 = self:GetCaster():GetForwardVector()
end
return ____self_vectorTargetDirection_2
end
function grimstroke_stroke_of_fate_custom.prototype.UpdateVectorValues(self)
CustomNetTables:SetTableValue(
"vector_targeting",
tostring(self:entindex()),
{
startWidth = self:GetVectorTargetStartRadius(),
endWidth = self:GetVectorTargetEndRadius(),
castLength = self:GetVectorTargetRange(),
dual = false,
ignoreArrow = false
}
)
end
function grimstroke_stroke_of_fate_custom.prototype.IsDualVectorDirection(self)
return true
end
function grimstroke_stroke_of_fate_custom.prototype.IgnoreVectorArrowWidth(self)
return true
end
function grimstroke_stroke_of_fate_custom.prototype.GetCastRange(self, _location, _target)
return self:GetSpecialValueFor("range") > 0 and self:GetSpecialValueFor("range") or BaseAbility.prototype.GetCastRange(self, _location, _target)
end
function grimstroke_stroke_of_fate_custom.prototype.OnAbilityPhaseStart(self)
local particleCast = "particles/units/heroes/hero_grimstroke/grimstroke_cast2_ground.vpcf"
local soundPrecast = "Hero_Grimstroke.DarkArtistry.PreCastPoint"
self.effectCast = ParticleManager:CreateParticle(
particleCast,
PATTACH_ABSORIGIN_FOLLOW,
self:GetCaster()
)
ParticleManager:SetParticleControlEnt(
self.effectCast,
0,
self:GetCaster(),
PATTACH_POINT_FOLLOW,
"attach_attack2",
Vector(0, 1, 1),
true
)
ParticleManager:ReleaseParticleIndex(self.effectCast)
EmitSoundOn(
soundPrecast,
self:GetCaster()
)
return true
end
function grimstroke_stroke_of_fate_custom.prototype.OnAbilityPhaseInterrupted(self)
local soundPrecast = "Hero_Grimstroke.DarkArtistry.PreCastPoint"
if self.effectCast then
ParticleManager:DestroyParticle(self.effectCast, true)
end
StopSoundOn(
soundPrecast,
self:GetCaster()
)
end
function grimstroke_stroke_of_fate_custom.prototype.OnVectorCastStart(self, vStartLocation, vDirection)
local caster = self:GetCaster()
local castOrigin = caster:GetAbsOrigin()
local startPoint = vStartLocation
local bendDirection = vDirection
local projectileName = "particles/units/heroes/hero_grimstroke/grimstroke_darkartistry_proj.vpcf"
local secondSegmentDistance = self:GetSpecialValueFor("range")
local startRadius = self:GetSpecialValueFor("start_radius")
local endRadius = self:GetSpecialValueFor("end_radius")
local speed = self:GetSpecialValueFor("projectile_speed")
bendDirection.z = 0
if bendDirection:Length2D() < 1 then
bendDirection = caster:GetForwardVector()
bendDirection.z = 0
end
bendDirection = bendDirection:Normalized()
local firstSegmentDirection = startPoint - castOrigin
firstSegmentDirection.z = 0
if firstSegmentDirection:Length2D() < 1 then
firstSegmentDirection = caster:GetForwardVector()
firstSegmentDirection.z = 0
end
local firstSegmentDistance = firstSegmentDirection:Length2D()
firstSegmentDirection = firstSegmentDirection:Normalized()
self.bentWaveId = self.bentWaveId + 1
local waveId = self.bentWaveId
self.waveState[waveId] = {hitCounter = 0, hitTargets = {}}
if firstSegmentDistance > 1 then
local firstProjectile = ProjectileManager:CreateLinearProjectile({
Source = caster,
Ability = self,
vSpawnOrigin = castOrigin,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_HERO),
EffectName = projectileName,
fDistance = firstSegmentDistance,
fStartRadius = startRadius,
fEndRadius = endRadius,
vVelocity = firstSegmentDirection * speed,
bHasFrontalCone = false,
bProvidesVision = false
})
self.projectileWaveId[firstProjectile] = waveId
end
local secondDelay = firstSegmentDistance > 1 and firstSegmentDistance / speed or 0
Timers:CreateTimer(
secondDelay,
function()
if self.bentWaveId ~= waveId or not caster or caster:IsNull() then
return nil
end
local secondProjectile = ProjectileManager:CreateLinearProjectile({
Source = caster,
Ability = self,
vSpawnOrigin = startPoint,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_BASIC, DOTA_UNIT_TARGET_HERO),
EffectName = projectileName,
fDistance = secondSegmentDistance,
fStartRadius = startRadius,
fEndRadius = endRadius,
vVelocity = bendDirection * speed,
bHasFrontalCone = false,
bProvidesVision = false
})
self.projectileWaveId[secondProjectile] = waveId
return nil
end
)
EmitSoundOn("Hero_Grimstroke.DarkArtistry.Cast", caster)
EmitSoundOn("Hero_Grimstroke.DarkArtistry.Cast.Layer", caster)
end
function grimstroke_stroke_of_fate_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local cursorPoint = self:GetCursorPosition()
local fallbackDirection = cursorPoint - caster:GetAbsOrigin()
self:OnVectorCastStart(cursorPoint, fallbackDirection)
end
function grimstroke_stroke_of_fate_custom.prototype.OnProjectileHitHandle(self, target, _location, projectileHandle)
if not IsServer() then
return
end
local waveId = self.projectileWaveId[projectileHandle]
local ____temp_3
if waveId ~= nil then
____temp_3 = self.waveState[waveId]
else
____temp_3 = nil
end
local state = ____temp_3
if not target then
self.activeProj[projectileHandle] = nil
self.projectileWaveId[projectileHandle] = nil
return true
end
if state then
local targetId = target:entindex()
if state.hitTargets[targetId] then
return
end
state.hitTargets[targetId] = true
elseif not self.activeProj[projectileHandle] then
self.activeProj[projectileHandle] = 0
end
local multiplier = state and state.hitCounter or (self.activeProj[projectileHandle] or 0)
local baseDamage = self:GetAbilityDamage()
local bonusDamage = self:GetSpecialValueFor("bonus_damage_per_target")
local duration = self:GetSpecialValueFor("duration")
ApplyDamage({
victim = target,
attacker = self:GetCaster(),
damage = baseDamage + bonusDamage * multiplier,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
target:AddNewModifier(
self:GetCaster(),
self,
____exports.modifier_grimstroke_stroke_of_fate_root.name,
{duration = duration}
)
local effectCast = ParticleManager:CreateParticle("particles/units/heroes/hero_grimstroke/grimstroke_darkartistry_dmg.vpcf", PATTACH_ABSORIGIN_FOLLOW, target)
ParticleManager:ReleaseParticleIndex(effectCast)
if state then
state.hitCounter = state.hitCounter + 1
else
local ____self_activeProj_4, ____projectileHandle_5 = self.activeProj, projectileHandle
____self_activeProj_4[____projectileHandle_5] = ____self_activeProj_4[____projectileHandle_5] + 1
end
EmitSoundOn(
target:IsCreep() and "Hero_Grimstroke.DarkArtistry.Damage.Creep" or "Hero_Grimstroke.DarkArtistry.Damage",
target
)
end
grimstroke_stroke_of_fate_custom = __TS__Decorate(
grimstroke_stroke_of_fate_custom,
grimstroke_stroke_of_fate_custom,
{registerAbility(nil)},
{kind = "class", name = "grimstroke_stroke_of_fate_custom"}
)
____exports.grimstroke_stroke_of_fate_custom = grimstroke_stroke_of_fate_custom
____exports.modifier_grimstroke_stroke_of_fate_root = __TS__Class()
local modifier_grimstroke_stroke_of_fate_root = ____exports.modifier_grimstroke_stroke_of_fate_root
modifier_grimstroke_stroke_of_fate_root.name = "modifier_grimstroke_stroke_of_fate_root"
modifier_grimstroke_stroke_of_fate_root.____file_path = "scripts/vscripts/abilities/heroes/grimstroke/grimstroke_stroke_of_fate_custom.lua"
__TS__ClassExtends(modifier_grimstroke_stroke_of_fate_root, BaseModifier)
function modifier_grimstroke_stroke_of_fate_root.prototype.CheckState(self)
return {[MODIFIER_STATE_ROOTED] = true}
end
function modifier_grimstroke_stroke_of_fate_root.prototype.OnCreated(self)
self:StartIntervalThink(0.5)
if IsClient() then
return
end
self.effectCast = ParticleManager:CreateParticle(
"particles/units/heroes/hero_grimstroke/grimstroke_soulchain_debuff.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControlEnt(
self.effectCast,
2,
self:GetParent(),
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
self:GetParent():GetOrigin(),
true
)
self:AddParticle(
self.effectCast,
false,
false,
-1,
false,
false
)
end
function modifier_grimstroke_stroke_of_fate_root.prototype.OnDestroy(self)
if self.effectCast ~= nil then
ParticleManager:DestroyParticle(self.effectCast, false)
end
end
function modifier_grimstroke_stroke_of_fate_root.prototype.OnIntervalThink(self)
if IsClient() then
return
end
ApplyDamage({
victim = self:GetParent(),
attacker = self:GetCaster(),
damage = self:GetAbility():GetSpecialValueFor("interval_damage"),
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self:GetAbility()
})
end
modifier_grimstroke_stroke_of_fate_root = __TS__Decorate(
modifier_grimstroke_stroke_of_fate_root,
modifier_grimstroke_stroke_of_fate_root,
{registerModifier(nil)},
{kind = "class", name = "modifier_grimstroke_stroke_of_fate_root"}
)
____exports.modifier_grimstroke_stroke_of_fate_root = modifier_grimstroke_stroke_of_fate_root
return ____exports
@@ -0,0 +1,487 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local __TS__Delete = ____lualib.__TS__Delete
local __TS__ObjectAssign = ____lualib.__TS__ObjectAssign
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 ____hoodwink_sharpshooter_custom = require("abilities.heroes.hoodwink.hoodwink_sharpshooter_custom")
local hoodwink_sharpshooter_custom = ____hoodwink_sharpshooter_custom.hoodwink_sharpshooter_custom
local ____luck = require("utils.luck")
local rollLuckChance = ____luck.rollLuckChance
____exports.hoodwink_acorn_shot_custom = __TS__Class()
local hoodwink_acorn_shot_custom = ____exports.hoodwink_acorn_shot_custom
hoodwink_acorn_shot_custom.name = "hoodwink_acorn_shot_custom"
hoodwink_acorn_shot_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_acorn_shot_custom.lua"
__TS__ClassExtends(hoodwink_acorn_shot_custom, BaseAbility)
function hoodwink_acorn_shot_custom.prototype.getClosestTree(self, location, radius)
local trees = GridNav:GetAllTreesAroundPoint(location, radius, true)
if #trees == 0 then
return nil
end
local bestTree = trees[1]
local bestDist = bestTree:GetAbsOrigin():__sub(location):Length2D()
do
local i = 1
while i < #trees do
local dist = trees[i + 1]:GetAbsOrigin():__sub(location):Length2D()
if dist < bestDist then
bestDist = dist
bestTree = trees[i + 1]
end
i = i + 1
end
end
return bestTree
end
function hoodwink_acorn_shot_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/tree_fx/tree_simple_explosion.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_tree.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_impact.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_slow.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_tracking.vpcf", context)
end
function hoodwink_acorn_shot_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_hoodwink_acorn_shot_custom_scepter.name
end
function hoodwink_acorn_shot_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local target = self:GetCursorTarget()
local point = self:GetCursorPosition()
local bounceCount = self:GetSpecialValueFor("bounce_count")
local info = {
Ability = self,
Source = caster,
iMoveSpeed = self:GetSpecialValueFor("projectile_speed"),
bDodgeable = true,
iSourceAttachment = DOTA_PROJECTILE_ATTACHMENT_HITLOCATION,
bVisibleToEnemies = true,
bProvidesVision = true,
iVisionRadius = 200,
iVisionTeamNumber = caster:GetTeamNumber(),
EffectName = "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_tracking.vpcf",
ExtraData = {count = bounceCount, nextTree = 0}
}
caster:EmitSound("Hero_Hoodwink.AcornShot.Cast")
if target then
info.Target = target
ProjectileManager:CreateTrackingProjectile(info)
return
end
point.z = point.z + 40
info.vTargetLoc = point
ProjectileManager:CreateTrackingProjectile(info)
end
function hoodwink_acorn_shot_custom.prototype.ProjectileFindAndHitEnemy(self, target, location, data)
local caster = self:GetCaster()
local radius = self:GetSpecialValueFor("bounce_range")
local bounceDelay = self:GetSpecialValueFor("bounce_delay")
Timers:CreateTimer(
bounceDelay,
function()
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
location,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_CLOSEST,
false
)
local canBounceTrees = self:GetSpecialValueFor("can_bounce_off_of_trees") > 0
local candidates = __TS__ArrayFilter(
enemies,
function(____, unit) return unit:GetEntityIndex() ~= (target and target:GetEntityIndex()) end
)
local nonRepeated = __TS__ArrayFilter(
candidates,
function(____, unit) return unit:GetEntityIndex() ~= data.lastEnemy end
)
local enemy = nonRepeated[1] or candidates[1]
if enemy ~= nil then
__TS__Delete(data, "targetTree")
local enemyInfo = {
Ability = self,
Target = enemy,
EffectName = "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_tracking.vpcf",
iMoveSpeed = self:GetSpecialValueFor("projectile_speed") / 2,
bDodgeable = true,
iSourceAttachment = DOTA_PROJECTILE_ATTACHMENT_HITLOCATION,
bVisibleToEnemies = true,
bProvidesVision = true,
iVisionRadius = 200,
iVisionTeamNumber = caster:GetTeamNumber(),
ExtraData = __TS__ObjectAssign({}, data, {nextTree = canBounceTrees and 1 or 0})
}
if target then
enemyInfo.Source = target
target:EmitSound("Hero_Hoodwink.AcornShot.Bounce")
else
enemyInfo.vSourceLoc = location
end
ProjectileManager:CreateTrackingProjectile(enemyInfo)
return
end
local shouldGoTree = canBounceTrees and data.nextTree == 1
if not shouldGoTree then
return
end
local tree = self:getClosestTree(location, radius)
if tree == nil then
return
end
local treeLoc = tree:GetAbsOrigin()
local treeTarget = CreateModifierThinker(
self:GetCaster(),
self,
"modifier_kill",
{duration = 1},
treeLoc,
self:GetCaster():GetTeamNumber(),
false
)
local treeInfo = {
Ability = self,
Target = treeTarget,
EffectName = "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_tracking.vpcf",
iMoveSpeed = self:GetSpecialValueFor("projectile_speed") / 2,
bDodgeable = true,
iSourceAttachment = DOTA_PROJECTILE_ATTACHMENT_HITLOCATION,
bVisibleToEnemies = true,
bProvidesVision = true,
iVisionRadius = 200,
iVisionTeamNumber = caster:GetTeamNumber(),
ExtraData = __TS__ObjectAssign({}, data, {targetTree = 1, nextTree = 0})
}
if target then
treeInfo.Source = target
target:EmitSound("Hero_Hoodwink.AcornShot.Bounce")
else
treeInfo.vSourceLoc = location
end
ProjectileManager:CreateTrackingProjectile(treeInfo)
end
)
end
function hoodwink_acorn_shot_custom.prototype.OnProjectileHit_ExtraData(self, target, location, data)
local caster = self:GetCaster()
local hitLoc = target and target:GetAbsOrigin() or location
if data.targetTree ~= 1 then
if not target then
CreateModifierThinker(
caster,
self,
____exports.modifier_hoodwink_acorn_shot_custom_thinker_tree.name,
{duration = self:GetSpecialValueFor("tree_duration")},
hitLoc,
caster:GetTeamNumber(),
false
)
else
if not target:TriggerSpellAbsorb(self) then
local modifier = ____exports.modifier_hoodwink_acorn_shot_custom_bonus_damage:apply(caster, caster, self, {})
caster:PerformAttack(
target,
false,
true,
true,
false,
false,
false,
true
)
modifier:Destroy()
local reduceCooldownUltimate = self:GetSpecialValueFor("reduce_cooldown_ultimate")
if reduceCooldownUltimate > 0 then
local ultimate = caster:FindAbilityByName(hoodwink_sharpshooter_custom.name)
if ultimate and not ultimate:IsCooldownReady() then
local time = ultimate:GetCooldownTimeRemaining()
ultimate:EndCooldown()
ultimate:StartCooldown(math.max(0, time - reduceCooldownUltimate))
end
end
end
target:EmitSound("Hero_Hoodwink.AcornShot.Target")
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_impact.vpcf", PATTACH_CUSTOMORIGIN, target)
ParticleManager:SetParticleControlEnt(
particle,
0,
target,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
target:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(particle)
____exports.modifier_hoodwink_acorn_shot_custom_debuff:apply(
target,
caster,
self,
{duration = self:GetSpecialValueFor("debuff_duration")}
)
data.lastEnemy = target:GetEntityIndex()
data.nextTree = self:GetSpecialValueFor("can_bounce_off_of_trees") > 0 and 1 or 0
end
else
EmitSoundOnLocationWithCaster(hitLoc, "Hero_Hoodwink.AcornShot.Target", caster)
data.nextTree = 0
end
data.count = data.count - 1
if data.count <= 0 then
return
end
self:ProjectileFindAndHitEnemy(target, hitLoc, data)
end
hoodwink_acorn_shot_custom = __TS__Decorate(
hoodwink_acorn_shot_custom,
hoodwink_acorn_shot_custom,
{registerAbility(nil)},
{kind = "class", name = "hoodwink_acorn_shot_custom"}
)
____exports.hoodwink_acorn_shot_custom = hoodwink_acorn_shot_custom
____exports.modifier_hoodwink_acorn_shot_custom_debuff = __TS__Class()
local modifier_hoodwink_acorn_shot_custom_debuff = ____exports.modifier_hoodwink_acorn_shot_custom_debuff
modifier_hoodwink_acorn_shot_custom_debuff.name = "modifier_hoodwink_acorn_shot_custom_debuff"
modifier_hoodwink_acorn_shot_custom_debuff.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_acorn_shot_custom.lua"
__TS__ClassExtends(modifier_hoodwink_acorn_shot_custom_debuff, BaseModifier)
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.slow = 0
end
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.IsHidden(self)
return false
end
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.IsPurgable(self)
return true
end
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.RemoveOnDeath(self)
return true
end
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.slow = ability:GetSpecialValueFor("slow")
end
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_slow.vpcf"
end
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_hoodwink_acorn_shot_custom_debuff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return -self.slow
end
modifier_hoodwink_acorn_shot_custom_debuff = __TS__Decorate(
modifier_hoodwink_acorn_shot_custom_debuff,
modifier_hoodwink_acorn_shot_custom_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_acorn_shot_custom_debuff"}
)
____exports.modifier_hoodwink_acorn_shot_custom_debuff = modifier_hoodwink_acorn_shot_custom_debuff
____exports.modifier_hoodwink_acorn_shot_custom_bonus_damage = __TS__Class()
local modifier_hoodwink_acorn_shot_custom_bonus_damage = ____exports.modifier_hoodwink_acorn_shot_custom_bonus_damage
modifier_hoodwink_acorn_shot_custom_bonus_damage.name = "modifier_hoodwink_acorn_shot_custom_bonus_damage"
modifier_hoodwink_acorn_shot_custom_bonus_damage.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_acorn_shot_custom.lua"
__TS__ClassExtends(modifier_hoodwink_acorn_shot_custom_bonus_damage, BaseModifier)
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.bonusDamage = 0
self.damagePercentage = 0
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.IsHidden(self)
return true
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.IsPurgable(self)
return false
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.IsPurgeException(self)
return false
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.RemoveOnDeath(self)
return false
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.bonusDamage = ability:GetSpecialValueFor("acorn_shot_damage")
self.damagePercentage = ability:GetSpecialValueFor("base_damage_pct") - 100
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE, MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE}
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.GetModifierPreAttack_BonusDamage(self)
return self.bonusDamage
end
function modifier_hoodwink_acorn_shot_custom_bonus_damage.prototype.GetModifierDamageOutgoing_Percentage(self)
return self.damagePercentage
end
modifier_hoodwink_acorn_shot_custom_bonus_damage = __TS__Decorate(
modifier_hoodwink_acorn_shot_custom_bonus_damage,
modifier_hoodwink_acorn_shot_custom_bonus_damage,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_acorn_shot_custom_bonus_damage"}
)
____exports.modifier_hoodwink_acorn_shot_custom_bonus_damage = modifier_hoodwink_acorn_shot_custom_bonus_damage
____exports.modifier_hoodwink_acorn_shot_custom_thinker_tree = __TS__Class()
local modifier_hoodwink_acorn_shot_custom_thinker_tree = ____exports.modifier_hoodwink_acorn_shot_custom_thinker_tree
modifier_hoodwink_acorn_shot_custom_thinker_tree.name = "modifier_hoodwink_acorn_shot_custom_thinker_tree"
modifier_hoodwink_acorn_shot_custom_thinker_tree.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_acorn_shot_custom.lua"
__TS__ClassExtends(modifier_hoodwink_acorn_shot_custom_thinker_tree, BaseModifier)
function modifier_hoodwink_acorn_shot_custom_thinker_tree.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.treeOrigin = Vector(0, 0, 0)
end
function modifier_hoodwink_acorn_shot_custom_thinker_tree.prototype.IsHidden(self)
return true
end
function modifier_hoodwink_acorn_shot_custom_thinker_tree.prototype.OnCreated(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
local caster = self:GetCaster()
if not ability or not caster then
return
end
self.treeOrigin = parent:GetAbsOrigin()
CreateTempTree(
self.treeOrigin,
ability:GetSpecialValueFor("tree_duration")
)
self.viewer = AddFOWViewer(
caster:GetTeamNumber(),
self.treeOrigin,
ability:GetSpecialValueFor("tree_radius"),
ability:GetSpecialValueFor("tree_duration"),
false
)
local units = FindUnitsInRadius(
parent:GetTeamNumber(),
self.treeOrigin,
nil,
100,
DOTA_UNIT_TARGET_TEAM_BOTH,
DOTA_UNIT_TARGET_ALL,
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES,
FIND_CLOSEST,
false
)
for ____, unit in ipairs(units) do
FindClearSpaceForUnit(
unit,
unit:GetAbsOrigin(),
true
)
end
local particle2 = ParticleManager:CreateParticle("particles/tree_fx/tree_simple_explosion.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(
particle2,
0,
self.treeOrigin:__add(Vector(1, 0, 0))
)
ParticleManager:ReleaseParticleIndex(particle2)
end
function modifier_hoodwink_acorn_shot_custom_thinker_tree.prototype.OnDestroy(self)
if not IsServer() then
return
end
GridNav:DestroyTreesAroundPoint(
self:GetParent():GetAbsOrigin(),
10,
true
)
local caster = self:GetCaster()
if self.viewer and caster then
RemoveFOWViewer(
caster:GetTeamNumber(),
self.viewer
)
self.viewer = nil
end
end
modifier_hoodwink_acorn_shot_custom_thinker_tree = __TS__Decorate(
modifier_hoodwink_acorn_shot_custom_thinker_tree,
modifier_hoodwink_acorn_shot_custom_thinker_tree,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_acorn_shot_custom_thinker_tree"}
)
____exports.modifier_hoodwink_acorn_shot_custom_thinker_tree = modifier_hoodwink_acorn_shot_custom_thinker_tree
____exports.modifier_hoodwink_acorn_shot_custom_scepter = __TS__Class()
local modifier_hoodwink_acorn_shot_custom_scepter = ____exports.modifier_hoodwink_acorn_shot_custom_scepter
modifier_hoodwink_acorn_shot_custom_scepter.name = "modifier_hoodwink_acorn_shot_custom_scepter"
modifier_hoodwink_acorn_shot_custom_scepter.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_acorn_shot_custom.lua"
__TS__ClassExtends(modifier_hoodwink_acorn_shot_custom_scepter, BaseModifier)
function modifier_hoodwink_acorn_shot_custom_scepter.prototype.IsHidden(self)
return true
end
function modifier_hoodwink_acorn_shot_custom_scepter.prototype.IsPurgable(self)
return false
end
function modifier_hoodwink_acorn_shot_custom_scepter.prototype.IsPurgeException(self)
return false
end
function modifier_hoodwink_acorn_shot_custom_scepter.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_hoodwink_acorn_shot_custom_scepter.prototype.OnAttackLanded(self, event)
local parent = self:GetParent()
if parent:PassivesDisabled() then
return
end
if event.attacker ~= parent or not parent:HasScepter() or event.no_attack_cooldown then
return
end
local ability = self:GetAbility()
if not ability then
return
end
if not parent:IsHero() then
return
end
local scepterChancePct = ability:GetSpecialValueFor("scepter_chance")
if rollLuckChance(nil, parent, scepterChancePct / 100) then
local target = event.target
if not target then
return
end
local info = {
Ability = ability,
Source = parent,
Target = target,
EffectName = "particles/units/heroes/hero_hoodwink/hoodwink_acorn_shot_tracking.vpcf",
iMoveSpeed = ability:GetSpecialValueFor("projectile_speed"),
bDodgeable = true,
iSourceAttachment = DOTA_PROJECTILE_ATTACHMENT_HITLOCATION,
bVisibleToEnemies = true,
bProvidesVision = true,
iVisionRadius = 200,
iVisionTeamNumber = parent:GetTeamNumber(),
ExtraData = {
count = ability:GetSpecialValueFor("bounce_count_scepter"),
nextTree = 0
}
}
ProjectileManager:CreateTrackingProjectile(info)
end
end
modifier_hoodwink_acorn_shot_custom_scepter = __TS__Decorate(
modifier_hoodwink_acorn_shot_custom_scepter,
modifier_hoodwink_acorn_shot_custom_scepter,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_acorn_shot_custom_scepter"}
)
____exports.modifier_hoodwink_acorn_shot_custom_scepter = modifier_hoodwink_acorn_shot_custom_scepter
return ____exports
@@ -0,0 +1,378 @@
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 BaseModifierMotionBoth = ____dota_ts_adapter.BaseModifierMotionBoth
local registerAbility = ____dota_ts_adapter.registerAbility
local registerModifier = ____dota_ts_adapter.registerModifier
____exports.hoodwink_bushwhack_custom = __TS__Class()
local hoodwink_bushwhack_custom = ____exports.hoodwink_bushwhack_custom
hoodwink_bushwhack_custom.name = "hoodwink_bushwhack_custom"
hoodwink_bushwhack_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_bushwhack_custom.lua"
__TS__ClassExtends(hoodwink_bushwhack_custom, BaseAbility)
function hoodwink_bushwhack_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function hoodwink_bushwhack_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local thinker = CreateModifierThinker(
caster,
self,
"modifier_kill",
{duration = 2},
point,
caster:GetTeamNumber(),
false
)
local projectile = {
Target = thinker,
iMoveSpeed = self:GetSpecialValueFor("projectile_speed"),
bDodgeable = true,
iSourceAttachment = DOTA_PROJECTILE_ATTACHMENT_ATTACK_1,
EffectName = "particles/units/heroes/hero_hoodwink/hoodwink_bushwhack_projectile.vpcf",
Ability = self,
Source = caster
}
ProjectileManager:CreateTrackingProjectile(projectile)
caster:EmitSound("Hero_Hoodwink.Bushwhack.Cast")
end
function hoodwink_bushwhack_custom.prototype.OnProjectileHit(self, target, location)
local impactLocation = target and target:GetAbsOrigin() or location
local caster = self:GetCaster()
local radius = self:GetSpecialValueFor("radius")
local duration = self:GetSpecialValueFor("duration")
AddFOWViewer(
caster:GetTeamNumber(),
impactLocation,
radius,
duration,
true
)
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
impactLocation,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NO_INVIS,
FIND_CLOSEST,
false
)
local trees = GridNav:GetAllTreesAroundPoint(impactLocation, radius, false)
local isSuccess = #trees > 0 and #enemies > 0
if isSuccess then
local tree = trees[1]
for ____, enemy in ipairs(enemies) do
if enemy:IsBoss() then
enemy:AddNewModifier(
caster,
self,
____exports.modifier_hoodwink_bushwhack_custom_boss.name,
{
duration = duration,
tree = tree:entindex()
}
)
else
enemy:AddNewModifier(
caster,
self,
____exports.modifier_hoodwink_bushwhack_custom.name,
{
duration = duration,
tree = tree:entindex()
}
)
end
end
end
local effectName = isSuccess and "particles/units/heroes/hero_hoodwink/hoodwink_bushwhack.vpcf" or "particles/units/heroes/hero_hoodwink/hoodwink_bushwhack_fail.vpcf"
local particle = ParticleManager:CreateParticle(effectName, PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particle, 0, impactLocation)
ParticleManager:SetParticleControl(
particle,
1,
Vector(radius, 0, 0)
)
ParticleManager:ReleaseParticleIndex(particle)
caster:StopSound("Hero_Hoodwink.Bushwhack.Cast")
EmitSoundOnLocationWithCaster(impactLocation, "Hero_Hoodwink.Bushwhack.Impact", caster)
end
hoodwink_bushwhack_custom = __TS__Decorate(
hoodwink_bushwhack_custom,
hoodwink_bushwhack_custom,
{registerAbility(nil)},
{kind = "class", name = "hoodwink_bushwhack_custom"}
)
____exports.hoodwink_bushwhack_custom = hoodwink_bushwhack_custom
____exports.modifier_hoodwink_bushwhack_custom = __TS__Class()
local modifier_hoodwink_bushwhack_custom = ____exports.modifier_hoodwink_bushwhack_custom
modifier_hoodwink_bushwhack_custom.name = "modifier_hoodwink_bushwhack_custom"
modifier_hoodwink_bushwhack_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_bushwhack_custom.lua"
__TS__ClassExtends(modifier_hoodwink_bushwhack_custom, BaseModifierMotionBoth)
function modifier_hoodwink_bushwhack_custom.prototype.____constructor(self, ...)
BaseModifierMotionBoth.prototype.____constructor(self, ...)
self.treeOrigin = Vector(0, 0, 0)
self.speed = 900
self.distance = 150
self.damage = 0
self.interval = 0
self.tickCount = 0
self.rate = 0.3
self.height = 50
self.damageMultiplier = 0
end
function modifier_hoodwink_bushwhack_custom.prototype.IsHidden(self)
return false
end
function modifier_hoodwink_bushwhack_custom.prototype.IsStunDebuff(self)
return true
end
function modifier_hoodwink_bushwhack_custom.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local tree = EntIndexToHScript(params.tree)
local ability = self:GetAbility()
if not tree or tree:IsNull() or not ability then
self:Destroy()
return
end
self.treeOrigin = tree:GetAbsOrigin()
self.damage = ability:GetSpecialValueFor("total_damage")
self.interval = ability:GetSpecialValueFor("interval")
self.tickCount = ability:GetSpecialValueFor("duration") / self.interval
self.damage = self.damage / self.tickCount
self.damageMultiplier = ability:GetSpecialValueFor("damage_multiplier")
if not self:ApplyHorizontalMotionController() then
self:Destroy()
return
end
self:StartIntervalThink(self.interval)
self:PlayEffects()
end
function modifier_hoodwink_bushwhack_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
self:GetParent():RemoveHorizontalMotionController(self)
end
function modifier_hoodwink_bushwhack_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
local caster = self:GetCaster()
if not ability or not caster then
return
end
local damage = self.damage
local hasShard = HasShard(nil, caster)
if hasShard then
damage = damage + caster:GetAverageTrueAttackDamage(self:GetParent()) * self.damageMultiplier / 100
end
ApplyDamage({
victim = self:GetParent(),
attacker = caster,
damage = damage,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
end
function modifier_hoodwink_bushwhack_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_OVERRIDE_ANIMATION, MODIFIER_PROPERTY_OVERRIDE_ANIMATION_RATE, MODIFIER_PROPERTY_VISUAL_Z_DELTA}
end
function modifier_hoodwink_bushwhack_custom.prototype.GetOverrideAnimation(self)
return ACT_DOTA_FLAIL
end
function modifier_hoodwink_bushwhack_custom.prototype.GetOverrideAnimationRate(self)
return self.rate
end
function modifier_hoodwink_bushwhack_custom.prototype.GetVisualZDelta(self)
return self.height
end
function modifier_hoodwink_bushwhack_custom.prototype.CheckState(self)
return {[MODIFIER_STATE_STUNNED] = true}
end
function modifier_hoodwink_bushwhack_custom.prototype.UpdateHorizontalMotion(self, me, dt)
local origin = me:GetAbsOrigin()
local dir = self.treeOrigin:__sub(origin)
local dist = dir:Length2D()
dir.z = 0
dir = dir:Normalized()
if dist < self.distance then
self:GetParent():RemoveHorizontalMotionController(self)
return
end
local target = dir:__mul(self.speed * dt)
local newPos = origin:__add(target)
local newDist = self.treeOrigin:__sub(newPos):Length2D()
if newDist < self.distance then
local finalPos = self.treeOrigin:__sub(dir:__mul(self.distance))
me:SetAbsOrigin(finalPos)
else
me:SetAbsOrigin(newPos)
end
end
function modifier_hoodwink_bushwhack_custom.prototype.OnHorizontalMotionInterrupted(self)
self:GetParent():RemoveHorizontalMotionController(self)
end
function modifier_hoodwink_bushwhack_custom.prototype.PlayEffects(self)
local effect = ParticleManager:CreateParticle(
"particles/units/heroes/hero_hoodwink/hoodwink_bushwhack_target.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(effect, 15, self.treeOrigin)
ParticleManager:SetParticleControlEnt(
effect,
1,
self:GetParent(),
PATTACH_POINT_FOLLOW,
"attach_hitloc",
self:GetParent():GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
effect,
4,
self:GetParent(),
PATTACH_POINT_FOLLOW,
"attach_hitloc",
self:GetParent():GetAbsOrigin(),
true
)
self:AddParticle(
effect,
false,
false,
-1,
false,
false
)
EmitSoundOn(
"Hero_Hoodwink.Bushwhack.Target",
self:GetParent()
)
end
modifier_hoodwink_bushwhack_custom = __TS__Decorate(
modifier_hoodwink_bushwhack_custom,
modifier_hoodwink_bushwhack_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_bushwhack_custom"}
)
____exports.modifier_hoodwink_bushwhack_custom = modifier_hoodwink_bushwhack_custom
____exports.modifier_hoodwink_bushwhack_custom_boss = __TS__Class()
local modifier_hoodwink_bushwhack_custom_boss = ____exports.modifier_hoodwink_bushwhack_custom_boss
modifier_hoodwink_bushwhack_custom_boss.name = "modifier_hoodwink_bushwhack_custom_boss"
modifier_hoodwink_bushwhack_custom_boss.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_bushwhack_custom.lua"
__TS__ClassExtends(modifier_hoodwink_bushwhack_custom_boss, BaseModifier)
function modifier_hoodwink_bushwhack_custom_boss.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.damage = 0
self.interval = 0
self.tickCount = 0
self.damageMultiplier = 0
end
function modifier_hoodwink_bushwhack_custom_boss.prototype.IsHidden(self)
return false
end
function modifier_hoodwink_bushwhack_custom_boss.prototype.IsStunDebuff(self)
return true
end
function modifier_hoodwink_bushwhack_custom_boss.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local tree = EntIndexToHScript(params.tree)
local ability = self:GetAbility()
if not tree or tree:IsNull() or not ability then
self:Destroy()
return
end
self.interval = ability:GetSpecialValueFor("interval")
self.damage = ability:GetSpecialValueFor("total_damage")
self.tickCount = ability:GetSpecialValueFor("duration") / self.interval
self.damage = self.damage / self.tickCount
self.damageMultiplier = ability:GetSpecialValueFor("damage_multiplier")
local effect = ParticleManager:CreateParticle(
"particles/units/heroes/hero_hoodwink/hoodwink_bushwhack_target.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
effect,
15,
tree:GetAbsOrigin()
)
ParticleManager:SetParticleControlEnt(
effect,
1,
self:GetParent(),
PATTACH_POINT_FOLLOW,
"attach_hitloc",
self:GetParent():GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
effect,
4,
self:GetParent(),
PATTACH_POINT_FOLLOW,
"attach_hitloc",
self:GetParent():GetAbsOrigin(),
true
)
self:AddParticle(
effect,
false,
false,
-1,
false,
false
)
EmitSoundOn(
"Hero_Hoodwink.Bushwhack.Target",
self:GetParent()
)
self:StartIntervalThink(self.interval)
end
function modifier_hoodwink_bushwhack_custom_boss.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
local caster = self:GetCaster()
local hasShard = HasShard(nil, caster)
if not ability or not caster then
return
end
local damage = self.damage
if hasShard then
damage = damage + caster:GetAverageTrueAttackDamage(self:GetParent()) * self.damageMultiplier / 100
end
ApplyDamage({
victim = self:GetParent(),
attacker = caster,
damage = damage,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
end
function modifier_hoodwink_bushwhack_custom_boss.prototype.CheckState(self)
return {[MODIFIER_STATE_STUNNED] = true}
end
modifier_hoodwink_bushwhack_custom_boss = __TS__Decorate(
modifier_hoodwink_bushwhack_custom_boss,
modifier_hoodwink_bushwhack_custom_boss,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_bushwhack_custom_boss"}
)
____exports.modifier_hoodwink_bushwhack_custom_boss = modifier_hoodwink_bushwhack_custom_boss
return ____exports
@@ -0,0 +1,108 @@
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 ____luck = require("utils.luck")
local addLuck = ____luck.addLuck
local reduceLuck = ____luck.reduceLuck
____exports.hoodwink_lucky_innate_custom = __TS__Class()
local hoodwink_lucky_innate_custom = ____exports.hoodwink_lucky_innate_custom
hoodwink_lucky_innate_custom.name = "hoodwink_lucky_innate_custom"
hoodwink_lucky_innate_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_lucky_innate_custom.lua"
__TS__ClassExtends(hoodwink_lucky_innate_custom, BaseAbility)
function hoodwink_lucky_innate_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_hoodwink_lucky_innate_custom.name
end
hoodwink_lucky_innate_custom = __TS__Decorate(
hoodwink_lucky_innate_custom,
hoodwink_lucky_innate_custom,
{registerAbility(nil)},
{kind = "class", name = "hoodwink_lucky_innate_custom"}
)
____exports.hoodwink_lucky_innate_custom = hoodwink_lucky_innate_custom
____exports.modifier_hoodwink_lucky_innate_custom = __TS__Class()
local modifier_hoodwink_lucky_innate_custom = ____exports.modifier_hoodwink_lucky_innate_custom
modifier_hoodwink_lucky_innate_custom.name = "modifier_hoodwink_lucky_innate_custom"
modifier_hoodwink_lucky_innate_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_lucky_innate_custom.lua"
__TS__ClassExtends(modifier_hoodwink_lucky_innate_custom, BaseModifier)
function modifier_hoodwink_lucky_innate_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.appliedLuckBonus = 0
end
function modifier_hoodwink_lucky_innate_custom.prototype.IsHidden(self)
return true
end
function modifier_hoodwink_lucky_innate_custom.prototype.IsPurgable(self)
return false
end
function modifier_hoodwink_lucky_innate_custom.prototype.OnGameEvent(self)
ListenToGameEvent(
"dota_player_gained_level",
function(event)
local parent = self:GetParent()
if not parent or not parent:IsHero() or parent:IsIllusion() then
return
end
local playerId = parent:GetPlayerOwnerID()
if playerId == nil or playerId == nil or playerId < 0 then
return
end
if event.player ~= playerId then
return
end
self:UpdateLuckFromHeroLevel()
end,
nil
)
end
function modifier_hoodwink_lucky_innate_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
self:UpdateLuckFromHeroLevel()
self.levelUpListener = ListenToGameEvent(
"dota_player_gained_level",
function()
local parent = self:GetParent()
if not parent or not parent:IsHero() or parent:IsIllusion() then
return
end
self:UpdateLuckFromHeroLevel()
end,
nil
)
end
function modifier_hoodwink_lucky_innate_custom.prototype.UpdateLuckFromHeroLevel(self)
local parent = self:GetParent()
local ability = self:GetAbility()
if not parent:IsHero() or parent:IsIllusion() or not ability then
return
end
local hero = parent
local luckPerLevel = math.max(
0,
ability:GetSpecialValueFor("luck_per_level")
)
local desiredLuckBonus = hero:GetLevel() * luckPerLevel
local delta = desiredLuckBonus - self.appliedLuckBonus
if delta > 0 then
addLuck(nil, hero, delta)
elseif delta < 0 then
reduceLuck(nil, hero, -delta)
end
self.appliedLuckBonus = desiredLuckBonus
end
modifier_hoodwink_lucky_innate_custom = __TS__Decorate(
modifier_hoodwink_lucky_innate_custom,
modifier_hoodwink_lucky_innate_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_lucky_innate_custom"}
)
____exports.modifier_hoodwink_lucky_innate_custom = modifier_hoodwink_lucky_innate_custom
return ____exports
@@ -0,0 +1,237 @@
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 ____luck = require("utils.luck")
local getLuck = ____luck.getLuck
local ____incoming_damage_reduction_combine = require("utils.incoming_damage_reduction_combine")
local removeIncomingDamageReductionSource = ____incoming_damage_reduction_combine.removeIncomingDamageReductionSource
local setIncomingDamageReductionSource = ____incoming_damage_reduction_combine.setIncomingDamageReductionSource
local HOODWINK_SCURRY_BUFF_INCOMING_SOURCE = "modifier_hoodwink_scurry_custom_buff"
____exports.hoodwink_scurry_custom = __TS__Class()
local hoodwink_scurry_custom = ____exports.hoodwink_scurry_custom
hoodwink_scurry_custom.name = "hoodwink_scurry_custom"
hoodwink_scurry_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_scurry_custom.lua"
__TS__ClassExtends(hoodwink_scurry_custom, BaseAbility)
function hoodwink_scurry_custom.prototype.GetCastRange(self, _location, _target)
return self:GetSpecialValueFor("radius")
end
function hoodwink_scurry_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_hoodwink_scurry_custom.name
end
function hoodwink_scurry_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
caster:AddNewModifier(
caster,
self,
____exports.modifier_hoodwink_scurry_custom_active.name,
{duration = self:GetSpecialValueFor("duration")}
)
caster:AddNewModifier(caster, self, ____exports.modifier_hoodwink_scurry_custom_buff.name, {})
EmitSoundOn("Hero_Hoodwink.Scurry.Cast", caster)
end
hoodwink_scurry_custom = __TS__Decorate(
hoodwink_scurry_custom,
hoodwink_scurry_custom,
{registerAbility(nil)},
{kind = "class", name = "hoodwink_scurry_custom"}
)
____exports.hoodwink_scurry_custom = hoodwink_scurry_custom
____exports.modifier_hoodwink_scurry_custom = __TS__Class()
local modifier_hoodwink_scurry_custom = ____exports.modifier_hoodwink_scurry_custom
modifier_hoodwink_scurry_custom.name = "modifier_hoodwink_scurry_custom"
modifier_hoodwink_scurry_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_scurry_custom.lua"
__TS__ClassExtends(modifier_hoodwink_scurry_custom, BaseModifier)
function modifier_hoodwink_scurry_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.radius = 0
end
function modifier_hoodwink_scurry_custom.prototype.IsHidden(self)
return true
end
function modifier_hoodwink_scurry_custom.prototype.IsPurgable(self)
return false
end
function modifier_hoodwink_scurry_custom.prototype.IsPurgeException(self)
return false
end
function modifier_hoodwink_scurry_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
self.radius = ability:GetSpecialValueFor("radius")
self:StartIntervalThink(0.2)
end
function modifier_hoodwink_scurry_custom.prototype.OnRefresh(self)
self:OnCreated()
end
function modifier_hoodwink_scurry_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
if GridNav:IsNearbyTree(
parent:GetAbsOrigin(),
self.radius,
true
) or parent:HasModifier(____exports.modifier_hoodwink_scurry_custom_active.name) then
parent:AddNewModifier(
parent,
self:GetAbility(),
____exports.modifier_hoodwink_scurry_custom_buff.name,
{}
)
else
parent:RemoveModifierByName(____exports.modifier_hoodwink_scurry_custom_buff.name)
end
end
modifier_hoodwink_scurry_custom = __TS__Decorate(
modifier_hoodwink_scurry_custom,
modifier_hoodwink_scurry_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_scurry_custom"}
)
____exports.modifier_hoodwink_scurry_custom = modifier_hoodwink_scurry_custom
____exports.modifier_hoodwink_scurry_custom_buff = __TS__Class()
local modifier_hoodwink_scurry_custom_buff = ____exports.modifier_hoodwink_scurry_custom_buff
modifier_hoodwink_scurry_custom_buff.name = "modifier_hoodwink_scurry_custom_buff"
modifier_hoodwink_scurry_custom_buff.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_scurry_custom.lua"
__TS__ClassExtends(modifier_hoodwink_scurry_custom_buff, BaseModifier)
function modifier_hoodwink_scurry_custom_buff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.bonusAttackSpeed = 0
self.bonusDamage = 0
self.luckEvasionMultiplier = 1
self.maxLuckEvasion = 75
end
function modifier_hoodwink_scurry_custom_buff.prototype.IsHidden(self)
return false
end
function modifier_hoodwink_scurry_custom_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT, MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE, MODIFIER_PROPERTY_EVASION_CONSTANT}
end
function modifier_hoodwink_scurry_custom_buff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.bonusAttackSpeed = ability:GetSpecialValueFor("bonus_attack_speed")
self.bonusDamage = ability:GetSpecialValueFor("bonus_damage")
self.luckEvasionMultiplier = ability:GetSpecialValueFor("luck_evasion_multiplier")
self.maxLuckEvasion = ability:GetSpecialValueFor("max_luck_evasion")
if not IsServer() then
return
end
setIncomingDamageReductionSource(
nil,
self:GetParent(),
HOODWINK_SCURRY_BUFF_INCOMING_SOURCE,
function()
if self:GetParent():PassivesDisabled() then
return 0
end
local buffAbility = self:GetAbility()
if not buffAbility then
return 0
end
local reductionPct = buffAbility:GetSpecialValueFor("incoming_damage_reduction_pct")
return reductionPct > 0 and reductionPct or 0
end
)
end
function modifier_hoodwink_scurry_custom_buff.prototype.OnRefresh(self)
self:OnCreated()
end
function modifier_hoodwink_scurry_custom_buff.prototype.OnDestroy(self)
if not IsServer() then
return
end
removeIncomingDamageReductionSource(
nil,
self:GetParent(),
HOODWINK_SCURRY_BUFF_INCOMING_SOURCE
)
end
function modifier_hoodwink_scurry_custom_buff.prototype.GetModifierPreAttack_BonusDamage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
return self.bonusDamage
end
function modifier_hoodwink_scurry_custom_buff.prototype.GetModifierAttackSpeedBonus_Constant(self)
if self:GetParent():PassivesDisabled() then
return 0
end
return self.bonusAttackSpeed
end
function modifier_hoodwink_scurry_custom_buff.prototype.GetModifierEvasion_Constant(self)
if self:GetParent():PassivesDisabled() then
return 0
end
local parent = self:GetParent()
if not parent:IsHero() then
return 0
end
local luck = getLuck(nil, parent)
self:SetStackCount(math.floor(math.max(0, luck)))
return math.min(self.maxLuckEvasion, luck * self.luckEvasionMultiplier)
end
function modifier_hoodwink_scurry_custom_buff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_hoodwink/hoodwink_scurry_passive.vpcf"
end
function modifier_hoodwink_scurry_custom_buff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_hoodwink_scurry_custom_buff = __TS__Decorate(
modifier_hoodwink_scurry_custom_buff,
modifier_hoodwink_scurry_custom_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_scurry_custom_buff"}
)
____exports.modifier_hoodwink_scurry_custom_buff = modifier_hoodwink_scurry_custom_buff
____exports.modifier_hoodwink_scurry_custom_active = __TS__Class()
local modifier_hoodwink_scurry_custom_active = ____exports.modifier_hoodwink_scurry_custom_active
modifier_hoodwink_scurry_custom_active.name = "modifier_hoodwink_scurry_custom_active"
modifier_hoodwink_scurry_custom_active.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_scurry_custom.lua"
__TS__ClassExtends(modifier_hoodwink_scurry_custom_active, BaseModifier)
function modifier_hoodwink_scurry_custom_active.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.bonusMovementSpeed = 0
end
function modifier_hoodwink_scurry_custom_active.prototype.IsHidden(self)
return false
end
function modifier_hoodwink_scurry_custom_active.prototype.CheckState(self)
return {[MODIFIER_STATE_NO_UNIT_COLLISION] = true}
end
function modifier_hoodwink_scurry_custom_active.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_hoodwink_scurry_custom_active.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.bonusMovementSpeed = ability:GetSpecialValueFor("movement_speed_pct")
end
function modifier_hoodwink_scurry_custom_active.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self.bonusMovementSpeed
end
modifier_hoodwink_scurry_custom_active = __TS__Decorate(
modifier_hoodwink_scurry_custom_active,
modifier_hoodwink_scurry_custom_active,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_scurry_custom_active"}
)
____exports.modifier_hoodwink_scurry_custom_active = modifier_hoodwink_scurry_custom_active
return ____exports
@@ -0,0 +1,527 @@
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 modifier_hoodwink_sharpshooter_custom_debuff, modifier_hoodwink_sharpshooter_custom_sound
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
____exports.hoodwink_sharpshooter_custom = __TS__Class()
local hoodwink_sharpshooter_custom = ____exports.hoodwink_sharpshooter_custom
hoodwink_sharpshooter_custom.name = "hoodwink_sharpshooter_custom"
hoodwink_sharpshooter_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_sharpshooter_custom.lua"
__TS__ClassExtends(hoodwink_sharpshooter_custom, BaseAbility)
function hoodwink_sharpshooter_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_projectile.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_impact.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_debuff.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_timer.vpcf", context)
end
function hoodwink_sharpshooter_custom.prototype.OnSpellStart(self)
local point = self:GetCursorPosition()
local duration = self:GetSpecialValueFor("misfire_time")
local caster = self:GetCaster()
caster:StartGesture(ACT_DOTA_CHANNEL_ABILITY_6)
caster:AddNewModifier(caster, self, ____exports.modifier_hoodwink_sharpshooter_custom.name, {duration = duration, x = point.x, y = point.y})
end
function hoodwink_sharpshooter_custom.prototype.OnProjectileThink_ExtraData(self, location, extraData)
local sound = EntIndexToHScript(extraData.sound)
if not sound or sound:IsNull() then
return
end
sound:SetOrigin(location)
end
function hoodwink_sharpshooter_custom.prototype.OnProjectileHit_ExtraData(self, target, _location, extraData)
local sound = EntIndexToHScript(extraData.sound)
if sound and not sound:IsNull() then
sound:StopSound("Hero_Hoodwink.Sharpshooter.Projectile")
UTIL_Remove(sound)
end
if not target then
return false
end
modifier_hoodwink_sharpshooter_custom_debuff:apply(
target,
self:GetCaster(),
self,
{duration = extraData.duration, x = extraData.x, y = extraData.y}
)
local real = ApplyDamage({
victim = target,
attacker = self:GetCaster(),
damage = extraData.damage + self:GetCaster():GetAverageTrueAttackDamage(target) * self:GetSpecialValueFor("damage_multiplier") * 0.01,
damage_type = self:GetAbilityDamageType(),
ability = self
})
SendOverheadEventMessage(
nil,
OVERHEAD_ALERT_BONUS_SPELL_DAMAGE,
target,
real,
self:GetCaster():GetPlayerOwner()
)
AddFOWViewer(
self:GetCaster():GetTeamNumber(),
target:GetOrigin(),
300,
4,
false
)
local direction = Vector(extraData.x, extraData.y, 0):Normalized()
local effect = ParticleManager:CreateParticle("particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_impact.vpcf", PATTACH_ABSORIGIN_FOLLOW, target)
ParticleManager:SetParticleControl(
effect,
0,
target:GetOrigin()
)
ParticleManager:SetParticleControl(
effect,
1,
target:GetOrigin()
)
ParticleManager:SetParticleControlForward(effect, 1, direction)
ParticleManager:ReleaseParticleIndex(effect)
target:EmitSound("Hero_Hoodwink.Sharpshooter.Target")
end
hoodwink_sharpshooter_custom = __TS__Decorate(
hoodwink_sharpshooter_custom,
hoodwink_sharpshooter_custom,
{registerAbility(nil)},
{kind = "class", name = "hoodwink_sharpshooter_custom"}
)
____exports.hoodwink_sharpshooter_custom = hoodwink_sharpshooter_custom
____exports.hoodwink_sharpshooter_release_custom = __TS__Class()
local hoodwink_sharpshooter_release_custom = ____exports.hoodwink_sharpshooter_release_custom
hoodwink_sharpshooter_release_custom.name = "hoodwink_sharpshooter_release_custom"
hoodwink_sharpshooter_release_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_sharpshooter_custom.lua"
__TS__ClassExtends(hoodwink_sharpshooter_release_custom, BaseAbility)
function hoodwink_sharpshooter_release_custom.prototype.OnSpellStart(self)
local mod = self:GetCaster():FindModifierByName(____exports.modifier_hoodwink_sharpshooter_custom.name)
if not mod then
return
end
mod:Destroy()
end
hoodwink_sharpshooter_release_custom = __TS__Decorate(
hoodwink_sharpshooter_release_custom,
hoodwink_sharpshooter_release_custom,
{registerAbility(nil)},
{kind = "class", name = "hoodwink_sharpshooter_release_custom"}
)
____exports.hoodwink_sharpshooter_release_custom = hoodwink_sharpshooter_release_custom
____exports.modifier_hoodwink_sharpshooter_custom = __TS__Class()
local modifier_hoodwink_sharpshooter_custom = ____exports.modifier_hoodwink_sharpshooter_custom
modifier_hoodwink_sharpshooter_custom.name = "modifier_hoodwink_sharpshooter_custom"
modifier_hoodwink_sharpshooter_custom.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_sharpshooter_custom.lua"
__TS__ClassExtends(modifier_hoodwink_sharpshooter_custom, BaseModifier)
function modifier_hoodwink_sharpshooter_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.charge = 0
self.base = 0
self.damage = 0
self.duration = 0
self.turnRate = 0
self.recoilDistance = 0
self.recoilDuration = 0
self.recoilHeight = 0
self.interval = 0.03
self.projectileSpeed = 0
self.projectileRange = 0
self.projectileWidth = 0
self.targetDir = Vector(0, 0, 0)
self.currentDir = Vector(0, 0, 0)
self.faceTarget = false
self.charged = false
self.half = false
self.turnSpeed = 0
self.info = {}
self.previewEffect = -1
end
function modifier_hoodwink_sharpshooter_custom.prototype.IsHidden(self)
return false
end
function modifier_hoodwink_sharpshooter_custom.prototype.IsPurgable(self)
return false
end
function modifier_hoodwink_sharpshooter_custom.prototype.OnCreated(self, kv)
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
self.charge = ability:GetSpecialValueFor("max_charge_time")
self.base = ability:GetSpecialValueFor("base_power")
self.damage = ability:GetSpecialValueFor("max_damage")
self.duration = ability:GetSpecialValueFor("max_slow_debuff_duration")
self.turnRate = ability:GetSpecialValueFor("turn_rate")
self.recoilDistance = ability:GetSpecialValueFor("recoil_distance")
self.recoilDuration = ability:GetSpecialValueFor("recoil_duration")
self.recoilHeight = ability:GetSpecialValueFor("recoil_height")
self.projectileSpeed = ability:GetSpecialValueFor("arrow_speed")
self.projectileRange = ability:GetSpecialValueFor("arrow_range")
self.projectileWidth = ability:GetSpecialValueFor("arrow_width")
self:StartIntervalThink(self.interval)
if not IsServer() then
return
end
local projectileVision = ability:GetSpecialValueFor("arrow_vision")
self:SetDirection(Vector(kv.x, kv.y, 0))
self.currentDir = self.targetDir
self.faceTarget = true
parent:SetForwardVector(self.currentDir)
self.turnSpeed = self.interval * self.turnRate
self.info = {
Source = parent,
Ability = ability,
bDeleteOnHit = false,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
EffectName = "particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_projectile.vpcf",
fDistance = self.projectileRange,
fStartRadius = self.projectileWidth,
fEndRadius = self.projectileWidth,
bHasFrontalCone = false,
bReplaceExisting = false,
bProvidesVision = true,
bVisibleToEnemies = true,
iVisionRadius = projectileVision,
iVisionTeamNumber = parent:GetTeamNumber()
}
parent:SwapAbilities(____exports.hoodwink_sharpshooter_custom.name, ____exports.hoodwink_sharpshooter_release_custom.name, false, true)
local effect = ParticleManager:CreateParticle("particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:SetParticleControlEnt(
effect,
1,
parent,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
parent:GetOrigin(),
true
)
self:AddParticle(
effect,
false,
false,
-1,
false,
false
)
self.previewEffect = effect
EmitSoundOn("Hero_Hoodwink.Sharpshooter.Channel", parent)
end
function modifier_hoodwink_sharpshooter_custom.prototype.Shoot(self, newPct)
if not IsServer() then
return
end
local parent = self:GetParent()
local pct = newPct or math.min(
1,
math.min(
self:GetElapsedTime(),
self.charge
) / self.charge + self.base
)
local realPct = pct == 0 and 1 or pct
local duration = self.duration * realPct
local damage = self.damage * realPct
self.info.vSpawnOrigin = parent:GetOrigin()
self.info.vVelocity = self.currentDir:__mul(self.projectileSpeed)
local sound = CreateModifierThinker(
parent,
self:GetAbility(),
modifier_hoodwink_sharpshooter_custom_sound.name,
{},
parent:GetOrigin(),
parent:GetTeamNumber(),
false
)
sound:EmitSound("Hero_Hoodwink.Sharpshooter.Projectile")
self.info.ExtraData = {
damage = damage,
pct = realPct,
duration = duration,
x = self.currentDir.x,
y = self.currentDir.y,
sound = sound:entindex()
}
ProjectileManager:CreateLinearProjectile(self.info)
end
function modifier_hoodwink_sharpshooter_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
StopSoundOn("Hero_Hoodwink.Sharpshooter.Channel", parent)
if parent:IsIllusion() and not parent:IsAlive() then
return
end
self:Shoot()
parent:RemoveGesture(ACT_DOTA_CHANNEL_ABILITY_6)
local bumpPoint = parent:GetAbsOrigin() + self.currentDir * self.recoilDistance
local mod = parent:AddNewModifier(
parent,
self:GetAbility(),
"modifier_knockback",
{
duration = self.recoilDuration,
knockback_height = self.recoilHeight,
knockback_distance = self.recoilDistance,
knockback_duration = self.recoilDuration,
center_x = bumpPoint.x,
center_y = bumpPoint.y,
center_z = bumpPoint.z
}
)
parent:SwapAbilities(____exports.hoodwink_sharpshooter_release_custom.name, ____exports.hoodwink_sharpshooter_custom.name, false, true)
if mod ~= nil then
local effect = ParticleManager:CreateParticle("particles/items_fx/force_staff.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
mod:AddParticle(
effect,
false,
false,
-1,
false,
false
)
end
parent:StopSound("Hero_Hoodwink.Sharpshooter.Cast")
parent:EmitSound("Hero_Hoodwink.Sharpshooter.Cast")
end
function modifier_hoodwink_sharpshooter_custom.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ORDER, MODIFIER_PROPERTY_DISABLE_TURNING, MODIFIER_PROPERTY_MOVESPEED_LIMIT, MODIFIER_PROPERTY_OVERRIDE_ANIMATION}
end
function modifier_hoodwink_sharpshooter_custom.prototype.GetOverrideAnimation(self)
return ACT_DOTA_CHANNEL_ABILITY_6
end
function modifier_hoodwink_sharpshooter_custom.prototype.GetPriority(self)
return MODIFIER_PRIORITY_ULTRA
end
function modifier_hoodwink_sharpshooter_custom.prototype.OnOrder(self, params)
if self:GetParent():IsIllusion() then
return
end
if params.unit ~= self:GetParent() then
return
end
if params.order_type == DOTA_UNIT_ORDER_MOVE_TO_POSITION or params.order_type == DOTA_UNIT_ORDER_MOVE_TO_DIRECTION then
self:SetDirection(params.new_pos)
elseif params.order_type == DOTA_UNIT_ORDER_MOVE_TO_TARGET or params.order_type == DOTA_UNIT_ORDER_ATTACK_TARGET then
local target = params.target
if target ~= nil then
self:SetDirection(target:GetOrigin())
end
end
end
function modifier_hoodwink_sharpshooter_custom.prototype.GetModifierMoveSpeed_Limit(self)
return 0.1
end
function modifier_hoodwink_sharpshooter_custom.prototype.GetModifierTurnRate_Percentage(self)
return -self.turnRate
end
function modifier_hoodwink_sharpshooter_custom.prototype.GetModifierDisableTurning(self)
return 1
end
function modifier_hoodwink_sharpshooter_custom.prototype.SetDirection(self, vec)
local parent = self:GetParent()
if not parent or parent:IsNull() then
return
end
if vec.x == parent:GetAbsOrigin().x and vec.y == parent:GetAbsOrigin().y then
vec = parent:GetAbsOrigin() + 100 * parent:GetForwardVector()
end
self.targetDir = ((vec - parent:GetOrigin()) * Vector(1, 1, 0)):Normalized()
self.faceTarget = false
end
function modifier_hoodwink_sharpshooter_custom.prototype.CheckState(self)
return {[MODIFIER_STATE_DISARMED] = true}
end
function modifier_hoodwink_sharpshooter_custom.prototype.TurnLogic(self)
local parent = self:GetParent()
if not parent or parent:IsNull() or self.faceTarget then
return
end
local currentAngle = VectorToAngles(self.currentDir).y
local targetAngle = VectorToAngles(self.targetDir).y
local angleDiff = AngleDiff(currentAngle, targetAngle)
local sign = angleDiff < 0 and 1 or -1
if math.abs(angleDiff) < 1.1 * self.turnSpeed then
self.currentDir = self.targetDir
self.faceTarget = true
else
self.currentDir = RotatePosition(
Vector(0, 0, 0),
QAngle(0, sign * self.turnSpeed, 0),
self.currentDir
)
end
local hasMotion = parent:IsCurrentlyHorizontalMotionControlled() or parent:IsCurrentlyVerticalMotionControlled()
if not hasMotion then
parent:SetForwardVector(self.currentDir)
end
end
function modifier_hoodwink_sharpshooter_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
self:UpdateStack()
local parent = self:GetParent()
if not parent or parent:IsNull() then
return
end
self:TurnLogic()
self:UpdateEffect()
local chargeThreshold = self.charge * (1 - self.base)
if not self.charged and self:GetElapsedTime() > chargeThreshold then
self.charged = true
parent:EmitSound("Hero_Hoodwink.Sharpshooter.MaxCharge")
end
local remaining = self:GetRemainingTime()
local seconds = math.ceil(remaining)
local isHalf = seconds - remaining > 0.5
if isHalf then
seconds = seconds - 1
end
if self.half ~= isHalf then
self.half = isHalf
local mid = isHalf and 8 or 1
local len = 2
if seconds < 1 then
len = 1
if not isHalf then
return
end
end
local effect = ParticleManager:CreateParticleForTeam(
"particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_timer.vpcf",
PATTACH_OVERHEAD_FOLLOW,
parent,
parent:GetTeamNumber()
)
ParticleManager:SetParticleControl(
effect,
1,
Vector(1, seconds, mid)
)
ParticleManager:SetParticleControl(
effect,
2,
Vector(len, 0, 0)
)
end
end
function modifier_hoodwink_sharpshooter_custom.prototype.UpdateStack(self)
local fullTime = self.charge * (1 - self.base)
local pct = math.min(
1,
self:GetElapsedTime() / fullTime
)
pct = math.floor(pct * 100)
self:SetStackCount(pct)
end
function modifier_hoodwink_sharpshooter_custom.prototype.UpdateEffect(self)
if self.previewEffect == -1 then
return
end
local startPos = self:GetParent():GetAbsOrigin()
local endPos = startPos:__add(self.currentDir:__mul(self.projectileRange))
ParticleManager:SetParticleControl(self.previewEffect, 0, startPos)
ParticleManager:SetParticleControl(self.previewEffect, 1, endPos)
end
modifier_hoodwink_sharpshooter_custom = __TS__Decorate(
modifier_hoodwink_sharpshooter_custom,
modifier_hoodwink_sharpshooter_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_sharpshooter_custom"}
)
____exports.modifier_hoodwink_sharpshooter_custom = modifier_hoodwink_sharpshooter_custom
modifier_hoodwink_sharpshooter_custom_debuff = __TS__Class()
modifier_hoodwink_sharpshooter_custom_debuff.name = "modifier_hoodwink_sharpshooter_custom_debuff"
modifier_hoodwink_sharpshooter_custom_debuff.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_sharpshooter_custom.lua"
__TS__ClassExtends(modifier_hoodwink_sharpshooter_custom_debuff, BaseModifier)
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.slow = 0
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.IsHidden(self)
return false
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.IsDebuff(self)
return true
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.IsPurgable(self)
return true
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.OnCreated(self, kv)
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
self.slow = -ability:GetSpecialValueFor("slow_move_pct")
if not IsServer() then
return
end
local direction = Vector(kv.x, kv.y, 0):Normalized()
local effect = ParticleManager:CreateParticle("particles/units/heroes/hero_hoodwink/hoodwink_sharpshooter_debuff.vpcf", PATTACH_POINT_FOLLOW, parent)
ParticleManager:SetParticleControlEnt(
effect,
0,
parent,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
parent:GetOrigin(),
true
)
ParticleManager:SetParticleControlForward(effect, 1, direction)
self:AddParticle(
effect,
false,
false,
-1,
false,
false
)
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self.slow
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.CheckState(self)
return {[MODIFIER_STATE_PASSIVES_DISABLED] = true}
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.GetEffectName(self)
return "particles/generic_gameplay/generic_break.vpcf"
end
function modifier_hoodwink_sharpshooter_custom_debuff.prototype.GetEffectAttachType(self)
return PATTACH_OVERHEAD_FOLLOW
end
modifier_hoodwink_sharpshooter_custom_debuff = __TS__Decorate(
modifier_hoodwink_sharpshooter_custom_debuff,
modifier_hoodwink_sharpshooter_custom_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_sharpshooter_custom_debuff"}
)
modifier_hoodwink_sharpshooter_custom_sound = __TS__Class()
modifier_hoodwink_sharpshooter_custom_sound.name = "modifier_hoodwink_sharpshooter_custom_sound"
modifier_hoodwink_sharpshooter_custom_sound.____file_path = "scripts/vscripts/abilities/heroes/hoodwink/hoodwink_sharpshooter_custom.lua"
__TS__ClassExtends(modifier_hoodwink_sharpshooter_custom_sound, BaseModifier)
function modifier_hoodwink_sharpshooter_custom_sound.prototype.IsHidden(self)
return true
end
function modifier_hoodwink_sharpshooter_custom_sound.prototype.IsPurgable(self)
return false
end
modifier_hoodwink_sharpshooter_custom_sound = __TS__Decorate(
modifier_hoodwink_sharpshooter_custom_sound,
modifier_hoodwink_sharpshooter_custom_sound,
{registerModifier(nil)},
{kind = "class", name = "modifier_hoodwink_sharpshooter_custom_sound"}
)
return ____exports
@@ -0,0 +1,309 @@
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 ____vampirism = require("utils.vampirism")
local addPhysicalVampirism = ____vampirism.addPhysicalVampirism
local reducePhysicalVampirism = ____vampirism.reducePhysicalVampirism
____exports.ability_juggernaut_blade_dance_custom = __TS__Class()
local ability_juggernaut_blade_dance_custom = ____exports.ability_juggernaut_blade_dance_custom
ability_juggernaut_blade_dance_custom.name = "ability_juggernaut_blade_dance_custom"
ability_juggernaut_blade_dance_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_dance_custom.lua"
__TS__ClassExtends(ability_juggernaut_blade_dance_custom, BaseAbility)
function ability_juggernaut_blade_dance_custom.prototype.GetIntrinsicModifierName(self)
return "modifier_juggernaut_blade_dance_custom"
end
function ability_juggernaut_blade_dance_custom.prototype.GetCooldown(self, _level)
return self:GetSpecialValueFor("AbilityCooldown")
end
function ability_juggernaut_blade_dance_custom.prototype.GetManaCost(self, _level)
return self:GetSpecialValueFor("AbilityManaCost")
end
function ability_juggernaut_blade_dance_custom.prototype.GetCastRange(self, _location, _target)
return self:GetSpecialValueFor("AbilityCastRange")
end
function ability_juggernaut_blade_dance_custom.prototype.PerformSlash(self, caster, startPos, endPos)
if not IsServer() then
return
end
local radius = self:GetSpecialValueFor("astral_slash_radius")
local debuffDuration = self:GetSpecialValueFor("astral_slash_debuff_duration")
local groundEnd = GetGroundPosition(endPos, nil)
caster:StartGestureWithPlaybackRate(ACT_DOTA_TELEPORT_END, 1)
FindClearSpaceForUnit(caster, groundEnd, true)
local enemies = FindUnitsInLine(
caster:GetTeamNumber(),
startPos,
groundEnd,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES
)
for ____, enemy in ipairs(enemies) do
do
if not enemy or not enemy:IsAlive() then
goto __continue8
end
local isAltCast = self:IsAltCastAbility()
if self:GetSpecialValueFor("juggernaut_blade_dance_jugg_step") > 0 then
enemy:AddNewModifier(caster, self, ____exports.modifier_juggernaut_blade_dance_astral_slash_debuff.name, {duration = debuffDuration})
if not isAltCast then
enemy:AddNewModifier(caster, self, ____exports.modifier_juggernaut_blade_dance_astral_slash_debuff.name, {duration = debuffDuration})
end
end
local count = self:GetSpecialValueFor("astral_slash_attack_count")
if self:IsAltCastAbility() then
count = math.max(
1,
math.floor(count / 2)
)
end
do
local i = 0
while i < count do
caster:PerformAttack(
enemy,
true,
true,
true,
false,
false,
false,
true
)
i = i + 1
end
end
end
::__continue8::
end
self:PlayEffects(startPos, groundEnd)
end
function ability_juggernaut_blade_dance_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local origin = caster:GetAbsOrigin()
local isAltCast = self:IsAltCastAbility()
local minDist = self:GetSpecialValueFor("min_travel_distance")
local maxDist = self:GetSpecialValueFor("max_travel_distance")
local direction = point - origin
direction.z = 0
local dist2D = direction:Length2D()
local dist = math.max(
math.min(maxDist, dist2D),
minDist
)
local dirNorm = direction:Normalized()
local endPos = Vector(origin.x + dirNorm.x * dist, origin.y + dirNorm.y * dist, origin.z)
local targetPos = GetGroundPosition(endPos, nil)
self:PerformSlash(caster, origin, targetPos)
if isAltCast then
local returnPos = GetGroundPosition(origin, nil)
caster:FaceTowards(returnPos)
caster:AddNewModifier(caster, self, ____exports.modifier_juggernaut_blade_dance_return.name, {duration = 0.25, x = returnPos.x, y = returnPos.y, z = returnPos.z})
end
end
function ability_juggernaut_blade_dance_custom.prototype.PlayEffects(self, origin, target)
local particleCast = "particles/juggernaut_step.vpcf"
local effectCast = ParticleManager:CreateParticle(particleCast, PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(effectCast, 0, origin)
ParticleManager:SetParticleControl(effectCast, 1, target)
ParticleManager:ReleaseParticleIndex(effectCast)
EmitSoundOnLocationWithCaster(
origin,
"Hero_Juggernaut.OmniSlash",
self:GetCaster()
)
EmitSoundOnLocationWithCaster(
target,
"Hero_Juggernaut.OmniSlash.End",
self:GetCaster()
)
end
ability_juggernaut_blade_dance_custom = __TS__Decorate(
ability_juggernaut_blade_dance_custom,
ability_juggernaut_blade_dance_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_juggernaut_blade_dance_custom"}
)
____exports.ability_juggernaut_blade_dance_custom = ability_juggernaut_blade_dance_custom
____exports.modifier_juggernaut_blade_dance_custom = __TS__Class()
local modifier_juggernaut_blade_dance_custom = ____exports.modifier_juggernaut_blade_dance_custom
modifier_juggernaut_blade_dance_custom.name = "modifier_juggernaut_blade_dance_custom"
modifier_juggernaut_blade_dance_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_dance_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_dance_custom, BaseModifier)
function modifier_juggernaut_blade_dance_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.lifestealAppliedAmount = 0
end
function modifier_juggernaut_blade_dance_custom.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_dance_custom.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_dance_custom.prototype.RemoveOnDeath(self)
return false
end
function modifier_juggernaut_blade_dance_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability or not parent:IsRealHero() then
return
end
local critMod = parent:FindModifierByName("modifier_stacking_crit")
local critChance = ability:GetSpecialValueFor("crit_chance")
local critMult = ability:GetSpecialValueFor("crit_mult")
if parent:PassivesDisabled() then
if critMod ~= nil then
critMod:RemoveCrit("blade_dance")
end
if self.lifestealAppliedAmount > 0 then
reducePhysicalVampirism(nil, parent, self.lifestealAppliedAmount)
self.lifestealAppliedAmount = 0
end
return
end
if critMod then
critMod:UpdateCrit(
0,
0,
critChance,
critMult,
"blade_dance"
)
end
local lifesteal = ability:GetSpecialValueFor("lifesteal_percent")
if lifesteal > 0 and self.lifestealAppliedAmount == 0 then
addPhysicalVampirism(nil, parent, lifesteal)
self.lifestealAppliedAmount = lifesteal
end
end
function modifier_juggernaut_blade_dance_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
self:StartIntervalThink(0.2)
self:OnIntervalThink()
end
function modifier_juggernaut_blade_dance_custom.prototype.OnRefresh(self)
if not IsServer() then
return
end
self:OnIntervalThink()
end
function modifier_juggernaut_blade_dance_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ____opt_2 = parent and parent:FindModifierByName("modifier_stacking_crit")
if ____opt_2 ~= nil then
____opt_2:RemoveCrit("blade_dance")
end
if self.lifestealAppliedAmount > 0 and (parent and parent:IsRealHero()) then
reducePhysicalVampirism(nil, parent, self.lifestealAppliedAmount)
end
end
modifier_juggernaut_blade_dance_custom = __TS__Decorate(
modifier_juggernaut_blade_dance_custom,
modifier_juggernaut_blade_dance_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_dance_custom"}
)
____exports.modifier_juggernaut_blade_dance_custom = modifier_juggernaut_blade_dance_custom
____exports.modifier_juggernaut_blade_dance_return = __TS__Class()
local modifier_juggernaut_blade_dance_return = ____exports.modifier_juggernaut_blade_dance_return
modifier_juggernaut_blade_dance_return.name = "modifier_juggernaut_blade_dance_return"
modifier_juggernaut_blade_dance_return.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_dance_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_dance_return, BaseModifier)
function modifier_juggernaut_blade_dance_return.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_dance_return.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_dance_return.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local x = params.x or 0
local y = params.y or 0
local z = params.z or 0
self.returnPos = Vector(x, y, z)
end
function modifier_juggernaut_blade_dance_return.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if parent and parent:IsAlive() and ability then
local startPos = parent:GetAbsOrigin()
ability:PerformSlash(parent, startPos, self.returnPos)
end
end
modifier_juggernaut_blade_dance_return = __TS__Decorate(
modifier_juggernaut_blade_dance_return,
modifier_juggernaut_blade_dance_return,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_dance_return"}
)
____exports.modifier_juggernaut_blade_dance_return = modifier_juggernaut_blade_dance_return
____exports.modifier_juggernaut_blade_dance_astral_slash_debuff = __TS__Class()
local modifier_juggernaut_blade_dance_astral_slash_debuff = ____exports.modifier_juggernaut_blade_dance_astral_slash_debuff
modifier_juggernaut_blade_dance_astral_slash_debuff.name = "modifier_juggernaut_blade_dance_astral_slash_debuff"
modifier_juggernaut_blade_dance_astral_slash_debuff.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_dance_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_dance_astral_slash_debuff, BaseModifier)
function modifier_juggernaut_blade_dance_astral_slash_debuff.prototype.IsHidden(self)
return false
end
function modifier_juggernaut_blade_dance_astral_slash_debuff.prototype.IsPurgable(self)
return true
end
function modifier_juggernaut_blade_dance_astral_slash_debuff.prototype.GetEffectName(self)
return "particles/econ/items/void_spirit/void_spirit_immortal_2021/void_spirit_immortal_2021_astral_step_debuff.vpcf"
end
function modifier_juggernaut_blade_dance_astral_slash_debuff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_juggernaut_blade_dance_astral_slash_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
end
function modifier_juggernaut_blade_dance_astral_slash_debuff.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_juggernaut_blade_dance_astral_slash_debuff.prototype.GetModifierPhysicalArmorBonus(self, event)
local parent = self:GetParent()
if not parent then
return 0
end
if not parent:IsRealHero() then
return 0
end
local hero = parent
local armor = hero:GetPhysicalArmorBaseValue()
return -armor * (self:GetAbility():GetSpecialValueFor("juggernaut_blade_dance_jugg_step_armor_reduce") * 0.01)
end
modifier_juggernaut_blade_dance_astral_slash_debuff = __TS__Decorate(
modifier_juggernaut_blade_dance_astral_slash_debuff,
modifier_juggernaut_blade_dance_astral_slash_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_dance_astral_slash_debuff"}
)
____exports.modifier_juggernaut_blade_dance_astral_slash_debuff = modifier_juggernaut_blade_dance_astral_slash_debuff
return ____exports
@@ -0,0 +1,730 @@
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 ____luck = require("utils.luck")
local rollLuckChance = ____luck.rollLuckChance
____exports.ability_juggernaut_blade_fury_custom = __TS__Class()
local ability_juggernaut_blade_fury_custom = ____exports.ability_juggernaut_blade_fury_custom
ability_juggernaut_blade_fury_custom.name = "ability_juggernaut_blade_fury_custom"
ability_juggernaut_blade_fury_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(ability_juggernaut_blade_fury_custom, BaseAbility)
function ability_juggernaut_blade_fury_custom.prototype.GetIntrinsicModifierName(self)
return "modifier_juggernaut_blade_fury_custom_passive"
end
function ability_juggernaut_blade_fury_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function ability_juggernaut_blade_fury_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local duration = self:GetSpecialValueFor("duration")
caster:Purge(
false,
true,
false,
true,
false
)
local isAltCast = self:IsAltCastAbility()
if isAltCast then
local point = self:GetCursorPosition()
local casterPos = caster:GetAbsOrigin()
local castRange = self:GetCastRange(casterPos, nil)
local delta = Vector(point.x - casterPos.x, point.y - casterPos.y, 0)
local dist2D = delta:Length2D()
local clampedPoint = dist2D > castRange and dist2D > 0 and Vector(casterPos.x + delta.x / dist2D * castRange, casterPos.y + delta.y / dist2D * castRange, point.z) or point
local groundPoint = GetGroundPosition(clampedPoint, nil)
local thinker = CreateModifierThinker(
caster,
self,
"modifier_juggernaut_blade_fury_thinker",
{x = groundPoint.x, y = groundPoint.y, z = groundPoint.z},
caster:GetAbsOrigin(),
caster:GetTeamNumber(),
false
)
local ____opt_0 = self:GetCaster()
if ____opt_0 ~= nil then
____opt_0:RemoveGesture(ACT_DOTA_ATTACK)
end
if thinker and IsValidEntity(thinker) then
thinker:AddNewModifier(caster, self, "modifier_juggernaut_blade_fury_sword_unit", {})
thinker:AddNewModifier(caster, self, "modifier_juggernaut_blade_fury_custom_point", {})
thinker:AddNewModifier(caster, self, "modifier_juggernaut_blade_fury_fly", {x = groundPoint.x, y = groundPoint.y})
EmitSoundOn("Hero_Juggernaut.BladeFuryStart", thinker)
end
return
else
caster:AddNewModifier(caster, self, "modifier_juggernaut_blade_fury_custom", {duration = duration})
EmitSoundOn("Hero_Juggernaut.BladeFuryStart", caster)
end
end
ability_juggernaut_blade_fury_custom = __TS__Decorate(
ability_juggernaut_blade_fury_custom,
ability_juggernaut_blade_fury_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_juggernaut_blade_fury_custom"}
)
____exports.ability_juggernaut_blade_fury_custom = ability_juggernaut_blade_fury_custom
____exports.modifier_juggernaut_blade_fury_custom = __TS__Class()
local modifier_juggernaut_blade_fury_custom = ____exports.modifier_juggernaut_blade_fury_custom
modifier_juggernaut_blade_fury_custom.name = "modifier_juggernaut_blade_fury_custom"
modifier_juggernaut_blade_fury_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_custom, BaseModifier)
function modifier_juggernaut_blade_fury_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.damageInterval = 1 / self:GetCaster():GetAttacksPerSecond(false)
end
function modifier_juggernaut_blade_fury_custom.prototype.IsHidden(self)
return false
end
function modifier_juggernaut_blade_fury_custom.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_custom.prototype.CheckState(self)
return {[MODIFIER_STATE_DEBUFF_IMMUNE] = true}
end
function modifier_juggernaut_blade_fury_custom.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
local ____opt_2 = self:GetCaster()
if ____opt_2 ~= nil then
____opt_2:StartGesture(ACT_DOTA_OVERRIDE_ABILITY_1)
end
local particleId = ParticleManager:CreateParticle(
"particles/units/heroes/hero_juggernaut/juggernaut_blade_fury.vpcf",
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
particleId,
0,
self:GetParent():GetAbsOrigin()
)
ParticleManager:SetParticleControl(
particleId,
1,
self:GetParent():GetAbsOrigin()
)
self.particleId = particleId
self:StartIntervalThink(self.damageInterval)
end
function modifier_juggernaut_blade_fury_custom.prototype.OnRefresh(self, params)
StopSoundOn(
"Hero_Juggernaut.BladeFuryStart",
self:GetParent()
)
end
function modifier_juggernaut_blade_fury_custom.prototype.OnDestroy(self)
if IsClient() then
return
end
local ____opt_4 = self:GetCaster()
if ____opt_4 ~= nil then
____opt_4:RemoveGesture(ACT_DOTA_OVERRIDE_ABILITY_1)
end
StopSoundOn(
"Hero_Juggernaut.BladeFuryStart",
self:GetParent()
)
if self.particleId ~= nil then
ParticleManager:DestroyParticle(self.particleId, false)
ParticleManager:ReleaseParticleIndex(self.particleId)
self.particleId = nil
end
self:GetParent():Purge(
false,
true,
false,
true,
false
)
EmitSoundOn(
"Hero_Juggernaut.BladeFuryStop",
self:GetParent()
)
end
function modifier_juggernaut_blade_fury_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not ability or not caster or not caster:IsAlive() or not parent:IsAlive() then
return
end
local radius = ability:GetSpecialValueFor("radius")
local damagePerTick = ability:GetSpecialValueFor("damage_per_tick")
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
if enemy and enemy:IsAlive() and not enemy:IsInvulnerable() then
if self:GetAbility():GetSpecialValueFor("leap_sword") > 0 then
caster:PerformAttack(
enemy,
true,
true,
true,
false,
false,
false,
true
)
end
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damagePerTick,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
local finaldamage
if self:GetAbility():GetSpecialValueFor("leap_sword") > 0 then
finaldamage = damagePerTick + caster:GetAverageTrueAttackDamage(enemy)
else
finaldamage = damagePerTick
end
SendOverheadEventMessage(
nil,
OVERHEAD_ALERT_DAMAGE,
enemy,
finaldamage,
nil
)
end
end
end
modifier_juggernaut_blade_fury_custom = __TS__Decorate(
modifier_juggernaut_blade_fury_custom,
modifier_juggernaut_blade_fury_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_custom"}
)
____exports.modifier_juggernaut_blade_fury_custom = modifier_juggernaut_blade_fury_custom
____exports.modifier_juggernaut_blade_fury_custom_passive = __TS__Class()
local modifier_juggernaut_blade_fury_custom_passive = ____exports.modifier_juggernaut_blade_fury_custom_passive
modifier_juggernaut_blade_fury_custom_passive.name = "modifier_juggernaut_blade_fury_custom_passive"
modifier_juggernaut_blade_fury_custom_passive.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_custom_passive, BaseModifier)
function modifier_juggernaut_blade_fury_custom_passive.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_fury_custom_passive.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_custom_passive.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_juggernaut_blade_fury_custom_passive.prototype.OnAttackLanded(self, event)
if not HasShard(
nil,
self:GetCaster()
) then
return
end
local caster = self:GetCaster()
if not caster then
return
end
if caster:PassivesDisabled() then
return
end
if event.attacker ~= self:GetParent() then
return
end
local parent = self:GetParent()
if not parent or not parent:IsRealHero() then
return
end
local hero = parent
local ability = self:GetAbility()
if not ability then
return
end
local baseChancePercent = ability:GetSpecialValueFor("proc_chance")
local baseChance = baseChancePercent / 100
if rollLuckChance(nil, hero, baseChance) then
if self:GetCaster():HasModifier("modifier_juggernaut_blade_fury_custom") then
caster:AddNewModifier(
caster,
ability,
"modifier_juggernaut_blade_fury_custom",
{duration = self:GetCaster():FindModifierByName("modifier_juggernaut_blade_fury_custom"):GetRemainingTime() + 1 / self:GetCaster():GetAttacksPerSecond(false)}
)
else
caster:AddNewModifier(
caster,
ability,
"modifier_juggernaut_blade_fury_custom",
{duration = 1 / self:GetCaster():GetAttacksPerSecond(false)}
)
end
end
end
modifier_juggernaut_blade_fury_custom_passive = __TS__Decorate(
modifier_juggernaut_blade_fury_custom_passive,
modifier_juggernaut_blade_fury_custom_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_custom_passive"}
)
____exports.modifier_juggernaut_blade_fury_custom_passive = modifier_juggernaut_blade_fury_custom_passive
____exports.modifier_juggernaut_blade_fury_sword_unit = __TS__Class()
local modifier_juggernaut_blade_fury_sword_unit = ____exports.modifier_juggernaut_blade_fury_sword_unit
modifier_juggernaut_blade_fury_sword_unit.name = "modifier_juggernaut_blade_fury_sword_unit"
modifier_juggernaut_blade_fury_sword_unit.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_sword_unit, BaseModifier)
function modifier_juggernaut_blade_fury_sword_unit.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_fury_sword_unit.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_sword_unit.prototype.CheckState(self)
return {
[MODIFIER_STATE_INVULNERABLE] = true,
[MODIFIER_STATE_UNSELECTABLE] = true,
[MODIFIER_STATE_UNTARGETABLE] = true,
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
[MODIFIER_STATE_NOT_ON_MINIMAP] = true,
[MODIFIER_STATE_NO_UNIT_COLLISION] = true
}
end
modifier_juggernaut_blade_fury_sword_unit = __TS__Decorate(
modifier_juggernaut_blade_fury_sword_unit,
modifier_juggernaut_blade_fury_sword_unit,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_sword_unit"}
)
____exports.modifier_juggernaut_blade_fury_sword_unit = modifier_juggernaut_blade_fury_sword_unit
local BLADE_FURY_FLY_SPEED = 800
local BLADE_FURY_FLY_INTERVAL = 0.03
local BLADE_FURY_THINKER_MOD = "modifier_juggernaut_blade_fury_thinker"
--- Точечный режим на thinker: при смерти/пропажи кастера убираем юнит, иначе вихрь крутится вечно.
local function cleanupBladeFuryThinkerAfterCasterLost(self, parent, caster)
if not IsServer() then
return
end
if caster ~= nil and caster ~= nil and caster:IsAlive() then
return
end
local thinkerMod = parent:FindModifierByName(BLADE_FURY_THINKER_MOD)
if thinkerMod then
thinkerMod:Destroy()
return
end
StopSoundOn("Hero_Juggernaut.BladeFuryStart", parent)
EmitSoundOn("Hero_Juggernaut.BladeFuryStop", parent)
if IsValidEntity(parent) then
UTIL_Remove(parent)
end
end
____exports.modifier_juggernaut_blade_fury_custom_point = __TS__Class()
local modifier_juggernaut_blade_fury_custom_point = ____exports.modifier_juggernaut_blade_fury_custom_point
modifier_juggernaut_blade_fury_custom_point.name = "modifier_juggernaut_blade_fury_custom_point"
modifier_juggernaut_blade_fury_custom_point.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_custom_point, BaseModifier)
function modifier_juggernaut_blade_fury_custom_point.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.radius = 0
self.damageTickInterval = 0.2
self.lastDamageTime = 0
end
function modifier_juggernaut_blade_fury_custom_point.prototype.IsHidden(self)
return false
end
function modifier_juggernaut_blade_fury_custom_point.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_custom_point.prototype.OnCreated(self, _params)
local ability = self:GetAbility()
if not ability then
return
end
self.radius = ability:GetSpecialValueFor("radius")
local caster = self:GetCaster()
if caster then
self.damageTickInterval = 0.1 + 1 / caster:GetAttacksPerSecond(false)
end
self.lastDamageTime = GameRules:GetGameTime()
if IsServer() then
local particleName = "particles/units/heroes/hero_juggernaut/juggernaut_blade_fury.vpcf"
local fx = ParticleManager:CreateParticle(
particleName,
PATTACH_ABSORIGIN_FOLLOW,
self:GetParent()
)
ParticleManager:SetParticleControl(
fx,
5,
Vector(self.radius * 1.2, 0, 0)
)
self:AddParticle(
fx,
false,
false,
-1,
false,
false
)
self.particleId = fx
end
self:StartIntervalThink(0.1)
end
function modifier_juggernaut_blade_fury_custom_point.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
local caster = self:GetCaster()
if not ability or not parent:IsAlive() then
return
end
if not caster or not caster:IsAlive() then
cleanupBladeFuryThinkerAfterCasterLost(nil, parent, caster)
return
end
local pos = parent:GetAbsOrigin()
local currentTime = GameRules:GetGameTime()
if currentTime - self.lastDamageTime >= self.damageTickInterval then
self.lastDamageTime = currentTime
local damagePerTick = ability:GetSpecialValueFor("damage_per_tick")
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
pos,
nil,
self.radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
if enemy and enemy:IsAlive() and not enemy:IsInvulnerable() then
if self:GetAbility():GetSpecialValueFor("leap_sword") > 0 then
caster:PerformAttack(
enemy,
true,
true,
true,
false,
false,
false,
true
)
end
ApplyDamage({
victim = enemy,
attacker = caster,
damage = damagePerTick,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
local finaldamage = damagePerTick + caster:GetAverageTrueAttackDamage(enemy)
SendOverheadEventMessage(
nil,
OVERHEAD_ALERT_DAMAGE,
enemy,
finaldamage,
nil
)
end
end
end
end
function modifier_juggernaut_blade_fury_custom_point.prototype.OnDestroy(self)
if IsServer() and self.particleId ~= nil then
ParticleManager:DestroyParticle(self.particleId, false)
ParticleManager:ReleaseParticleIndex(self.particleId)
self.particleId = nil
end
end
modifier_juggernaut_blade_fury_custom_point = __TS__Decorate(
modifier_juggernaut_blade_fury_custom_point,
modifier_juggernaut_blade_fury_custom_point,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_custom_point"}
)
____exports.modifier_juggernaut_blade_fury_custom_point = modifier_juggernaut_blade_fury_custom_point
____exports.modifier_juggernaut_blade_fury_fly = __TS__Class()
local modifier_juggernaut_blade_fury_fly = ____exports.modifier_juggernaut_blade_fury_fly
modifier_juggernaut_blade_fury_fly.name = "modifier_juggernaut_blade_fury_fly"
modifier_juggernaut_blade_fury_fly.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_fly, BaseModifier)
function modifier_juggernaut_blade_fury_fly.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.speed = BLADE_FURY_FLY_SPEED
self.interval = BLADE_FURY_FLY_INTERVAL
end
function modifier_juggernaut_blade_fury_fly.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_fury_fly.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_fly.prototype.RemoveOnDeath(self)
return false
end
function modifier_juggernaut_blade_fury_fly.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
local z = GetGroundPosition(
Vector(params.x or 0, params.y or 0, 0),
nil
).z
self.targetPos = Vector(params.x or 0, params.y or 0, z)
self:StartIntervalThink(self.interval)
end
function modifier_juggernaut_blade_fury_fly.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
if not caster or not caster:IsAlive() then
cleanupBladeFuryThinkerAfterCasterLost(nil, parent, caster)
return
end
local pos = parent:GetAbsOrigin()
local delta = Vector(self.targetPos.x - pos.x, self.targetPos.y - pos.y, self.targetPos.z - pos.z)
local dist = delta:Length2D()
local dir = delta:Normalized()
local step = self.speed * self.interval
if dist <= step + 5 then
parent:SetAbsOrigin(self.targetPos)
local ability = self:GetAbility()
local duration = ability and ability:GetSpecialValueFor("duration") or 5
parent:AddNewModifier(
self:GetCaster(),
ability,
"modifier_juggernaut_blade_fury_pause",
{duration = duration}
)
self:Destroy()
return
end
local newPos = Vector(pos.x + dir.x * step, pos.y + dir.y * step, pos.z + dir.z * step)
parent:SetAbsOrigin(GetGroundPosition(newPos, nil))
end
modifier_juggernaut_blade_fury_fly = __TS__Decorate(
modifier_juggernaut_blade_fury_fly,
modifier_juggernaut_blade_fury_fly,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_fly"}
)
____exports.modifier_juggernaut_blade_fury_fly = modifier_juggernaut_blade_fury_fly
____exports.modifier_juggernaut_blade_fury_pause = __TS__Class()
local modifier_juggernaut_blade_fury_pause = ____exports.modifier_juggernaut_blade_fury_pause
modifier_juggernaut_blade_fury_pause.name = "modifier_juggernaut_blade_fury_pause"
modifier_juggernaut_blade_fury_pause.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_pause, BaseModifier)
function modifier_juggernaut_blade_fury_pause.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_fury_pause.prototype.RemoveOnDeath(self)
return false
end
function modifier_juggernaut_blade_fury_pause.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_pause.prototype.OnDestroy(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or not caster:IsAlive() then
return
end
self:GetParent():AddNewModifier(
caster,
self:GetAbility(),
"modifier_juggernaut_blade_fury_fly_back",
{}
)
end
modifier_juggernaut_blade_fury_pause = __TS__Decorate(
modifier_juggernaut_blade_fury_pause,
modifier_juggernaut_blade_fury_pause,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_pause"}
)
____exports.modifier_juggernaut_blade_fury_pause = modifier_juggernaut_blade_fury_pause
____exports.modifier_juggernaut_blade_fury_fly_back = __TS__Class()
local modifier_juggernaut_blade_fury_fly_back = ____exports.modifier_juggernaut_blade_fury_fly_back
modifier_juggernaut_blade_fury_fly_back.name = "modifier_juggernaut_blade_fury_fly_back"
modifier_juggernaut_blade_fury_fly_back.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_fly_back, BaseModifier)
function modifier_juggernaut_blade_fury_fly_back.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.interval = BLADE_FURY_FLY_INTERVAL
self.speed = BLADE_FURY_FLY_SPEED
end
function modifier_juggernaut_blade_fury_fly_back.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_fury_fly_back.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_fly_back.prototype.RemoveOnDeath(self)
return false
end
function modifier_juggernaut_blade_fury_fly_back.prototype.OnCreated(self, _params)
if not IsServer() then
return
end
self:StartIntervalThink(self.interval)
end
function modifier_juggernaut_blade_fury_fly_back.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
if not caster or not caster:IsAlive() then
cleanupBladeFuryThinkerAfterCasterLost(nil, parent, caster)
return
end
local pos = parent:GetAbsOrigin()
local casterPos = caster:GetAbsOrigin()
local delta = Vector(casterPos.x - pos.x, casterPos.y - pos.y, casterPos.z - pos.z)
local dist = delta:Length2D()
local dir = delta:Normalized()
local step = self.speed * self.interval
if dist <= 50 then
local thinkerMod = parent:FindModifierByName("modifier_juggernaut_blade_fury_thinker")
if thinkerMod then
thinkerMod:Destroy()
end
self:Destroy()
return
end
local move = math.min(step, dist)
local newPos = Vector(pos.x + dir.x * move, pos.y + dir.y * move, pos.z + dir.z * move)
parent:SetAbsOrigin(GetGroundPosition(newPos, nil))
end
modifier_juggernaut_blade_fury_fly_back = __TS__Decorate(
modifier_juggernaut_blade_fury_fly_back,
modifier_juggernaut_blade_fury_fly_back,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_fly_back"}
)
____exports.modifier_juggernaut_blade_fury_fly_back = modifier_juggernaut_blade_fury_fly_back
____exports.ability_juggernaut_blade_fury_custom_alt = __TS__Class()
local ability_juggernaut_blade_fury_custom_alt = ____exports.ability_juggernaut_blade_fury_custom_alt
ability_juggernaut_blade_fury_custom_alt.name = "ability_juggernaut_blade_fury_custom_alt"
ability_juggernaut_blade_fury_custom_alt.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(ability_juggernaut_blade_fury_custom_alt, BaseAbility)
function ability_juggernaut_blade_fury_custom_alt.prototype.GetIntrinsicModifierName(self)
return "modifier_juggernaut_blade_fury_custom_passive"
end
function ability_juggernaut_blade_fury_custom_alt.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local casterPos = caster:GetAbsOrigin()
local castRange = self:GetCastRange(casterPos, nil)
local delta = Vector(point.x - casterPos.x, point.y - casterPos.y, 0)
local dist2D = delta:Length2D()
local clampedPoint = dist2D > castRange and dist2D > 0 and Vector(casterPos.x + delta.x / dist2D * castRange, casterPos.y + delta.y / dist2D * castRange, point.z) or point
local groundPoint = GetGroundPosition(clampedPoint, nil)
local thinker = CreateModifierThinker(
caster,
self,
"modifier_juggernaut_blade_fury_thinker",
{x = groundPoint.x, y = groundPoint.y, z = groundPoint.z},
caster:GetAbsOrigin(),
caster:GetTeamNumber(),
false
)
if thinker and IsValidEntity(thinker) then
thinker:AddNewModifier(caster, self, "modifier_juggernaut_blade_fury_sword_unit", {})
thinker:AddNewModifier(caster, self, "modifier_juggernaut_blade_fury_custom_point", {})
thinker:AddNewModifier(caster, self, "modifier_juggernaut_blade_fury_fly", {x = groundPoint.x, y = groundPoint.y})
EmitSoundOn("Hero_Juggernaut.BladeFuryStart", thinker)
end
end
ability_juggernaut_blade_fury_custom_alt = __TS__Decorate(
ability_juggernaut_blade_fury_custom_alt,
ability_juggernaut_blade_fury_custom_alt,
{registerAbility(nil)},
{kind = "class", name = "ability_juggernaut_blade_fury_custom_alt"}
)
____exports.ability_juggernaut_blade_fury_custom_alt = ability_juggernaut_blade_fury_custom_alt
____exports.modifier_juggernaut_blade_fury_thinker = __TS__Class()
local modifier_juggernaut_blade_fury_thinker = ____exports.modifier_juggernaut_blade_fury_thinker
modifier_juggernaut_blade_fury_thinker.name = "modifier_juggernaut_blade_fury_thinker"
modifier_juggernaut_blade_fury_thinker.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_blade_fury_custom.lua"
__TS__ClassExtends(modifier_juggernaut_blade_fury_thinker, BaseModifier)
function modifier_juggernaut_blade_fury_thinker.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_blade_fury_thinker.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_blade_fury_thinker.prototype.OnCreated(self, _params)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or not caster:IsAlive() then
self:Destroy()
end
end
function modifier_juggernaut_blade_fury_thinker.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or not caster:IsAlive() then
self:Destroy()
end
end
function modifier_juggernaut_blade_fury_thinker.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
StopSoundOn("Hero_Juggernaut.BladeFuryStart", parent)
EmitSoundOn("Hero_Juggernaut.BladeFuryStop", parent)
if parent and IsValidEntity(parent) then
UTIL_Remove(parent)
end
end
modifier_juggernaut_blade_fury_thinker = __TS__Decorate(
modifier_juggernaut_blade_fury_thinker,
modifier_juggernaut_blade_fury_thinker,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_blade_fury_thinker"}
)
____exports.modifier_juggernaut_blade_fury_thinker = modifier_juggernaut_blade_fury_thinker
return ____exports
@@ -0,0 +1,162 @@
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 ____heal_tracker = require("utils.heal_tracker")
local HealWithBattlePass = ____heal_tracker.HealWithBattlePass
____exports.ability_juggernaut_healing_ward_custom = __TS__Class()
local ability_juggernaut_healing_ward_custom = ____exports.ability_juggernaut_healing_ward_custom
ability_juggernaut_healing_ward_custom.name = "ability_juggernaut_healing_ward_custom"
ability_juggernaut_healing_ward_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_healing_ward_custom.lua"
__TS__ClassExtends(ability_juggernaut_healing_ward_custom, BaseAbility)
function ability_juggernaut_healing_ward_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local duration = self:GetSpecialValueFor("ward_duration")
local ward = CreateUnitByName(
"npc_dota_juggernaut_healing_ward_custom",
point,
true,
caster,
caster,
caster:GetTeamNumber()
)
if not ward or not IsValidEntity(ward) then
return
end
Timers:CreateTimer(
0.2,
function()
ward:MoveToNPC(caster)
return nil
end
)
ward:SetOwner(caster)
ward:SetControllableByPlayer(
caster:GetPlayerOwnerID(),
false
)
ward:AddNewModifier(caster, self, "modifier_juggernaut_healing_ward_custom", {duration = duration})
EmitSoundOn("Hero_Juggernaut.HealingWard.Cast", caster)
EmitSoundOn("Hero_Juggernaut.HealingWard.Loop", ward)
end
ability_juggernaut_healing_ward_custom = __TS__Decorate(
ability_juggernaut_healing_ward_custom,
ability_juggernaut_healing_ward_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_juggernaut_healing_ward_custom"}
)
____exports.ability_juggernaut_healing_ward_custom = ability_juggernaut_healing_ward_custom
____exports.modifier_juggernaut_healing_ward_custom = __TS__Class()
local modifier_juggernaut_healing_ward_custom = ____exports.modifier_juggernaut_healing_ward_custom
modifier_juggernaut_healing_ward_custom.name = "modifier_juggernaut_healing_ward_custom"
modifier_juggernaut_healing_ward_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_healing_ward_custom.lua"
__TS__ClassExtends(modifier_juggernaut_healing_ward_custom, BaseModifier)
function modifier_juggernaut_healing_ward_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.healInterval = 1
end
function modifier_juggernaut_healing_ward_custom.prototype.IsHidden(self)
return false
end
function modifier_juggernaut_healing_ward_custom.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_healing_ward_custom.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
self.particleId = ParticleManager:CreateParticle("particles/units/heroes/hero_juggernaut/juggernaut_healing_ward.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
self:StartIntervalThink(self.healInterval)
end
function modifier_juggernaut_healing_ward_custom.prototype.OnDestroy(self)
if self.particleId ~= nil then
ParticleManager:DestroyParticle(self.particleId, false)
ParticleManager:ReleaseParticleIndex(self.particleId)
self.particleId = nil
self:GetParent():Kill(
self:GetAbility(),
nil
)
end
StopSoundOn(
"Hero_Juggernaut.HealingWard.Loop",
self:GetParent()
)
end
function modifier_juggernaut_healing_ward_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not ability or not caster or not parent:IsAlive() then
return
end
local radius = ability:GetSpecialValueFor("heal_radius")
local healPerSecond = ability:GetSpecialValueFor("heal_per_second")
local allies = FindUnitsInRadius(
caster:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_FRIENDLY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, ally in ipairs(allies) do
if ally and ally:IsAlive() then
local finalheal = healPerSecond * 0.01 * ally:GetMaxHealth()
HealWithBattlePass(
nil,
ally,
finalheal,
ability,
caster
)
local healParticle = ParticleManager:CreateParticle("particles/generic_gameplay/generic_lifesteal.vpcf", PATTACH_ABSORIGIN_FOLLOW, ally)
ParticleManager:ReleaseParticleIndex(healParticle)
SendOverheadEventMessage(
nil,
OVERHEAD_ALERT_HEAL,
ally,
finalheal,
nil
)
end
end
end
function modifier_juggernaut_healing_ward_custom.prototype.GetEffectName(self)
return "particles/units/heroes/hero_juggernaut/juggernaut_healing_ward.vpcf"
end
function modifier_juggernaut_healing_ward_custom.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_juggernaut_healing_ward_custom.prototype.CheckState(self)
return {[MODIFIER_STATE_NO_HEALTH_BAR] = true, [MODIFIER_STATE_INVULNERABLE] = true}
end
modifier_juggernaut_healing_ward_custom = __TS__Decorate(
modifier_juggernaut_healing_ward_custom,
modifier_juggernaut_healing_ward_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_healing_ward_custom"}
)
____exports.modifier_juggernaut_healing_ward_custom = modifier_juggernaut_healing_ward_custom
return ____exports
@@ -0,0 +1,348 @@
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
____exports.ability_juggernaut_omnislash_custom = __TS__Class()
local ability_juggernaut_omnislash_custom = ____exports.ability_juggernaut_omnislash_custom
ability_juggernaut_omnislash_custom.name = "ability_juggernaut_omnislash_custom"
ability_juggernaut_omnislash_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_omnislash_custom.lua"
__TS__ClassExtends(ability_juggernaut_omnislash_custom, BaseAbility)
function ability_juggernaut_omnislash_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not target or not target:IsAlive() then
return
end
local duration = self:GetSpecialValueFor("duration")
caster:AddNewModifier(
caster,
self,
"modifier_juggernaut_omnislash_custom",
{
target = target:entindex(),
duration = duration
}
)
EmitSoundOn("Hero_Juggernaut.Omnislash", caster)
end
ability_juggernaut_omnislash_custom = __TS__Decorate(
ability_juggernaut_omnislash_custom,
ability_juggernaut_omnislash_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_juggernaut_omnislash_custom"}
)
____exports.ability_juggernaut_omnislash_custom = ability_juggernaut_omnislash_custom
____exports.ability_juggernaut_miniomnislash_custom = __TS__Class()
local ability_juggernaut_miniomnislash_custom = ____exports.ability_juggernaut_miniomnislash_custom
ability_juggernaut_miniomnislash_custom.name = "ability_juggernaut_miniomnislash_custom"
ability_juggernaut_miniomnislash_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_omnislash_custom.lua"
__TS__ClassExtends(ability_juggernaut_miniomnislash_custom, BaseAbility)
function ability_juggernaut_miniomnislash_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not target or not target:IsAlive() then
return
end
local duration = self:GetSpecialValueFor("duration")
caster:AddNewModifier(
caster,
self,
"modifier_juggernaut_omnislash_custom",
{
target = target:entindex(),
duration = duration
}
)
EmitSoundOn("Hero_Juggernaut.Omnislash", caster)
end
ability_juggernaut_miniomnislash_custom = __TS__Decorate(
ability_juggernaut_miniomnislash_custom,
ability_juggernaut_miniomnislash_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_juggernaut_miniomnislash_custom"}
)
____exports.ability_juggernaut_miniomnislash_custom = ability_juggernaut_miniomnislash_custom
____exports.modifier_juggernaut_omnislash_custom = __TS__Class()
local modifier_juggernaut_omnislash_custom = ____exports.modifier_juggernaut_omnislash_custom
modifier_juggernaut_omnislash_custom.name = "modifier_juggernaut_omnislash_custom"
modifier_juggernaut_omnislash_custom.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_omnislash_custom.lua"
__TS__ClassExtends(modifier_juggernaut_omnislash_custom, BaseModifier)
function modifier_juggernaut_omnislash_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.attackCount = 0
self.interval = 0
self.radius = 0
self.endInterval = 0.15
end
function modifier_juggernaut_omnislash_custom.prototype.IsHidden(self)
return false
end
function modifier_juggernaut_omnislash_custom.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_omnislash_custom.prototype.CheckState(self)
return {
[MODIFIER_STATE_NO_UNIT_COLLISION] = true,
[MODIFIER_STATE_INVULNERABLE] = true,
[MODIFIER_STATE_NO_HEALTH_BAR] = true,
[MODIFIER_STATE_DISARMED] = true,
[MODIFIER_STATE_ROOTED] = true,
[MODIFIER_STATE_SILENCED] = true
}
end
function modifier_juggernaut_omnislash_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_IGNORE_CAST_ANGLE}
end
function modifier_juggernaut_omnislash_custom.prototype.GetModifierIgnoreCastAngle(self)
return 1
end
function modifier_juggernaut_omnislash_custom.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local caster = self:GetParent()
local ability = self:GetAbility()
if not caster or not ability then
return
end
self.interval = 1 / self:GetCaster():GetAttacksPerSecond(false) / ability:GetSpecialValueFor("slash_interval_mult")
self.radius = ability:GetSpecialValueFor("bounce_radius")
if params.target ~= nil then
self.currentTarget = EntIndexToHScript(params.target)
end
caster:StartGesture(ACT_DOTA_OVERRIDE_ABILITY_4)
self:OnIntervalThink()
self:StartIntervalThink(self.interval)
end
function modifier_juggernaut_omnislash_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
self.attackCount = self.attackCount + 1
local caster = self:GetParent()
local ability = self:GetAbility()
if not caster or not caster:IsAlive() or not ability then
self:Destroy()
return
end
if self:GetRemainingTime() <= 0 then
self:Destroy()
return
end
local enemy = nil
local final = self.currentTarget == nil
if self.currentTarget and IsValidEntity(self.currentTarget) and self.currentTarget:IsAlive() and not self.currentTarget:IsOutOfGame() and (not self.currentTarget:IsInvisible() or caster:CanEntityBeSeenByMyTeam(self.currentTarget)) then
local distance = (self.currentTarget:GetAbsOrigin() - caster:GetAbsOrigin()):Length2D()
if distance <= self.radius or self.attackCount == 1 then
enemy = self.currentTarget
end
end
if not enemy then
local targets = FindUnitsInRadius(
caster:GetTeamNumber(),
caster:GetAbsOrigin(),
nil,
self.radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
bit.bor(
bit.bor(DOTA_UNIT_TARGET_FLAG_MAGIC_IMMUNE_ENEMIES, DOTA_UNIT_TARGET_FLAG_NO_INVIS),
DOTA_UNIT_TARGET_FLAG_INVULNERABLE
),
FIND_ANY_ORDER,
false
)
if targets and #targets > 0 then
enemy = targets[1]
end
end
if not enemy then
if final then
self:Destroy()
return
end
self.currentTarget = nil
self:StartIntervalThink(self.endInterval)
return
end
self.currentTarget = enemy
self:PlayEffect(enemy)
self:DealAttack(enemy)
if self:GetRemainingTime() > self.interval then
self:StartIntervalThink(self.interval)
end
end
function modifier_juggernaut_omnislash_custom.prototype.PlayEffect(self, enemy)
if not IsServer() then
return
end
local caster = self:GetParent()
caster:RemoveGesture(ACT_DOTA_OVERRIDE_ABILITY_4)
caster:StartGesture(ACT_DOTA_OVERRIDE_ABILITY_4)
local position1 = caster:GetAbsOrigin()
local turn = (enemy:GetAbsOrigin() - position1):Normalized()
turn.z = 0
local linePos = enemy:GetAbsOrigin() + turn * 90
local angle = -45 + 90 * RandomInt(0, 1)
local finalPos = rotatePositionYaw(
nil,
enemy:GetAbsOrigin(),
angle,
linePos
)
caster:SetAbsOrigin(finalPos)
local position2 = caster:GetAbsOrigin()
local direction = (enemy:GetAbsOrigin() - caster:GetAbsOrigin()):Normalized()
direction.z = 0
caster:SetForwardVector(direction)
caster:FaceTowards(enemy:GetAbsOrigin())
local trailParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_juggernaut/juggernaut_omni_slash_trail.vpcf", PATTACH_ABSORIGIN, caster)
ParticleManager:SetParticleControl(trailParticle, 0, position1)
ParticleManager:SetParticleControl(trailParticle, 1, position2)
ParticleManager:ReleaseParticleIndex(trailParticle)
if self.attackCount == 1 then
local dashParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_juggernaut/juggernaut_omni_dash.vpcf", PATTACH_CUSTOMORIGIN, caster)
local vDirection = (position2 - position1):Normalized()
ParticleManager:SetParticleControl(dashParticle, 0, position1)
ParticleManager:SetParticleControlForward(dashParticle, 0, vDirection * -1)
ParticleManager:SetParticleControlEnt(
dashParticle,
1,
enemy,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
enemy:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
dashParticle,
2,
enemy,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
enemy:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(dashParticle)
end
end
function modifier_juggernaut_omnislash_custom.prototype.DealAttack(self, target)
if not IsServer() then
return
end
local caster = self:GetParent()
local ability = self:GetAbility()
if not caster or not ability then
return
end
local attackModifier = caster:AddNewModifier(caster, ability, "modifier_juggernaut_omnislash_attack", {})
caster:PerformAttack(
target,
true,
true,
true,
false,
false,
false,
false
)
if attackModifier ~= nil then
attackModifier:Destroy()
end
local tgtParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_juggernaut/juggernaut_omni_slash_tgt.vpcf", PATTACH_ABSORIGIN_FOLLOW, target)
ParticleManager:SetParticleControlEnt(
tgtParticle,
0,
target,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
target:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
tgtParticle,
1,
target,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
target:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(tgtParticle)
EmitSoundOn("Hero_Juggernaut.OmniSlash", target)
end
function modifier_juggernaut_omnislash_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
local caster = self:GetParent()
if caster and caster:IsAlive() then
caster:FadeGesture(ACT_DOTA_OVERRIDE_ABILITY_4)
caster:Stop()
end
EmitSoundOn("Hero_Juggernaut.Omnislash.End", caster)
end
function modifier_juggernaut_omnislash_custom.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_omnislash.vpcf"
end
function modifier_juggernaut_omnislash_custom.prototype.StatusEffectPriority(self)
return 10
end
modifier_juggernaut_omnislash_custom = __TS__Decorate(
modifier_juggernaut_omnislash_custom,
modifier_juggernaut_omnislash_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_omnislash_custom"}
)
____exports.modifier_juggernaut_omnislash_custom = modifier_juggernaut_omnislash_custom
____exports.modifier_juggernaut_omnislash_attack = __TS__Class()
local modifier_juggernaut_omnislash_attack = ____exports.modifier_juggernaut_omnislash_attack
modifier_juggernaut_omnislash_attack.name = "modifier_juggernaut_omnislash_attack"
modifier_juggernaut_omnislash_attack.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_omnislash_custom.lua"
__TS__ClassExtends(modifier_juggernaut_omnislash_attack, BaseModifier)
function modifier_juggernaut_omnislash_attack.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.damagePercent = 0
end
function modifier_juggernaut_omnislash_attack.prototype.IsHidden(self)
return true
end
function modifier_juggernaut_omnislash_attack.prototype.OnCreated(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
self.damagePercent = ability:GetSpecialValueFor("damage") - 100
end
function modifier_juggernaut_omnislash_attack.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE}
end
function modifier_juggernaut_omnislash_attack.prototype.GetModifierDamageOutgoing_Percentage(self, event)
if event.inflictor then
return 0
end
return self.damagePercent
end
modifier_juggernaut_omnislash_attack = __TS__Decorate(
modifier_juggernaut_omnislash_attack,
modifier_juggernaut_omnislash_attack,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_omnislash_attack"}
)
____exports.modifier_juggernaut_omnislash_attack = modifier_juggernaut_omnislash_attack
return ____exports
@@ -0,0 +1,193 @@
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
____exports.ability_juggernaut_samurai_soul = __TS__Class()
local ability_juggernaut_samurai_soul = ____exports.ability_juggernaut_samurai_soul
ability_juggernaut_samurai_soul.name = "ability_juggernaut_samurai_soul"
ability_juggernaut_samurai_soul.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_samurai_soul.lua"
__TS__ClassExtends(ability_juggernaut_samurai_soul, BaseAbility)
function ability_juggernaut_samurai_soul.prototype.GetIntrinsicModifierName(self)
return "modifier_juggernaut_samurai_soul"
end
ability_juggernaut_samurai_soul = __TS__Decorate(
ability_juggernaut_samurai_soul,
ability_juggernaut_samurai_soul,
{registerAbility(nil)},
{kind = "class", name = "ability_juggernaut_samurai_soul"}
)
____exports.ability_juggernaut_samurai_soul = ability_juggernaut_samurai_soul
____exports.modifier_juggernaut_samurai_soul = __TS__Class()
local modifier_juggernaut_samurai_soul = ____exports.modifier_juggernaut_samurai_soul
modifier_juggernaut_samurai_soul.name = "modifier_juggernaut_samurai_soul"
modifier_juggernaut_samurai_soul.____file_path = "scripts/vscripts/abilities/heroes/juggernaut/ability_juggernaut_samurai_soul.lua"
__TS__ClassExtends(modifier_juggernaut_samurai_soul, BaseModifier)
function modifier_juggernaut_samurai_soul.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.lastAttackTime = 0
self.RESET_TIMEOUT = self:GetAbility():GetSpecialValueFor("cooldown")
self.maxRestoreCount = 2
end
function modifier_juggernaut_samurai_soul.prototype.IsHidden(self)
return false
end
function modifier_juggernaut_samurai_soul.prototype.IsPurgable(self)
return false
end
function modifier_juggernaut_samurai_soul.prototype.IsDebuff(self)
if self:GetStackCount() > 0 then
return true
end
return false
end
function modifier_juggernaut_samurai_soul.prototype.RemoveOnDeath(self)
return false
end
function modifier_juggernaut_samurai_soul.prototype.OnCreated(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
if ability then
local configuredLimit = ability:GetSpecialValueFor("max_restore_count")
if configuredLimit > 0 then
self.maxRestoreCount = configuredLimit
end
end
self:StartIntervalThink(0.1)
end
function modifier_juggernaut_samurai_soul.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local currentTime = GameRules:GetGameTime()
local timeSinceLastAttack = currentTime - self.lastAttackTime
if timeSinceLastAttack >= self.RESET_TIMEOUT and self:GetStackCount() > 0 then
local parent = self:GetParent()
if parent and parent:IsRealHero() then
local hero = parent
self:SetStackCount(0)
hero:CalculateStatBonus(true)
end
end
end
function modifier_juggernaut_samurai_soul.prototype.DeclareFunctions(self)
return {
MODIFIER_PROPERTY_MIN_HEALTH,
MODIFIER_PROPERTY_STATS_AGILITY_BONUS,
MODIFIER_PROPERTY_STATS_INTELLECT_BONUS,
MODIFIER_PROPERTY_STATS_STRENGTH_BONUS,
MODIFIER_EVENT_ON_DEATH
}
end
function modifier_juggernaut_samurai_soul.prototype.OnDeath(self, event)
if event.unit == self:GetParent() then
self:GetCaster():RemoveModifierByName("modifier_juggernaut_samurai_soul")
end
end
function modifier_juggernaut_samurai_soul.prototype.GetModifierBonusStats_Strength(self)
if not IsServer() then
return 0
end
local parent = self:GetParent()
if not parent then
return 0
end
if parent:PassivesDisabled() then
return 0
end
if not parent:IsRealHero() then
return 0
end
local hero = parent
local baseStr = hero:GetBaseStrength()
return -baseStr * (self:GetStackCount() * (0.01 * self:GetAbility():GetSpecialValueFor("debuff_pct")))
end
function modifier_juggernaut_samurai_soul.prototype.GetModifierBonusStats_Agility(self)
if not IsServer() then
return 0
end
local parent = self:GetParent()
if not parent then
return 0
end
if parent:PassivesDisabled() then
return 0
end
if not parent:IsRealHero() then
return 0
end
local hero = parent
local baseAgi = hero:GetBaseAgility()
return -baseAgi * (self:GetStackCount() * (0.01 * self:GetAbility():GetSpecialValueFor("debuff_pct")))
end
function modifier_juggernaut_samurai_soul.prototype.GetModifierBonusStats_Intellect(self)
if not IsServer() then
return 0
end
local parent = self:GetParent()
if not parent then
return 0
end
if parent:PassivesDisabled() then
return 0
end
if not parent:IsRealHero() then
return 0
end
local hero = parent
local baseInt = hero:GetBaseIntellect()
return -baseInt * (self:GetStackCount() * (0.01 * self:GetAbility():GetSpecialValueFor("debuff_pct")))
end
function modifier_juggernaut_samurai_soul.prototype.GetMinHealth(self)
if self:GetParent():PassivesDisabled() then
return 0
end
self:SetDuration(11, true)
self.lastAttackTime = GameRules:GetGameTime()
if self:GetStackCount() >= self.maxRestoreCount then
return 0
end
if self:GetCaster():GetHealth() < 10 then
self:GetCaster():SetHealth(self:GetCaster():GetMaxHealth())
self:IncrementStackCount()
self:GetCaster():CalculateStatBonus(true)
end
return 1
end
function modifier_juggernaut_samurai_soul.prototype.OnDestroy(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local ability = self:GetAbility()
if caster and not caster:IsNull() and caster:IsAlive() and ability and not ability:IsNull() then
caster:AddNewModifier(
self:GetParent(),
ability,
"modifier_juggernaut_samurai_soul",
{}
)
end
end
function modifier_juggernaut_samurai_soul.prototype.GetTexture(self)
if self:GetStackCount() > 0 then
return "new_heroes/juggernaut_death"
else
return "new_heroes/juggernaut_miracle"
end
end
modifier_juggernaut_samurai_soul = __TS__Decorate(
modifier_juggernaut_samurai_soul,
modifier_juggernaut_samurai_soul,
{registerModifier(nil)},
{kind = "class", name = "modifier_juggernaut_samurai_soul"}
)
____exports.modifier_juggernaut_samurai_soul = modifier_juggernaut_samurai_soul
return ____exports
@@ -0,0 +1,134 @@
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
____exports.keeper_of_the_light_blinding_light_custom = __TS__Class()
local keeper_of_the_light_blinding_light_custom = ____exports.keeper_of_the_light_blinding_light_custom
keeper_of_the_light_blinding_light_custom.name = "keeper_of_the_light_blinding_light_custom"
keeper_of_the_light_blinding_light_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_blinding_light_custom.lua"
__TS__ClassExtends(keeper_of_the_light_blinding_light_custom, BaseAbility)
function keeper_of_the_light_blinding_light_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function keeper_of_the_light_blinding_light_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/econ/items/keeper_of_the_light/kotl_ti10_immortal/kotl_ti10_blinding_light.vpcf", context)
end
function keeper_of_the_light_blinding_light_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local particle = ParticleManager:CreateParticle("particles/econ/items/keeper_of_the_light/kotl_ti10_immortal/kotl_ti10_blinding_light.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControl(particle, 1, point)
ParticleManager:ReleaseParticleIndex(particle)
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
point,
nil,
self:GetSpecialValueFor("radius"),
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
EmitSoundOnLocationWithCaster(point, "Hero_KeeperOfTheLight.BlindingLight", caster)
for ____, enemy in ipairs(enemies) do
do
ApplyDamage({
victim = enemy,
attacker = caster,
damage = self:GetSpecialValueFor("damage"),
damage_type = self:GetAbilityDamageType(),
ability = self
})
if not enemy:IsAlive() then
goto __continue6
end
if not enemy:IsBossCreature() then
enemy:AddNewModifier(
caster,
self,
"modifier_knockback",
{
center_x = point.x,
center_y = point.y,
center_z = point.z,
duration = self:GetSpecialValueFor("knockback_duration"),
knockback_duration = self:GetSpecialValueFor("knockback_duration"),
knockback_distance = self:GetSpecialValueFor("knockback_distance"),
knockback_height = 0
}
)
end
local debuff = enemy:AddNewModifier(
caster,
self,
____exports.modifier_keeper_of_the_light_blinding_light_custom.name,
{duration = self:GetSpecialValueFor("duration_stack")}
)
if not debuff then
goto __continue6
end
local stacks = enemy:IsBossCreature() and self:GetSpecialValueFor("miss_stack_boss") or self:GetSpecialValueFor("miss_stack")
debuff:SetStackCount(debuff:GetStackCount() + stacks)
end
::__continue6::
end
end
keeper_of_the_light_blinding_light_custom = __TS__Decorate(
keeper_of_the_light_blinding_light_custom,
keeper_of_the_light_blinding_light_custom,
{registerAbility(nil)},
{kind = "class", name = "keeper_of_the_light_blinding_light_custom"}
)
____exports.keeper_of_the_light_blinding_light_custom = keeper_of_the_light_blinding_light_custom
____exports.modifier_keeper_of_the_light_blinding_light_custom = __TS__Class()
local modifier_keeper_of_the_light_blinding_light_custom = ____exports.modifier_keeper_of_the_light_blinding_light_custom
modifier_keeper_of_the_light_blinding_light_custom.name = "modifier_keeper_of_the_light_blinding_light_custom"
modifier_keeper_of_the_light_blinding_light_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_blinding_light_custom.lua"
__TS__ClassExtends(modifier_keeper_of_the_light_blinding_light_custom, BaseModifier)
function modifier_keeper_of_the_light_blinding_light_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MISS_PERCENTAGE, MODIFIER_EVENT_ON_ATTACK_FAIL}
end
function modifier_keeper_of_the_light_blinding_light_custom.prototype.GetModifierMiss_Percentage(self)
return self:GetStackCount() > 0 and self:GetAbility():GetSpecialValueFor("miss_pct") or 0
end
function modifier_keeper_of_the_light_blinding_light_custom.prototype.OnAttackFail(self, event)
if not IsServer() then
return
end
if event.attacker ~= self:GetParent() then
return
end
if self:GetStackCount() > 0 then
self:DecrementStackCount()
end
if self:GetStackCount() <= 0 then
self:Destroy()
end
end
function modifier_keeper_of_the_light_blinding_light_custom.prototype.IsPurgable(self)
return true
end
function modifier_keeper_of_the_light_blinding_light_custom.prototype.IsPurgeException(self)
return true
end
function modifier_keeper_of_the_light_blinding_light_custom.prototype.GetEffectName(self)
return "particles/units/heroes/hero_keeper_of_the_light/keeper_of_the_light_blinding_light_debuff.vpcf"
end
modifier_keeper_of_the_light_blinding_light_custom = __TS__Decorate(
modifier_keeper_of_the_light_blinding_light_custom,
modifier_keeper_of_the_light_blinding_light_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_keeper_of_the_light_blinding_light_custom"}
)
____exports.modifier_keeper_of_the_light_blinding_light_custom = modifier_keeper_of_the_light_blinding_light_custom
return ____exports
@@ -0,0 +1,171 @@
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 ____incoming_damage_reduction_combine = require("utils.incoming_damage_reduction_combine")
local removeIncomingDamageReductionSource = ____incoming_damage_reduction_combine.removeIncomingDamageReductionSource
local setIncomingDamageReductionSource = ____incoming_damage_reduction_combine.setIncomingDamageReductionSource
local CHAKRA_MAGIC_INCOMING_SOURCE = "modifier_keeper_of_the_light_chakra_magic_buff"
____exports.keeper_of_the_light_chakra_magic_custom = __TS__Class()
local keeper_of_the_light_chakra_magic_custom = ____exports.keeper_of_the_light_chakra_magic_custom
keeper_of_the_light_chakra_magic_custom.name = "keeper_of_the_light_chakra_magic_custom"
keeper_of_the_light_chakra_magic_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_chakra_magic_custom.lua"
__TS__ClassExtends(keeper_of_the_light_chakra_magic_custom, BaseAbility)
function keeper_of_the_light_chakra_magic_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local target = self:GetCursorTarget()
if not target then
return
end
self:OnCustomSpellStart(target)
end
function keeper_of_the_light_chakra_magic_custom.prototype.OnCustomSpellStart(self, target)
if not IsServer() then
return
end
local caster = self:GetCaster()
target:GiveMana(self:GetSpecialValueFor("mana_restore"))
do
local i = 0
while i < target:GetAbilityCount() - 1 do
do
local ability = target:GetAbilityByIndex(i)
if not ability or ability:IsItem() or ability:GetName() == self:GetName() then
goto __continue7
end
local cooldownReduction = self:GetSpecialValueFor("cooldown_reduction")
local cooldownRemaining = ability:GetCooldownTimeRemaining()
if cooldownRemaining > 0 then
ability:EndCooldown()
ability:StartCooldown(math.max(cooldownRemaining - cooldownReduction, 0))
end
local maxCharges = ability:GetMaxAbilityCharges(ability:GetLevel())
if self:GetSpecialValueFor("refresh_charges") > 0 and maxCharges > 0 then
ability:SetCurrentAbilityCharges(math.min(
ability:GetCurrentAbilityCharges() + 1,
maxCharges
))
end
end
::__continue7::
i = i + 1
end
end
if self:GetSpecialValueFor("strong_dispel") > 0 then
target:Purge(
false,
true,
false,
true,
true
)
end
local buffDuration = self:GetSpecialValueFor("damage_reduction_duration")
if buffDuration > 0 then
____exports.modifier_keeper_of_the_light_chakra_magic_buff:apply(target, caster, self, {duration = buffDuration})
end
local chakraCast = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_chakra_magic.vpcf", PATTACH_POINT_FOLLOW, caster)
ParticleManager:SetParticleControlEnt(
chakraCast,
0,
caster,
PATTACH_POINT_FOLLOW,
"attach_attack1",
caster:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
chakraCast,
1,
target,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
target:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(chakraCast)
EmitSoundOn("Hero_KeeperOfTheLight.ChakraMagic.Target", target)
end
keeper_of_the_light_chakra_magic_custom = __TS__Decorate(
keeper_of_the_light_chakra_magic_custom,
keeper_of_the_light_chakra_magic_custom,
{registerAbility(nil)},
{kind = "class", name = "keeper_of_the_light_chakra_magic_custom"}
)
____exports.keeper_of_the_light_chakra_magic_custom = keeper_of_the_light_chakra_magic_custom
____exports.modifier_keeper_of_the_light_chakra_magic_buff = __TS__Class()
local modifier_keeper_of_the_light_chakra_magic_buff = ____exports.modifier_keeper_of_the_light_chakra_magic_buff
modifier_keeper_of_the_light_chakra_magic_buff.name = "modifier_keeper_of_the_light_chakra_magic_buff"
modifier_keeper_of_the_light_chakra_magic_buff.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_chakra_magic_custom.lua"
__TS__ClassExtends(modifier_keeper_of_the_light_chakra_magic_buff, BaseModifier)
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.damageReductionPct = 0
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.IsHidden(self)
return false
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.IsDebuff(self)
return false
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.IsPurgable(self)
return true
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.IsPurgeException(self)
return false
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.OnCreated(self)
local ability = self:GetAbility()
if not ability then
return
end
self.damageReductionPct = ability:GetSpecialValueFor("incoming_damage_reduction_pct")
self:SetStackCount(self.damageReductionPct)
if not IsServer() then
return
end
setIncomingDamageReductionSource(
nil,
self:GetParent(),
CHAKRA_MAGIC_INCOMING_SOURCE,
function() return math.max(0, self.damageReductionPct) end
)
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.OnRefresh(self)
self:OnCreated()
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.OnDestroy(self)
if not IsServer() then
return
end
removeIncomingDamageReductionSource(
nil,
self:GetParent(),
CHAKRA_MAGIC_INCOMING_SOURCE
)
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_keeper_of_the_light/keeper_dazzling.vpcf"
end
function modifier_keeper_of_the_light_chakra_magic_buff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_keeper_of_the_light_chakra_magic_buff = __TS__Decorate(
modifier_keeper_of_the_light_chakra_magic_buff,
modifier_keeper_of_the_light_chakra_magic_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_keeper_of_the_light_chakra_magic_buff"}
)
____exports.modifier_keeper_of_the_light_chakra_magic_buff = modifier_keeper_of_the_light_chakra_magic_buff
return ____exports
@@ -0,0 +1,116 @@
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 registerAbility = ____dota_ts_adapter.registerAbility
local ____heal_tracker = require("utils.heal_tracker")
local HealWithBattlePass = ____heal_tracker.HealWithBattlePass
____exports.keeper_of_the_light_illuminate_custom = __TS__Class()
local keeper_of_the_light_illuminate_custom = ____exports.keeper_of_the_light_illuminate_custom
keeper_of_the_light_illuminate_custom.name = "keeper_of_the_light_illuminate_custom"
keeper_of_the_light_illuminate_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_illuminate_custom.lua"
__TS__ClassExtends(keeper_of_the_light_illuminate_custom, BaseAbility)
function keeper_of_the_light_illuminate_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
caster:EmitSound("Hero_KeeperOfTheLight.Illuminate.Charge")
caster:SwapAbilities(
self:GetAbilityName(),
"keeper_of_the_light_illuminate_end",
false,
true
)
end
function keeper_of_the_light_illuminate_custom.prototype.OnChannelFinish(self, _interrupted)
local caster = self:GetCaster()
local casterPoint = caster:GetOrigin()
local distance = self:GetCastRange(casterPoint, nil)
local speed = self:GetSpecialValueFor("speed")
local radius = self:GetSpecialValueFor("radius")
local multiple = (GameRules:GetGameTime() - self:GetChannelStartTime()) / self:GetChannelTime()
caster:EmitSound("Hero_KeeperOfTheLight.Illuminate.Discharge")
local direction = self:GetCursorPosition() - casterPoint
direction.z = 0
direction = direction:Normalized() * distance
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/kotl_illuminate.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:SetParticleControl(
particle,
1,
direction:Normalized() * speed
)
ParticleManager:SetParticleControl(particle, 3, casterPoint)
ProjectileManager:CreateLinearProjectile({
Ability = self,
vSpawnOrigin = casterPoint,
vVelocity = direction:Normalized() * speed,
fDistance = distance,
fStartRadius = radius,
fEndRadius = radius,
Source = caster,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_BOTH,
iUnitTargetFlags = DOTA_UNIT_TARGET_FLAG_NONE,
iUnitTargetType = bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
bProvidesVision = true,
iVisionRadius = self:GetSpecialValueFor("vision_radius"),
iVisionTeamNumber = caster:GetTeamNumber(),
ExtraData = {particleId = particle, multiple = multiple}
})
caster:SwapAbilities(
self:GetAbilityName(),
"keeper_of_the_light_illuminate_end",
true,
false
)
caster:EmitSound("keeper_of_the_light_keep_illuminate_05")
end
function keeper_of_the_light_illuminate_custom.prototype.OnProjectileHit_ExtraData(self, target, _location, extraData)
if not target then
ParticleManager:DestroyParticle(extraData.particleId, false)
return
end
local caster = self:GetCaster()
local minDamage = self:GetSpecialValueFor("min_damage")
local scaledDamage = (self:GetSpecialValueFor("max_damage") - minDamage) * extraData.multiple
local totalValue = scaledDamage + minDamage
target:EmitSound("Hero_KeeperOfTheLight.Illuminate.Target")
local impactFx = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_of_the_light_illuminate_impact.vpcf", PATTACH_CUSTOMORIGIN, target)
ParticleManager:SetParticleControlEnt(
impactFx,
0,
target,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
target:GetOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(impactFx)
if target:GetTeamNumber() == caster:GetTeamNumber() then
local healPct = self:GetSpecialValueFor("heal_percent")
local heal = totalValue * (caster:GetSpellAmplification(false) + 1) * healPct / 100
HealWithBattlePass(
nil,
target,
heal,
self,
caster
)
return
end
ApplyDamage({
victim = target,
attacker = caster,
damage = totalValue + self:GetCaster():GetMaxMana() * 0.5,
damage_type = self:GetAbilityDamageType(),
ability = self
})
end
keeper_of_the_light_illuminate_custom = __TS__Decorate(
keeper_of_the_light_illuminate_custom,
keeper_of_the_light_illuminate_custom,
{registerAbility(nil)},
{kind = "class", name = "keeper_of_the_light_illuminate_custom"}
)
____exports.keeper_of_the_light_illuminate_custom = keeper_of_the_light_illuminate_custom
return ____exports
@@ -0,0 +1,170 @@
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
____exports.keeper_of_the_light_radiant_bind_custom = __TS__Class()
local keeper_of_the_light_radiant_bind_custom = ____exports.keeper_of_the_light_radiant_bind_custom
keeper_of_the_light_radiant_bind_custom.name = "keeper_of_the_light_radiant_bind_custom"
keeper_of_the_light_radiant_bind_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_radiant_bind_custom.lua"
__TS__ClassExtends(keeper_of_the_light_radiant_bind_custom, BaseAbility)
function keeper_of_the_light_radiant_bind_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local target = self:GetCursorTarget()
local caster = self:GetCaster()
if not target then
return
end
EmitSoundOn("Hero_KeeperOfTheLight.ManaLeak.Cast", caster)
local particle = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_radiant_bind_cast.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControlEnt(
particle,
0,
caster,
PATTACH_POINT_FOLLOW,
"attach_attack1",
caster:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControl(
particle,
1,
target:GetAbsOrigin()
)
ParticleManager:ReleaseParticleIndex(particle)
____exports.modifier_keeper_of_the_light_radiant_bind_custom:apply(
target,
caster,
self,
{duration = self:GetSpecialValueFor("duration")}
)
end
keeper_of_the_light_radiant_bind_custom = __TS__Decorate(
keeper_of_the_light_radiant_bind_custom,
keeper_of_the_light_radiant_bind_custom,
{registerAbility(nil)},
{kind = "class", name = "keeper_of_the_light_radiant_bind_custom"}
)
____exports.keeper_of_the_light_radiant_bind_custom = keeper_of_the_light_radiant_bind_custom
____exports.modifier_keeper_of_the_light_radiant_bind_custom = __TS__Class()
local modifier_keeper_of_the_light_radiant_bind_custom = ____exports.modifier_keeper_of_the_light_radiant_bind_custom
modifier_keeper_of_the_light_radiant_bind_custom.name = "modifier_keeper_of_the_light_radiant_bind_custom"
modifier_keeper_of_the_light_radiant_bind_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_radiant_bind_custom.lua"
__TS__ClassExtends(modifier_keeper_of_the_light_radiant_bind_custom, BaseModifier)
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.totalDistanceMoved = 0
self.movespeedPct = 0
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_MOVESPEED_ABSOLUTE_MAX, MODIFIER_PROPERTY_IGNORE_MOVESPEED_LIMIT, MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS}
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.IsDebuff(self)
local caster = self:GetCaster()
local parent = self:GetParent()
if not caster then
return true
end
return caster:GetTeamNumber() ~= parent:GetTeamNumber()
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.IsPurgable(self)
return true
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.IsPurgeException(self)
return true
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
local parent = self:GetParent()
self.particle = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_of_the_light_radiant_bind_debuff.vpcf", PATTACH_CUSTOMORIGIN_FOLLOW, parent)
self:AddParticle(
self.particle,
false,
false,
0,
false,
false
)
self.lastPosition = parent:GetAbsOrigin()
self:StartIntervalThink(0.1)
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
local parent = self:GetParent()
if not ability then
return
end
local distanceForSlow = ability:GetSpecialValueFor("distance_for_slow")
local slowPctPerDistance = ability:GetSpecialValueFor("slow_pct_per_distance")
local newPos = parent:GetAbsOrigin()
if self.lastPosition then
self.totalDistanceMoved = self.totalDistanceMoved + (newPos - self.lastPosition):Length2D()
end
self.lastPosition = newPos
local slowStacks = math.floor(self.totalDistanceMoved / distanceForSlow)
if slowStacks < 1 then
self.movespeedPct = 0
return
end
if self.particle then
ParticleManager:SetParticleControl(
self.particle,
0,
parent:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
self.particle,
1,
Vector(
math.max(
math.floor(slowStacks / 1.5),
1
),
0,
0
)
)
end
self.movespeedPct = slowStacks * slowPctPerDistance
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self:IsDebuff() and -self.movespeedPct or self.movespeedPct
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.GetModifierIgnoreMovespeedLimit(self)
return 1
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.GetModifierMoveSpeed_AbsoluteMax(self)
local ability = self:GetAbility()
if not ability or self:IsDebuff() then
return 0
end
return ability:GetSpecialValueFor("movespeed_limit")
end
function modifier_keeper_of_the_light_radiant_bind_custom.prototype.GetModifierMagicalResistanceBonus(self)
local ability = self:GetAbility()
if not ability then
return 0
end
local value = ability:GetSpecialValueFor("magres_pct")
return self:IsDebuff() and -value or value
end
modifier_keeper_of_the_light_radiant_bind_custom = __TS__Decorate(
modifier_keeper_of_the_light_radiant_bind_custom,
modifier_keeper_of_the_light_radiant_bind_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_keeper_of_the_light_radiant_bind_custom"}
)
____exports.modifier_keeper_of_the_light_radiant_bind_custom = modifier_keeper_of_the_light_radiant_bind_custom
return ____exports
@@ -0,0 +1,185 @@
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
____exports.keeper_of_the_light_recall_custom = __TS__Class()
local keeper_of_the_light_recall_custom = ____exports.keeper_of_the_light_recall_custom
keeper_of_the_light_recall_custom.name = "keeper_of_the_light_recall_custom"
keeper_of_the_light_recall_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_recall_custom.lua"
__TS__ClassExtends(keeper_of_the_light_recall_custom, BaseAbility)
function keeper_of_the_light_recall_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local cursorTarget = self:GetCursorTarget()
if not cursorTarget then
return
end
EmitSoundOn("Hero_KeeperOfTheLight.Recall.Cast", caster)
local recallCast = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_of_the_light_recall_cast.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControlEnt(
recallCast,
0,
caster,
PATTACH_POINT_FOLLOW,
"attach_origin",
caster:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
recallCast,
1,
caster,
PATTACH_POINT_FOLLOW,
"attach_origin",
caster:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(recallCast)
local duration = self:GetSpecialValueFor("teleport_delay")
if self:GetAutoCastState() then
EmitSoundOn("Hero_KeeperOfTheLight.Recall.Target", caster)
caster:AddNewModifier(
caster,
self,
____exports.modifier_keeper_of_the_light_recall_custom.name,
{
duration = duration,
target = cursorTarget:GetEntityIndex()
}
)
return
end
EmitSoundOn("Hero_KeeperOfTheLight.Recall.Target", cursorTarget)
cursorTarget:AddNewModifier(
caster,
self,
____exports.modifier_keeper_of_the_light_recall_custom.name,
{
duration = duration,
target = caster:GetEntityIndex()
}
)
end
function keeper_of_the_light_recall_custom.prototype.CastFilterResultTarget(self, target)
if self:GetCaster() == target then
return UF_FAIL_OTHER
end
return UnitFilter(
target,
DOTA_UNIT_TARGET_TEAM_FRIENDLY,
DOTA_UNIT_TARGET_HERO,
DOTA_UNIT_TARGET_FLAG_NOT_CREEP_HERO,
self:GetCaster():GetTeamNumber()
)
end
keeper_of_the_light_recall_custom = __TS__Decorate(
keeper_of_the_light_recall_custom,
keeper_of_the_light_recall_custom,
{registerAbility(nil)},
{kind = "class", name = "keeper_of_the_light_recall_custom"}
)
____exports.keeper_of_the_light_recall_custom = keeper_of_the_light_recall_custom
____exports.modifier_keeper_of_the_light_recall_custom = __TS__Class()
local modifier_keeper_of_the_light_recall_custom = ____exports.modifier_keeper_of_the_light_recall_custom
modifier_keeper_of_the_light_recall_custom.name = "modifier_keeper_of_the_light_recall_custom"
modifier_keeper_of_the_light_recall_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_recall_custom.lua"
__TS__ClassExtends(modifier_keeper_of_the_light_recall_custom, BaseModifier)
function modifier_keeper_of_the_light_recall_custom.prototype.OnCreated(self, params)
if not IsServer() then
return
end
self.target = EntIndexToHScript(params.target)
local parent = self:GetParent()
local caster = self:GetCaster()
local ability = self:GetAbility()
if not ability then
return
end
parent:AddNewModifier(
caster,
ability,
____exports.modifier_keeper_of_the_light_recall_custom_speed.name,
{duration = ability:GetSpecialValueFor("movespeed_bonus_duration")}
)
end
function modifier_keeper_of_the_light_recall_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
if not self.target or self.target:IsNull() then
return
end
local ability = self:GetAbility()
local parent = self:GetParent()
local caster = self:GetCaster()
if not ability or not caster then
return
end
StopSoundOn("Hero_KeeperOfTheLight.Recall.Target", parent)
EmitSoundOn("Hero_KeeperOfTheLight.Recall.End", parent)
local poof = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_of_the_light_recall_poof.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:ReleaseParticleIndex(poof)
FindClearSpaceForUnit(
parent,
self.target:GetAbsOrigin(),
false
)
local speedDuration = ability:GetSpecialValueFor("movespeed_bonus_duration")
parent:AddNewModifier(caster, ability, ____exports.modifier_keeper_of_the_light_recall_custom_speed.name, {duration = speedDuration})
self.target:AddNewModifier(caster, ability, ____exports.modifier_keeper_of_the_light_recall_custom_speed.name, {duration = speedDuration})
local chakraAbility = caster:FindAbilityByName("keeper_of_the_light_chakra_magic_custom")
if chakraAbility and chakraAbility:GetLevel() > 0 then
chakraAbility:OnCustomSpellStart(parent)
end
end
function modifier_keeper_of_the_light_recall_custom.prototype.IsPurgable(self)
return false
end
function modifier_keeper_of_the_light_recall_custom.prototype.GetEffectName(self)
return "particles/units/heroes/hero_keeper_of_the_light/keeper_of_the_light_recall.vpcf"
end
function modifier_keeper_of_the_light_recall_custom.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
modifier_keeper_of_the_light_recall_custom = __TS__Decorate(
modifier_keeper_of_the_light_recall_custom,
modifier_keeper_of_the_light_recall_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_keeper_of_the_light_recall_custom"}
)
____exports.modifier_keeper_of_the_light_recall_custom = modifier_keeper_of_the_light_recall_custom
____exports.modifier_keeper_of_the_light_recall_custom_speed = __TS__Class()
local modifier_keeper_of_the_light_recall_custom_speed = ____exports.modifier_keeper_of_the_light_recall_custom_speed
modifier_keeper_of_the_light_recall_custom_speed.name = "modifier_keeper_of_the_light_recall_custom_speed"
modifier_keeper_of_the_light_recall_custom_speed.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_recall_custom.lua"
__TS__ClassExtends(modifier_keeper_of_the_light_recall_custom_speed, BaseModifier)
function modifier_keeper_of_the_light_recall_custom_speed.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.allyMoveSpeed = 0
end
function modifier_keeper_of_the_light_recall_custom_speed.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_keeper_of_the_light_recall_custom_speed.prototype.OnCreated(self)
local ____opt_0 = self:GetAbility()
self.allyMoveSpeed = ____opt_0 and ____opt_0:GetSpecialValueFor("ally_movespeed_pct") or 0
end
function modifier_keeper_of_the_light_recall_custom_speed.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return self.allyMoveSpeed
end
modifier_keeper_of_the_light_recall_custom_speed = __TS__Decorate(
modifier_keeper_of_the_light_recall_custom_speed,
modifier_keeper_of_the_light_recall_custom_speed,
{registerModifier(nil)},
{kind = "class", name = "modifier_keeper_of_the_light_recall_custom_speed"}
)
____exports.modifier_keeper_of_the_light_recall_custom_speed = modifier_keeper_of_the_light_recall_custom_speed
return ____exports
@@ -0,0 +1,205 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__NumberToFixed = ____lualib.__TS__NumberToFixed
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
____exports.keeper_of_the_light_will_o_wisp_custom = __TS__Class()
local keeper_of_the_light_will_o_wisp_custom = ____exports.keeper_of_the_light_will_o_wisp_custom
keeper_of_the_light_will_o_wisp_custom.name = "keeper_of_the_light_will_o_wisp_custom"
keeper_of_the_light_will_o_wisp_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_will_o_wisp_custom.lua"
__TS__ClassExtends(keeper_of_the_light_will_o_wisp_custom, BaseAbility)
function keeper_of_the_light_will_o_wisp_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function keeper_of_the_light_will_o_wisp_custom.prototype.Precache(self, context)
PrecacheResource("model", "models/heroes/keeper_of_the_light/kotl_wisp.vmdl", context)
end
function keeper_of_the_light_will_o_wisp_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local unit = CreateUnitByName(
"npc_kotl_wisp",
point,
true,
caster,
caster,
caster:GetTeamNumber()
)
____exports.modifier_keeper_of_the_light_will_o_wisp_custom:apply(unit, caster, self, {})
end
keeper_of_the_light_will_o_wisp_custom = __TS__Decorate(
keeper_of_the_light_will_o_wisp_custom,
keeper_of_the_light_will_o_wisp_custom,
{registerAbility(nil)},
{kind = "class", name = "keeper_of_the_light_will_o_wisp_custom"}
)
____exports.keeper_of_the_light_will_o_wisp_custom = keeper_of_the_light_will_o_wisp_custom
____exports.modifier_keeper_of_the_light_will_o_wisp_custom = __TS__Class()
local modifier_keeper_of_the_light_will_o_wisp_custom = ____exports.modifier_keeper_of_the_light_will_o_wisp_custom
modifier_keeper_of_the_light_will_o_wisp_custom.name = "modifier_keeper_of_the_light_will_o_wisp_custom"
modifier_keeper_of_the_light_will_o_wisp_custom.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_will_o_wisp_custom.lua"
__TS__ClassExtends(modifier_keeper_of_the_light_will_o_wisp_custom, BaseModifier)
function modifier_keeper_of_the_light_will_o_wisp_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.radius = 0
self.delay = 0
self.activeDuration = 0
self.activeTick = 0
self.activeChannel = 0
self.damage = 0
self.hitCount = 0
end
function modifier_keeper_of_the_light_will_o_wisp_custom.prototype.CheckState(self)
return {[MODIFIER_STATE_INVULNERABLE] = true, [MODIFIER_STATE_NO_HEALTH_BAR] = true, [MODIFIER_STATE_UNSELECTABLE] = true}
end
function modifier_keeper_of_the_light_will_o_wisp_custom.prototype.GetEffectName(self)
return "particles/units/heroes/hero_keeper_of_the_light/keeper_dazzling.vpcf"
end
function modifier_keeper_of_the_light_will_o_wisp_custom.prototype.OnCreated(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
self.radius = ability:GetSpecialValueFor("radius")
self.delay = ability:GetSpecialValueFor("delay")
self.activeDuration = tonumber(__TS__NumberToFixed(
ability:GetSpecialValueFor("active_duration"),
1
)) or 0
self.activeTick = ability:GetSpecialValueFor("active_tick")
self.damage = ability:GetSpecialValueFor("damage")
self.particleAura = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_dazzling_aoe_ring.vpcf", PATTACH_CUSTOMORIGIN, parent)
ParticleManager:SetParticleControl(
self.particleAura,
0,
parent:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
self.particleAura,
1,
Vector(self.radius, self.radius, self.radius)
)
EmitSoundOn("Hero_KeeperOfTheLight.Wisp.Spawn", parent)
self:StartIntervalThink(self.delay)
end
function modifier_keeper_of_the_light_will_o_wisp_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
if self.particleAura ~= nil then
ParticleManager:DestroyParticle(self.particleAura, false)
ParticleManager:ReleaseParticleIndex(self.particleAura)
self.particleAura = nil
end
if self.particleActive ~= nil then
ParticleManager:DestroyParticle(self.particleActive, false)
ParticleManager:ReleaseParticleIndex(self.particleActive)
self.particleActive = nil
end
end
function modifier_keeper_of_the_light_will_o_wisp_custom.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability then
return
end
if self.activeChannel == 0 then
EmitSoundOn("Hero_KeeperOfTheLight.Wisp.Active", parent)
end
self:StartIntervalThink(self.activeTick)
self.activeChannel = self.activeChannel + self.activeTick
if not self.particleActive then
self.particleActive = ParticleManager:CreateParticle("particles/units/heroes/hero_keeper_of_the_light/keeper_dazzling_on.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
end
local enemies = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetOrigin(),
nil,
self.radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
local manaDamagePerSecond = self:GetCaster():GetMana() * 0.25
ApplyDamage({
victim = enemy,
attacker = parent,
damage = (self.damage + manaDamagePerSecond) * self.activeTick,
damage_type = ability:GetAbilityDamageType(),
ability = ability
})
____exports.modifier_keeper_will_o_wisp_debuff:apply(
enemy,
self:GetCaster(),
ability,
{duration = self.activeTick + 0.1}
)
end
if self.activeChannel < self.activeDuration then
return
end
self:StartIntervalThink(self.delay)
if self.particleActive ~= nil then
ParticleManager:DestroyParticle(self.particleActive, false)
ParticleManager:ReleaseParticleIndex(self.particleActive)
self.particleActive = nil
end
self.activeChannel = 0
self.hitCount = self.hitCount + 1
if ability:GetSpecialValueFor("hit_count") <= self.hitCount then
parent:ForceKill(true)
EmitSoundOn("Hero_KeeperOfTheLight.Wisp.Destroy", parent)
end
end
modifier_keeper_of_the_light_will_o_wisp_custom = __TS__Decorate(
modifier_keeper_of_the_light_will_o_wisp_custom,
modifier_keeper_of_the_light_will_o_wisp_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_keeper_of_the_light_will_o_wisp_custom"}
)
____exports.modifier_keeper_of_the_light_will_o_wisp_custom = modifier_keeper_of_the_light_will_o_wisp_custom
____exports.modifier_keeper_will_o_wisp_debuff = __TS__Class()
local modifier_keeper_will_o_wisp_debuff = ____exports.modifier_keeper_will_o_wisp_debuff
modifier_keeper_will_o_wisp_debuff.name = "modifier_keeper_will_o_wisp_debuff"
modifier_keeper_will_o_wisp_debuff.____file_path = "scripts/vscripts/abilities/heroes/keeper_of_the_light/keeper_of_the_light_will_o_wisp_custom.lua"
__TS__ClassExtends(modifier_keeper_will_o_wisp_debuff, BaseModifier)
function modifier_keeper_will_o_wisp_debuff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_keeper_will_o_wisp_debuff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
local ____opt_0 = self:GetAbility()
return ____opt_0 and ____opt_0:GetSpecialValueFor("slow_movespeed") or 0
end
function modifier_keeper_will_o_wisp_debuff.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_keeper_dazzle.vpcf"
end
function modifier_keeper_will_o_wisp_debuff.prototype.StatusEffectPriority(self)
return MODIFIER_PRIORITY_HIGH
end
modifier_keeper_will_o_wisp_debuff = __TS__Decorate(
modifier_keeper_will_o_wisp_debuff,
modifier_keeper_will_o_wisp_debuff,
{registerModifier(nil)},
{kind = "class", name = "modifier_keeper_will_o_wisp_debuff"}
)
____exports.modifier_keeper_will_o_wisp_debuff = modifier_keeper_will_o_wisp_debuff
return ____exports
@@ -0,0 +1,601 @@
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 DUEL_DEBUG_ENABLED = true
local DUEL_DEBUG_PREFIX = "[LC_DUEL_DEBUG]"
local function duelDebug(self, message)
if not DUEL_DEBUG_ENABLED then
return
end
print((DUEL_DEBUG_PREFIX .. " ") .. message)
end
local function removeDuelModifiersFrom(self, unit)
duelDebug(
nil,
(("removeDuelModifiersFrom unit=" .. unit:GetUnitName()) .. "#") .. tostring(unit:entindex())
)
while unit:HasModifier(____exports.modifier_legion_commander_duel_custom.name) do
unit:RemoveModifierByName(____exports.modifier_legion_commander_duel_custom.name)
end
local ____this_1
____this_1 = unit
local ____opt_0 = ____this_1.SetForceAttackTarget
if ____opt_0 ~= nil then
____opt_0(____this_1, nil)
end
end
local DUEL_RESOLUTION_LOCK_DURATION = 0.3
____exports.ability_legion_commander_duel_custom = __TS__Class()
local ability_legion_commander_duel_custom = ____exports.ability_legion_commander_duel_custom
ability_legion_commander_duel_custom.name = "ability_legion_commander_duel_custom"
ability_legion_commander_duel_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_duel_custom.lua"
__TS__ClassExtends(ability_legion_commander_duel_custom, BaseAbility)
function ability_legion_commander_duel_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_duel_victory.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_press_a.vpcf", context)
PrecacheResource("particle", "particles/status_fx/status_effect_legion_commander_duel.vpcf", context)
PrecacheResource("particle", "particles/econ/items/legion/legion_weapon_voth_domosh/legion_duel_ring_arcana.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_legion_commander.vsndevts", context)
end
function ability_legion_commander_duel_custom.prototype.GetCastAnimation(self)
return ACT_DOTA_CAST_ABILITY_4
end
function ability_legion_commander_duel_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local target = self:GetCursorTarget()
duelDebug(
nil,
(((((("OnSpellStart caster=" .. (caster and caster:GetUnitName())) .. "#") .. tostring(caster and caster:entindex())) .. " target=") .. tostring(target and target:GetUnitName())) .. "#") .. tostring(target and target:entindex())
)
if not caster or not caster:IsAlive() or not target or not target:IsAlive() or target:IsCourier() then
return
end
if target:GetTeamNumber() == caster:GetTeamNumber() then
return
end
if target:TriggerSpellAbsorb(self) then
return
end
self:startDuel(caster, target)
end
function ability_legion_commander_duel_custom.prototype.startDuel(self, caster, target)
local duration = self:GetSpecialValueFor("duration")
if caster:IsIllusion() then
duration = 1.5
end
local durTarget = duration * (1 - target:GetStatusResistance())
duelDebug(
nil,
(((((("startDuel caster=" .. tostring(caster:entindex())) .. " target=") .. tostring(target:entindex())) .. " duration=") .. tostring(duration)) .. " durTarget=") .. tostring(durTarget)
)
EmitSoundOn("Hero_LegionCommander.Duel.Cast", caster)
caster:AddNewModifier(
caster,
self,
____exports.modifier_legion_commander_duel_custom.name,
{
duration = duration,
counterpart_entindex = target:entindex()
}
)
target:AddNewModifier(
caster,
self,
____exports.modifier_legion_commander_duel_custom.name,
{
duration = durTarget,
counterpart_entindex = caster:entindex()
}
)
ParticleManager:ReleaseParticleIndex(ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_press_a.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster))
ParticleManager:ReleaseParticleIndex(ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_press_a.vpcf", PATTACH_ABSORIGIN_FOLLOW, target))
EmitSoundOn("Hero_LegionCommander.Duel", caster)
ExecuteOrderFromTable({
UnitIndex = caster:entindex(),
OrderType = DOTA_UNIT_ORDER_ATTACK_TARGET,
TargetIndex = target:entindex(),
Queue = false
})
ExecuteOrderFromTable({
UnitIndex = target:entindex(),
OrderType = DOTA_UNIT_ORDER_ATTACK_TARGET,
TargetIndex = caster:entindex(),
Queue = false
})
end
function ability_legion_commander_duel_custom.prototype.completeDuelWithWinner(self, winner, loser)
if not IsServer() then
return
end
duelDebug(
nil,
(("completeDuelWithWinner winner=" .. tostring(winner:entindex())) .. " loser=") .. tostring(loser:entindex())
)
local hasResolutionLock = winner:HasModifier(____exports.modifier_legion_commander_duel_resolution_lock_custom.name)
removeDuelModifiersFrom(nil, winner)
removeDuelModifiersFrom(nil, loser)
if hasResolutionLock then
return
end
winner:AddNewModifier(winner, self, ____exports.modifier_legion_commander_duel_resolution_lock_custom.name, {duration = DUEL_RESOLUTION_LOCK_DURATION})
self:grantDuelVictoryStacks(winner, loser)
end
function ability_legion_commander_duel_custom.prototype.grantDuelVictoryStacks(self, winner, loser)
duelDebug(
nil,
(("grantDuelVictoryStacks winner=" .. tostring(winner and winner:entindex())) .. " loser=") .. tostring(loser and loser:entindex())
)
if not winner or not winner:IsAlive() then
return
end
if not loser or loser:IsIllusion() then
return
end
if loser:IsHero() and loser:IsTempestDouble() then
return
end
local isCreepLike = loser:IsCreep() and not loser:IsHero()
local add = math.floor(isCreepLike and self:GetSpecialValueFor("reward_damage_creep") or self:GetSpecialValueFor("reward_damage"))
if add <= 0 then
return
end
local cap = self:GetSpecialValueFor("max_stack_damage")
local stackMod = winner:FindModifierByName(____exports.modifier_legion_commander_duel_damage_stack_custom.name)
if not stackMod then
winner:AddNewModifier(winner, self, ____exports.modifier_legion_commander_duel_damage_stack_custom.name, {})
stackMod = winner:FindModifierByName(____exports.modifier_legion_commander_duel_damage_stack_custom.name)
end
if stackMod then
local next = stackMod:GetStackCount() + add
stackMod:SetStackCount(cap > 0 and math.min(cap, next) or next)
end
local randomStatPerWin = math.max(
0,
math.floor(self:GetSpecialValueFor("reward_random_stat"))
)
if randomStatPerWin > 0 and winner:IsRealHero() then
self:grantRandomStat(winner, randomStatPerWin)
end
local pWin = ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_duel_victory.vpcf", PATTACH_OVERHEAD_FOLLOW, winner)
ParticleManager:ReleaseParticleIndex(pWin)
EmitSoundOn("Hero_LegionCommander.Duel.Victory", winner)
end
function ability_legion_commander_duel_custom.prototype.grantRandomStat(self, winner, amount)
local roll = RandomInt(1, 3)
local modName = ____exports.modifier_legion_commander_duel_random_stat_str_custom.name
if roll == 2 then
modName = ____exports.modifier_legion_commander_duel_random_stat_agi_custom.name
end
if roll == 3 then
modName = ____exports.modifier_legion_commander_duel_random_stat_int_custom.name
end
local mod = winner:FindModifierByName(modName)
if not mod then
winner:AddNewModifier(winner, self, modName, {})
mod = winner:FindModifierByName(modName)
end
if mod then
mod:SetStackCount(mod:GetStackCount() + amount)
end
end
function ability_legion_commander_duel_custom.prototype.terminateDuelNoReward(self, attackerSide, defenderSide)
if not IsServer() then
return
end
removeDuelModifiersFrom(nil, attackerSide)
removeDuelModifiersFrom(nil, defenderSide)
end
ability_legion_commander_duel_custom = __TS__Decorate(
ability_legion_commander_duel_custom,
ability_legion_commander_duel_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_legion_commander_duel_custom"}
)
____exports.ability_legion_commander_duel_custom = ability_legion_commander_duel_custom
____exports.modifier_legion_commander_duel_damage_stack_custom = __TS__Class()
local modifier_legion_commander_duel_damage_stack_custom = ____exports.modifier_legion_commander_duel_damage_stack_custom
modifier_legion_commander_duel_damage_stack_custom.name = "modifier_legion_commander_duel_damage_stack_custom"
modifier_legion_commander_duel_damage_stack_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_duel_custom.lua"
__TS__ClassExtends(modifier_legion_commander_duel_damage_stack_custom, BaseModifier)
function modifier_legion_commander_duel_damage_stack_custom.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_duel_damage_stack_custom.prototype.IsPurgable(self)
return false
end
function modifier_legion_commander_duel_damage_stack_custom.prototype.IsDebuff(self)
return false
end
function modifier_legion_commander_duel_damage_stack_custom.prototype.RemoveOnDeath(self)
return false
end
function modifier_legion_commander_duel_damage_stack_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE}
end
function modifier_legion_commander_duel_damage_stack_custom.prototype.GetModifierPreAttack_BonusDamage(self)
return self:GetStackCount()
end
function modifier_legion_commander_duel_damage_stack_custom.prototype.GetTexture(self)
return "legion_commander_duel"
end
modifier_legion_commander_duel_damage_stack_custom = __TS__Decorate(
modifier_legion_commander_duel_damage_stack_custom,
modifier_legion_commander_duel_damage_stack_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_duel_damage_stack_custom"}
)
____exports.modifier_legion_commander_duel_damage_stack_custom = modifier_legion_commander_duel_damage_stack_custom
____exports.modifier_legion_commander_duel_resolution_lock_custom = __TS__Class()
local modifier_legion_commander_duel_resolution_lock_custom = ____exports.modifier_legion_commander_duel_resolution_lock_custom
modifier_legion_commander_duel_resolution_lock_custom.name = "modifier_legion_commander_duel_resolution_lock_custom"
modifier_legion_commander_duel_resolution_lock_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_duel_custom.lua"
__TS__ClassExtends(modifier_legion_commander_duel_resolution_lock_custom, BaseModifier)
function modifier_legion_commander_duel_resolution_lock_custom.prototype.IsHidden(self)
return true
end
function modifier_legion_commander_duel_resolution_lock_custom.prototype.IsPurgable(self)
return false
end
modifier_legion_commander_duel_resolution_lock_custom = __TS__Decorate(
modifier_legion_commander_duel_resolution_lock_custom,
modifier_legion_commander_duel_resolution_lock_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_duel_resolution_lock_custom"}
)
____exports.modifier_legion_commander_duel_resolution_lock_custom = modifier_legion_commander_duel_resolution_lock_custom
____exports.modifier_legion_commander_duel_random_stat_str_custom = __TS__Class()
local modifier_legion_commander_duel_random_stat_str_custom = ____exports.modifier_legion_commander_duel_random_stat_str_custom
modifier_legion_commander_duel_random_stat_str_custom.name = "modifier_legion_commander_duel_random_stat_str_custom"
modifier_legion_commander_duel_random_stat_str_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_duel_custom.lua"
__TS__ClassExtends(modifier_legion_commander_duel_random_stat_str_custom, BaseModifier)
function modifier_legion_commander_duel_random_stat_str_custom.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_duel_random_stat_str_custom.prototype.IsPurgable(self)
return false
end
function modifier_legion_commander_duel_random_stat_str_custom.prototype.RemoveOnDeath(self)
return false
end
function modifier_legion_commander_duel_random_stat_str_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_STATS_STRENGTH_BONUS}
end
function modifier_legion_commander_duel_random_stat_str_custom.prototype.GetModifierBonusStats_Strength(self)
return self:GetStackCount()
end
function modifier_legion_commander_duel_random_stat_str_custom.prototype.GetTexture(self)
return "legion_commander_duel"
end
modifier_legion_commander_duel_random_stat_str_custom = __TS__Decorate(
modifier_legion_commander_duel_random_stat_str_custom,
modifier_legion_commander_duel_random_stat_str_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_duel_random_stat_str_custom"}
)
____exports.modifier_legion_commander_duel_random_stat_str_custom = modifier_legion_commander_duel_random_stat_str_custom
____exports.modifier_legion_commander_duel_random_stat_agi_custom = __TS__Class()
local modifier_legion_commander_duel_random_stat_agi_custom = ____exports.modifier_legion_commander_duel_random_stat_agi_custom
modifier_legion_commander_duel_random_stat_agi_custom.name = "modifier_legion_commander_duel_random_stat_agi_custom"
modifier_legion_commander_duel_random_stat_agi_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_duel_custom.lua"
__TS__ClassExtends(modifier_legion_commander_duel_random_stat_agi_custom, BaseModifier)
function modifier_legion_commander_duel_random_stat_agi_custom.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_duel_random_stat_agi_custom.prototype.IsPurgable(self)
return false
end
function modifier_legion_commander_duel_random_stat_agi_custom.prototype.RemoveOnDeath(self)
return false
end
function modifier_legion_commander_duel_random_stat_agi_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_STATS_AGILITY_BONUS}
end
function modifier_legion_commander_duel_random_stat_agi_custom.prototype.GetModifierBonusStats_Agility(self)
return self:GetStackCount()
end
function modifier_legion_commander_duel_random_stat_agi_custom.prototype.GetTexture(self)
return "legion_commander_duel"
end
modifier_legion_commander_duel_random_stat_agi_custom = __TS__Decorate(
modifier_legion_commander_duel_random_stat_agi_custom,
modifier_legion_commander_duel_random_stat_agi_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_duel_random_stat_agi_custom"}
)
____exports.modifier_legion_commander_duel_random_stat_agi_custom = modifier_legion_commander_duel_random_stat_agi_custom
____exports.modifier_legion_commander_duel_random_stat_int_custom = __TS__Class()
local modifier_legion_commander_duel_random_stat_int_custom = ____exports.modifier_legion_commander_duel_random_stat_int_custom
modifier_legion_commander_duel_random_stat_int_custom.name = "modifier_legion_commander_duel_random_stat_int_custom"
modifier_legion_commander_duel_random_stat_int_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_duel_custom.lua"
__TS__ClassExtends(modifier_legion_commander_duel_random_stat_int_custom, BaseModifier)
function modifier_legion_commander_duel_random_stat_int_custom.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_duel_random_stat_int_custom.prototype.IsPurgable(self)
return false
end
function modifier_legion_commander_duel_random_stat_int_custom.prototype.RemoveOnDeath(self)
return false
end
function modifier_legion_commander_duel_random_stat_int_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_STATS_INTELLECT_BONUS}
end
function modifier_legion_commander_duel_random_stat_int_custom.prototype.GetModifierBonusStats_Intellect(self)
return self:GetStackCount()
end
function modifier_legion_commander_duel_random_stat_int_custom.prototype.GetTexture(self)
return "legion_commander_duel"
end
modifier_legion_commander_duel_random_stat_int_custom = __TS__Decorate(
modifier_legion_commander_duel_random_stat_int_custom,
modifier_legion_commander_duel_random_stat_int_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_duel_random_stat_int_custom"}
)
____exports.modifier_legion_commander_duel_random_stat_int_custom = modifier_legion_commander_duel_random_stat_int_custom
____exports.modifier_legion_commander_duel_custom = __TS__Class()
local modifier_legion_commander_duel_custom = ____exports.modifier_legion_commander_duel_custom
modifier_legion_commander_duel_custom.name = "modifier_legion_commander_duel_custom"
modifier_legion_commander_duel_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_duel_custom.lua"
__TS__ClassExtends(modifier_legion_commander_duel_custom, BaseModifier)
function modifier_legion_commander_duel_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.thinkInterval = 0.1
self.nextDebugAt = 0
self.nextShardAutoOddsAt = 0
self.finished = false
end
function modifier_legion_commander_duel_custom.prototype.getShardOverwhelmingInterval(self)
local ab = self:GetAbility()
if not ab then
return 2
end
return math.max(
0.1,
ab:GetSpecialValueFor("shard_overwhelming_interval")
)
end
function modifier_legion_commander_duel_custom.prototype.getCounterpart(self)
if self.counterpartEi == nil or self.counterpartEi == -1 then
return nil
end
local unit = EntIndexToHScript(self.counterpartEi)
if not unit or unit:IsNull() then
return nil
end
return unit
end
function modifier_legion_commander_duel_custom.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_duel_custom.prototype.IsPurgable(self)
return false
end
function modifier_legion_commander_duel_custom.prototype.IsDebuff(self)
return true
end
function modifier_legion_commander_duel_custom.prototype.RemoveOnDeath(self)
return false
end
function modifier_legion_commander_duel_custom.prototype.GetTexture(self)
return "legion_commander_duel"
end
function modifier_legion_commander_duel_custom.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_legion_commander_duel.vpcf"
end
function modifier_legion_commander_duel_custom.prototype.StatusEffectPriority(self)
return MODIFIER_PRIORITY_ULTRA
end
function modifier_legion_commander_duel_custom.prototype.CheckState(self)
return {[MODIFIER_STATE_COMMAND_RESTRICTED] = true, [MODIFIER_STATE_TAUNTED] = true, [MODIFIER_STATE_SILENCED] = true}
end
function modifier_legion_commander_duel_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT, MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS, MODIFIER_EVENT_ON_DEATH}
end
function modifier_legion_commander_duel_custom.prototype.GetModifierAttackSpeedBonus_Constant(self)
local ab = self:GetAbility()
if not ab then
return 0
end
return ab:GetSpecialValueFor("bonus_attack_speed")
end
function modifier_legion_commander_duel_custom.prototype.GetModifierMagicalResistanceBonus(self)
local parent = self:GetParent()
local caster = self:GetCaster()
local ab = self:GetAbility()
if not ab or not caster or not parent or parent ~= caster then
return 0
end
if not caster:HasScepter() then
return 0
end
return ab:GetSpecialValueFor("scepter_magic_resist")
end
function modifier_legion_commander_duel_custom.prototype.OnCreated(self, params)
if not IsServer() then
return
end
self.counterpartEi = params.counterpart_entindex or -1
duelDebug(
nil,
(("modifier_duel.OnCreated parent=" .. tostring(self:GetParent():entindex())) .. " counterpartEi=") .. tostring(self.counterpartEi)
)
if self.counterpartEi == -1 then
self:breakDuelNoReward()
return
end
local ab = self:GetAbility()
self.victoryRange = ab and ab:GetSpecialValueFor("victory_range") or 1500
local parent = self:GetParent()
local counterpart = self:getCounterpart()
if counterpart and not parent:IsCreep() then
local ____opt_14 = parent.SetForceAttackTarget
if ____opt_14 ~= nil then
____opt_14(parent, counterpart)
end
parent:MoveToTargetToAttack(counterpart)
end
if self:GetCaster() == parent then
self.nextShardAutoOddsAt = GameRules:GetGameTime() + self:getShardOverwhelmingInterval()
end
if counterpart and self:GetCaster() == parent then
local center = GetGroundPosition(
parent:GetAbsOrigin(),
parent
)
local ringFx = ParticleManager:CreateParticle("particles/econ/items/legion/legion_weapon_voth_domosh/legion_duel_ring_arcana.vpcf", PATTACH_WORLDORIGIN, parent)
ParticleManager:SetParticleControl(ringFx, 0, center)
ParticleManager:SetParticleControl(ringFx, 7, center)
self:AddParticle(
ringFx,
false,
false,
-1,
true,
false
)
end
self:StartIntervalThink(self.thinkInterval)
end
function modifier_legion_commander_duel_custom.prototype.OnIntervalThink(self)
if not IsServer() or self.finished then
return
end
local parent = self:GetParent()
local counterpart = self:getCounterpart()
local now = GameRules:GetGameTime()
if now >= self.nextDebugAt then
self.nextDebugAt = now + 1
duelDebug(
nil,
(((((("modifier_duel.Tick parent=" .. tostring(parent:entindex())) .. " alive=") .. tostring(parent:IsAlive())) .. " counterpart=") .. tostring(counterpart and counterpart:entindex())) .. " counterpartAlive=") .. tostring(counterpart and counterpart:IsAlive())
)
end
if not parent or not parent:IsAlive() then
return
end
if not counterpart then
self:breakDuelNoReward()
return
end
local ability = self:GetAbility()
if not counterpart:IsAlive() then
if ability then
ability:completeDuelWithWinner(parent, counterpart)
else
self:breakDuelNoReward()
end
return
end
if not counterpart:HasModifier(____exports.modifier_legion_commander_duel_custom.name) then
self:breakDuelNoReward()
return
end
local d = parent:GetAbsOrigin():__sub(counterpart:GetAbsOrigin()):Length2D()
if d > self.victoryRange then
self:breakDuelNoReward()
return
end
if self:GetCaster() == parent and HasShard(nil, parent) then
local gameTime = GameRules:GetGameTime()
if gameTime >= self.nextShardAutoOddsAt then
self.nextShardAutoOddsAt = gameTime + self:getShardOverwhelmingInterval()
local odds = parent:FindAbilityByName("ability_legion_commander_overwhelming_odds_custom")
if odds and odds:GetLevel() > 0 then
odds:ExecuteBurstAt(GetGroundPosition(
parent:GetAbsOrigin(),
parent
))
end
end
end
if not parent:IsCreep() then
local ____opt_20 = parent.SetForceAttackTarget
if ____opt_20 ~= nil then
____opt_20(parent, counterpart)
end
parent:MoveToTargetToAttack(counterpart)
end
end
function modifier_legion_commander_duel_custom.prototype.OnDeath(self, event)
if not IsServer() or self.finished then
return
end
local deadUnit = event.unit
if not deadUnit or deadUnit:entindex() ~= self:GetParent():entindex() then
return
end
local ____duelDebug_25 = duelDebug
local ____temp_24 = deadUnit:entindex()
local ____opt_22 = self:getCounterpart()
____duelDebug_25(
nil,
(("modifier_duel.OnDeath dead=" .. tostring(____temp_24)) .. " counterpart=") .. tostring(____opt_22 and ____opt_22:entindex())
)
local ability = self:GetAbility()
local loser = self:GetParent()
local winner = self:getCounterpart()
if not ability or not winner then
removeDuelModifiersFrom(nil, loser)
return
end
self.finished = true
if winner:IsAlive() then
ability:completeDuelWithWinner(winner, loser)
else
ability:terminateDuelNoReward(loser, winner)
end
end
function modifier_legion_commander_duel_custom.prototype.breakDuelNoReward(self)
if not IsServer() or self.finished then
return
end
self.finished = true
local ____duelDebug_29 = duelDebug
local ____temp_28 = self:GetParent():entindex()
local ____opt_26 = self:getCounterpart()
____duelDebug_29(
nil,
(("modifier_duel.breakDuelNoReward parent=" .. tostring(____temp_28)) .. " counterpart=") .. tostring(____opt_26 and ____opt_26:entindex())
)
local parent = self:GetParent()
local counterpart = self:getCounterpart()
local ability = self:GetAbility()
if not ability or not counterpart then
removeDuelModifiersFrom(nil, parent)
return
end
ability:terminateDuelNoReward(parent, counterpart)
end
function modifier_legion_commander_duel_custom.prototype.OnDestroy(self)
if not IsServer() then
return
end
local parent = self:GetParent()
duelDebug(
nil,
"modifier_duel.OnDestroy parent=" .. tostring(parent:entindex())
)
local ____opt_30 = parent.SetForceAttackTarget
if ____opt_30 ~= nil then
____opt_30(parent, nil)
end
end
modifier_legion_commander_duel_custom = __TS__Decorate(
modifier_legion_commander_duel_custom,
modifier_legion_commander_duel_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_duel_custom"}
)
____exports.modifier_legion_commander_duel_custom = modifier_legion_commander_duel_custom
return ____exports
@@ -0,0 +1,180 @@
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 ____luck = require("utils.luck")
local calculateLuckChance = ____luck.calculateLuckChance
____exports.ability_legion_commander_moment_of_courage_custom = __TS__Class()
local ability_legion_commander_moment_of_courage_custom = ____exports.ability_legion_commander_moment_of_courage_custom
ability_legion_commander_moment_of_courage_custom.name = "ability_legion_commander_moment_of_courage_custom"
ability_legion_commander_moment_of_courage_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_moment_of_courage_custom.lua"
__TS__ClassExtends(ability_legion_commander_moment_of_courage_custom, BaseAbility)
function ability_legion_commander_moment_of_courage_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_courage_cnt.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_legion_commander.vsndevts", context)
end
function ability_legion_commander_moment_of_courage_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_legion_commander_moment_of_courage_intrinsic.name
end
ability_legion_commander_moment_of_courage_custom = __TS__Decorate(
ability_legion_commander_moment_of_courage_custom,
ability_legion_commander_moment_of_courage_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_legion_commander_moment_of_courage_custom"}
)
____exports.ability_legion_commander_moment_of_courage_custom = ability_legion_commander_moment_of_courage_custom
____exports.modifier_legion_commander_moment_of_courage_intrinsic = __TS__Class()
local modifier_legion_commander_moment_of_courage_intrinsic = ____exports.modifier_legion_commander_moment_of_courage_intrinsic
modifier_legion_commander_moment_of_courage_intrinsic.name = "modifier_legion_commander_moment_of_courage_intrinsic"
modifier_legion_commander_moment_of_courage_intrinsic.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_moment_of_courage_custom.lua"
__TS__ClassExtends(modifier_legion_commander_moment_of_courage_intrinsic, BaseModifier)
function modifier_legion_commander_moment_of_courage_intrinsic.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.lastProcGameTime = -999
end
function modifier_legion_commander_moment_of_courage_intrinsic.prototype.IsHidden(self)
return true
end
function modifier_legion_commander_moment_of_courage_intrinsic.prototype.IsPurgable(self)
return false
end
function modifier_legion_commander_moment_of_courage_intrinsic.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_legion_commander_moment_of_courage_intrinsic.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if parent:PassivesDisabled() or not ability then
return
end
if event.target ~= parent then
return
end
local attacker = event.attacker
if not attacker or attacker == parent or not attacker:IsAlive() then
return
end
if attacker:GetTeamNumber() == parent:GetTeamNumber() then
return
end
local icd = ability:GetSpecialValueFor("proc_cooldown")
local now = GameRules:GetGameTime()
if now < self.lastProcGameTime + icd then
return
end
local basePct = ability:GetSpecialValueFor("trigger_chance_pct")
--- Слот псевдослучайности движка (не выносим в KV — не показывать игроку в тултипе).
local prdSlot = 27
local pid = parent:GetPlayerOwnerID()
local isPlayerHero = pid >= 0 and parent:IsRealHero()
local rolled = false
if isPlayerHero then
local luckPct = math.floor(calculateLuckChance(nil, parent, basePct / 100) * 100)
local clamped = math.min(
95,
math.max(5, luckPct)
)
rolled = RollPseudoRandomPercentage(clamped, prdSlot, parent)
else
rolled = RollPercentage(basePct)
end
if not rolled then
return
end
self.lastProcGameTime = now
self:procCounter(ability, attacker)
end
function modifier_legion_commander_moment_of_courage_intrinsic.prototype.procCounter(self, ability, mainTarget)
local parent = self:GetParent()
local lsPct = ability:GetSpecialValueFor("counter_lifesteal_pct")
local swings = math.max(
1,
math.floor(ability:GetSpecialValueFor("attack_count"))
)
local buffDur = ability:GetSpecialValueFor("buff_duration")
local buffMs = ability:GetSpecialValueFor("buff_bonus_movespeed")
local pfx = ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_courage_cnt.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:ReleaseParticleIndex(pfx)
EmitSoundOn("Hero_LegionCommander.MomentOfCourage", parent)
EmitSoundOn("Hero_LegionCommander.Courage", parent)
parent:StartGestureWithPlaybackRate(ACT_DOTA_ATTACK, 2)
parent:AddNewModifier(parent, ability, ____exports.modifier_legion_commander_moment_proc_haste.name, {duration = buffDur, ms = buffMs})
do
local i = 0
while i < swings do
parent:PerformAttack(
mainTarget,
true,
true,
true,
false,
false,
false,
false
)
i = i + 1
end
end
local estDamage = math.max(
1,
parent:GetAverageTrueAttackDamage(mainTarget)
)
local heal = estDamage * swings * lsPct / 100
if heal > 0 and parent:IsAlive() then
parent:Heal(heal, ability)
end
end
modifier_legion_commander_moment_of_courage_intrinsic = __TS__Decorate(
modifier_legion_commander_moment_of_courage_intrinsic,
modifier_legion_commander_moment_of_courage_intrinsic,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_moment_of_courage_intrinsic"}
)
____exports.modifier_legion_commander_moment_of_courage_intrinsic = modifier_legion_commander_moment_of_courage_intrinsic
____exports.modifier_legion_commander_moment_proc_haste = __TS__Class()
local modifier_legion_commander_moment_proc_haste = ____exports.modifier_legion_commander_moment_proc_haste
modifier_legion_commander_moment_proc_haste.name = "modifier_legion_commander_moment_proc_haste"
modifier_legion_commander_moment_proc_haste.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_moment_of_courage_custom.lua"
__TS__ClassExtends(modifier_legion_commander_moment_proc_haste, BaseModifier)
function modifier_legion_commander_moment_proc_haste.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.ms = 0
end
function modifier_legion_commander_moment_proc_haste.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_moment_proc_haste.prototype.IsPurgable(self)
return true
end
function modifier_legion_commander_moment_proc_haste.prototype.IsDebuff(self)
return false
end
function modifier_legion_commander_moment_proc_haste.prototype.OnCreated(self, params)
self.ms = params.ms or 0
end
function modifier_legion_commander_moment_proc_haste.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT}
end
function modifier_legion_commander_moment_proc_haste.prototype.GetModifierMoveSpeedBonus_Constant(self)
return self.ms
end
function modifier_legion_commander_moment_proc_haste.prototype.GetTexture(self)
return "legion_commander_moment_of_courage"
end
modifier_legion_commander_moment_proc_haste = __TS__Decorate(
modifier_legion_commander_moment_proc_haste,
modifier_legion_commander_moment_proc_haste,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_moment_proc_haste"}
)
____exports.modifier_legion_commander_moment_proc_haste = modifier_legion_commander_moment_proc_haste
return ____exports
@@ -0,0 +1,307 @@
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
____exports.ability_legion_commander_overwhelming_odds_custom = __TS__Class()
local ability_legion_commander_overwhelming_odds_custom = ____exports.ability_legion_commander_overwhelming_odds_custom
ability_legion_commander_overwhelming_odds_custom.name = "ability_legion_commander_overwhelming_odds_custom"
ability_legion_commander_overwhelming_odds_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_overwhelming_odds_custom.lua"
__TS__ClassExtends(ability_legion_commander_overwhelming_odds_custom, BaseAbility)
function ability_legion_commander_overwhelming_odds_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function ability_legion_commander_overwhelming_odds_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_odds_cast.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_odds.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_odds_dmga.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_odds_buff.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_legion_commander.vsndevts", context)
end
function ability_legion_commander_overwhelming_odds_custom.prototype.OnAbilityPhaseStart(self)
if not IsServer() then
return true
end
local caster = self:GetCaster()
if not caster then
return true
end
local p = ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_odds_cast.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControlEnt(
p,
1,
caster,
PATTACH_POINT_FOLLOW,
"attach_attack1",
caster:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(p)
EmitSoundOn("Hero_LegionCommander.Overwhelming.Cast", caster)
return true
end
function ability_legion_commander_overwhelming_odds_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
self:ExecuteBurstAt(self:GetCursorPosition())
end
function ability_legion_commander_overwhelming_odds_custom.prototype.ExecuteBurstAt(self, groundPoint)
if not IsServer() then
return
end
local caster = self:GetCaster()
if not caster or not caster:IsAlive() then
return
end
local point = GetGroundPosition(groundPoint, nil)
local radius = self:GetSpecialValueFor("radius")
local dmgBase = self:GetSpecialValueFor("damage_base")
local dmgPerEnemy = self:GetSpecialValueFor("damage_per_enemy")
local armorDur = self:GetSpecialValueFor("armor_buff_duration")
local debuffDurBase = self:GetSpecialValueFor("debuff_duration")
local slowPct = self:GetSpecialValueFor("enemy_movespeed_slow")
local selfDur = self:GetSpecialValueFor("self_buff_duration")
local selfAs = self:GetSpecialValueFor("self_bonus_attack_speed")
local selfMs = self:GetSpecialValueFor("self_bonus_movespeed")
EmitSoundOnLocationWithCaster(point, "Hero_LegionCommander.Overwhelming.Location", caster)
local pFx = ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_odds.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(pFx, 0, point)
ParticleManager:SetParticleControl(
pFx,
1,
caster:GetAbsOrigin()
)
ParticleManager:SetParticleControl(pFx, 2, point)
ParticleManager:SetParticleControl(pFx, 3, point)
ParticleManager:SetParticleControl(
pFx,
4,
Vector(radius, radius, radius)
)
ParticleManager:SetParticleControl(pFx, 6, point)
ParticleManager:ReleaseParticleIndex(pFx)
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
point,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
local counted = 0
for ____, u in ipairs(enemies) do
do
if not u or not u:IsAlive() or u:IsCourier() then
goto __continue12
end
counted = counted + 1
end
::__continue12::
end
local totalDamage = dmgBase + dmgPerEnemy * counted
for ____, enemy in ipairs(enemies) do
do
if not enemy or not enemy:IsAlive() or enemy:IsCourier() then
goto __continue15
end
local pHit = ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_odds_dmga.vpcf", PATTACH_ABSORIGIN_FOLLOW, enemy)
ParticleManager:SetParticleControlEnt(
pHit,
0,
enemy,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
enemy:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
pHit,
1,
enemy,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
enemy:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
pHit,
3,
caster,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
caster:GetAbsOrigin(),
true
)
ParticleManager:ReleaseParticleIndex(pHit)
EmitSoundOn("Hero_LegionCommander.Overwhelming.Creep", enemy)
ApplyDamage({
victim = enemy,
attacker = caster,
damage = totalDamage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = self
})
local durSlow = debuffDurBase * (1 - enemy:GetStatusResistance())
enemy:AddNewModifier(caster, self, ____exports.modifier_legion_commander_overwhelming_slow.name, {duration = durSlow, slow = slowPct})
end
::__continue15::
end
if counted > 0 then
caster:RemoveModifierByName(____exports.modifier_legion_commander_overwhelming_armor.name)
local mod = caster:AddNewModifier(caster, self, ____exports.modifier_legion_commander_overwhelming_armor.name, {duration = armorDur})
if mod ~= nil and mod ~= nil then
mod:SetStackCount(math.min(counted, 20))
end
end
caster:AddNewModifier(caster, self, ____exports.modifier_legion_commander_overwhelming_self.name, {duration = selfDur, as = selfAs, ms = selfMs})
end
function ability_legion_commander_overwhelming_odds_custom.tryAutoCastAfterDuelCast(self, caster)
if not caster or not caster:IsRealHero() or not caster:IsAlive() then
return
end
local odds = caster:FindAbilityByName("ability_legion_commander_overwhelming_odds_custom")
if not odds or odds:GetLevel() <= 0 then
return
end
if not odds:IsCooldownReady() then
return
end
local idx = odds:GetLevel() - 1
local manaNeed = odds:GetManaCost(math.max(0, idx))
if caster:GetMana() < manaNeed then
return
end
local at = caster:GetAbsOrigin()
odds:ExecuteBurstAt(GetGroundPosition(at, caster))
odds:UseResources(true, false, false, true)
end
ability_legion_commander_overwhelming_odds_custom = __TS__Decorate(
ability_legion_commander_overwhelming_odds_custom,
ability_legion_commander_overwhelming_odds_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_legion_commander_overwhelming_odds_custom"}
)
____exports.ability_legion_commander_overwhelming_odds_custom = ability_legion_commander_overwhelming_odds_custom
____exports.modifier_legion_commander_overwhelming_slow = __TS__Class()
local modifier_legion_commander_overwhelming_slow = ____exports.modifier_legion_commander_overwhelming_slow
modifier_legion_commander_overwhelming_slow.name = "modifier_legion_commander_overwhelming_slow"
modifier_legion_commander_overwhelming_slow.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_overwhelming_odds_custom.lua"
__TS__ClassExtends(modifier_legion_commander_overwhelming_slow, BaseModifier)
function modifier_legion_commander_overwhelming_slow.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_overwhelming_slow.prototype.IsDebuff(self)
return true
end
function modifier_legion_commander_overwhelming_slow.prototype.IsPurgable(self)
return true
end
function modifier_legion_commander_overwhelming_slow.prototype.OnCreated(self, params)
self.slowPct = params.slow or 40
end
function modifier_legion_commander_overwhelming_slow.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE}
end
function modifier_legion_commander_overwhelming_slow.prototype.GetModifierMoveSpeedBonus_Percentage(self)
return -math.abs(self.slowPct)
end
function modifier_legion_commander_overwhelming_slow.prototype.GetStatusEffectName(self)
return "particles/status_fx/status_effect_snapfire_slow.vpcf"
end
function modifier_legion_commander_overwhelming_slow.prototype.GetTexture(self)
return "legion_commander_overwhelming_odds"
end
modifier_legion_commander_overwhelming_slow = __TS__Decorate(
modifier_legion_commander_overwhelming_slow,
modifier_legion_commander_overwhelming_slow,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_overwhelming_slow"}
)
____exports.modifier_legion_commander_overwhelming_slow = modifier_legion_commander_overwhelming_slow
____exports.modifier_legion_commander_overwhelming_self = __TS__Class()
local modifier_legion_commander_overwhelming_self = ____exports.modifier_legion_commander_overwhelming_self
modifier_legion_commander_overwhelming_self.name = "modifier_legion_commander_overwhelming_self"
modifier_legion_commander_overwhelming_self.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_overwhelming_odds_custom.lua"
__TS__ClassExtends(modifier_legion_commander_overwhelming_self, BaseModifier)
function modifier_legion_commander_overwhelming_self.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.as = 0
self.ms = 0
end
function modifier_legion_commander_overwhelming_self.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_overwhelming_self.prototype.IsPurgable(self)
return true
end
function modifier_legion_commander_overwhelming_self.prototype.IsDebuff(self)
return false
end
function modifier_legion_commander_overwhelming_self.prototype.OnCreated(self, params)
self.as = params.as or 0
self.ms = params.ms or 0
if not IsServer() then
return
end
local caster = self:GetParent()
local pBuff = ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_odds_buff.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:ReleaseParticleIndex(pBuff)
end
function modifier_legion_commander_overwhelming_self.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT, MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT}
end
function modifier_legion_commander_overwhelming_self.prototype.GetModifierAttackSpeedBonus_Constant(self)
return self.as
end
function modifier_legion_commander_overwhelming_self.prototype.GetModifierMoveSpeedBonus_Constant(self)
return self.ms
end
function modifier_legion_commander_overwhelming_self.prototype.GetTexture(self)
return "legion_commander_overwhelming_odds"
end
modifier_legion_commander_overwhelming_self = __TS__Decorate(
modifier_legion_commander_overwhelming_self,
modifier_legion_commander_overwhelming_self,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_overwhelming_self"}
)
____exports.modifier_legion_commander_overwhelming_self = modifier_legion_commander_overwhelming_self
____exports.modifier_legion_commander_overwhelming_armor = __TS__Class()
local modifier_legion_commander_overwhelming_armor = ____exports.modifier_legion_commander_overwhelming_armor
modifier_legion_commander_overwhelming_armor.name = "modifier_legion_commander_overwhelming_armor"
modifier_legion_commander_overwhelming_armor.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_overwhelming_odds_custom.lua"
__TS__ClassExtends(modifier_legion_commander_overwhelming_armor, BaseModifier)
function modifier_legion_commander_overwhelming_armor.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_overwhelming_armor.prototype.IsPurgable(self)
return true
end
function modifier_legion_commander_overwhelming_armor.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PHYSICAL_ARMOR_BONUS}
end
function modifier_legion_commander_overwhelming_armor.prototype.GetModifierPhysicalArmorBonus(self)
local ab = self:GetAbility()
local per = ab and ab:GetSpecialValueFor("armor_per_enemy") or 0
return per * self:GetStackCount()
end
function modifier_legion_commander_overwhelming_armor.prototype.GetTexture(self)
return "legion_commander_overwhelming_odds"
end
modifier_legion_commander_overwhelming_armor = __TS__Decorate(
modifier_legion_commander_overwhelming_armor,
modifier_legion_commander_overwhelming_armor,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_overwhelming_armor"}
)
____exports.modifier_legion_commander_overwhelming_armor = modifier_legion_commander_overwhelming_armor
return ____exports
@@ -0,0 +1,105 @@
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
____exports.ability_legion_commander_press_the_attack_custom = __TS__Class()
local ability_legion_commander_press_the_attack_custom = ____exports.ability_legion_commander_press_the_attack_custom
ability_legion_commander_press_the_attack_custom.name = "ability_legion_commander_press_the_attack_custom"
ability_legion_commander_press_the_attack_custom.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_press_the_attack_custom.lua"
__TS__ClassExtends(ability_legion_commander_press_the_attack_custom, BaseAbility)
function ability_legion_commander_press_the_attack_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_press_halo.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_press.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_legion_commander/legion_commander_press_a.vpcf", context)
PrecacheResource("soundfile", "soundevents/game_sounds_heroes/game_sounds_legion_commander.vsndevts", context)
end
function ability_legion_commander_press_the_attack_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not caster or not caster:IsAlive() then
return
end
if not target or not target:IsAlive() then
target = caster
end
if not target:IsHero() then
return
end
if target:GetTeamNumber() ~= caster:GetTeamNumber() then
return
end
target:Purge(
false,
true,
false,
true,
false
)
local duration = self:GetSpecialValueFor("duration")
target:AddNewModifier(caster, self, ____exports.modifier_legion_commander_press_the_attack_buff.name, {duration = duration})
local halo = ParticleManager:CreateParticle("particles/units/heroes/hero_legion_commander/legion_commander_press_halo.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:ReleaseParticleIndex(halo)
EmitSoundOn("Hero_LegionCommander.PressTheAttack", target)
end
ability_legion_commander_press_the_attack_custom = __TS__Decorate(
ability_legion_commander_press_the_attack_custom,
ability_legion_commander_press_the_attack_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_legion_commander_press_the_attack_custom"}
)
____exports.ability_legion_commander_press_the_attack_custom = ability_legion_commander_press_the_attack_custom
____exports.modifier_legion_commander_press_the_attack_buff = __TS__Class()
local modifier_legion_commander_press_the_attack_buff = ____exports.modifier_legion_commander_press_the_attack_buff
modifier_legion_commander_press_the_attack_buff.name = "modifier_legion_commander_press_the_attack_buff"
modifier_legion_commander_press_the_attack_buff.____file_path = "scripts/vscripts/abilities/heroes/legion_commander/ability_legion_commander_press_the_attack_custom.lua"
__TS__ClassExtends(modifier_legion_commander_press_the_attack_buff, BaseModifier)
function modifier_legion_commander_press_the_attack_buff.prototype.IsHidden(self)
return false
end
function modifier_legion_commander_press_the_attack_buff.prototype.IsDebuff(self)
return false
end
function modifier_legion_commander_press_the_attack_buff.prototype.IsPurgable(self)
return true
end
function modifier_legion_commander_press_the_attack_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_ATTACKSPEED_BONUS_CONSTANT, MODIFIER_PROPERTY_HEALTH_REGEN_CONSTANT, MODIFIER_PROPERTY_MOVESPEED_BONUS_CONSTANT}
end
function modifier_legion_commander_press_the_attack_buff.prototype.GetModifierAttackSpeedBonus_Constant(self)
local ab = self:GetAbility()
return ab and ab:GetSpecialValueFor("attack_speed_bonus") or 0
end
function modifier_legion_commander_press_the_attack_buff.prototype.GetModifierConstantHealthRegen(self)
local ab = self:GetAbility()
return ab and ab:GetSpecialValueFor("hp_regen") or 0
end
function modifier_legion_commander_press_the_attack_buff.prototype.GetModifierMoveSpeedBonus_Constant(self)
local ab = self:GetAbility()
return ab and ab:GetSpecialValueFor("movespeed_bonus") or 0
end
function modifier_legion_commander_press_the_attack_buff.prototype.GetEffectName(self)
return "particles/units/heroes/hero_legion_commander/legion_commander_press.vpcf"
end
function modifier_legion_commander_press_the_attack_buff.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_legion_commander_press_the_attack_buff.prototype.GetTexture(self)
return "legion_commander_press_the_attack"
end
modifier_legion_commander_press_the_attack_buff = __TS__Decorate(
modifier_legion_commander_press_the_attack_buff,
modifier_legion_commander_press_the_attack_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_legion_commander_press_the_attack_buff"}
)
____exports.modifier_legion_commander_press_the_attack_buff = modifier_legion_commander_press_the_attack_buff
return ____exports
@@ -0,0 +1,134 @@
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_fired = require("abilities.modifiers.modifier_general_fired")
local modifier_general_fired = ____modifier_general_fired.modifier_general_fired
local ____lina_mana_bonus = require("abilities.heroes.lina.lina_mana_bonus")
local getLinaManaFlatDamage = ____lina_mana_bonus.getLinaManaFlatDamage
____exports.ability_lina_dragon_slave_custom = __TS__Class()
local ability_lina_dragon_slave_custom = ____exports.ability_lina_dragon_slave_custom
ability_lina_dragon_slave_custom.name = "ability_lina_dragon_slave_custom"
ability_lina_dragon_slave_custom.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_dragon_slave_custom.lua"
__TS__ClassExtends(ability_lina_dragon_slave_custom, BaseAbility)
function ability_lina_dragon_slave_custom.prototype.GetIntrinsicModifierName(self)
return "modifier_lina_dragon_slave_custom_passive"
end
function ability_lina_dragon_slave_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local toPoint = point - caster:GetAbsOrigin()
local direction = toPoint:Length2D() < 1 and caster:GetForwardVector() or toPoint:Normalized()
local speed = self:GetSpecialValueFor("dragon_slave_speed")
local width_initial = self:GetSpecialValueFor("dragon_slave_width_initial")
local width_end = self:GetSpecialValueFor("dragon_slave_width_end")
local distance = self:GetSpecialValueFor("dragon_slave_distance")
ProjectileManager:CreateLinearProjectile({
Ability = self,
EffectName = "particles/units/heroes/hero_lina/lina_spell_dragon_slave.vpcf",
vSpawnOrigin = caster:GetAbsOrigin(),
fDistance = distance,
fStartRadius = width_initial,
fEndRadius = width_end,
Source = caster,
bHasFrontalCone = true,
iUnitTargetTeam = DOTA_UNIT_TARGET_TEAM_ENEMY,
iUnitTargetType = DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
vVelocity = direction * speed,
bProvidesVision = true,
iVisionRadius = 150,
iVisionTeamNumber = caster:GetTeamNumber()
})
EmitSoundOn("Hero_Lina.DragonSlave", caster)
end
function ability_lina_dragon_slave_custom.prototype.OnProjectileHit(self, target, location)
if not target then
return false
end
if IsServer() then
local caster = self:GetCaster()
local damage = self:GetSpecialValueFor("dragon_slave_damage") + caster:GetAttackDamage() + getLinaManaFlatDamage(nil, self, caster)
ApplyDamage({
victim = target,
attacker = self:GetCaster(),
damage = damage,
damage_type = self:GetAbilityDamageType(),
ability = self
})
local modifier = target:AddNewModifier(
self:GetCaster(),
self,
modifier_general_fired.name,
{}
)
if modifier then
local stacksPerLevel = self:GetSpecialValueFor("fire_stacks_per_level")
do
local i = 0
while i < stacksPerLevel do
modifier:IncrementStackCount()
i = i + 1
end
end
end
local particleHit = ParticleManager:CreateParticle("particles/units/heroes/hero_lina/lina_spell_dragon_slave_impact.vpcf", PATTACH_ABSORIGIN, target)
ParticleManager:ReleaseParticleIndex(particleHit)
end
return false
end
ability_lina_dragon_slave_custom = __TS__Decorate(
ability_lina_dragon_slave_custom,
ability_lina_dragon_slave_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_lina_dragon_slave_custom"}
)
____exports.ability_lina_dragon_slave_custom = ability_lina_dragon_slave_custom
____exports.modifier_lina_dragon_slave_custom_passive = __TS__Class()
local modifier_lina_dragon_slave_custom_passive = ____exports.modifier_lina_dragon_slave_custom_passive
modifier_lina_dragon_slave_custom_passive.name = "modifier_lina_dragon_slave_custom_passive"
modifier_lina_dragon_slave_custom_passive.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_dragon_slave_custom.lua"
__TS__ClassExtends(modifier_lina_dragon_slave_custom_passive, BaseModifier)
function modifier_lina_dragon_slave_custom_passive.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_lina_dragon_slave_custom_passive.prototype.IsHidden(self)
return true
end
function modifier_lina_dragon_slave_custom_passive.prototype.IsPurgable(self)
return false
end
function modifier_lina_dragon_slave_custom_passive.prototype.OnAttackLanded(self, event)
if IsServer() then
if self:GetParent():PassivesDisabled() then
return
end
local ____temp_3 = event.attacker == self:GetParent()
if ____temp_3 then
local ____RandomInt_result_2 = RandomInt(1, 100)
local ____opt_0 = self:GetAbility()
____temp_3 = ____RandomInt_result_2 <= (____opt_0 and ____opt_0:GetSpecialValueFor("proc_chance"))
end
if ____temp_3 then
local ability = self:GetParent():FindAbilityByName("ability_lina_dragon_slave_custom")
if ability and event.target:IsAlive() and not event.attacker:IsIllusion() then
local targetPosition = event.target:GetAbsOrigin()
ability:GetCaster():SetCursorPosition(targetPosition)
ability:OnSpellStart()
end
end
end
end
modifier_lina_dragon_slave_custom_passive = __TS__Decorate(
modifier_lina_dragon_slave_custom_passive,
modifier_lina_dragon_slave_custom_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_lina_dragon_slave_custom_passive"}
)
____exports.modifier_lina_dragon_slave_custom_passive = modifier_lina_dragon_slave_custom_passive
return ____exports
@@ -0,0 +1,290 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
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_fired = require("abilities.modifiers.modifier_general_fired")
local modifier_general_fired = ____modifier_general_fired.modifier_general_fired
local ____lina_mana_bonus = require("abilities.heroes.lina.lina_mana_bonus")
local getLinaManaFlatDamage = ____lina_mana_bonus.getLinaManaFlatDamage
____exports.ability_lina_flame_cloak_custom = __TS__Class()
local ability_lina_flame_cloak_custom = ____exports.ability_lina_flame_cloak_custom
ability_lina_flame_cloak_custom.name = "ability_lina_flame_cloak_custom"
ability_lina_flame_cloak_custom.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_flame_cloak_custom.lua"
__TS__ClassExtends(ability_lina_flame_cloak_custom, BaseAbility)
function ability_lina_flame_cloak_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
function ability_lina_flame_cloak_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
self.duration = self:GetSpecialValueFor("duration")
caster:AddNewModifier(caster, self, "modifier_lina_flame_cloak_custom", {duration = self.duration})
EmitSoundOn("Hero_Lina.FlameCloak.Cast", caster)
end
function ability_lina_flame_cloak_custom.prototype.GetIntrinsicModifierName(self)
return "modifier_lina_flame_cloak_custom_passive"
end
ability_lina_flame_cloak_custom = __TS__Decorate(
ability_lina_flame_cloak_custom,
ability_lina_flame_cloak_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_lina_flame_cloak_custom"}
)
____exports.ability_lina_flame_cloak_custom = ability_lina_flame_cloak_custom
____exports.modifier_lina_flame_cloak_custom = __TS__Class()
local modifier_lina_flame_cloak_custom = ____exports.modifier_lina_flame_cloak_custom
modifier_lina_flame_cloak_custom.name = "modifier_lina_flame_cloak_custom"
modifier_lina_flame_cloak_custom.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_flame_cloak_custom.lua"
__TS__ClassExtends(modifier_lina_flame_cloak_custom, BaseModifier)
function modifier_lina_flame_cloak_custom.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.thinkInterval = 0.33
end
function modifier_lina_flame_cloak_custom.prototype.OnCreated(self)
if IsServer() then
self:StartIntervalThink(self.thinkInterval)
local parent = self:GetParent()
local flameCloakParticle = ParticleManager:CreateParticle("particles/units/heroes/hero_lina/lina_flame_cloak.vpcf", PATTACH_ABSORIGIN_FOLLOW, parent)
ParticleManager:SetParticleControl(
flameCloakParticle,
0,
parent:GetAbsOrigin()
)
ParticleManager:SetParticleControlEnt(
flameCloakParticle,
1,
parent,
PATTACH_ABSORIGIN_FOLLOW,
"attach_hitloc",
parent:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControl(
flameCloakParticle,
3,
parent:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
flameCloakParticle,
4,
parent:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
flameCloakParticle,
10,
parent:GetAbsOrigin()
)
self:AddParticle(
flameCloakParticle,
false,
false,
-1,
false,
false
)
end
end
function modifier_lina_flame_cloak_custom.prototype.OnDestroy(self)
if IsClient() then
return
end
local parent = self:GetParent()
local currentPos = parent:GetAbsOrigin()
local groundPos = GetGroundPosition(currentPos, parent)
parent:SetAbsOrigin(groundPos)
end
function modifier_lina_flame_cloak_custom.prototype.CheckState(self)
return {[MODIFIER_STATE_FLYING] = true, [MODIFIER_STATE_NO_UNIT_COLLISION] = true}
end
function modifier_lina_flame_cloak_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_VISUAL_Z_DELTA}
end
function modifier_lina_flame_cloak_custom.prototype.GetVisualZDelta(self)
local ____opt_0 = self:GetAbility()
return ____opt_0 and ____opt_0:GetSpecialValueFor("visualzdelta") or 0
end
function modifier_lina_flame_cloak_custom.prototype.GetModifierMoveSpeedBonus_Percentage(self)
local ____opt_2 = self:GetAbility()
return ____opt_2 and ____opt_2:GetSpecialValueFor("movespeed_bonus") or 0
end
function modifier_lina_flame_cloak_custom.prototype.GetEffectName(self)
return "particles/econ/items/ember_spirit/ember_ti9/ember_ti9_flameguard.vpcf"
end
function modifier_lina_flame_cloak_custom.prototype.GetEffectAttachType(self)
return PATTACH_ABSORIGIN_FOLLOW
end
function modifier_lina_flame_cloak_custom.prototype.OnIntervalThink(self)
if IsServer() then
local ability = self:GetAbility()
if not ability then
return
end
local caster = self:GetCaster()
if not caster then
return
end
local damage = ability:GetSpecialValueFor("damage_per_second") * self.thinkInterval + getLinaManaFlatDamage(nil, ability, caster)
local ____FindUnitsInRadius_8 = FindUnitsInRadius
local ____temp_6 = caster:GetTeamNumber()
local ____temp_7 = caster:GetAbsOrigin()
local ____opt_4 = self:GetAbility()
local units = ____FindUnitsInRadius_8(
____temp_6,
____temp_7,
nil,
____opt_4 and ____opt_4:GetSpecialValueFor("radius"),
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
__TS__ArrayForEach(
units,
function(____, unit)
ApplyDamage({
victim = unit,
attacker = caster,
damage = damage,
damage_type = DAMAGE_TYPE_MAGICAL,
ability = ability
})
local modifier = unit:AddNewModifier(caster, ability, modifier_general_fired.name, {})
if modifier then
modifier:IncrementStackCount()
end
end
)
end
end
modifier_lina_flame_cloak_custom = __TS__Decorate(
modifier_lina_flame_cloak_custom,
modifier_lina_flame_cloak_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_lina_flame_cloak_custom"}
)
____exports.modifier_lina_flame_cloak_custom = modifier_lina_flame_cloak_custom
____exports.modifier_lina_flame_cloak_custom_passive = __TS__Class()
local modifier_lina_flame_cloak_custom_passive = ____exports.modifier_lina_flame_cloak_custom_passive
modifier_lina_flame_cloak_custom_passive.name = "modifier_lina_flame_cloak_custom_passive"
modifier_lina_flame_cloak_custom_passive.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_flame_cloak_custom.lua"
__TS__ClassExtends(modifier_lina_flame_cloak_custom_passive, BaseModifier)
function modifier_lina_flame_cloak_custom_passive.prototype.IsHidden(self)
return true
end
function modifier_lina_flame_cloak_custom_passive.prototype.IsPurgable(self)
return false
end
function modifier_lina_flame_cloak_custom_passive.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_TAKEDAMAGE}
end
function modifier_lina_flame_cloak_custom_passive.prototype.OnTakeDamage(self, event)
if not IsServer() then
return
end
if self:GetParent():PassivesDisabled() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
if event.inflictor == ability then
return
end
local unit = event.unit
if unit == self:GetParent() or unit:GetTeamNumber() == self:GetParent():GetTeamNumber() or self:GetParent() ~= event.attacker then
return
end
local modifier = self:GetParent():FindModifierByName("modifier_lina_flame_cloak_custom_passive_buff")
local ____modifier_12 = modifier
if ____modifier_12 then
local ____temp_11 = modifier:GetStackCount()
local ____opt_9 = self:GetAbility()
____modifier_12 = ____temp_11 == (____opt_9 and ____opt_9:GetSpecialValueFor("max_stacks"))
end
if ____modifier_12 then
local ____self_15 = self:GetParent():AddNewModifier(
self:GetParent(),
self:GetAbility(),
"modifier_lina_flame_cloak_custom_passive_buff",
{duration = 5}
)
local ____self_15_SetStackCount_16 = ____self_15.SetStackCount
local ____opt_13 = self:GetAbility()
____self_15_SetStackCount_16(
____self_15,
____opt_13 and ____opt_13:GetSpecialValueFor("max_stacks")
)
else
self:GetParent():AddNewModifier(
self:GetParent(),
self:GetAbility(),
"modifier_lina_flame_cloak_custom_passive_buff",
{duration = 5}
):IncrementStackCount()
end
end
modifier_lina_flame_cloak_custom_passive = __TS__Decorate(
modifier_lina_flame_cloak_custom_passive,
modifier_lina_flame_cloak_custom_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_lina_flame_cloak_custom_passive"}
)
____exports.modifier_lina_flame_cloak_custom_passive = modifier_lina_flame_cloak_custom_passive
____exports.modifier_lina_flame_cloak_custom_passive_buff = __TS__Class()
local modifier_lina_flame_cloak_custom_passive_buff = ____exports.modifier_lina_flame_cloak_custom_passive_buff
modifier_lina_flame_cloak_custom_passive_buff.name = "modifier_lina_flame_cloak_custom_passive_buff"
modifier_lina_flame_cloak_custom_passive_buff.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_flame_cloak_custom.lua"
__TS__ClassExtends(modifier_lina_flame_cloak_custom_passive_buff, BaseModifier)
function modifier_lina_flame_cloak_custom_passive_buff.prototype.IsHidden(self)
return false
end
function modifier_lina_flame_cloak_custom_passive_buff.prototype.IsPurgable(self)
return false
end
function modifier_lina_flame_cloak_custom_passive_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_MOVESPEED_BONUS_PERCENTAGE, MODIFIER_PROPERTY_ATTACKSPEED_PERCENTAGE, MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE, MODIFIER_PROPERTY_MAGICAL_RESISTANCE_BONUS}
end
function modifier_lina_flame_cloak_custom_passive_buff.prototype.GetModifierMoveSpeedBonus_Percentage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
local ____opt_17 = self:GetAbility()
return (____opt_17 and ____opt_17:GetSpecialValueFor("movespeed_bonus")) * self:GetStackCount()
end
function modifier_lina_flame_cloak_custom_passive_buff.prototype.GetModifierAttackSpeedPercentage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
local ____opt_19 = self:GetAbility()
return (____opt_19 and ____opt_19:GetSpecialValueFor("attackspeed_bonus")) * self:GetStackCount()
end
function modifier_lina_flame_cloak_custom_passive_buff.prototype.GetModifierSpellAmplify_Percentage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
local ____opt_21 = self:GetAbility()
return (____opt_21 and ____opt_21:GetSpecialValueFor("spell_amplify")) * self:GetStackCount()
end
function modifier_lina_flame_cloak_custom_passive_buff.prototype.GetModifierMagicalResistanceBonus(self)
if self:GetParent():PassivesDisabled() then
return 0
end
local ____opt_23 = self:GetAbility()
return (____opt_23 and ____opt_23:GetSpecialValueFor("magical_resistance")) * self:GetStackCount()
end
modifier_lina_flame_cloak_custom_passive_buff = __TS__Decorate(
modifier_lina_flame_cloak_custom_passive_buff,
modifier_lina_flame_cloak_custom_passive_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_lina_flame_cloak_custom_passive_buff"}
)
____exports.modifier_lina_flame_cloak_custom_passive_buff = modifier_lina_flame_cloak_custom_passive_buff
return ____exports
@@ -0,0 +1,150 @@
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 ____lina_mana_bonus = require("abilities.heroes.lina.lina_mana_bonus")
local getLinaManaFlatDamage = ____lina_mana_bonus.getLinaManaFlatDamage
____exports.ability_lina_laguna_blade_custom = __TS__Class()
local ability_lina_laguna_blade_custom = ____exports.ability_lina_laguna_blade_custom
ability_lina_laguna_blade_custom.name = "ability_lina_laguna_blade_custom"
ability_lina_laguna_blade_custom.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_laguna_blade_custom.lua"
__TS__ClassExtends(ability_lina_laguna_blade_custom, BaseAbility)
function ability_lina_laguna_blade_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not caster or not target then
return
end
if caster:HasScepter() and self:GetSpecialValueFor("mana_cost_facet") > 0 then
caster:AddNewModifier(
caster,
self,
"modifier_lina_laguna_blade_custom_buff",
{duration = self:GetSpecialValueFor("duration")}
)
end
EmitSoundOn("Ability.LagunaBlade", caster)
EmitSoundOn("Ability.LagunaBladeImpact", target)
local particleId = ParticleManager:CreateParticle("particles/units/heroes/hero_lina/lina_spell_laguna_blade.vpcf", PATTACH_CUSTOMORIGIN, caster)
ParticleManager:SetParticleControlEnt(
particleId,
0,
caster,
PATTACH_POINT_FOLLOW,
"attach_attack1",
caster:GetAbsOrigin(),
true
)
ParticleManager:SetParticleControlEnt(
particleId,
1,
target,
PATTACH_POINT_FOLLOW,
"attach_hitloc",
target:GetAbsOrigin(),
true
)
Timers:CreateTimer(
0.5,
function()
ParticleManager:DestroyParticle(particleId, false)
ParticleManager:ReleaseParticleIndex(particleId)
return nil
end
)
Timers:CreateTimer(
self:GetSpecialValueFor("damage_delay"),
function()
if target and not target:IsNull() and target:IsAlive() then
local ____caster_HasScepter_result_0
if caster:HasScepter() then
____caster_HasScepter_result_0 = DAMAGE_TYPE_PURE
else
____caster_HasScepter_result_0 = DAMAGE_TYPE_MAGICAL
end
local damageType = ____caster_HasScepter_result_0
local damage = self:GetSpecialValueFor("damage") + getLinaManaFlatDamage(nil, self, caster)
if caster:HasScepter() then
damage = damage + caster:GetIntellect(true) * self:GetSpecialValueFor("damage_mult_agh")
end
ApplyDamage({
victim = target,
attacker = caster,
damage = damage,
damage_type = damageType,
ability = self
})
end
return nil
end
)
end
function ability_lina_laguna_blade_custom.prototype.GetManaCost(self, level)
local caster = self:GetCaster()
if caster and caster:HasScepter() and self:GetSpecialValueFor("mana_cost_facet") > 0 then
return caster:GetMana() * (1 - self:GetSpecialValueFor("mana_cost_facet_tooltip") * 0.01) + self:GetSpecialValueFor("mana_cost")
end
return self:GetSpecialValueFor("mana_cost")
end
ability_lina_laguna_blade_custom = __TS__Decorate(
ability_lina_laguna_blade_custom,
ability_lina_laguna_blade_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_lina_laguna_blade_custom"}
)
____exports.ability_lina_laguna_blade_custom = ability_lina_laguna_blade_custom
____exports.modifier_lina_laguna_blade_custom_buff = __TS__Class()
local modifier_lina_laguna_blade_custom_buff = ____exports.modifier_lina_laguna_blade_custom_buff
modifier_lina_laguna_blade_custom_buff.name = "modifier_lina_laguna_blade_custom_buff"
modifier_lina_laguna_blade_custom_buff.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_laguna_blade_custom.lua"
__TS__ClassExtends(modifier_lina_laguna_blade_custom_buff, BaseModifier)
function modifier_lina_laguna_blade_custom_buff.prototype.IsDebuff(self)
return false
end
function modifier_lina_laguna_blade_custom_buff.prototype.IsHidden(self)
return false
end
function modifier_lina_laguna_blade_custom_buff.prototype.IsPurgable(self)
return false
end
function modifier_lina_laguna_blade_custom_buff.prototype.RemoveOnDeath(self)
return true
end
function modifier_lina_laguna_blade_custom_buff.prototype.OnCreated(self, params)
self:StartIntervalThink(0.1)
end
function modifier_lina_laguna_blade_custom_buff.prototype.OnIntervalThink(self)
local ____self_SetStackCount_9 = self.SetStackCount
local ____opt_1 = self:GetCaster()
local ____temp_5 = ____opt_1 and ____opt_1:GetMaxMana()
local ____opt_3 = self:GetCaster()
local ____temp_8 = ____temp_5 - (____opt_3 and ____opt_3:GetMana())
local ____opt_6 = self:GetAbility()
____self_SetStackCount_9(
self,
____temp_8 * (____opt_6 and ____opt_6:GetSpecialValueFor("spell_amplify")) * 0.01
)
end
function modifier_lina_laguna_blade_custom_buff.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE}
end
function modifier_lina_laguna_blade_custom_buff.prototype.GetModifierSpellAmplify_Percentage(self, event)
return self:GetStackCount()
end
modifier_lina_laguna_blade_custom_buff = __TS__Decorate(
modifier_lina_laguna_blade_custom_buff,
modifier_lina_laguna_blade_custom_buff,
{registerModifier(nil)},
{kind = "class", name = "modifier_lina_laguna_blade_custom_buff"}
)
____exports.modifier_lina_laguna_blade_custom_buff = modifier_lina_laguna_blade_custom_buff
return ____exports
@@ -0,0 +1,158 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__ArrayForEach = ____lualib.__TS__ArrayForEach
local __TS__Decorate = ____lualib.__TS__Decorate
local ____exports = {}
local ____dota_ts_adapter = require("lib.dota_ts_adapter")
local BaseAbility = ____dota_ts_adapter.BaseAbility
local registerAbility = ____dota_ts_adapter.registerAbility
local ____modifier_general_fired = require("abilities.modifiers.modifier_general_fired")
local modifier_general_fired = ____modifier_general_fired.modifier_general_fired
local ____lina_mana_bonus = require("abilities.heroes.lina.lina_mana_bonus")
local getLinaManaFlatDamage = ____lina_mana_bonus.getLinaManaFlatDamage
____exports.ability_lina_light_strike_array_custom = __TS__Class()
local ability_lina_light_strike_array_custom = ____exports.ability_lina_light_strike_array_custom
ability_lina_light_strike_array_custom.name = "ability_lina_light_strike_array_custom"
ability_lina_light_strike_array_custom.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_light_strike_array_custom.lua"
__TS__ClassExtends(ability_lina_light_strike_array_custom, BaseAbility)
function ability_lina_light_strike_array_custom.prototype.GetAOERadius(self)
return 250
end
function ability_lina_light_strike_array_custom.prototype.OnSpellStart(self)
local caster = self:GetCaster()
local point = self:GetCursorPosition()
local delay = self:GetSpecialValueFor("light_strike_array_delay_time")
local radius = self:GetSpecialValueFor("light_strike_array_aoe")
local stun_duration = self:GetSpecialValueFor("light_strike_array_stun_duration")
local multicast_max = self:GetLevel()
local multicast_chance = self:GetSpecialValueFor("light_strike_chance")
self:CastLSA(point, delay, radius, stun_duration)
local additional_casts = 0
do
local i = 1
while i < multicast_max do
local roll = RandomInt(1, 100)
if roll <= multicast_chance then
additional_casts = additional_casts + 1
end
i = i + 1
end
end
do
local i = 0
while i < additional_casts do
Timers:CreateTimer(
delay * (i + 1),
function()
self:CastLSA(point, delay, radius, stun_duration)
end
)
i = i + 1
end
end
end
function ability_lina_light_strike_array_custom.prototype.CastLSA(self, point, delay, radius, stun_duration)
local caster = self:GetCaster()
local particleWarning = ParticleManager:CreateParticle("particles/units/heroes/hero_lina/lina_spell_light_strike_array_ray_team.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particleWarning, 0, point)
ParticleManager:SetParticleControl(
particleWarning,
1,
Vector(radius, 0, 0)
)
local particleRay = ParticleManager:CreateParticle("particles/units/heroes/hero_lina/lina_spell_light_strike_array_ray.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particleRay, 0, point)
ParticleManager:SetParticleControl(
particleRay,
1,
Vector(radius, 0, 0)
)
EmitSoundOnLocationWithCaster(point, "Ability.PreLightStrikeArray", caster)
Timers:CreateTimer(
delay,
function()
self:CreateExplosion(point, radius, stun_duration, caster)
if not HasTalent(
nil,
self:GetCaster(),
"special_bonus_unique_lina_light_strike_array_five"
) then
return
end
local sideDistance = radius / 2
local leftPoint = Vector(point.x - sideDistance, point.y, point.z)
self:CreateExplosion(leftPoint, radius, stun_duration, caster)
local rightPoint = Vector(point.x + sideDistance, point.y, point.z)
self:CreateExplosion(rightPoint, radius, stun_duration, caster)
local topPoint = Vector(point.x, point.y + sideDistance, point.z)
self:CreateExplosion(topPoint, radius, stun_duration, caster)
local bottomPoint = Vector(point.x, point.y - sideDistance, point.z)
self:CreateExplosion(bottomPoint, radius, stun_duration, caster)
ParticleManager:DestroyParticle(particleWarning, false)
ParticleManager:ReleaseParticleIndex(particleWarning)
ParticleManager:DestroyParticle(particleRay, false)
ParticleManager:ReleaseParticleIndex(particleRay)
end
)
end
function ability_lina_light_strike_array_custom.prototype.CreateExplosion(self, point, radius, stun_duration, caster)
local damage = self:GetSpecialValueFor("light_strike_array_damage") + getLinaManaFlatDamage(nil, self, caster)
local units = FindUnitsInRadius(
caster:GetTeamNumber(),
point,
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
__TS__ArrayForEach(
units,
function(____, unit)
ApplyDamage({
victim = unit,
attacker = caster,
damage = damage,
damage_type = self:GetAbilityDamageType(),
ability = self
})
local modifier = unit:AddNewModifier(
self:GetCaster(),
self,
modifier_general_fired.name,
{}
)
if modifier then
local stacksPerLevel = self:GetSpecialValueFor("fire_stacks_per_level")
do
local i = 0
while i < stacksPerLevel do
modifier:IncrementStackCount()
i = i + 1
end
end
end
unit:AddNewModifier(caster, self, "modifier_stunned", {duration = stun_duration})
end
)
local particleEffect = ParticleManager:CreateParticle("particles/units/heroes/hero_lina/lina_spell_light_strike_array.vpcf", PATTACH_WORLDORIGIN, nil)
ParticleManager:SetParticleControl(particleEffect, 0, point)
ParticleManager:SetParticleControl(
particleEffect,
1,
Vector(radius, 0, 0)
)
ParticleManager:ReleaseParticleIndex(particleEffect)
EmitSoundOnLocationWithCaster(point, "Ability.LightStrikeArray", caster)
end
ability_lina_light_strike_array_custom = __TS__Decorate(
ability_lina_light_strike_array_custom,
ability_lina_light_strike_array_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_lina_light_strike_array_custom"}
)
____exports.ability_lina_light_strike_array_custom = ability_lina_light_strike_array_custom
return ____exports
@@ -0,0 +1,158 @@
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_fired = require("abilities.modifiers.modifier_general_fired")
local modifier_general_fired = ____modifier_general_fired.modifier_general_fired
local ____incoming_damage_reduction_combine = require("utils.incoming_damage_reduction_combine")
local removeIncomingDamageReductionSource = ____incoming_damage_reduction_combine.removeIncomingDamageReductionSource
local setIncomingDamageReductionSource = ____incoming_damage_reduction_combine.setIncomingDamageReductionSource
local LINA_SCORCH_AFFINITY_INCOMING_SOURCE = "modifier_lina_scorch_affinity_innate"
____exports.ability_lina_scorch_affinity_innate = __TS__Class()
local ability_lina_scorch_affinity_innate = ____exports.ability_lina_scorch_affinity_innate
ability_lina_scorch_affinity_innate.name = "ability_lina_scorch_affinity_innate"
ability_lina_scorch_affinity_innate.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_scorch_affinity_innate.lua"
__TS__ClassExtends(ability_lina_scorch_affinity_innate, BaseAbility)
function ability_lina_scorch_affinity_innate.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_lina_scorch_affinity_innate.name
end
function ability_lina_scorch_affinity_innate.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("radius")
end
ability_lina_scorch_affinity_innate = __TS__Decorate(
ability_lina_scorch_affinity_innate,
ability_lina_scorch_affinity_innate,
{registerAbility(nil)},
{kind = "class", name = "ability_lina_scorch_affinity_innate"}
)
____exports.ability_lina_scorch_affinity_innate = ability_lina_scorch_affinity_innate
____exports.modifier_lina_scorch_affinity_innate = __TS__Class()
local modifier_lina_scorch_affinity_innate = ____exports.modifier_lina_scorch_affinity_innate
modifier_lina_scorch_affinity_innate.name = "modifier_lina_scorch_affinity_innate"
modifier_lina_scorch_affinity_innate.____file_path = "scripts/vscripts/abilities/heroes/lina/ability_lina_scorch_affinity_innate.lua"
__TS__ClassExtends(modifier_lina_scorch_affinity_innate, BaseModifier)
function modifier_lina_scorch_affinity_innate.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.burningUnitCount = 0
self.totalBonusPct = 0
end
function modifier_lina_scorch_affinity_innate.prototype.IsHidden(self)
return false
end
function modifier_lina_scorch_affinity_innate.prototype.IsDebuff(self)
return false
end
function modifier_lina_scorch_affinity_innate.prototype.IsPurgable(self)
return false
end
function modifier_lina_scorch_affinity_innate.prototype.RemoveOnDeath(self)
return false
end
function modifier_lina_scorch_affinity_innate.prototype.OnCreated(self)
self:refreshBurningUnits()
self:StartIntervalThink(0.25)
if not IsServer() then
return
end
setIncomingDamageReductionSource(
nil,
self:GetParent(),
LINA_SCORCH_AFFINITY_INCOMING_SOURCE,
function()
if self:GetParent():PassivesDisabled() then
return 0
end
return math.max(0, self.totalBonusPct)
end
)
end
function modifier_lina_scorch_affinity_innate.prototype.OnRefresh(self)
self:refreshBurningUnits()
end
function modifier_lina_scorch_affinity_innate.prototype.OnDestroy(self)
if not IsServer() then
return
end
removeIncomingDamageReductionSource(
nil,
self:GetParent(),
LINA_SCORCH_AFFINITY_INCOMING_SOURCE
)
end
function modifier_lina_scorch_affinity_innate.prototype.OnIntervalThink(self)
self:refreshBurningUnits()
end
function modifier_lina_scorch_affinity_innate.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_DAMAGEOUTGOING_PERCENTAGE, MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE}
end
function modifier_lina_scorch_affinity_innate.prototype.refreshBurningUnits(self)
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability or not parent or parent:IsNull() then
self.burningUnitCount = 0
self.totalBonusPct = 0
self:SetStackCount(0)
return
end
local radius = ability:GetSpecialValueFor("radius")
local basePct = ability:GetSpecialValueFor("bonus_pct_base")
local pctPerHeroLevel = ability:GetSpecialValueFor("bonus_pct_per_hero_level")
local heroLevel = parent:IsHero() and parent:GetLevel() or 1
local pctPerUnit = basePct + heroLevel * pctPerHeroLevel
local count = 0
local units = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_BOTH,
bit.bor(DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_BASIC),
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, unit in ipairs(units) do
do
if not unit or unit:IsNull() or not unit:IsAlive() then
goto __continue19
end
if unit == parent then
goto __continue19
end
local fired = unit:FindModifierByName(modifier_general_fired.name)
if fired and not fired:IsNull() then
count = count + 1
end
end
::__continue19::
end
self.burningUnitCount = count
self.totalBonusPct = count * pctPerUnit
self:SetStackCount(count)
end
function modifier_lina_scorch_affinity_innate.prototype.GetModifierDamageOutgoing_Percentage(self)
if self:GetParent():PassivesDisabled() then
return 0
end
return self.totalBonusPct
end
function modifier_lina_scorch_affinity_innate.prototype.GetModifierSpellAmplify_Percentage(self, event)
if self:GetParent():PassivesDisabled() then
return 0
end
return self.totalBonusPct
end
modifier_lina_scorch_affinity_innate = __TS__Decorate(
modifier_lina_scorch_affinity_innate,
modifier_lina_scorch_affinity_innate,
{registerModifier(nil)},
{kind = "class", name = "modifier_lina_scorch_affinity_innate"}
)
____exports.modifier_lina_scorch_affinity_innate = modifier_lina_scorch_affinity_innate
return ____exports
@@ -0,0 +1,14 @@
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
local ____exports = {}
--- Доп. урон кастомок Лины: текущая мана × (`mana_damage_from_current_pct` / 100) из AbilityValues.
function ____exports.getLinaManaFlatDamage(self, ability, caster)
if caster == nil or not caster:IsAlive() or not caster:IsHero() then
return 0
end
local pct = ability:GetSpecialValueFor("mana_damage_from_current_pct")
if pct <= 0 then
return 0
end
return caster:GetMana() * (pct * 0.01)
end
return ____exports
@@ -0,0 +1,182 @@
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 ____luna_lucent_beam_shared = require("abilities.heroes.luna.luna_lucent_beam_shared")
local applyLucentBeamHit = ____luna_lucent_beam_shared.applyLucentBeamHit
local getLunaLucentBeamAbility = ____luna_lucent_beam_shared.getLunaLucentBeamAbility
____exports.ability_luna_eclipse_custom = __TS__Class()
local ability_luna_eclipse_custom = ____exports.ability_luna_eclipse_custom
ability_luna_eclipse_custom.name = "ability_luna_eclipse_custom"
ability_luna_eclipse_custom.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_eclipse_custom.lua"
__TS__ClassExtends(ability_luna_eclipse_custom, BaseAbility)
function ability_luna_eclipse_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_luna/luna_eclipse.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_luna/luna_lucent_beam.vpcf", context)
end
function ability_luna_eclipse_custom.prototype.GetBehavior(self)
return DOTA_ABILITY_BEHAVIOR_NO_TARGET
end
function ability_luna_eclipse_custom.prototype.OnUpgrade(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local lucentBeam = getLunaLucentBeamAbility(nil, caster)
if not lucentBeam or lucentBeam:GetLevel() > 0 then
return
end
if self:GetLevel() > 0 then
self:SetLevel(0)
if caster:IsRealHero() then
local heroCaster = caster
heroCaster:SetAbilityPoints(heroCaster:GetAbilityPoints() + 1)
end
end
end
function ability_luna_eclipse_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local duration = self:GetSpecialValueFor("eclipse_duration")
local radius = self:GetSpecialValueFor("eclipse_radius")
local eclipsePfx = ParticleManager:CreateParticle("particles/units/heroes/hero_luna/luna_eclipse.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:SetParticleControl(
eclipsePfx,
0,
caster:GetAbsOrigin()
)
ParticleManager:SetParticleControl(
eclipsePfx,
1,
Vector(radius, 0, 0)
)
Timers:CreateTimer(
duration + 0.5,
function()
ParticleManager:DestroyParticle(eclipsePfx, false)
ParticleManager:ReleaseParticleIndex(eclipsePfx)
return nil
end
)
caster:AddNewModifier(caster, self, ____exports.modifier_luna_eclipse_active.name, {duration = duration})
EmitSoundOn("Hero_Luna.Eclipse", caster)
end
ability_luna_eclipse_custom = __TS__Decorate(
ability_luna_eclipse_custom,
ability_luna_eclipse_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_luna_eclipse_custom"}
)
____exports.ability_luna_eclipse_custom = ability_luna_eclipse_custom
____exports.modifier_luna_eclipse_active = __TS__Class()
local modifier_luna_eclipse_active = ____exports.modifier_luna_eclipse_active
modifier_luna_eclipse_active.name = "modifier_luna_eclipse_active"
modifier_luna_eclipse_active.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_eclipse_custom.lua"
__TS__ClassExtends(modifier_luna_eclipse_active, BaseModifier)
function modifier_luna_eclipse_active.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.beamsDone = 0
end
function modifier_luna_eclipse_active.prototype.IsHidden(self)
return false
end
function modifier_luna_eclipse_active.prototype.IsPurgable(self)
return false
end
function modifier_luna_eclipse_active.prototype.GetAttributes(self)
return MODIFIER_ATTRIBUTE_MULTIPLE
end
function modifier_luna_eclipse_active.prototype.OnCreated(self)
if not IsServer() then
return
end
local interval = self:GetAbility():GetSpecialValueFor("beam_interval")
self:StartIntervalThink(interval)
self:OnIntervalThink()
end
function modifier_luna_eclipse_active.prototype.OnIntervalThink(self)
if not IsServer() then
return
end
local ability = self:GetAbility()
local parent = self:GetParent()
if not ability or not parent then
self:Destroy()
return
end
local facetWaves = parent:HasScepter() and math.floor(ability:GetSpecialValueFor("eclipse_facet_wave_count")) or 0
local maxBeams = facetWaves > 0 and facetWaves or math.floor(ability:GetSpecialValueFor("eclipse_beam_count"))
if self.beamsDone >= maxBeams then
self:Destroy()
return
end
local radius = ability:GetSpecialValueFor("eclipse_radius")
local lucentBeam = getLunaLucentBeamAbility(nil, parent)
local hasLeveledLucentBeam = not not lucentBeam and lucentBeam:GetLevel() > 0
local damage = hasLeveledLucentBeam and lucentBeam:GetSpecialValueFor("lucent_beam_damage") or 0
local stun = hasLeveledLucentBeam and lucentBeam:GetSpecialValueFor("stun_duration") or 0
local enemies = FindUnitsInRadius(
parent:GetTeamNumber(),
parent:GetAbsOrigin(),
nil,
radius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
if #enemies == 0 then
self.beamsDone = self.beamsDone + 1
return
end
if facetWaves > 0 then
for ____, victim in ipairs(enemies) do
do
if not victim or not victim:IsAlive() then
goto __continue23
end
applyLucentBeamHit(
nil,
parent,
ability,
victim,
damage,
stun
)
end
::__continue23::
end
else
local victim = enemies[RandomInt(0, #enemies - 1) + 1]
if not victim or not victim:IsAlive() then
self.beamsDone = self.beamsDone + 1
return
end
applyLucentBeamHit(
nil,
parent,
ability,
victim,
damage,
stun
)
end
self.beamsDone = self.beamsDone + 1
end
modifier_luna_eclipse_active = __TS__Decorate(
modifier_luna_eclipse_active,
modifier_luna_eclipse_active,
{registerModifier(nil)},
{kind = "class", name = "modifier_luna_eclipse_active"}
)
____exports.modifier_luna_eclipse_active = modifier_luna_eclipse_active
return ____exports
@@ -0,0 +1,78 @@
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 registerAbility = ____dota_ts_adapter.registerAbility
local ____luna_lucent_beam_shared = require("abilities.heroes.luna.luna_lucent_beam_shared")
local applyLucentBeamHit = ____luna_lucent_beam_shared.applyLucentBeamHit
____exports.ability_luna_lucent_beam_custom = __TS__Class()
local ability_luna_lucent_beam_custom = ____exports.ability_luna_lucent_beam_custom
ability_luna_lucent_beam_custom.name = "ability_luna_lucent_beam_custom"
ability_luna_lucent_beam_custom.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_lucent_beam_custom.lua"
__TS__ClassExtends(ability_luna_lucent_beam_custom, BaseAbility)
function ability_luna_lucent_beam_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_luna/luna_lucent_beam.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_luna/luna_lucent_beam_precast.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_luna/luna_lucent_beam_cast.vpcf", context)
end
function ability_luna_lucent_beam_custom.prototype.GetBehavior(self)
return DOTA_ABILITY_BEHAVIOR_UNIT_TARGET
end
function ability_luna_lucent_beam_custom.prototype.GetAOERadius(self)
local r = self:GetSpecialValueFor("lucent_beam_aoe_radius")
return r > 0 and r or 0
end
function ability_luna_lucent_beam_custom.prototype.OnAbilityPhaseStart(self)
if not IsServer() then
return true
end
local caster = self:GetCaster()
self.precastPfx = ParticleManager:CreateParticle("particles/units/heroes/hero_luna/luna_lucent_beam_precast.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
return true
end
function ability_luna_lucent_beam_custom.prototype.OnAbilityPhaseInterrupted(self)
self:clearPrecastPfx()
end
function ability_luna_lucent_beam_custom.prototype.clearPrecastPfx(self)
if self.precastPfx == nil then
return
end
ParticleManager:DestroyParticle(self.precastPfx, false)
ParticleManager:ReleaseParticleIndex(self.precastPfx)
self.precastPfx = nil
end
function ability_luna_lucent_beam_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
self:clearPrecastPfx()
local caster = self:GetCaster()
local target = self:GetCursorTarget()
if not target or target:IsNull() or not target:IsAlive() then
return
end
local castPfx = ParticleManager:CreateParticle("particles/units/heroes/hero_luna/luna_lucent_beam_cast.vpcf", PATTACH_ABSORIGIN_FOLLOW, caster)
ParticleManager:ReleaseParticleIndex(castPfx)
EmitSoundOn("Hero_Luna.LucentBeam.Cast", caster)
local damage = self:GetSpecialValueFor("lucent_beam_damage") + caster:GetMaxMana() * (self:GetSpecialValueFor("mana_damage_pct") / 100)
local stun = self:GetSpecialValueFor("stun_duration")
applyLucentBeamHit(
nil,
caster,
self,
target,
damage,
stun
)
end
ability_luna_lucent_beam_custom = __TS__Decorate(
ability_luna_lucent_beam_custom,
ability_luna_lucent_beam_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_luna_lucent_beam_custom"}
)
____exports.ability_luna_lucent_beam_custom = ability_luna_lucent_beam_custom
return ____exports
@@ -0,0 +1,134 @@
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 ____moon_sisters_synergy = require("abilities.heroes.mirana_luna.moon_sisters_synergy")
local ensureMoonSistersInnateModifier = ____moon_sisters_synergy.ensureMoonSistersInnateModifier
local removeMoonSistersInnateModifier = ____moon_sisters_synergy.removeMoonSistersInnateModifier
____exports.ability_luna_lunar_blessing_custom = __TS__Class()
local ability_luna_lunar_blessing_custom = ____exports.ability_luna_lunar_blessing_custom
ability_luna_lunar_blessing_custom.name = "ability_luna_lunar_blessing_custom"
ability_luna_lunar_blessing_custom.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_lunar_blessing_custom.lua"
__TS__ClassExtends(ability_luna_lunar_blessing_custom, BaseAbility)
function ability_luna_lunar_blessing_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_luna_lunar_blessing_aura_custom.name
end
function ability_luna_lunar_blessing_custom.prototype.GetAOERadius(self)
return self:GetSpecialValueFor("blessing_radius")
end
ability_luna_lunar_blessing_custom = __TS__Decorate(
ability_luna_lunar_blessing_custom,
ability_luna_lunar_blessing_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_luna_lunar_blessing_custom"}
)
____exports.ability_luna_lunar_blessing_custom = ability_luna_lunar_blessing_custom
____exports.modifier_luna_lunar_blessing_aura_custom = __TS__Class()
local modifier_luna_lunar_blessing_aura_custom = ____exports.modifier_luna_lunar_blessing_aura_custom
modifier_luna_lunar_blessing_aura_custom.name = "modifier_luna_lunar_blessing_aura_custom"
modifier_luna_lunar_blessing_aura_custom.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_lunar_blessing_custom.lua"
__TS__ClassExtends(modifier_luna_lunar_blessing_aura_custom, BaseModifier)
function modifier_luna_lunar_blessing_aura_custom.prototype.IsHidden(self)
return true
end
function modifier_luna_lunar_blessing_aura_custom.prototype.IsPurgable(self)
return false
end
function modifier_luna_lunar_blessing_aura_custom.prototype.IsDebuff(self)
return false
end
function modifier_luna_lunar_blessing_aura_custom.prototype.IsAura(self)
return true
end
function modifier_luna_lunar_blessing_aura_custom.prototype.GetModifierAura(self)
return ____exports.modifier_luna_lunar_blessing_buff_custom.name
end
function modifier_luna_lunar_blessing_aura_custom.prototype.GetAuraRadius(self)
return self:GetAbility():GetSpecialValueFor("blessing_radius")
end
function modifier_luna_lunar_blessing_aura_custom.prototype.GetAuraDuration(self)
return 0.5
end
function modifier_luna_lunar_blessing_aura_custom.prototype.GetAuraSearchTeam(self)
return DOTA_UNIT_TARGET_TEAM_FRIENDLY
end
function modifier_luna_lunar_blessing_aura_custom.prototype.GetAuraSearchType(self)
return DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC
end
function modifier_luna_lunar_blessing_aura_custom.prototype.GetAuraSearchFlags(self)
return DOTA_UNIT_TARGET_FLAG_NONE
end
function modifier_luna_lunar_blessing_aura_custom.prototype.OnCreated(self)
local parent = self:GetParent()
local ability = self:GetAbility()
if ability then
ensureMoonSistersInnateModifier(nil, parent, ability)
end
end
function modifier_luna_lunar_blessing_aura_custom.prototype.OnDestroy(self)
removeMoonSistersInnateModifier(
nil,
self:GetParent()
)
end
function modifier_luna_lunar_blessing_aura_custom.prototype.GetAuraEntityReject(self, _hTarget)
return self:GetParent():PassivesDisabled()
end
modifier_luna_lunar_blessing_aura_custom = __TS__Decorate(
modifier_luna_lunar_blessing_aura_custom,
modifier_luna_lunar_blessing_aura_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_luna_lunar_blessing_aura_custom"}
)
____exports.modifier_luna_lunar_blessing_aura_custom = modifier_luna_lunar_blessing_aura_custom
____exports.modifier_luna_lunar_blessing_buff_custom = __TS__Class()
local modifier_luna_lunar_blessing_buff_custom = ____exports.modifier_luna_lunar_blessing_buff_custom
modifier_luna_lunar_blessing_buff_custom.name = "modifier_luna_lunar_blessing_buff_custom"
modifier_luna_lunar_blessing_buff_custom.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_lunar_blessing_custom.lua"
__TS__ClassExtends(modifier_luna_lunar_blessing_buff_custom, BaseModifier)
function modifier_luna_lunar_blessing_buff_custom.prototype.IsHidden(self)
return false
end
function modifier_luna_lunar_blessing_buff_custom.prototype.IsPurgable(self)
return false
end
function modifier_luna_lunar_blessing_buff_custom.prototype.IsDebuff(self)
return false
end
function modifier_luna_lunar_blessing_buff_custom.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE, MODIFIER_PROPERTY_SPELL_AMPLIFY_PERCENTAGE}
end
function modifier_luna_lunar_blessing_buff_custom.prototype.GetModifierPreAttack_BonusDamage(self)
local caster = self:GetCaster()
if caster and caster:PassivesDisabled() then
return 0
end
local ability = self:GetAbility()
if not ability then
return 0
end
return ability:GetSpecialValueFor("blessing_bonus_damage") * self:GetParent():GetLevel()
end
function modifier_luna_lunar_blessing_buff_custom.prototype.GetModifierSpellAmplify_Percentage(self)
local caster = self:GetCaster()
if caster and caster:PassivesDisabled() then
return 0
end
local ability = self:GetAbility()
local perLevel = ability:GetSpecialValueFor("spell_amp_per_level")
return perLevel * self:GetParent():GetLevel()
end
modifier_luna_lunar_blessing_buff_custom = __TS__Decorate(
modifier_luna_lunar_blessing_buff_custom,
modifier_luna_lunar_blessing_buff_custom,
{registerModifier(nil)},
{kind = "class", name = "modifier_luna_lunar_blessing_buff_custom"}
)
____exports.modifier_luna_lunar_blessing_buff_custom = modifier_luna_lunar_blessing_buff_custom
return ____exports
@@ -0,0 +1,192 @@
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
____exports.ability_luna_moon_glaive_custom = __TS__Class()
local ability_luna_moon_glaive_custom = ____exports.ability_luna_moon_glaive_custom
ability_luna_moon_glaive_custom.name = "ability_luna_moon_glaive_custom"
ability_luna_moon_glaive_custom.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_moon_glaive_custom.lua"
__TS__ClassExtends(ability_luna_moon_glaive_custom, BaseAbility)
function ability_luna_moon_glaive_custom.prototype.Precache(self, context)
PrecacheResource("particle", "particles/units/heroes/hero_luna/luna_moon_glaive.vpcf", context)
PrecacheResource("particle", "particles/units/heroes/hero_luna/luna_base_attack.vpcf", context)
end
function ability_luna_moon_glaive_custom.prototype.GetIntrinsicModifierName(self)
return ____exports.modifier_luna_moon_glaive_passive.name
end
function ability_luna_moon_glaive_custom.prototype.LaunchGlaive(self, from, to, state)
if not IsServer() then
return
end
self.glaiveChain = state
local caster = self:GetCaster()
local speed = math.max(
600,
caster:GetProjectileSpeed()
)
ProjectileManager:CreateTrackingProjectile({
Ability = self,
EffectName = "particles/units/heroes/hero_luna/luna_moon_glaive.vpcf",
Source = from,
Target = to,
iMoveSpeed = speed,
bDodgeable = true,
bVisibleToEnemies = true
})
end
function ability_luna_moon_glaive_custom.prototype.OnProjectileHit(self, target, location)
if not IsServer() then
return
end
if not target or target:IsNull() or not target:IsAlive() then
self.glaiveChain = nil
return
end
local state = self.glaiveChain
local ability = self
local caster = ability:GetCaster()
if not state or not caster then
self.glaiveChain = nil
return
end
local atk = state.attacker:GetAverageTrueAttackDamage(target)
local dmg = atk * state.damageMult
ApplyDamage({
victim = target,
attacker = state.attacker,
damage = dmg,
damage_type = DAMAGE_TYPE_PHYSICAL,
damage_flags = bit.bor(DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION, DOTA_DAMAGE_FLAG_ATTACK_MODIFIER),
ability = ability
})
EmitSoundOn("Hero_Luna.MoonGlaive", target)
local bounceRange = ability:GetSpecialValueFor("bounce_range")
local falloff = state.falloffPct / 100
local nextMult = state.damageMult * falloff
if state.bouncesRemaining <= 0 then
self.glaiveChain = nil
return
end
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
target:GetAbsOrigin(),
nil,
bounceRange,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_CLOSEST,
false
)
local next
local targetIdx = target:entindex()
for ____, e in ipairs(enemies) do
do
if not e or not e:IsAlive() then
goto __continue11
end
if e:entindex() == targetIdx then
goto __continue11
end
next = e
break
end
::__continue11::
end
if not next then
self.glaiveChain = nil
return
end
local nextState = {attacker = state.attacker, bouncesRemaining = state.bouncesRemaining - 1, damageMult = nextMult, falloffPct = state.falloffPct}
self:LaunchGlaive(target, next, nextState)
end
ability_luna_moon_glaive_custom = __TS__Decorate(
ability_luna_moon_glaive_custom,
ability_luna_moon_glaive_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_luna_moon_glaive_custom"}
)
____exports.ability_luna_moon_glaive_custom = ability_luna_moon_glaive_custom
____exports.modifier_luna_moon_glaive_passive = __TS__Class()
local modifier_luna_moon_glaive_passive = ____exports.modifier_luna_moon_glaive_passive
modifier_luna_moon_glaive_passive.name = "modifier_luna_moon_glaive_passive"
modifier_luna_moon_glaive_passive.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_moon_glaive_custom.lua"
__TS__ClassExtends(modifier_luna_moon_glaive_passive, BaseModifier)
function modifier_luna_moon_glaive_passive.prototype.IsHidden(self)
return true
end
function modifier_luna_moon_glaive_passive.prototype.IsPurgable(self)
return false
end
function modifier_luna_moon_glaive_passive.prototype.DeclareFunctions(self)
return {MODIFIER_EVENT_ON_ATTACK_LANDED}
end
function modifier_luna_moon_glaive_passive.prototype.OnAttackLanded(self, event)
if not IsServer() then
return
end
local parent = self:GetParent()
if parent:PassivesDisabled() then
return
end
if event.attacker ~= parent then
return
end
local primary = event.target
if not primary or not primary:IsAlive() then
return
end
local ability = self:GetAbility()
if not ability then
return
end
local bounceRange = ability:GetSpecialValueFor("bounce_range")
local totalBounces = math.floor(ability:GetSpecialValueFor("moon_glaive_bounce_count"))
local basePct = ability:GetSpecialValueFor("bounce_damage_pct") / 100
local falloff = ability:GetSpecialValueFor("bounce_falloff_pct")
local enemies = FindUnitsInRadius(
parent:GetTeamNumber(),
primary:GetAbsOrigin(),
nil,
bounceRange,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_CLOSEST,
false
)
local first
local primaryIdx = primary:entindex()
for ____, e in ipairs(enemies) do
do
if not e or not e:IsAlive() then
goto __continue25
end
if e:entindex() == primaryIdx then
goto __continue25
end
first = e
break
end
::__continue25::
end
if not first or totalBounces <= 0 then
return
end
local state = {attacker = parent, bouncesRemaining = totalBounces - 1, damageMult = basePct, falloffPct = falloff}
ability:LaunchGlaive(primary, first, state)
end
modifier_luna_moon_glaive_passive = __TS__Decorate(
modifier_luna_moon_glaive_passive,
modifier_luna_moon_glaive_passive,
{registerModifier(nil)},
{kind = "class", name = "modifier_luna_moon_glaive_passive"}
)
____exports.modifier_luna_moon_glaive_passive = modifier_luna_moon_glaive_passive
return ____exports
@@ -0,0 +1,509 @@
local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__Decorate = ____lualib.__TS__Decorate
local Set = ____lualib.Set
local __TS__New = ____lualib.__TS__New
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 function applyTwinGlaiveFacetVuln(self, caster, victim, ability)
if not IsServer() then
return
end
if not victim or victim:IsNull() or not victim:IsAlive() then
return
end
local dur = ability:GetSpecialValueFor("twin_facet_vuln_duration")
if dur <= 0 then
return
end
victim:AddNewModifier(caster, ability, ____exports.modifier_luna_twin_glaives_facet_vuln.name, {duration = dur})
end
--- Как в ванили Wild Axes / примере temple_guardian: vpcf цепляется к юниту оси, а не к linear projectile.
local WILD_AXE_PARTICLE = "particles/twin_glaves.vpcf"
local BEASTMASTER_AXE_UNIT = "npc_dota_beastmaster_axe"
local THINK_INTERVAL = 0.03
--- Близко к владельцу — считаем, что ось вернулась
local RETURN_ARRIVE_DIST = 96
--- Минимальный радиус «круга» урона вокруг оси (шире узкой линии)
local MIN_DAMAGE_RADIUS = 140
--- Множитель к projectile_width для зоны урона
local DAMAGE_RADIUS_WIDTH_MULT = 2.25
--- Слот W: слева/справа → дугой к цели (не прямиком) → перекрёстом назад; широкий круг урона; главная цель не промахивается.
____exports.ability_luna_twin_glaives_custom = __TS__Class()
local ability_luna_twin_glaives_custom = ____exports.ability_luna_twin_glaives_custom
ability_luna_twin_glaives_custom.name = "ability_luna_twin_glaives_custom"
ability_luna_twin_glaives_custom.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_twin_glaives_custom.lua"
__TS__ClassExtends(ability_luna_twin_glaives_custom, BaseAbility)
function ability_luna_twin_glaives_custom.prototype.Precache(self, context)
PrecacheResource("particle", WILD_AXE_PARTICLE, context)
end
function ability_luna_twin_glaives_custom.prototype.GetCastRange(self, location, target)
return self:GetSpecialValueFor("cast_range")
end
function ability_luna_twin_glaives_custom.prototype.OnSpellStart(self)
if not IsServer() then
return
end
local caster = self:GetCaster()
local cursor = self:GetCursorPosition()
local unitUnderCursor = self:GetCursorTarget()
local primaryIdx = unitUnderCursor and not unitUnderCursor:IsNull() and unitUnderCursor:IsAlive() and unitUnderCursor:GetTeamNumber() ~= caster:GetTeamNumber() and unitUnderCursor:entindex() or -1
local origin = caster:GetAbsOrigin()
local speed = self:GetSpecialValueFor("projectile_speed")
local maxRange = self:GetSpecialValueFor("projectile_range")
local width = self:GetSpecialValueFor("projectile_width")
local spread = self:GetSpecialValueFor("axe_spread")
local damage = self:GetSpecialValueFor("glaive_damage")
local toTarget = cursor - origin
local flat = Vector(toTarget.x, toTarget.y, 0)
local len2d = flat:Length2D()
local fwd = len2d < 16 and Vector(
caster:GetForwardVector().x,
caster:GetForwardVector().y,
0
):Normalized() or flat:Normalized()
local perp = Vector(-fwd.y, fwd.x, 0)
local lift = 72
local left = Vector(origin.x + perp.x * spread, origin.y + perp.y * spread, origin.z + lift)
local right = Vector(origin.x - perp.x * spread, origin.y - perp.y * spread, origin.z + lift)
local mid = Vector((left.x + right.x) / 2, (left.y + right.y) / 2, (left.z + right.z) / 2)
local toEnemy = cursor - mid
local flatEn = Vector(toEnemy.x, toEnemy.y, 0)
local distEn = flatEn:Length2D()
local dirToEnemy = distEn < 8 and fwd or flatEn:Normalized()
local travel = math.min(distEn, maxRange)
local endPoint = Vector(
mid.x + dirToEnemy.x * travel,
mid.y + dirToEnemy.y * travel,
mid.z + toEnemy.z / math.max(distEn, 1) * travel * 0.35
)
caster:AddNewModifier(caster, self, ____exports.modifier_luna_twin_glaives_flight.name, {
s = speed,
w = width,
sp = spread,
dmg = damage,
lx = left.x,
ly = left.y,
lz = left.z,
rx = right.x,
ry = right.y,
rz = right.z,
ex = endPoint.x,
ey = endPoint.y,
ez = endPoint.z,
te = primaryIdx
})
EmitSoundOn("Hero_Beastmaster.WildAxes", caster)
end
ability_luna_twin_glaives_custom = __TS__Decorate(
ability_luna_twin_glaives_custom,
ability_luna_twin_glaives_custom,
{registerAbility(nil)},
{kind = "class", name = "ability_luna_twin_glaives_custom"}
)
____exports.ability_luna_twin_glaives_custom = ability_luna_twin_glaives_custom
____exports.modifier_luna_twin_glaives_flight = __TS__Class()
local modifier_luna_twin_glaives_flight = ____exports.modifier_luna_twin_glaives_flight
modifier_luna_twin_glaives_flight.name = "modifier_luna_twin_glaives_flight"
modifier_luna_twin_glaives_flight.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_twin_glaives_custom.lua"
__TS__ClassExtends(modifier_luna_twin_glaives_flight, BaseModifier)
function modifier_luna_twin_glaives_flight.prototype.____constructor(self, ...)
BaseModifier.prototype.____constructor(self, ...)
self.outSegmentLen = 1
self.outT = 0
self.returning = false
self.hitForward = __TS__New(Set)
self.hitBackward = __TS__New(Set)
self.primaryEntIndex = -1
self.primaryOutboundEnsured = false
self.finished = false
end
function modifier_luna_twin_glaives_flight.prototype.setupAxeDummy(self, unit, caster, ability)
unit:AddNewModifier(caster, ability, "modifier_invulnerable", {})
unit:AddNewModifier(caster, ability, "modifier_attack_immune", {})
unit:AddNewModifier(caster, ability, "modifier_no_healthbar", {})
unit:AddNewModifier(caster, ability, "modifier_phased", {})
unit:SetDayTimeVisionRange(0)
unit:SetNightTimeVisionRange(0)
unit:SetAcquisitionRange(0)
end
function modifier_luna_twin_glaives_flight.prototype.IsHidden(self)
return true
end
function modifier_luna_twin_glaives_flight.prototype.IsDebuff(self)
return false
end
function modifier_luna_twin_glaives_flight.prototype.RemoveOnDeath(self)
return true
end
function modifier_luna_twin_glaives_flight.prototype.OnCreated(self, params)
if not IsServer() then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not ability or not parent or not parent:IsAlive() then
self:Destroy()
return
end
self.speed = params.s
self.damageRadius = math.max(MIN_DAMAGE_RADIUS, params.w * DAMAGE_RADIUS_WIDTH_MULT)
self.spread = params.sp
self.damage = params.dmg
self.startL = Vector(params.lx, params.ly, params.lz)
self.startR = Vector(params.rx, params.ry, params.rz)
self.posL = self.startL
self.posR = self.startR
self.endPoint = Vector(params.ex, params.ey, params.ez)
self.primaryEntIndex = params.te
self.controlL = self:bezierControlOutward(self.startL, self.endPoint, 1)
self.controlR = self:bezierControlOutward(self.startR, self.endPoint, -1)
local lenL = (self.endPoint - self.startL):Length()
local lenR = (self.endPoint - self.startR):Length()
self.outSegmentLen = math.max(48, (lenL + lenR) / 2 * 1.22)
local team = parent:GetTeamNumber()
self.hammerL = CreateUnitByName(
BEASTMASTER_AXE_UNIT,
self.startL,
false,
nil,
nil,
team
)
self.hammerR = CreateUnitByName(
BEASTMASTER_AXE_UNIT,
self.startR,
false,
nil,
nil,
team
)
if not self.hammerL or not self.hammerR then
self:cleanup()
self:Destroy()
return
end
self.hammerL:AddEffects(EF_NODRAW)
self.hammerR:AddEffects(EF_NODRAW)
self:setupAxeDummy(self.hammerL, parent, ability)
self:setupAxeDummy(self.hammerR, parent, ability)
self.pfxL = ParticleManager:CreateParticle(WILD_AXE_PARTICLE, PATTACH_CUSTOMORIGIN, nil)
ParticleManager:SetParticleControlEnt(
self.pfxL,
0,
self.hammerL,
PATTACH_ABSORIGIN_FOLLOW,
nil,
self.hammerL:GetAbsOrigin(),
true
)
self.pfxR = ParticleManager:CreateParticle(WILD_AXE_PARTICLE, PATTACH_CUSTOMORIGIN, nil)
ParticleManager:SetParticleControlEnt(
self.pfxR,
0,
self.hammerR,
PATTACH_ABSORIGIN_FOLLOW,
nil,
self.hammerR:GetAbsOrigin(),
true
)
self:StartIntervalThink(THINK_INTERVAL)
end
function modifier_luna_twin_glaives_flight.prototype.bezierControlOutward(self, start, ____end, sideSign)
local dx = ____end.x - start.x
local dy = ____end.y - start.y
local len2d = math.sqrt(dx * dx + dy * dy)
local midZ = (start.z + ____end.z) / 2
local mid = Vector((start.x + ____end.x) / 2, (start.y + ____end.y) / 2, midZ)
if len2d < 12 then
return mid
end
local nx = -dy / len2d
local ny = dx / len2d
local bulge = math.min(len2d * 0.44, self.spread * 2.6)
return Vector(mid.x + nx * bulge * sideSign, mid.y + ny * bulge * sideSign, mid.z)
end
function modifier_luna_twin_glaives_flight.prototype.bezierQuadratic(self, p0, p1, p2, t)
local u = math.min(
1,
math.max(0, 1 - t)
)
local s = math.min(
1,
math.max(0, t)
)
return Vector(u * u * p0.x + 2 * u * s * p1.x + s * s * p2.x, u * u * p0.y + 2 * u * s * p1.y + s * s * p2.y, u * u * p0.z + 2 * u * s * p1.z + s * s * p2.z)
end
function modifier_luna_twin_glaives_flight.prototype.OnIntervalThink(self)
if not IsServer() or self.finished then
return
end
local parent = self:GetParent()
local ability = self:GetAbility()
if not parent or not parent:IsAlive() or not ability or not self.hammerL or not self.hammerR then
self:finish()
return
end
local dt = THINK_INTERVAL
if not self.returning then
self.outT = self.outT + self.speed * dt / self.outSegmentLen
if self.outT >= 1 then
self.outT = 1
self.posL = self.endPoint
self.posR = self.endPoint
self.returning = true
else
self.posL = self:bezierQuadratic(self.startL, self.controlL, self.endPoint, self.outT)
self.posR = self:bezierQuadratic(self.startR, self.controlR, self.endPoint, self.outT)
end
self.hammerL:SetAbsOrigin(self.posL)
self.hammerR:SetAbsOrigin(self.posR)
self:damageAlongAxe(
self.hammerL:GetAbsOrigin(),
self.hitForward,
parent,
ability
)
self:damageAlongAxe(
self.hammerR:GetAbsOrigin(),
self.hitForward,
parent,
ability
)
if self.returning then
self:ensurePrimaryOutboundHit(parent, ability)
end
return
end
local lift = 72
local fwd2 = Vector(
parent:GetForwardVector().x,
parent:GetForwardVector().y,
0
)
local len = fwd2:Length2D()
local fwd = len > 0.01 and fwd2:Normalized() or Vector(1, 0, 0)
local perp = Vector(-fwd.y, fwd.x, 0)
local o = parent:GetAbsOrigin()
local shoulderL = Vector(o.x + perp.x * self.spread, o.y + perp.y * self.spread, o.z + lift)
local shoulderR = Vector(o.x - perp.x * self.spread, o.y - perp.y * self.spread, o.z + lift)
self.posL = self:moveTowards(self.posL, shoulderR, self.speed, dt)
self.posR = self:moveTowards(self.posR, shoulderL, self.speed, dt)
self.hammerL:SetAbsOrigin(self.posL)
self.hammerR:SetAbsOrigin(self.posR)
self:damageAlongAxe(
self.hammerL:GetAbsOrigin(),
self.hitBackward,
parent,
ability
)
self:damageAlongAxe(
self.hammerR:GetAbsOrigin(),
self.hitBackward,
parent,
ability
)
local dL = (shoulderR - self.posL):Length2D()
local dR = (shoulderL - self.posR):Length2D()
if dL < RETURN_ARRIVE_DIST and dR < RETURN_ARRIVE_DIST then
self:finish()
end
end
function modifier_luna_twin_glaives_flight.prototype.ensurePrimaryOutboundHit(self, caster, ability)
if self.primaryOutboundEnsured then
return
end
local pe = self.primaryEntIndex
if pe < 0 then
return
end
local ent = EntIndexToHScript(self.primaryEntIndex)
if not ent or ent:IsNull() or not ent:IsAlive() then
self.primaryOutboundEnsured = true
return
end
if ent:GetTeamNumber() == caster:GetTeamNumber() then
self.primaryOutboundEnsured = true
return
end
if self.hitForward:has(self.primaryEntIndex) then
self.primaryOutboundEnsured = true
return
end
ApplyDamage({
victim = ent,
attacker = caster,
damage = self.damage + self:GetCaster():GetAverageTrueAttackDamage(ent) * 0.5,
damage_type = DAMAGE_TYPE_PHYSICAL,
damage_flags = DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION,
ability = ability
})
ApplyDamage({
victim = ent,
attacker = caster,
damage = self.damage + self:GetCaster():GetAverageTrueAttackDamage(ent) * 0.5,
damage_type = DAMAGE_TYPE_MAGICAL,
damage_flags = DOTA_DAMAGE_FLAG_ATTACK_MODIFIER,
ability = ability
})
applyTwinGlaiveFacetVuln(nil, caster, ent, ability)
self.hitForward:add(self.primaryEntIndex)
self.primaryOutboundEnsured = true
end
function modifier_luna_twin_glaives_flight.prototype.moveTowards(self, from, to, speed, dt)
local delta = to - from
local dist = delta:Length()
if dist < 1 then
return to
end
local step = math.min(speed * dt, dist)
local dir = delta:Normalized()
return from + dir * step
end
function modifier_luna_twin_glaives_flight.prototype.damageAlongAxe(self, pos, hitSet, caster, ability)
local enemies = FindUnitsInRadius(
caster:GetTeamNumber(),
pos,
nil,
self.damageRadius,
DOTA_UNIT_TARGET_TEAM_ENEMY,
DOTA_UNIT_TARGET_HERO + DOTA_UNIT_TARGET_BASIC,
DOTA_UNIT_TARGET_FLAG_NONE,
FIND_ANY_ORDER,
false
)
for ____, enemy in ipairs(enemies) do
do
if not enemy or enemy:IsNull() or not enemy:IsAlive() then
goto __continue38
end
local idx = enemy:entindex()
if hitSet:has(idx) then
goto __continue38
end
hitSet:add(idx)
ApplyDamage({
victim = enemy,
attacker = caster,
damage = self.damage + self:GetCaster():GetAverageTrueAttackDamage(enemy) * 0.5,
damage_type = DAMAGE_TYPE_PHYSICAL,
damage_flags = DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION,
ability = ability
})
ApplyDamage({
victim = enemy,
attacker = caster,
damage = self.damage + self:GetCaster():GetAverageTrueAttackDamage(enemy) * 0.5,
damage_type = DAMAGE_TYPE_MAGICAL,
damage_flags = DOTA_DAMAGE_FLAG_ATTACK_MODIFIER,
ability = ability
})
applyTwinGlaiveFacetVuln(nil, caster, enemy, ability)
end
::__continue38::
end
end
function modifier_luna_twin_glaives_flight.prototype.OnDestroy(self)
if not IsServer() then
return
end
self:cleanup()
end
function modifier_luna_twin_glaives_flight.prototype.finish(self)
if self.finished then
return
end
self.finished = true
self:StartIntervalThink(-1)
self:Destroy()
end
function modifier_luna_twin_glaives_flight.prototype.cleanup(self)
if self.pfxL ~= nil then
ParticleManager:DestroyParticle(self.pfxL, false)
ParticleManager:ReleaseParticleIndex(self.pfxL)
self.pfxL = nil
end
if self.pfxR ~= nil then
ParticleManager:DestroyParticle(self.pfxR, false)
ParticleManager:ReleaseParticleIndex(self.pfxR)
self.pfxR = nil
end
if self.hammerL then
UTIL_Remove(self.hammerL)
self.hammerL = nil
end
if self.hammerR then
UTIL_Remove(self.hammerR)
self.hammerR = nil
end
end
modifier_luna_twin_glaives_flight = __TS__Decorate(
modifier_luna_twin_glaives_flight,
modifier_luna_twin_glaives_flight,
{registerModifier(nil)},
{kind = "class", name = "modifier_luna_twin_glaives_flight"}
)
____exports.modifier_luna_twin_glaives_flight = modifier_luna_twin_glaives_flight
____exports.modifier_luna_twin_glaives_facet_vuln = __TS__Class()
local modifier_luna_twin_glaives_facet_vuln = ____exports.modifier_luna_twin_glaives_facet_vuln
modifier_luna_twin_glaives_facet_vuln.name = "modifier_luna_twin_glaives_facet_vuln"
modifier_luna_twin_glaives_facet_vuln.____file_path = "scripts/vscripts/abilities/heroes/luna/ability_luna_twin_glaives_custom.lua"
__TS__ClassExtends(modifier_luna_twin_glaives_facet_vuln, BaseModifier)
function modifier_luna_twin_glaives_facet_vuln.prototype.IsHidden(self)
return false
end
function modifier_luna_twin_glaives_facet_vuln.prototype.IsDebuff(self)
return true
end
function modifier_luna_twin_glaives_facet_vuln.prototype.IsPurgable(self)
return true
end
function modifier_luna_twin_glaives_facet_vuln.prototype.OnRefresh(self, params)
local ____self_SetDuration_2 = self.SetDuration
local ____opt_0 = self:GetAbility()
____self_SetDuration_2(
self,
____opt_0 and ____opt_0:GetSpecialValueFor("twin_facet_vuln_duration"),
true
)
self:IncrementStackCount()
end
function modifier_luna_twin_glaives_facet_vuln.prototype.DeclareFunctions(self)
return {MODIFIER_PROPERTY_INCOMING_DAMAGE_PERCENTAGE, MODIFIER_PROPERTY_INCOMING_PHYSICAL_DAMAGE_PERCENTAGE}
end
function modifier_luna_twin_glaives_facet_vuln.prototype.GetModifierIncomingDamage_Percentage(self, event)
local ab = self:GetAbility()
if not ab then
return 0
end
local pct = ab:GetSpecialValueFor("twin_facet_pct")
local value = self:GetStackCount() * (pct / 100)
print(value)
return self:GetStackCount() * pct
end
function modifier_luna_twin_glaives_facet_vuln.prototype.GetModifierIncomingPhysicalDamage_Percentage(self, event)
local ab = self:GetAbility()
if not ab then
return 0
end
local pct = ab:GetSpecialValueFor("twin_facet_pct")
local value = self:GetStackCount() * (pct / 100)
print(value)
return self:GetStackCount() * pct
end
function modifier_luna_twin_glaives_facet_vuln.prototype.GetTexture(self)
return "luna_lunar_orbit"
end
modifier_luna_twin_glaives_facet_vuln = __TS__Decorate(
modifier_luna_twin_glaives_facet_vuln,
modifier_luna_twin_glaives_facet_vuln,
{registerModifier(nil)},
{kind = "class", name = "modifier_luna_twin_glaives_facet_vuln"}
)
____exports.modifier_luna_twin_glaives_facet_vuln = modifier_luna_twin_glaives_facet_vuln
return ____exports

Some files were not shown because too many files have changed in this diff Show More