evolve
Магазин/Общие библиотеки

threats

Enemy casts the overlays and the dodger react to: which particle system or sound belongs to which ability, where its spot is, and its radius, width, speed and timing from valve's ability data; and for

hunnyc0 скриптов используют
ПоддержкаИсходник открыт
Подключить в скрипт
pack.json
"requires": { "threats": "^1.0" }
твой lua
local threats = require("lib/threats")

Игрокам ставить ничего не нужно: скрипт приносит библиотеку сам, любую версию в пределах диапазона. Правку можно проверить до публикации в dev-сессии, в scripts/lib/threats/.

API
threats.value(ab: string, key: string, level?: integer): number?#

One number from valve's data for a catalogued ability.

Параметры
ab string ability name
key string a special (radius), or AbilityCastPoint, AbilityChannelTime, AbilityDuration, AbilityCastRange
level integer ability level, 1-based
Возвращает
number? nil when the ability is not catalogued or has no such value

A list by level picks level: nil or past the last level reads the last one, below 1 the first.

local Threats = require("lib/threats")
Threats.value("faceless_void_chronosphere", "duration", 2)   -- 4.25
threats.hero(ab: string): string?#

The hero that owns a catalogued ability.

Параметры
ab string
Возвращает
string? npc_dota_hero_*
threats.short_name(name_or_path: string): string?#

The short name of a particle system: the file name without .vpcf / .vpcf_c.

Параметры
name_or_path string particles/units/heroes/hero_lina/lina_spell_light_strike_array.vpcf or the short name
Возвращает
string?
threats.ability(ab: string, level?: integer): threats.Sizes?#

Sizes of a catalogued ability at a level.

Параметры
ab string
level integer
Возвращает
threats.Sizes?

A new table every call; nil sizes are the ones the catalog has no value for.

local s = Threats.ability("faceless_void_chronosphere")   -- level nil: the last level
print(s.radius, s.life)                                    -- 500  4.75
threats.particle(name_or_path: string, level?: integer): threats.Particle?#

A catalogued particle system: its ability, where the spot is, and its sizes.

Параметры
name_or_path string
level integer
Возвращает
threats.Particle?

A size the system row lacks comes from its ability.

events.register("on_particle_create", function(p)
   local t = Threats.particle(p.name)   -- short name or full path
   if t and t.radius then draw_ring(p.position, t.radius) end
end)
threats.sound(sound_name: string, level?: integer): threats.Sizes?#

A cast the dodger hears by its sound: the ability and its sizes.

Параметры
sound_name string the sound event, Ability.SandKing_BurrowStrike
level integer
Возвращает
threats.Sizes?
threats.particles_of(ab: string): string[]#

Short names of the catalogued particle systems of one ability, sorted.

Параметры
ab string
Возвращает
string[]
threats.tier(ab: string): threats.Tier?#

How a hero ability threatens, from its mechanics in valve's data: the shape of the threat and

Параметры
ab string
Возвращает
threats.Tier? a new table; nil when the data gives the ability no threat

the special that sizes it. Covers every hero ability that can hurt or disable, not only the catalogued ones.

local t = Threats.tier("lina_light_strike_array")   -- { tier = "aoe_point", radiusKey = "light_strike_array_aoe" }
threats.tiers(): table<string, threats.Tier>#

Every ability tier knows, as a new map from the ability name to its tier.

Возвращает
table<string, threats.Tier>
threats.list(kind: "abilities"|"particles"|"sounds"|"tiers"): string[]#

Every catalogued name of one kind, sorted. tiers lists the abilities tier knows.

Параметры
kind "abilities"|"particles"|"sounds"|"tiers"
Возвращает
string[]
threats.ice_blast_radius(travel: number, level?: integer): number?#

Ice Blast's explosion radius after the tracer travelled travel units.

Параметры
travel number distance from the cast point to the release
level integer
Возвращает
number? nil when the data lacks one of the four values

Valve's rule: radius_min + radius_grow per second of flight, capped at radius_max.

threats.Sizes

Поля
ab: stringthe ability
hero: string?the hero that owns it, npc_dota_hero_*
radius: number?ground circle
width: number?a line's half-width
speed: number?units per second
length: number?a line's reach
delay: number?seconds from the system or sound to the hit
life: number?seconds the zone stays dangerous after the hit

threats.Particle

Поля
name: stringthe short name, the file name without .vpcf
path: string?the full name, when code matches the hash
cps: integer[]?control points that carry the spot as a world position; empty: no spot
tell: booleanthe warning before the spell, not the spell
fog: booleansent to every team, created in fogged casts (docs/FOG_PARTICLES.md)
lab: booleanalso seen arriving live from a caster in the fog

threats.Tier

Поля
tier: stringtarget_unit, target_disable, aoe_point, aoe_notarget, channel or global
radiusKey: string?the special that holds its zone; ask the live ability, talents included
projectile: boolean?it travels
isGlobal: boolean?it reaches anywhere on the map
Описание

lib/threats

Enemy casts the overlays and the dodger react to: which particle system or sound belongs to which ability, where its spot is, and its radius, width, speed and timing from valve's ability data; and for every hero ability the shape of its threat (tier). One catalog instead of three hand tables (#132 step 8). Its readers keep only their own choice of names and how to react: utea/alerts/danger_catalog.lua, utea/minimap/threat_tracker_catalog.lua, the special captures in utea/dodger/dodger.lua, and the ice blast ring in utea/awareness/awareness.lua and utea/minimap/threat_tracker_logic.lua. The dodger reads tiers() and merges its own utea/dodger/dodge_overrides.lua over it.

local Threats = require("lib/threats")

local p = Threats.particle("faceless_void_chronosphere")   -- or the full .vpcf path
-- { ab = "faceless_void_chronosphere", hero = "npc_dota_hero_faceless_void", radius = 500,
--   delay = 0, life = 4.75, cps = { 0 }, fog = true, lab = true, tell = false, path = "particles/..." }
local lsa = Threats.particle("lina_spell_light_strike_array", 2)   -- sizes at level 2
local r = Threats.ice_blast_radius(travel)                          -- 300 + 50 per second, max 1000
local t = Threats.tier("lina_light_strike_array")   -- { tier = "aoe_point", radiusKey = "light_strike_array_aoe" }

files

file what
catalog.lua by hand: per ability the data key of each size (or a function of keys, or a literal with its reason), per particle system its ability and spot, per sound its ability
data/values.lua generated by tools/threats/gen_values.py from docs/dota_abilities/_data/combat.json: every numeric special of the catalog's abilities by level, the hero, and AbilityCastPoint, AbilityChannelTime, AbilityDuration, AbilityCastRange. The dump pipeline reruns it (tools/dumper/agentfmt.py ABILITY_GENERATORS)
data/tiers.lua generated by tools/threats/gen_tiers.py from the same json, same pipeline: for every hero ability that can hurt or disable, its tier, the special key of its zone (radiusKey), projectile, isGlobal. Keys only, never the numbers: the reader asks the live ability, so talents and scepter count

A new ability: add its row to C.abilities (one line start, 4 spaces, the generator reads the keys), run python tools/threats/gen_values.py, then the selftest. Not here: utea/dodger/dodge_overrides.lua (the dodger's corrections and item reactions) and utea/core/autopilot/threat.lua (autopilot policy).

sizes

field meaning
radius ground circle
width a line's half-width, as valve's *_width / *_radius
speed units per second
length a line's reach
delay seconds from the system or sound to the hit
life seconds the zone stays dangerous after the hit

A level picks from a list by level: nil or past the last level reads the last one, so a reader that does not know the caster's level gets the largest zone. A size the particle row lacks comes from its ability; a size neither has is nil and the reader keeps its own default. A data key that disappears after a patch reads nil with one log.warn.

api

function returns
particle(name_or_path, level?) a new table: name ab hero path cps tell fog lab and the sizes; nil when not catalogued
ability(ab, level?) ab hero and the sizes
sound(sound_name, level?) name ab hero and the sizes
value(ab, key, level?) one number from data/values.lua
hero(ab) npc_dota_hero_*
particles_of(ab) short names of its systems, sorted
tier(ab) tier radiusKey projectile isGlobal; nil when the data gives the ability no threat
tiers() a new map, ability name to its tier(ab)
list(kind) sorted names of abilities, particles, sounds or tiers; another kind errors
short_name(name_or_path) the file name without .vpcf / .vpcf_c
ice_blast_radius(travel, level?) radius_min + radius_grow per second of flight (travel / speed), capped at radius_max

Stateless: no events, no registry, every call returns a fresh table.

test

tools\lua\lua.exe scripts\lib\threats\selftest.lua from the repo root: the generated file and the catalog name the same abilities, every size resolves to a number at every level, overrides, copies, well-formed tiers and the ice blast rule.

Исходник

Код версии 1.0.1, как его получает клиент. Байткод в сборке собран из этих файлов.

init.lua235 строк
---@diagnostic disable: undefined-global
-- lib/threats: enemy casts the overlays and the dodger react to. which particle system or sound
-- belongs to which ability, and its sizes from valve's data. api and data in README.md.
--
-- Owns: sizes and timings of dangerous casts (catalog.lua, data/values.lua), the threat tier
-- of every hero ability (data/tiers.lua)
-- Must not: register events, keep state, decide what to report or dodge.

local Catalog = require("lib/threats/catalog")
local Values = require("lib/threats/data/values")
local Tiers = require("lib/threats/data/tiers")

local M = {}

local SIZES = { "radius", "width", "speed", "length", "delay", "life" }

---@class threats.Sizes
---@field ab string the ability
---@field hero string? the hero that owns it, `npc_dota_hero_*`
---@field radius number? ground circle
---@field width number? a line's half-width
---@field speed number? units per second
---@field length number? a line's reach
---@field delay number? seconds from the system or sound to the hit
---@field life number? seconds the zone stays dangerous after the hit

---@class threats.Particle: threats.Sizes
---@field name string the short name, the file name without .vpcf
---@field path string? the full name, when code matches the hash
---@field cps integer[]? control points that carry the spot as a world position; empty: no spot
---@field tell boolean the warning before the spell, not the spell
---@field fog boolean sent to every team, created in fogged casts (docs/FOG_PARTICLES.md)
---@field lab boolean also seen arriving live from a caster in the fog

local warned = {}
local function warn_once(key, msg)
    if warned[key] then return end
    warned[key] = true
    pcall(function() log.warn("[lib/threats] " .. msg) end)
end

local function pick(v, level)
    if type(v) ~= "table" then return v end
    local n = #v
    if n == 0 then return nil end
    if not level or level >= n then return v[n] end
    if level < 1 then return v[1] end
    return v[math.floor(level)]
end

---One number from valve's data for a catalogued ability.
---A list by level picks `level`: nil or past the last level reads the last one, below 1 the first.
---```lua
---local Threats = require("lib/threats")
---Threats.value("faceless_void_chronosphere", "duration", 2)   -- 4.25
---```
---@param ab string ability name
---@param key string a special (`radius`), or AbilityCastPoint, AbilityChannelTime, AbilityDuration, AbilityCastRange
---@param level? integer ability level, 1-based
---@return number? # nil when the ability is not catalogued or has no such value
function M.value(ab, key, level)
    local row = Values[ab]
    if not row or key == "hero" then return nil end
    return pick(row[key], level)
end

---The hero that owns a catalogued ability.
---@param ab string
---@return string? # `npc_dota_hero_*`
function M.hero(ab)
    local row = Values[ab]
    return row and row.hero or nil
end

local function resolve(spec, ab, level, what)
    local t = type(spec)
    if t == "number" or spec == nil then return spec end
    if t == "string" then
        local v = M.value(ab, spec, level)
        if v == nil then warn_once(ab .. spec, ab .. " has no " .. spec .. " in data/values.lua (" .. what .. ")") end
        return v
    end
    if t == "function" then
        local ok, v = pcall(spec, function(k, l) return M.value(ab, k, l) end, level)
        if ok and type(v) == "number" then return v end
        warn_once(ab .. what, ab .. " " .. what .. " failed: " .. tostring(v))
        return nil
    end
    return nil
end

local function fill(out, row, base, ab, level)
    for _, f in ipairs(SIZES) do
        local spec = row[f]
        if spec == nil and base then spec = base[f] end
        out[f] = resolve(spec, ab, level, f)
    end
    return out
end

---The short name of a particle system: the file name without .vpcf / .vpcf_c.
---@param name_or_path string `particles/units/heroes/hero_lina/lina_spell_light_strike_array.vpcf` or the short name
---@return string?
function M.short_name(name_or_path)
    if type(name_or_path) ~= "string" then return nil end
    local s = name_or_path:match("([^/\\]+)$") or name_or_path
    return (s:gsub("%.vpcf_c$", ""):gsub("%.vpcf$", ""))
end

---Sizes of a catalogued ability at a level.
---A new table every call; nil sizes are the ones the catalog has no value for.
---```lua
---local s = Threats.ability("faceless_void_chronosphere")   -- level nil: the last level
---print(s.radius, s.life)                                    -- 500  4.75
---```
---@param ab string
---@param level? integer
---@return threats.Sizes?
function M.ability(ab, level)
    local row = Catalog.abilities[ab]
    if not row then return nil end
    return fill({ ab = ab, hero = M.hero(ab) }, row, nil, ab, level)
end

---A catalogued particle system: its ability, where the spot is, and its sizes.
---A size the system row lacks comes from its ability.
---```lua
---events.register("on_particle_create", function(p)
---    local t = Threats.particle(p.name)   -- short name or full path
---    if t and t.radius then draw_ring(p.position, t.radius) end
---end)
---```
---@param name_or_path string
---@param level? integer
---@return threats.Particle?
function M.particle(name_or_path, level)
    local name = M.short_name(name_or_path)
    local row = name and Catalog.particles[name]
    if not row then return nil end
    local ab = row.ab
    local out = {
        name = name, ab = ab, hero = M.hero(ab), path = row.path,
        tell = row.tell == true, fog = row.fog == true, lab = row.lab == true,
    }
    if row.cps then
        out.cps = {}
        for i, cp in ipairs(row.cps) do out.cps[i] = cp end
    end
    return fill(out, row, Catalog.abilities[ab], ab, level)
end

---A cast the dodger hears by its sound: the ability and its sizes.
---@param sound_name string the sound event, `Ability.SandKing_BurrowStrike`
---@param level? integer
---@return threats.Sizes?
function M.sound(sound_name, level)
    local row = Catalog.sounds[sound_name]
    if not row then return nil end
    local ab = row.ab
    return fill({ ab = ab, hero = M.hero(ab), name = sound_name }, row, Catalog.abilities[ab], ab, level)
end

---Short names of the catalogued particle systems of one ability, sorted.
---@param ab string
---@return string[]
function M.particles_of(ab)
    local out = {}
    for name, row in pairs(Catalog.particles) do
        if row.ab == ab then out[#out + 1] = name end
    end
    table.sort(out)
    return out
end

---@class threats.Tier
---@field tier string `target_unit`, `target_disable`, `aoe_point`, `aoe_notarget`, `channel` or `global`
---@field radiusKey string? the special that holds its zone; ask the live ability, talents included
---@field projectile boolean? it travels
---@field isGlobal boolean? it reaches anywhere on the map

local function tier_copy(row)
    return { tier = row.tier, radiusKey = row.radiusKey, projectile = row.projectile, isGlobal = row.isGlobal }
end

---How a hero ability threatens, from its mechanics in valve's data: the shape of the threat and
---the special that sizes it. Covers every hero ability that can hurt or disable, not only the
---catalogued ones.
---```lua
---local t = Threats.tier("lina_light_strike_array")   -- { tier = "aoe_point", radiusKey = "light_strike_array_aoe" }
---```
---@param ab string
---@return threats.Tier? # a new table; nil when the data gives the ability no threat
function M.tier(ab)
    local row = Tiers[ab]
    return row and tier_copy(row)
end

---Every ability `tier` knows, as a new map from the ability name to its tier.
---@return table<string, threats.Tier>
function M.tiers()
    local out = {}
    for ab, row in pairs(Tiers) do out[ab] = tier_copy(row) end
    return out
end

---Every catalogued name of one kind, sorted. `tiers` lists the abilities `tier` knows.
---@param kind "abilities"|"particles"|"sounds"|"tiers"
---@return string[]
function M.list(kind)
    local t = kind == "tiers" and Tiers or Catalog[kind]
    if type(t) ~= "table" then error("lib/threats.list: kind is abilities, particles, sounds or tiers, got " .. tostring(kind), 2) end
    local out = {}
    for k in pairs(t) do out[#out + 1] = k end
    table.sort(out)
    return out
end

---Ice Blast's explosion radius after the tracer travelled `travel` units.
---Valve's rule: radius_min + radius_grow per second of flight, capped at radius_max.
---@param travel number distance from the cast point to the release
---@param level? integer
---@return number? # nil when the data lacks one of the four values
function M.ice_blast_radius(travel, level)
    local ab = "ancient_apparition_ice_blast"
    local lo, grow, hi, speed = M.value(ab, "radius_min", level), M.value(ab, "radius_grow", level),
        M.value(ab, "radius_max", level), M.value(ab, "speed", level)
    if not (lo and grow and hi and speed and speed > 0) then
        warn_once("ice_blast", "ice blast radius: radius_min, radius_grow, radius_max or speed missing")
        return nil
    end
    return math.min(hi, lo + grow * math.max(0, travel or 0) / speed)
end

return M
pack.json2 строк
{ "kind": "lib", "version": "1.0.0" }
catalog.lua199 строк
-- lib/threats catalog, by hand. a size is a key of data/values.lua (valve's special, or
-- AbilityCastPoint / AbilityChannelTime / AbilityDuration / AbilityCastRange), a function
-- (v, level) -> number with v(key, level) reading the same file, or a literal number where the
-- data has no such value, with the reason beside it. sizes: radius (ground circle), width (a
-- line's half-width, as valve's *_width / *_radius), speed, length, delay (from the system or
-- sound to the hit), life (seconds the zone stays dangerous after the hit).
-- tools/threats/gen_values.py reads the keys of C.abilities: one row per line start, 4 spaces.
local H = "particles/units/heroes/"

local C = {}

C.abilities = {
    ancient_apparition_ice_blast = { radius = "radius_max", width = "path_radius", speed = "speed" },
    bloodseeker_blood_bath = { radius = "radius", delay = "delay" },
    centaur_stampede = {},
    dark_seer_vacuum = { radius = "radius" },
    dark_willow_terrorize = { radius = "destination_radius" },
    dawnbreaker_solar_guardian = {
        radius = "radius",
        -- the channel, then the leap
        delay = function(v, l) return v("AbilityChannelTime", l) + v("airtime_duration", l) end,
    },
    death_prophet_carrion_swarm = { width = "start_radius", speed = "speed" },
    disruptor_static_storm = { radius = "radius" },
    dragon_knight_breathe_fire = { width = "start_radius", speed = "speed" },
    earth_spirit_boulder_smash = { width = "radius", speed = "speed" },
    earth_spirit_rolling_boulder = { width = "radius", speed = "speed" },
    earthshaker_echo_slam = { radius = "echo_slam_damage_range" },
    earthshaker_fissure = { width = "fissure_radius" },
    elder_titan_earth_splitter = { width = "crack_width", speed = "speed", delay = "crack_time" },
    faceless_void_chronosphere = { radius = "radius", life = "duration" },
    -- the projectile's radius is not in the data
    hoodwink_bushwhack = { width = 120, speed = "projectile_speed" },
    invoker_sun_strike = { radius = "area_of_effect", delay = "delay" },
    invoker_tornado = { width = "area_of_effect", speed = "travel_speed" },
    jakiro_dual_breath = { width = "start_radius", speed = "speed" },
    jakiro_ice_path = { width = "path_radius", delay = "path_delay" },
    -- 260 was path_radius until 2023-08; the data now has path_width 500, and whether that is
    -- a width or a radius is not settled
    jakiro_macropyre = { radius = 260 },
    kunkka_ghostship = { radius = "ghostship_width", width = "ghostship_width", speed = "ghostship_speed" },
    kunkka_torrent = { radius = "radius", delay = "delay" },
    lina_light_strike_array = { radius = "light_strike_array_aoe", delay = "light_strike_array_delay_time" },
    lion_impale = { width = "width", speed = "speed" },
    magnataur_reverse_polarity = { radius = "pull_radius" },
    mars_arena_of_blood = { radius = "radius" },
    mars_spear = { width = "spear_width", speed = "spear_speed" },
    mirana_arrow = { width = "arrow_width", speed = "arrow_speed" },
    mirana_invis = {},
    monkey_king_boundless_strike = { radius = "strike_radius", delay = "AbilityCastPoint" },
    monkey_king_wukongs_command = { radius = "second_radius" },
    nevermore_requiem = { radius = "requiem_radius" },
    night_stalker_darkness = {},
    nyx_assassin_impale = { width = "width", speed = "speed" },
    -- no area in the data: the ring marks where nyx went invisible
    nyx_assassin_vendetta = { radius = 200 },
    phoenix_supernova = { radius = "aura_radius", delay = "AbilityDuration" },
    puck_dream_coil = { radius = "coil_break_radius", life = "coil_duration" },
    pudge_meat_hook = { width = "hook_width", speed = "hook_speed" },
    rattletrap_hookshot = { width = "latch_radius", speed = "speed" },
    -- length: the cast range is 550-775 by level; 900 is the dodger's older reach, kept
    sandking_burrowstrike = { width = "burrow_width", speed = "burrow_speed", length = 900, life = 1.2 },
    sandking_epicenter = {
        -- the last pulse reaches base + increment per pulse
        radius = function(v, l)
            return v("epicenter_radius_base", l) + v("epicenter_radius_increment", l) * v("epicenter_pulses", l)
        end,
    },
    silencer_global_silence = {},
    snapfire_firesnap_cookie = { radius = "impact_radius", delay = "jump_duration" },
    snapfire_mortimer_kisses = { radius = "impact_radius" },
    spirit_breaker_charge_of_darkness = {},
    tidehunter_ravage = { radius = "radius" },
    tiny_avalanche = { radius = "radius" },
    treant_overgrowth = { radius = "radius" },
    -- one target in the data (cast range 150); the dodger keeps a ring around tusk
    tusk_walrus_punch = { radius = 250, delay = 0.1, life = 0.8 },
    venomancer_poison_nova = { radius = "radius" },
    -- the remnant watches along its facing; speed: the pull starts at once. life: the dodger's
    -- window, the remnant itself stays 17 s
    void_spirit_aether_remnant = {
        width = "remnant_watch_radius", length = "remnant_watch_distance", speed = 99999, life = 1.2,
    },
    warlock_rain_of_chaos = { radius = "aoe" },
    windrunner_powershot = { width = "arrow_width", speed = "arrow_speed" },
    -- no area in the data: the ring marks where io lands
    wisp_relocate = { radius = 300 },
    zuus_thundergods_wrath = {},
}

-- by the system's short name (the file name without .vpcf), the one utea callbacks pass.
-- ab: the ability. path: the full name, for code that matches the hash. cps: the control
-- points carrying the spot as a world position ({} = no spot). tell: the warning before the
-- spell. fog: sent to every team and created in fogged casts in the demo survey
-- (docs/FOG_PARTICLES.md). lab: also seen arriving live from a caster in the fog (2026-10-05).
-- a size here overrides the ability's. life literals: how long the dodger keeps the zone after
-- the hit, not in the data.
C.particles = {
    ancient_apparition_ice_blast_explode = { ab = "ancient_apparition_ice_blast" },
    ancient_apparition_ice_blast_final = { ab = "ancient_apparition_ice_blast" },
    ancient_apparition_ice_blast_initial = { ab = "ancient_apparition_ice_blast" },
    bloodseeker_bloodritual_ring = { ab = "bloodseeker_blood_bath" },
    centaur_stampede_cast = { ab = "centaur_stampede", path = H .. "hero_centaur/centaur_stampede_cast.vpcf",
        cps = {}, fog = true },
    dark_seer_vacuum = { ab = "dark_seer_vacuum", width = "radius" },
    dark_willow_wisp_spell_marker = { ab = "dark_willow_terrorize",
        path = H .. "hero_dark_willow/dark_willow_wisp_spell_marker.vpcf", cps = { 0 }, fog = true },
    dawnbreaker_solar_guardian_aoe = { ab = "dawnbreaker_solar_guardian", life = 2.0 },
    death_prophet_carrion_swarm = { ab = "death_prophet_carrion_swarm" },
    disruptor_static_storm = { ab = "disruptor_static_storm", path = H .. "hero_disruptor/disruptor_static_storm.vpcf",
        cps = { 0 }, fog = true },
    dragon_knight_breathe_fire = { ab = "dragon_knight_breathe_fire" },
    earth_spirit_boulder_smash = { ab = "earth_spirit_boulder_smash" },
    earth_spirit_rolling_boulder = { ab = "earth_spirit_rolling_boulder" },
    -- echoslam_start carries counts, not a spot
    earthshaker_echoslam_start = { ab = "earthshaker_echo_slam",
        path = H .. "hero_earthshaker/earthshaker_echoslam_start.vpcf", cps = {}, fog = true, lab = true },
    earthshaker_fissure = { ab = "earthshaker_fissure" },
    elder_titan_earth_splitter = { ab = "elder_titan_earth_splitter", life = 3.2 },
    espirit_rollingboulder = { ab = "earth_spirit_rolling_boulder" },
    faceless_void_chronosphere = { ab = "faceless_void_chronosphere",
        path = H .. "hero_faceless_void/faceless_void_chronosphere.vpcf", cps = { 0 }, fog = true, lab = true,
        delay = 0 },
    hero_snapfire_cookie_receive = { ab = "snapfire_firesnap_cookie", life = 1.0 },
    hoodwink_bushwhack_projectile = { ab = "hoodwink_bushwhack" },
    -- the strike itself, the beam before it is team-only
    invoker_sun_strike = { ab = "invoker_sun_strike", delay = 0 },
    invoker_tornado = { ab = "invoker_tornado" },
    jakiro_dual_breath = { ab = "jakiro_dual_breath" },
    jakiro_ice_path = { ab = "jakiro_ice_path" },
    jakiro_macropyre = { ab = "jakiro_macropyre", path = H .. "hero_jakiro/jakiro_macropyre.vpcf",
        cps = { 0 }, fog = true },
    kunkka_ghost_ship = { ab = "kunkka_ghostship" },
    kunkka_ghostship_marker = { ab = "kunkka_ghostship", path = H .. "hero_kunkka/kunkka_ghostship_marker.vpcf",
        cps = { 0 }, fog = true },
    -- the splash is the hit
    kunkka_spell_torrent_splash = { ab = "kunkka_torrent", delay = 0 },
    lina_spell_light_strike_array = { ab = "lina_light_strike_array" },
    lion_spell_impale = { ab = "lion_impale" },
    -- cp1 is the radius as a vector; the spot is cp3, bound to magnus with his position as fallback
    magnataur_reverse_polarity = { ab = "magnataur_reverse_polarity",
        path = H .. "hero_magnataur/magnataur_reverse_polarity.vpcf", cps = { 3 }, fog = true, lab = true },
    mars_arena_of_blood = { ab = "mars_arena_of_blood", path = H .. "hero_mars/mars_arena_of_blood.vpcf",
        cps = { 0 }, fog = true },
    mars_spear = { ab = "mars_spear" },
    mirana_moonlight_cast = { ab = "mirana_invis", path = H .. "hero_mirana/mirana_moonlight_cast.vpcf",
        cps = {}, fog = true },
    mirana_spell_arrow = { ab = "mirana_arrow" },
    monkey_king_fur_army_cast = { ab = "monkey_king_wukongs_command",
        path = H .. "hero_monkey_king/monkey_king_fur_army_cast.vpcf", cps = {}, fog = true },
    monkey_king_strike_cast = { ab = "monkey_king_boundless_strike", life = 1.0 },
    nevermore_requiemofsouls = { ab = "nevermore_requiem", path = H .. "hero_nevermore/nevermore_requiemofsouls.vpcf",
        cps = { 0 }, fog = true, delay = 0, life = 1.6 },
    nightstalker_ulti = { ab = "night_stalker_darkness", path = H .. "hero_night_stalker/nightstalker_ulti.vpcf",
        cps = {}, fog = true },
    nyx_assassin_impale = { ab = "nyx_assassin_impale" },
    nyx_assassin_vendetta_start = { ab = "nyx_assassin_vendetta",
        path = H .. "hero_nyx_assassin/nyx_assassin_vendetta_start.vpcf", cps = { 0 }, fog = true },
    phoenix_supernova_start = { ab = "phoenix_supernova", path = H .. "hero_phoenix/phoenix_supernova_start.vpcf",
        cps = {}, fog = true, life = 2.0 },
    powershot_channel = { ab = "windrunner_powershot" },
    puck_dreamcoil = { ab = "puck_dream_coil", delay = 0 },
    pudge_meathook = { ab = "pudge_meat_hook" },
    rattletrap_hookshot = { ab = "rattletrap_hookshot" },
    sandking_epicenter = { ab = "sandking_epicenter", path = H .. "hero_sandking/sandking_epicenter.vpcf",
        cps = { 0 }, fog = true, lab = true },
    sandking_epicenter_tell = { ab = "sandking_epicenter", path = H .. "hero_sandking/sandking_epicenter_tell.vpcf",
        cps = { 0 }, fog = true, lab = true, tell = true, delay = "AbilityCastPoint" },
    silencer_global_silence = { ab = "silencer_global_silence",
        path = H .. "hero_silencer/silencer_global_silence.vpcf", cps = {}, fog = true },
    -- lobbed: the landing circle, not the projectile's width
    snapfire_mortimer_kisses = { ab = "snapfire_mortimer_kisses", width = "impact_radius" },
    spirit_breaker_charge_start = { ab = "spirit_breaker_charge_of_darkness",
        path = H .. "hero_spirit_breaker/spirit_breaker_charge_start.vpcf", cps = {}, fog = true },
    tidehunter_spell_ravage = { ab = "tidehunter_ravage", path = H .. "hero_tidehunter/tidehunter_spell_ravage.vpcf",
        cps = { 0 }, fog = true, lab = true, delay = 0, life = 1.3 },
    tiny_avalanche_projectile_lvl1 = { ab = "tiny_avalanche", width = "radius" },
    treant_overgrowth_cast = { ab = "treant_overgrowth", path = H .. "hero_treant/treant_overgrowth_cast.vpcf",
        cps = {}, fog = true },
    venomancer_poison_nova = { ab = "venomancer_poison_nova", delay = 0, life = 2.0 },
    warlock_rain_of_chaos = { ab = "warlock_rain_of_chaos", path = H .. "hero_warlock/warlock_rain_of_chaos.vpcf",
        cps = { 0 }, fog = true },
    windrunner_spell_powershot = { ab = "windrunner_powershot" },
    -- the endpoint marker is where io and his partner arrive
    wisp_relocate_marker_endpoint = { ab = "wisp_relocate",
        path = H .. "hero_wisp/wisp_relocate_marker_endpoint.vpcf", cps = { 0 }, fog = true },
    zuus_thundergods_wrath_start = { ab = "zuus_thundergods_wrath",
        path = H .. "hero_zuus/zuus_thundergods_wrath_start.vpcf", cps = {}, fog = true },
}

-- casts the dodger hears before any system arrives
C.sounds = {
    ["Ability.SandKing_BurrowStrike"] = { ab = "sandking_burrowstrike" },
    ["Hero_Tusk.WalrusPunch.Cast"] = { ab = "tusk_walrus_punch" },
    ["Hero_VoidSpirit.AetherRemnant.Spawn_lp"] = { ab = "void_spirit_aether_remnant" },
}

return C
data/tiers.lua2093 строк
---@diagnostic disable: undefined-global
-- AUTO-GENERATED by tools/threats/gen_tiers.py from docs/dota_abilities — do not edit.
-- source vpk:6962 (Oct 15 2026), 528 entries, 395 with a radiusKey, 90 projectiles, 12 global.
--
-- radiusKey is a KEY NAME, not a number: Geometry.read_special asks the live ability,
-- so talents and scepter are already in the answer. tier/projectile/isGlobal come from
-- the ability's mechanics; per-spell corrections belong to the reader (the dodger's
-- utea/dodger/dodge_overrides.lua is merged over this table). read it through
-- lib/threats tier() and tiers().
return {
    ["abaddon_death_coil"] = {
        tier = "target_unit",
        radiusKey = "effect_radius",
    },
    ["abyssal_underlord_dark_portal"] = {
        tier = "channel",
        radiusKey = "radius",
    },
    ["abyssal_underlord_firestorm"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["abyssal_underlord_pit_of_malice"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["alchemist_acid_spray"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["alchemist_unstable_concoction"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["alchemist_unstable_concoction_throw"] = {
        tier = "target_disable",
        radiusKey = "midair_explosion_radius",
        projectile = true,
    },
    ["ancient_apparition_chilling_touch"] = {
        tier = "target_unit",
    },
    ["ancient_apparition_cold_feet"] = {
        tier = "target_disable",
        radiusKey = "area_of_effect",
    },
    ["ancient_apparition_ice_age"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["ancient_apparition_ice_blast"] = {
        tier = "global",
        radiusKey = "path_radius",
        isGlobal = true,
        projectile = true,
    },
    ["ancient_apparition_ice_blast_release"] = {
        tier = "aoe_notarget",
    },
    ["ancient_apparition_ice_vortex"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["antimage_blink"] = {
        tier = "aoe_point",
        radiusKey = "min_blink_range",
    },
    ["antimage_mana_void"] = {
        tier = "target_disable",
        radiusKey = "mana_void_aoe_radius",
    },
    ["arc_warden_flux"] = {
        tier = "target_disable",
        radiusKey = "search_radius",
    },
    ["arc_warden_magnetic_field"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["arc_warden_spark_wraith"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["arc_warden_tempest_double"] = {
        tier = "aoe_point",
    },
    ["axe_battle_hunger"] = {
        tier = "target_unit",
    },
    ["axe_berserkers_call"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["axe_culling_blade"] = {
        tier = "target_unit",
        radiusKey = "speed_aoe",
    },
    ["bane_brain_sap"] = {
        tier = "target_unit",
    },
    ["bane_enfeeble"] = {
        tier = "target_unit",
    },
    ["bane_fiends_grip"] = {
        tier = "channel",
    },
    ["bane_nightmare"] = {
        tier = "target_disable",
        radiusKey = "vector_render_radius",
    },
    ["batrider_firefly"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["batrider_flamebreak"] = {
        tier = "aoe_point",
        radiusKey = "collision_radius",
        projectile = true,
    },
    ["batrider_flaming_lasso"] = {
        tier = "target_disable",
        radiusKey = "drag_distance",
    },
    ["batrider_sticky_napalm"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["beastmaster_hawk_dive"] = {
        tier = "target_unit",
    },
    ["beastmaster_hawk_perch"] = {
        tier = "target_unit",
    },
    ["beastmaster_mark_of_the_beast"] = {
        tier = "target_unit",
    },
    ["beastmaster_primal_roar"] = {
        tier = "target_disable",
        radiusKey = "damage_radius",
    },
    ["beastmaster_summon_raptor"] = {
        tier = "aoe_notarget",
        radiusKey = "attack_radius",
    },
    ["beastmaster_summon_raptor_attack"] = {
        tier = "target_unit",
    },
    ["beastmaster_summon_razorback"] = {
        tier = "aoe_notarget",
    },
    ["beastmaster_wild_axes"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["bloodseeker_blood_bath"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["bloodseeker_blood_mist"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["bloodseeker_bloodrage"] = {
        tier = "aoe_notarget",
    },
    ["bloodseeker_rupture"] = {
        tier = "target_unit",
    },
    ["bounty_hunter_jinada"] = {
        tier = "target_unit",
    },
    ["bounty_hunter_lookout"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["bounty_hunter_shuriken_toss"] = {
        tier = "target_unit",
        radiusKey = "passthrough_width",
        projectile = true,
    },
    ["bounty_hunter_wind_walk"] = {
        tier = "aoe_notarget",
    },
    ["brewmaster_cinder_brew"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["brewmaster_drunken_brawler"] = {
        tier = "aoe_notarget",
    },
    ["brewmaster_drunken_haze"] = {
        tier = "target_unit",
    },
    ["brewmaster_earth_hurl_boulder"] = {
        tier = "target_disable",
        projectile = true,
    },
    ["brewmaster_fire_pull"] = {
        tier = "target_unit",
        radiusKey = "pull_distance",
    },
    ["brewmaster_storm_cyclone"] = {
        tier = "target_disable",
    },
    ["brewmaster_storm_dispel_magic"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["brewmaster_thunder_clap"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["brewmaster_void_astral_pulse"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["bristleback_hairball"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["bristleback_quill_spray"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["bristleback_viscous_nasal_goo"] = {
        tier = "target_unit",
    },
    ["broodmother_insatiable_hunger"] = {
        tier = "aoe_notarget",
        radiusKey = "aura_radius",
    },
    ["broodmother_silken_bola"] = {
        tier = "target_disable",
        radiusKey = "aoe",
        projectile = true,
    },
    ["broodmother_spawn_spiderlings"] = {
        tier = "target_unit",
        projectile = true,
    },
    ["broodmother_spin_web"] = {
        tier = "global",
        radiusKey = "radius",
        isGlobal = true,
    },
    ["broodmother_sticky_snare"] = {
        tier = "channel",
        radiusKey = "width",
    },
    ["centaur_double_edge"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["centaur_hoof_stomp"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["centaur_overrun"] = {
        tier = "aoe_notarget",
    },
    ["centaur_stampede"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["chaos_knight_chaos_bolt"] = {
        tier = "target_disable",
        radiusKey = "fake_bolt_distance",
    },
    ["chaos_knight_reality_rift"] = {
        tier = "target_unit",
        radiusKey = "pull_distance",
    },
    ["chen_holy_persuasion"] = {
        tier = "global",
        isGlobal = true,
    },
    ["chen_penitence"] = {
        tier = "target_unit",
        projectile = true,
    },
    ["chen_test_of_faith"] = {
        tier = "target_unit",
    },
    ["clinkz_burning_army"] = {
        tier = "aoe_point",
    },
    ["clinkz_burning_barrage"] = {
        tier = "channel",
        radiusKey = "projectile_width",
    },
    ["clinkz_searing_arrows"] = {
        tier = "target_unit",
    },
    ["clinkz_tar_bomb"] = {
        tier = "target_unit",
        radiusKey = "radius",
        projectile = true,
    },
    ["clinkz_wind_walk"] = {
        tier = "aoe_notarget",
    },
    ["crystal_maiden_crystal_clone"] = {
        tier = "aoe_point",
        radiusKey = "frostbite_radius",
    },
    ["crystal_maiden_crystal_nova"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["crystal_maiden_freezing_field"] = {
        tier = "channel",
        radiusKey = "radius",
    },
    ["crystal_maiden_frostbite"] = {
        tier = "target_disable",
    },
    ["crystal_maiden_let_it_go"] = {
        tier = "aoe_point",
        radiusKey = "path_radius",
        projectile = true,
    },
    ["dark_seer_ion_shell"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["dark_seer_vacuum"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["dark_seer_wall_of_replica"] = {
        tier = "aoe_point",
        radiusKey = "width",
    },
    ["dark_troll_warlord_ensnare"] = {
        tier = "target_disable",
    },
    ["dark_willow_bramble_maze"] = {
        tier = "aoe_point",
        radiusKey = "latch_range",
    },
    ["dark_willow_cursed_crown"] = {
        tier = "target_disable",
        radiusKey = "stun_radius",
    },
    ["dark_willow_shadow_realm"] = {
        tier = "aoe_notarget",
        radiusKey = "aura_radius",
    },
    ["dark_willow_terrorize"] = {
        tier = "aoe_point",
        radiusKey = "destination_radius",
    },
    ["dawnbreaker_celestial_hammer"] = {
        tier = "aoe_point",
        radiusKey = "flare_radius",
        projectile = true,
    },
    ["dawnbreaker_fire_wreath"] = {
        tier = "aoe_point",
        radiusKey = "smash_radius",
    },
    ["dawnbreaker_solar_guardian"] = {
        tier = "global",
        radiusKey = "radius",
        isGlobal = true,
    },
    ["dazzle_bad_juju"] = {
        tier = "aoe_notarget",
    },
    ["dazzle_nothl_projection"] = {
        tier = "aoe_point",
    },
    ["dazzle_poison_touch"] = {
        tier = "target_unit",
        radiusKey = "end_radius",
        projectile = true,
    },
    ["dazzle_rain_of_vermin"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["dazzle_weave"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["death_prophet_carrion_swarm"] = {
        tier = "target_unit",
        radiusKey = "end_radius",
        projectile = true,
    },
    ["death_prophet_exorcism"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["death_prophet_silence"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["death_prophet_spirit_siphon"] = {
        tier = "target_unit",
    },
    ["disruptor_glimpse"] = {
        tier = "target_disable",
    },
    ["disruptor_kinetic_fence"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["disruptor_kinetic_field"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["disruptor_static_storm"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["disruptor_thunder_strike"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["doom_bringer_doom"] = {
        tier = "target_unit",
        radiusKey = "scepter_aura_radius",
    },
    ["doom_bringer_infernal_blade"] = {
        tier = "target_disable",
    },
    ["doom_bringer_scorched_earth"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["dragon_knight_breathe_fire"] = {
        tier = "target_unit",
        radiusKey = "end_radius",
        projectile = true,
    },
    ["dragon_knight_dragon_tail"] = {
        tier = "target_disable",
        radiusKey = "aoe",
        projectile = true,
    },
    ["dragon_knight_elder_dragon_form"] = {
        tier = "aoe_notarget",
        radiusKey = "ranged_splash_radius",
    },
    ["dragon_knight_fireball"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["drow_ranger_frost_arrows"] = {
        tier = "target_unit",
    },
    ["drow_ranger_glacier"] = {
        tier = "aoe_notarget",
        radiusKey = "ramp_radius",
    },
    ["drow_ranger_multishot"] = {
        tier = "channel",
        radiusKey = "arrow_width",
    },
    ["drow_ranger_silence"] = {
        tier = "aoe_point",
        radiusKey = "silence_radius",
    },
    ["drow_ranger_wave_of_silence"] = {
        tier = "aoe_point",
        radiusKey = "wave_width",
    },
    ["earth_spirit_boulder_smash"] = {
        tier = "target_disable",
        radiusKey = "radius",
        projectile = true,
    },
    ["earth_spirit_magnetize"] = {
        tier = "aoe_notarget",
        radiusKey = "cast_radius",
    },
    ["earth_spirit_petrify"] = {
        tier = "target_unit",
        radiusKey = "aoe",
    },
    ["earth_spirit_rolling_boulder"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["earth_spirit_stone_caller"] = {
        tier = "aoe_point",
        radiusKey = "rolling_offset_distance",
    },
    ["earthshaker_echo_slam"] = {
        tier = "aoe_notarget",
        radiusKey = "echo_slam_echo_range",
    },
    ["earthshaker_enchant_totem"] = {
        tier = "aoe_notarget",
        radiusKey = "bonus_attack_range",
    },
    ["earthshaker_fissure"] = {
        tier = "aoe_point",
        radiusKey = "fissure_radius",
    },
    ["elder_titan_ancestral_spirit"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["elder_titan_earth_splitter"] = {
        tier = "aoe_point",
        radiusKey = "crack_width",
        projectile = true,
    },
    ["elder_titan_echo_stomp"] = {
        tier = "channel",
        radiusKey = "radius",
    },
    ["elder_titan_echo_stomp_spirit"] = {
        tier = "channel",
        radiusKey = "radius",
    },
    ["elder_titan_fundamental_fury"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["elder_titan_fundamental_fury_spirit"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["ember_spirit_activate_fire_remnant"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["ember_spirit_fire_remnant"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["ember_spirit_flame_guard"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["ember_spirit_searing_chains"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["ember_spirit_sleight_of_fist"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["enchantress_enchant"] = {
        tier = "target_unit",
    },
    ["enchantress_impetus"] = {
        tier = "target_unit",
    },
    ["enchantress_little_friends"] = {
        tier = "target_disable",
        radiusKey = "radius",
    },
    ["enigma_black_hole"] = {
        tier = "channel",
        radiusKey = "radius",
    },
    ["enigma_demonic_conversion"] = {
        tier = "aoe_point",
        radiusKey = "eidolon_attack_range",
    },
    ["enigma_malefice"] = {
        tier = "target_disable",
    },
    ["enigma_midnight_pulse"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["faceless_void_chronosphere"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["faceless_void_time_dilation"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["furion_curse_of_the_forest"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["furion_force_of_nature"] = {
        tier = "aoe_point",
        radiusKey = "area_of_effect",
    },
    ["furion_hedgerow"] = {
        tier = "aoe_point",
        radiusKey = "hedge_width",
    },
    ["furion_sprout"] = {
        tier = "target_disable",
        radiusKey = "sprout_damage_radius",
    },
    ["furion_summon_fey"] = {
        tier = "target_unit",
        radiusKey = "attack_radius",
    },
    ["furion_teleportation"] = {
        tier = "global",
        isGlobal = true,
    },
    ["furion_wrath_of_nature"] = {
        tier = "target_unit",
    },
    ["grimstroke_dark_artistry"] = {
        tier = "aoe_point",
        radiusKey = "end_radius",
        projectile = true,
    },
    ["grimstroke_ink_creature"] = {
        tier = "target_disable",
        radiusKey = "infection_search_radius",
        projectile = true,
    },
    ["grimstroke_ink_over"] = {
        tier = "target_unit",
    },
    ["grimstroke_soul_chain"] = {
        tier = "target_disable",
        radiusKey = "chain_latch_radius",
    },
    ["gyrocopter_call_down"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["gyrocopter_flak_cannon"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["gyrocopter_homing_missile"] = {
        tier = "target_disable",
        radiusKey = "max_distance",
        projectile = true,
    },
    ["gyrocopter_rocket_barrage"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["hoodwink_acorn_shot"] = {
        tier = "target_unit",
        radiusKey = "bonus_range",
        projectile = true,
    },
    ["hoodwink_bushwhack"] = {
        tier = "aoe_point",
        radiusKey = "trap_radius",
        projectile = true,
    },
    ["hoodwink_decoy"] = {
        tier = "aoe_notarget",
        radiusKey = "decoy_detonate_radius",
        projectile = true,
    },
    ["hoodwink_hunters_boomerang"] = {
        tier = "target_unit",
        radiusKey = "radius",
        projectile = true,
    },
    ["hoodwink_scurry"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["hoodwink_sharpshooter"] = {
        tier = "aoe_point",
        radiusKey = "arrow_width",
    },
    ["huskar_burning_spear"] = {
        tier = "target_unit",
    },
    ["huskar_inner_fire"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["huskar_life_break"] = {
        tier = "target_disable",
        radiusKey = "splash_radius",
    },
    ["invoker_chaos_meteor"] = {
        tier = "aoe_point",
        radiusKey = "area_of_effect",
    },
    ["invoker_chaos_meteor_ad"] = {
        tier = "aoe_point",
        radiusKey = "travel_distance",
    },
    ["invoker_cold_snap"] = {
        tier = "target_unit",
    },
    ["invoker_deafening_blast"] = {
        tier = "aoe_point",
        radiusKey = "travel_distance",
    },
    ["invoker_deafening_blast_ad"] = {
        tier = "aoe_point",
    },
    ["invoker_emp"] = {
        tier = "aoe_point",
        radiusKey = "area_of_effect",
    },
    ["invoker_ghost_walk"] = {
        tier = "aoe_notarget",
        radiusKey = "area_of_effect",
    },
    ["invoker_ghost_walk_ad"] = {
        tier = "aoe_notarget",
    },
    ["invoker_ice_wall"] = {
        tier = "aoe_notarget",
        radiusKey = "wall_width",
    },
    ["invoker_ice_wall_ad"] = {
        tier = "aoe_notarget",
        radiusKey = "wall_width",
    },
    ["invoker_sun_strike"] = {
        tier = "aoe_point",
        radiusKey = "area_of_effect",
    },
    ["invoker_sun_strike_ad"] = {
        tier = "aoe_point",
    },
    ["invoker_tornado"] = {
        tier = "aoe_point",
        radiusKey = "twister_radius",
    },
    ["invoker_tornado_ad"] = {
        tier = "aoe_point",
        radiusKey = "travel_distance",
    },
    ["invoker_wex"] = {
        tier = "aoe_notarget",
    },
    ["jakiro_dual_breath"] = {
        tier = "target_unit",
        radiusKey = "end_radius",
        projectile = true,
    },
    ["jakiro_ice_path"] = {
        tier = "aoe_point",
        radiusKey = "path_radius",
    },
    ["jakiro_liquid_fire"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["jakiro_liquid_ice"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["jakiro_macropyre"] = {
        tier = "aoe_point",
        radiusKey = "ice_edge_path_radius",
    },
    ["juggernaut_blade_fury"] = {
        tier = "aoe_notarget",
        radiusKey = "blade_fury_radius",
    },
    ["juggernaut_healing_ward"] = {
        tier = "aoe_point",
        radiusKey = "healing_ward_aura_radius",
    },
    ["juggernaut_omni_slash"] = {
        tier = "target_unit",
        radiusKey = "omni_slash_radius",
    },
    ["juggernaut_swift_slash"] = {
        tier = "target_unit",
    },
    ["juggernaut_trinity"] = {
        tier = "aoe_notarget",
        radiusKey = "jump_attack_radius",
    },
    ["juggernaut_vaulted_strike"] = {
        tier = "aoe_notarget",
        radiusKey = "slash_end_radius",
    },
    ["keeper_of_the_light_blinding_light"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["keeper_of_the_light_illuminate"] = {
        tier = "channel",
        radiusKey = "radius",
        projectile = true,
    },
    ["keeper_of_the_light_mana_leak"] = {
        tier = "target_disable",
    },
    ["keeper_of_the_light_radiant_bind"] = {
        tier = "target_disable",
    },
    ["keeper_of_the_light_spirit_form"] = {
        tier = "channel",
    },
    ["keeper_of_the_light_will_o_wisp"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["kez_echo_slash"] = {
        tier = "aoe_notarget",
        radiusKey = "katana_radius",
    },
    ["kez_falcon_rush"] = {
        tier = "aoe_notarget",
        radiusKey = "rush_range",
    },
    ["kez_grappling_claw"] = {
        tier = "target_unit",
        radiusKey = "land_distance",
        projectile = true,
    },
    ["kez_kazurai_katana"] = {
        tier = "target_unit",
    },
    ["kez_raptor_dance"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["kez_ravens_veil"] = {
        tier = "aoe_notarget",
        radiusKey = "blast_radius",
    },
    ["kez_shodo_sai"] = {
        tier = "aoe_point",
    },
    ["kez_switch_weapons"] = {
        tier = "aoe_notarget",
        radiusKey = "sai_attack_range",
    },
    ["kez_talon_toss"] = {
        tier = "target_disable",
        radiusKey = "radius",
        projectile = true,
    },
    ["kez_talon_toss_ad"] = {
        tier = "target_unit",
    },
    ["kunkka_ghostship"] = {
        tier = "aoe_point",
        radiusKey = "ghostship_width",
    },
    ["kunkka_tidal_wave"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["kunkka_tidebringer"] = {
        tier = "target_unit",
        radiusKey = "cleave_ending_width",
    },
    ["kunkka_torrent"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["kunkka_torrent_storm"] = {
        tier = "aoe_point",
    },
    ["largo_amphibian_rhapsody"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["largo_catchy_lick"] = {
        tier = "target_unit",
        radiusKey = "pull_distance",
    },
    ["largo_frogstomp"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["largo_song_double_time"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["largo_song_fight_song"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["legion_commander_duel"] = {
        tier = "target_disable",
        radiusKey = "team_duel_radius",
    },
    ["legion_commander_intimidate"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["legion_commander_overwhelming_odds"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["leshrac_diabolic_edict"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["leshrac_greater_lightning_storm"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["leshrac_lightning_storm"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["leshrac_pulse_nova"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["leshrac_split_earth"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["lich_chain_frost"] = {
        tier = "target_unit",
        radiusKey = "jump_range",
        projectile = true,
    },
    ["lich_frost_nova"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["lich_ice_spire"] = {
        tier = "aoe_point",
        radiusKey = "aura_radius",
    },
    ["lich_sinister_gaze"] = {
        tier = "channel",
    },
    ["life_stealer_assimilate_eject"] = {
        tier = "aoe_notarget",
    },
    ["life_stealer_infest"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["life_stealer_open_wounds"] = {
        tier = "target_unit",
        radiusKey = "spread_radius",
    },
    ["lina_dragon_slave"] = {
        tier = "channel",
        radiusKey = "dragon_slave_distance",
    },
    ["lina_laguna_blade"] = {
        tier = "target_unit",
    },
    ["lina_light_strike_array"] = {
        tier = "aoe_point",
        radiusKey = "light_strike_array_aoe",
    },
    ["lion_finger_of_death"] = {
        tier = "target_unit",
        radiusKey = "cleave_ending_width",
    },
    ["lion_impale"] = {
        tier = "target_disable",
        radiusKey = "width",
        projectile = true,
    },
    ["lion_voodoo"] = {
        tier = "target_disable",
        radiusKey = "radius",
    },
    ["lone_druid_entangle"] = {
        tier = "aoe_point",
        radiusKey = "active_radius",
    },
    ["lone_druid_rabid"] = {
        tier = "aoe_notarget",
    },
    ["lone_druid_spirit_bear"] = {
        tier = "aoe_notarget",
        radiusKey = "bear_attack_leash_range",
    },
    ["lone_druid_spirit_bear_fetch"] = {
        tier = "target_disable",
        radiusKey = "drag_distance",
    },
    ["lone_druid_true_form"] = {
        tier = "aoe_notarget",
    },
    ["luna_lucent_beam"] = {
        tier = "target_disable",
        radiusKey = "glaives_attack_radius",
    },
    ["luna_lunar_blessing"] = {
        tier = "global",
        radiusKey = "radius",
        isGlobal = true,
    },
    ["luna_lunar_orbit"] = {
        tier = "aoe_notarget",
        radiusKey = "rotating_glaives_hit_radius",
    },
    ["lycan_howl"] = {
        tier = "global",
        radiusKey = "radius",
        isGlobal = true,
    },
    ["lycan_summon_wolves_hamstring"] = {
        tier = "target_disable",
    },
    ["magnataur_greater_shockwave"] = {
        tier = "aoe_point",
    },
    ["magnataur_horn_toss"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["magnataur_reverse_polarity"] = {
        tier = "aoe_notarget",
        radiusKey = "pull_radius",
    },
    ["magnataur_shockwave"] = {
        tier = "target_unit",
        radiusKey = "shock_width",
    },
    ["magnataur_skewer"] = {
        tier = "aoe_point",
        radiusKey = "skewer_radius",
    },
    ["marci_grapple"] = {
        tier = "target_unit",
        radiusKey = "landing_radius",
    },
    ["marci_unleash"] = {
        tier = "aoe_notarget",
        radiusKey = "pulse_radius",
    },
    ["mars_arena_of_blood"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["mars_bulwark"] = {
        tier = "aoe_point",
        radiusKey = "attack_redirection_grace_distance",
    },
    ["mars_gods_rebuke"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["mars_spear"] = {
        tier = "aoe_point",
        radiusKey = "spear_width",
    },
    ["medusa_gorgon_grasp"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["medusa_mystic_snake"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["medusa_stone_gaze"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["meepo_earthbind"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["meepo_fling_release"] = {
        tier = "target_unit",
    },
    ["meepo_megameepo"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["meepo_megameepo_fling"] = {
        tier = "target_unit",
        radiusKey = "fling_radius",
    },
    ["mirana_arrow"] = {
        tier = "aoe_point",
        radiusKey = "arrow_width",
    },
    ["mirana_celestial_quiver"] = {
        tier = "target_unit",
    },
    ["mirana_invis"] = {
        tier = "aoe_notarget",
    },
    ["mirana_starfall"] = {
        tier = "aoe_notarget",
        radiusKey = "starfall_radius",
    },
    ["monkey_king_boundless_strike"] = {
        tier = "aoe_point",
        radiusKey = "strike_radius",
    },
    ["monkey_king_primal_spring"] = {
        tier = "channel",
        radiusKey = "impact_radius",
    },
    ["monkey_king_tree_dance"] = {
        tier = "channel",
        radiusKey = "give_up_distance",
    },
    ["monkey_king_wukongs_command"] = {
        tier = "aoe_point",
        radiusKey = "first_radius",
    },
    ["morphling_adaptive_strike_agi"] = {
        tier = "target_disable",
        projectile = true,
    },
    ["morphling_morph_agi"] = {
        tier = "aoe_notarget",
    },
    ["morphling_morph_str"] = {
        tier = "aoe_notarget",
    },
    ["morphling_syntropy"] = {
        tier = "target_unit",
    },
    ["morphling_waveform"] = {
        tier = "aoe_point",
        radiusKey = "width",
        projectile = true,
    },
    ["muerta_dead_shot"] = {
        tier = "target_disable",
        radiusKey = "radius",
        projectile = true,
    },
    ["muerta_parting_shot"] = {
        tier = "target_unit",
        radiusKey = "knockback_distance",
        projectile = true,
    },
    ["muerta_pierce_the_veil"] = {
        tier = "aoe_notarget",
    },
    ["muerta_spectral_slug"] = {
        tier = "target_unit",
        radiusKey = "knockback_distance",
        projectile = true,
    },
    ["muerta_the_calling"] = {
        tier = "aoe_point",
        radiusKey = "hit_radius",
    },
    ["naga_siren_ensnare"] = {
        tier = "target_disable",
        radiusKey = "fake_ensnare_distance",
    },
    ["naga_siren_reel_in"] = {
        tier = "channel",
        radiusKey = "radius",
    },
    ["naga_siren_song_of_the_siren"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["necrolyte_death_pulse"] = {
        tier = "aoe_notarget",
        radiusKey = "area_of_effect",
        projectile = true,
    },
    ["necrolyte_death_seeker"] = {
        tier = "target_unit",
    },
    ["necrolyte_ghost_shroud"] = {
        tier = "aoe_notarget",
        radiusKey = "slow_aoe",
    },
    ["necrolyte_reapers_scythe"] = {
        tier = "target_disable",
    },
    ["nevermore_frenzy"] = {
        tier = "aoe_notarget",
        radiusKey = "soul_collection_radius",
    },
    ["nevermore_requiem"] = {
        tier = "aoe_notarget",
        radiusKey = "requiem_radius",
    },
    ["nevermore_shadowraze1"] = {
        tier = "aoe_notarget",
        radiusKey = "shadowraze_radius",
    },
    ["nevermore_shadowraze2"] = {
        tier = "aoe_notarget",
        radiusKey = "shadowraze_radius",
    },
    ["nevermore_shadowraze3"] = {
        tier = "aoe_notarget",
        radiusKey = "shadowraze_radius",
    },
    ["night_stalker_crippling_fear"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["night_stalker_darkness"] = {
        tier = "aoe_notarget",
    },
    ["night_stalker_void"] = {
        tier = "channel",
        radiusKey = "cast_radius",
    },
    ["nyx_assassin_burrow"] = {
        tier = "aoe_notarget",
        radiusKey = "carapace_radius",
    },
    ["nyx_assassin_impale"] = {
        tier = "aoe_point",
        radiusKey = "width",
        projectile = true,
    },
    ["nyx_assassin_jolt"] = {
        tier = "target_unit",
        radiusKey = "aoe",
    },
    ["nyx_assassin_mana_burn"] = {
        tier = "target_unit",
    },
    ["nyx_assassin_spiked_carapace"] = {
        tier = "aoe_notarget",
    },
    ["nyx_assassin_vendetta"] = {
        tier = "aoe_notarget",
    },
    ["obsidian_destroyer_arcane_orb"] = {
        tier = "target_unit",
    },
    ["obsidian_destroyer_astral_imprisonment"] = {
        tier = "target_disable",
    },
    ["obsidian_destroyer_sanity_eclipse"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["ogre_magi_fireblast"] = {
        tier = "target_disable",
    },
    ["ogre_magi_ignite"] = {
        tier = "target_unit",
        radiusKey = "ignite_multicast_aoe",
        projectile = true,
    },
    ["ogre_magi_unrefined_fireblast"] = {
        tier = "target_disable",
    },
    ["omniknight_guardian_angel"] = {
        tier = "global",
        radiusKey = "radius",
        isGlobal = true,
    },
    ["omniknight_hammer_of_purity"] = {
        tier = "target_unit",
    },
    ["omniknight_pacify"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["oracle_fates_edict"] = {
        tier = "target_disable",
    },
    ["oracle_fortunes_end"] = {
        tier = "channel",
        radiusKey = "radius",
    },
    ["oracle_purifying_flames"] = {
        tier = "target_unit",
    },
    ["oracle_rain_of_destiny"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["pangolier_gyroshell"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["pangolier_rollup"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["pangolier_shield_crash"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["pangolier_swashbuckle"] = {
        tier = "aoe_point",
        radiusKey = "end_radius",
    },
    ["phantom_assassin_fan_of_knives"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["phantom_assassin_stifling_dagger"] = {
        tier = "target_unit",
    },
    ["phantom_lancer_doppelwalk"] = {
        tier = "aoe_point",
        radiusKey = "search_radius",
    },
    ["phantom_lancer_phantom_edge"] = {
        tier = "aoe_notarget",
        radiusKey = "max_distance",
    },
    ["phantom_lancer_spirit_lance"] = {
        tier = "target_unit",
        radiusKey = "fake_lance_distance",
    },
    ["phoenix_fire_spirits"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["phoenix_icarus_dive"] = {
        tier = "aoe_point",
        radiusKey = "hit_radius",
    },
    ["phoenix_launch_fire_spirit"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["phoenix_sun_ray"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["primal_beast_onslaught"] = {
        tier = "aoe_point",
        radiusKey = "knockback_radius",
    },
    ["primal_beast_pulverize"] = {
        tier = "channel",
        radiusKey = "splash_radius",
    },
    ["primal_beast_rock_throw"] = {
        tier = "aoe_point",
        radiusKey = "impact_radius",
    },
    ["primal_beast_trample"] = {
        tier = "aoe_notarget",
        radiusKey = "effect_radius",
    },
    ["primal_beast_uproar"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["puck_dream_coil"] = {
        tier = "aoe_point",
        radiusKey = "coil_radius",
    },
    ["puck_illusory_orb"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["puck_waning_rift"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["pudge_dismember"] = {
        tier = "channel",
    },
    ["pudge_meat_hook"] = {
        tier = "aoe_point",
        radiusKey = "hook_width",
    },
    ["pudge_rot"] = {
        tier = "aoe_notarget",
        radiusKey = "rot_radius",
    },
    ["pugna_decrepify"] = {
        tier = "target_unit",
    },
    ["pugna_life_drain"] = {
        tier = "channel",
    },
    ["pugna_nether_blast"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["pugna_nether_ward"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["queenofpain_blink"] = {
        tier = "aoe_point",
        radiusKey = "min_blink_range",
    },
    ["queenofpain_scream_of_pain"] = {
        tier = "aoe_notarget",
        radiusKey = "area_of_effect",
        projectile = true,
    },
    ["queenofpain_shadow_strike"] = {
        tier = "target_unit",
        radiusKey = "aoe_radius",
        projectile = true,
    },
    ["queenofpain_sonic_wave"] = {
        tier = "aoe_point",
        radiusKey = "final_aoe",
        projectile = true,
    },
    ["rattletrap_battery_assault"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["rattletrap_hookshot"] = {
        tier = "aoe_point",
        radiusKey = "stun_radius",
        projectile = true,
    },
    ["rattletrap_overclocking"] = {
        tier = "aoe_notarget",
        radiusKey = "cogs_radius",
    },
    ["rattletrap_power_cogs"] = {
        tier = "aoe_notarget",
        radiusKey = "cogs_radius",
        projectile = true,
    },
    ["rattletrap_rocket_flare"] = {
        tier = "global",
        radiusKey = "radius",
        isGlobal = true,
        projectile = true,
    },
    ["razor_eye_of_the_storm"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["razor_plasma_field"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["razor_static_link"] = {
        tier = "target_unit",
        radiusKey = "radius",
        projectile = true,
    },
    ["riki_blink_strike"] = {
        tier = "target_unit",
    },
    ["riki_poison_dart"] = {
        tier = "target_unit",
        projectile = true,
    },
    ["riki_smoke_screen"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["ringmaster_impalement"] = {
        tier = "aoe_point",
        radiusKey = "dagger_width",
    },
    ["ringmaster_spotlight"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["ringmaster_tame_the_beasts"] = {
        tier = "channel",
        radiusKey = "end_width",
    },
    ["ringmaster_tame_the_beasts_crack"] = {
        tier = "aoe_notarget",
    },
    ["ringmaster_wheel"] = {
        tier = "aoe_point",
        radiusKey = "knockback_radius",
        projectile = true,
    },
    ["rubick_fade_bolt"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["rubick_telekinesis"] = {
        tier = "target_disable",
        radiusKey = "radius",
    },
    ["rubick_telekinesis_land"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["rubick_telekinesis_land_self"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["sandking_burrowstrike"] = {
        tier = "aoe_point",
        radiusKey = "burrow_width",
    },
    ["sandking_epicenter"] = {
        tier = "aoe_notarget",
        radiusKey = "shard_radius",
    },
    ["sandking_sand_storm"] = {
        tier = "aoe_notarget",
        radiusKey = "sand_storm_radius",
    },
    ["sandking_scorpion_strike"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["shadow_demon_demonic_purge"] = {
        tier = "target_unit",
    },
    ["shadow_demon_disruption"] = {
        tier = "target_disable",
    },
    ["shadow_demon_shadow_poison"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["shadow_demon_soul_catcher"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["shadow_shaman_ether_shock"] = {
        tier = "target_unit",
        radiusKey = "end_radius",
    },
    ["shadow_shaman_mass_serpent_ward"] = {
        tier = "aoe_point",
        radiusKey = "spawn_radius",
    },
    ["shadow_shaman_serpentine"] = {
        tier = "aoe_point",
    },
    ["shadow_shaman_shackles"] = {
        tier = "channel",
        radiusKey = "bonus_targets_search_range",
    },
    ["shadow_shaman_urnaconda"] = {
        tier = "aoe_point",
        radiusKey = "impact_radius",
        projectile = true,
    },
    ["shadow_shaman_voodoo"] = {
        tier = "target_disable",
    },
    ["shredder_chakram"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["shredder_chakram_2"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["shredder_flamethrower"] = {
        tier = "aoe_notarget",
        radiusKey = "width",
    },
    ["shredder_timber_chain"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["shredder_whirling_death"] = {
        tier = "aoe_notarget",
        radiusKey = "whirling_radius",
    },
    ["silencer_curse_of_the_silent"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["silencer_glaives_of_wisdom"] = {
        tier = "target_disable",
    },
    ["silencer_global_silence"] = {
        tier = "global",
        isGlobal = true,
    },
    ["silencer_last_word"] = {
        tier = "target_disable",
        radiusKey = "radius",
    },
    ["skeleton_king_hellfire_blast"] = {
        tier = "target_disable",
    },
    ["skywrath_mage_ancient_seal"] = {
        tier = "target_disable",
    },
    ["skywrath_mage_arcane_bolt"] = {
        tier = "target_unit",
        radiusKey = "extra_bolt_search_radius",
    },
    ["skywrath_mage_concussive_shot"] = {
        tier = "aoe_notarget",
        radiusKey = "slow_radius",
        projectile = true,
    },
    ["skywrath_mage_mystic_flare"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["slardar_slithereen_crush"] = {
        tier = "aoe_notarget",
        radiusKey = "crush_radius",
    },
    ["slardar_sprint"] = {
        tier = "aoe_notarget",
    },
    ["slark_dark_pact"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["slark_depth_shroud"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["slark_fish_bait"] = {
        tier = "target_unit",
    },
    ["slark_pounce"] = {
        tier = "aoe_notarget",
        radiusKey = "leash_radius",
    },
    ["slark_saltwater_shiv"] = {
        tier = "target_unit",
    },
    ["slark_shadow_dance"] = {
        tier = "aoe_notarget",
    },
    ["snapfire_lil_shredder"] = {
        tier = "aoe_notarget",
    },
    ["snapfire_mortimer_kisses"] = {
        tier = "aoe_point",
        radiusKey = "impact_radius",
        projectile = true,
    },
    ["snapfire_scatterblast"] = {
        tier = "aoe_point",
        radiusKey = "point_blank_range",
    },
    ["snapfire_spit_creep"] = {
        tier = "aoe_point",
        radiusKey = "impact_radius",
        projectile = true,
    },
    ["sniper_assassinate"] = {
        tier = "target_disable",
        projectile = true,
    },
    ["sniper_concussive_grenade"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["sniper_shrapnel"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["sniper_take_aim"] = {
        tier = "aoe_notarget",
    },
    ["spectre_haunt"] = {
        tier = "aoe_notarget",
        radiusKey = "fear_aoe",
    },
    ["spectre_shadow_step"] = {
        tier = "target_unit",
    },
    ["spectre_spectral_dagger"] = {
        tier = "target_unit",
        radiusKey = "path_radius",
        projectile = true,
    },
    ["spirit_breaker_bulldoze"] = {
        tier = "aoe_notarget",
    },
    ["spirit_breaker_charge_of_darkness"] = {
        tier = "target_disable",
        radiusKey = "bash_radius",
    },
    ["spirit_breaker_nether_strike"] = {
        tier = "target_unit",
    },
    ["storm_spirit_ball_lightning"] = {
        tier = "aoe_point",
        radiusKey = "ball_lightning_aoe",
    },
    ["storm_spirit_electric_vortex"] = {
        tier = "target_unit",
        radiusKey = "electric_vortex_pull_distance",
    },
    ["storm_spirit_static_remnant"] = {
        tier = "aoe_notarget",
        radiusKey = "static_remnant_radius",
    },
    ["sven_gods_strength"] = {
        tier = "channel",
    },
    ["sven_storm_bolt"] = {
        tier = "target_disable",
        radiusKey = "bolt_aoe",
    },
    ["techies_focused_detonate"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["techies_land_mines"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["techies_minefield_sign"] = {
        tier = "aoe_point",
        radiusKey = "aura_radius",
    },
    ["techies_remote_mines"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["techies_remote_mines_self_detonate"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["techies_snare_trap"] = {
        tier = "aoe_point",
        radiusKey = "effect_radius",
    },
    ["techies_stasis_trap"] = {
        tier = "aoe_point",
        radiusKey = "stun_radius",
    },
    ["techies_sticky_bomb"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["techies_suicide"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["templar_assassin_meld"] = {
        tier = "aoe_notarget",
    },
    ["templar_assassin_psionic_trap"] = {
        tier = "aoe_point",
        radiusKey = "trap_radius",
    },
    ["templar_assassin_refraction"] = {
        tier = "aoe_notarget",
    },
    ["terrorblade_demon_zeal"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["terrorblade_metamorphosis"] = {
        tier = "aoe_notarget",
        radiusKey = "bonus_range",
    },
    ["terrorblade_reflection"] = {
        tier = "global",
        isGlobal = true,
    },
    ["terrorblade_terror_wave"] = {
        tier = "aoe_notarget",
        radiusKey = "scepter_radius",
    },
    ["tidehunter_anchor_smash"] = {
        tier = "aoe_notarget",
        radiusKey = "additional_range",
    },
    ["tidehunter_arm_of_the_deep"] = {
        tier = "aoe_point",
        radiusKey = "projectile_width",
    },
    ["tidehunter_dead_in_the_water"] = {
        tier = "target_unit",
        projectile = true,
    },
    ["tidehunter_gush"] = {
        tier = "target_unit",
        projectile = true,
    },
    ["tidehunter_kraken_shell"] = {
        tier = "aoe_notarget",
    },
    ["tidehunter_ravage"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["tinker_deploy_turrets"] = {
        tier = "aoe_point",
        radiusKey = "drop_aoe_radius",
    },
    ["tinker_heat_seeking_missile"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["tinker_laser"] = {
        tier = "target_unit",
    },
    ["tinker_march_of_the_machines"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["tinker_shrink_ray"] = {
        tier = "target_unit",
    },
    ["tinker_warp_grenade"] = {
        tier = "target_unit",
        radiusKey = "max_distance",
    },
    ["tiny_avalanche"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["tiny_toss"] = {
        tier = "target_disable",
        radiusKey = "radius",
    },
    ["tiny_toss_tree"] = {
        tier = "target_unit",
        radiusKey = "splash_radius",
        projectile = true,
    },
    ["tiny_tree_channel"] = {
        tier = "channel",
        radiusKey = "splash_radius",
        projectile = true,
    },
    ["tiny_tree_grab"] = {
        tier = "target_unit",
        radiusKey = "splash_width",
    },
    ["treant_leech_seed"] = {
        tier = "target_disable",
        radiusKey = "radius",
        projectile = true,
    },
    ["treant_natures_grasp"] = {
        tier = "aoe_point",
        radiusKey = "latch_range",
    },
    ["treant_overgrowth"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["treant_super_bloom"] = {
        tier = "aoe_notarget",
        radiusKey = "splash_radius",
    },
    ["troll_warlord_whirling_axes_melee"] = {
        tier = "aoe_notarget",
        radiusKey = "hit_radius",
    },
    ["troll_warlord_whirling_axes_ranged"] = {
        tier = "target_unit",
        radiusKey = "axe_width",
    },
    ["tusk_frozen_sigil"] = {
        tier = "aoe_notarget",
        radiusKey = "sigil_radius",
    },
    ["tusk_ice_shards"] = {
        tier = "aoe_point",
        radiusKey = "shard_width",
    },
    ["tusk_snowball"] = {
        tier = "target_disable",
        radiusKey = "snowball_radius",
    },
    ["tusk_tag_team"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["tusk_walrus_kick"] = {
        tier = "target_disable",
        radiusKey = "search_radius",
    },
    ["tusk_walrus_punch"] = {
        tier = "target_unit",
    },
    ["undying_decay"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["undying_flesh_golem"] = {
        tier = "aoe_notarget",
    },
    ["undying_soul_rip"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["ursa_earthshock"] = {
        tier = "aoe_notarget",
        radiusKey = "shock_radius",
    },
    ["ursa_overpower"] = {
        tier = "aoe_notarget",
    },
    ["vengefulspirit_magic_missile"] = {
        tier = "target_disable",
    },
    ["vengefulspirit_nether_swap"] = {
        tier = "channel",
    },
    ["vengefulspirit_wave_of_terror"] = {
        tier = "aoe_point",
        radiusKey = "wave_width",
    },
    ["venomancer_area_poison"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["venomancer_latent_poison"] = {
        tier = "target_disable",
        projectile = true,
    },
    ["venomancer_noxious_plague"] = {
        tier = "target_unit",
        radiusKey = "debuff_radius",
        projectile = true,
    },
    ["venomancer_plague_ward"] = {
        tier = "aoe_point",
    },
    ["venomancer_poison_nova"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["venomancer_snakebite"] = {
        tier = "target_unit",
    },
    ["venomancer_venomous_gale"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["viper_nethertoxin"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["viper_nose_dive"] = {
        tier = "aoe_point",
        radiusKey = "corrosive_radius",
    },
    ["viper_poison_attack"] = {
        tier = "target_unit",
        radiusKey = "expiration_damage_radius",
    },
    ["viper_viper_strike"] = {
        tier = "target_unit",
        projectile = true,
    },
    ["visage_soul_assumption"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["visage_stone_form_self_cast"] = {
        tier = "aoe_notarget",
        radiusKey = "stun_radius",
    },
    ["visage_summon_familiars"] = {
        tier = "aoe_notarget",
        radiusKey = "additional_target_search_radius",
    },
    ["visage_summon_familiars_recall"] = {
        tier = "aoe_notarget",
    },
    ["visage_summon_familiars_stone_form"] = {
        tier = "aoe_notarget",
        radiusKey = "stun_radius",
    },
    ["void_spirit_aether_remnant"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["void_spirit_astral_step"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["void_spirit_dissimilate"] = {
        tier = "aoe_notarget",
        radiusKey = "damage_radius",
    },
    ["void_spirit_resonant_pulse"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["warlock_fatal_bonds"] = {
        tier = "target_unit",
        radiusKey = "search_aoe",
    },
    ["warlock_rain_of_chaos"] = {
        tier = "aoe_point",
        radiusKey = "aoe",
    },
    ["warlock_shadow_word"] = {
        tier = "target_unit",
        radiusKey = "spell_aoe",
    },
    ["warlock_upheaval"] = {
        tier = "channel",
        radiusKey = "aoe",
    },
    ["weaver_geminate_attack"] = {
        tier = "target_unit",
    },
    ["weaver_shukuchi"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
        projectile = true,
    },
    ["weaver_the_swarm"] = {
        tier = "aoe_point",
        radiusKey = "radius",
        projectile = true,
    },
    ["windrunner_gale_force"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["windrunner_powershot"] = {
        tier = "channel",
        radiusKey = "arrow_width",
    },
    ["windrunner_shackleshot"] = {
        tier = "target_disable",
        radiusKey = "shackle_distance",
    },
    ["winter_wyvern_arctic_burn"] = {
        tier = "aoe_notarget",
    },
    ["winter_wyvern_splinter_blast"] = {
        tier = "target_disable",
        radiusKey = "split_radius",
        projectile = true,
    },
    ["winter_wyvern_winters_curse"] = {
        tier = "target_disable",
        radiusKey = "radius",
    },
    ["wisp_overcharge"] = {
        tier = "aoe_notarget",
    },
    ["wisp_spirits"] = {
        tier = "aoe_notarget",
        radiusKey = "hit_radius",
    },
    ["witch_doctor_death_ward"] = {
        tier = "channel",
        radiusKey = "bonus_attack_range",
    },
    ["witch_doctor_maledict"] = {
        tier = "aoe_point",
        radiusKey = "radius",
    },
    ["witch_doctor_paralyzing_cask"] = {
        tier = "target_disable",
        radiusKey = "bounce_range",
        projectile = true,
    },
    ["witch_doctor_voodoo_restoration"] = {
        tier = "aoe_notarget",
        radiusKey = "radius",
    },
    ["zuus_arc_lightning"] = {
        tier = "target_unit",
        radiusKey = "radius",
    },
    ["zuus_cloud"] = {
        tier = "global",
        radiusKey = "cloud_radius",
        isGlobal = true,
    },
    ["zuus_heavenly_jump"] = {
        tier = "aoe_notarget",
        radiusKey = "hop_distance",
    },
    ["zuus_lightning_bolt"] = {
        tier = "target_disable",
        radiusKey = "true_sight_radius",
    },
    ["zuus_thundergods_wrath"] = {
        tier = "aoe_notarget",
    },
}
data/values.lua756 строк
-- generated by tools/threats/gen_values.py from docs/dota_abilities/_data/combat.json.
-- do not edit: the dump pipeline rewrites it (tools/dumper/agentfmt.py). a number is the
-- same at every level, a list is by level.
return {
    ancient_apparition_ice_blast = {
        hero = "npc_dota_hero_ancient_apparition",
        AbilityCastPoint = 0.01,
        AbilityCastRange = 0,
        cold_feet_stun_duration_pct = 0,
        damage_per_second = { 12, 24, 36 },
        frostbite_duration = { 10, 11, 12 },
        kill_pct = { 12, 13, 14 },
        path_radius = 300,
        radius_grow = 50,
        radius_max = 1000,
        radius_min = 300,
        speed = 1500,
        target_sight_radius = 500,
    },
    bloodseeker_blood_bath = {
        hero = "npc_dota_hero_bloodseeker",
        AbilityCastPoint = 0.3,
        AbilityCastRange = 1500,
        damage = { 100, 155, 210, 265 },
        delay = 2.6,
        delay_plus_castpoint_tooltip = 2.9,
        heal = 0,
        radius = 600,
        silence_duration = { 3, 4, 5, 6 },
        strong_dispel_count = 0,
    },
    centaur_stampede = {
        hero = "npc_dota_hero_centaur",
        base_damage = 0,
        damage_reduction = 0,
        duration = { 3.5, 4, 4.5 },
        has_flying_movement = 0,
        radius = 105,
        slow_duration = 3,
        slow_movement_speed = 100,
        strength_damage = { 2, 2.5, 3 },
    },
    dark_seer_vacuum = {
        hero = "npc_dota_hero_dark_seer",
        AbilityCastPoint = 0.4,
        AbilityCastRange = { 450, 500, 550, 600 },
        damage = { 70, 130, 190, 250 },
        duration = { 0.3, 0.4, 0.5, 0.6 },
        radius = { 325, 400, 475, 550 },
        radius_tree = 150,
    },
    dark_willow_terrorize = {
        hero = "npc_dota_hero_dark_willow",
        AbilityCastPoint = 1,
        AbilityCastRange = 1200,
        destination_radius = { 450, 500, 550 },
        destination_status_duration = { 2.8, 3, 3.2 },
        destination_travel_speed = 2000,
        return_travel_speed = 800,
        starting_height = 300,
        telegraph_to_enemies = 0,
    },
    dawnbreaker_solar_guardian = {
        hero = "npc_dota_hero_dawnbreaker",
        AbilityCastPoint = 0.1,
        AbilityCastRange = 0,
        AbilityChannelTime = 1.7,
        airtime_duration = 0.8,
        airtime_scepter_movement_speed = 200,
        base_damage = { 30, 50, 70 },
        base_heal = { 45, 70, 95 },
        daytime_duration = 6,
        land_damage = { 130, 160, 190 },
        land_stun_duration = { 1.2, 1.4, 1.6 },
        max_offset_distance = 350,
        pulse_interval = 0.5,
        radius = 500,
    },
    death_prophet_carrion_swarm = {
        hero = "npc_dota_hero_death_prophet",
        AbilityCastPoint = 0.2,
        AbilityCastRange = 900,
        damage = { 100, 175, 250, 325 },
        end_radius = 300,
        range = 900,
        slow_duration = 0,
        slow_percent = 0,
        speed = 1100,
        start_radius = 110,
    },
    disruptor_static_storm = {
        hero = "npc_dota_hero_disruptor",
        AbilityCastPoint = 0.05,
        AbilityCastRange = 800,
        damage_max = { 200, 275, 350 },
        duration = 6,
        pulses = 20,
        radius = 550,
    },
    dragon_knight_breathe_fire = {
        hero = "npc_dota_hero_dragon_knight",
        AbilityCastPoint = 0.2,
        AbilityCastRange = 1000,
        damage = { 80, 160, 240, 320 },
        dragon_form_bonus_pct = 0,
        duration = 11,
        end_radius = 250,
        range = 750,
        reduction = { 20, 24, 28, 32 },
        speed = 1050,
        start_radius = 150,
    },
    earth_spirit_boulder_smash = {
        hero = "npc_dota_hero_earth_spirit",
        AbilityCastPoint = 0,
        AbilityCastRange = 150,
        creep_multiplier = 1,
        duration = { 1.75, 2.5, 3.25, 4 },
        move_slow = 50,
        radius = 180,
        remnant_smash_radius_tooltip = 200,
        rock_damage = { 110, 180, 250, 320 },
        rock_distance = 2000,
        rock_search_aoe = 200,
        speed = 900,
        stun_duration = 0,
        unit_distance = { 500, 600, 700, 800 },
    },
    earth_spirit_rolling_boulder = {
        hero = "npc_dota_hero_earth_spirit",
        AbilityCastPoint = 0,
        AbilityCastRange = 3000,
        can_roll_over_allied_heroes = 0,
        damage = { 60, 70, 80, 90 },
        damage_str = 100,
        delay = 0.6,
        destroy_stone = 1,
        distance = 800,
        radius = 160,
        rock_bonus_duration = { 0.3, 0.5, 0.7, 0.9 },
        rock_distance_multiplier = 2,
        rock_speed = 1600,
        speed = 1000,
        stun_duration = { 0.3, 0.5, 0.7, 0.9 },
    },
    earthshaker_echo_slam = {
        hero = "npc_dota_hero_earthshaker",
        AbilityCastPoint = 0,
        echo_slam_damage_range = 700,
        echo_slam_echo_damage = { 70, 90, 110 },
        echo_slam_echo_range = 700,
        echo_slam_echo_search_range = 700,
        echo_slam_initial_damage = { 100, 140, 180 },
    },
    earthshaker_fissure = {
        hero = "npc_dota_hero_earthshaker",
        AbilityCastPoint = 0.69,
        AbilityCastRange = 1600,
        echoes_damage_multiplier = 0,
        echoes_radius = 0,
        fissure_damage = { 100, 160, 220, 280 },
        fissure_duration = { 6.5, 7, 7.5, 8 },
        fissure_max_distance_moved = 300,
        fissure_radius = 225,
        free_pathing_all_allies = 0,
        free_pathing_application_radius = 0,
        stun_duration = { 1, 1.2, 1.4, 1.6 },
    },
    elder_titan_earth_splitter = {
        hero = "npc_dota_hero_elder_titan",
        AbilityCastPoint = 0.4,
        AbilityCastRange = 2400,
        crack_distance = 2400,
        crack_time = 2.7182,
        crack_width = 315,
        damage_pct = { 34, 42, 50 },
        slow_duration = { 3, 4, 5 },
        slow_pct = { 40, 45, 50 },
        speed = 1100,
        total_steps = 12,
        vision_duration = 4,
        vision_interval = 0.22,
        vision_step = 200,
        vision_width = 500,
    },
    faceless_void_chronosphere = {
        hero = "npc_dota_hero_faceless_void",
        AbilityCastPoint = 0.35,
        AbilityCastRange = 500,
        bonus_attack_speed = 0,
        duration = { 3.75, 4.25, 4.75 },
        radius = 500,
        vision_radius = 475,
    },
    hoodwink_bushwhack = {
        hero = "npc_dota_hero_hoodwink",
        AbilityCastPoint = 0.2,
        AbilityCastRange = 1100,
        animation_rate = 0.3,
        debuff_duration = { 1.5, 1.7, 1.9, 2.1 },
        projectile_speed = 1300,
        total_damage = { 90, 180, 270, 360 },
        trap_radius = 265,
        visual_height = 50,
    },
    invoker_sun_strike = {
        hero = "npc_dota_hero_invoker",
        AbilityCastPoint = 0.05,
        AbilityCastRange = 0,
        area_of_effect = 175,
        cataclysm_cooldown = 90,
        cataclysm_count = 0,
        cataclysm_damage_pct = 75,
        cataclysm_max_range = 180,
        cataclysm_min_range = 90,
        create_forged_spirit_on_hero_damage = 0,
        damage = { 175, 225, 275, 325, 375, 425, 475, 525, 575 },
        delay = 1.7,
        vision_distance = 400,
        vision_duration = 4,
    },
    invoker_tornado = {
        hero = "npc_dota_hero_invoker",
        AbilityCastPoint = 0.05,
        AbilityCastRange = 2000,
        area_of_effect = 200,
        base_damage = 50,
        end_vision_duration = 1.75,
        lift_duration = { 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4, 2.6, 2.8 },
        quas_damage = 0,
        travel_distance = { 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600, 3900 },
        travel_speed = 1000,
        twister_damage = 0,
        twister_distance_interval = 0,
        twister_duration = 0,
        twister_radius = 150,
        twister_tick_rate = 0.25,
        vision_distance = 200,
        wex_damage = { 45, 90, 135, 180, 225, 270, 315, 360, 405 },
    },
    jakiro_dual_breath = {
        hero = "npc_dota_hero_jakiro",
        AbilityCastPoint = 0.35,
        AbilityCastRange = 850,
        AbilityDuration = 5,
        burn_damage = { 20, 40, 60, 80 },
        end_radius = 275,
        fire_delay = 0.2,
        slow_attack_speed_pct = { -25, -30, -35, -40 },
        slow_movement_speed_pct = { -25, -30, -35, -40 },
        speed = 1050,
        speed_fire = 1050,
        start_radius = 150,
    },
    jakiro_ice_path = {
        hero = "npc_dota_hero_jakiro",
        AbilityCastPoint = 0.65,
        AbilityCastRange = 1100,
        damage = 50,
        detonate_damage = 0,
        detonate_projectile_speed = 0,
        detonate_stun_duration = 0,
        path_delay = 0.2,
        path_duration = { 3, 3.5, 4, 4.5 },
        path_radius = 150,
        stun_duration = { 1.25, 1.5, 1.75, 2 },
    },
    jakiro_macropyre = {
        hero = "npc_dota_hero_jakiro",
        AbilityCastPoint = 0.4,
        AbilityCastRange = 1400,
        burn_interval = 0.5,
        damage = { 100, 150, 200 },
        duration = 10,
        ice_edge_linger_duration = 0,
        ice_edge_movement_slow = 0,
        ice_edge_path_offset = 0,
        ice_edge_path_radius = 0,
        linger_duration = 1,
        path_width = 500,
        pierces_magic_immunity = 0,
        pure_damage_type = 0,
    },
    kunkka_ghostship = {
        hero = "npc_dota_hero_kunkka",
        AbilityCastPoint = 0.3,
        AbilityCastRange = 1000,
        base_cannon_rotation = 20,
        distance_between_cannons = 75,
        ghostship_distance = 2000,
        ghostship_speed = 650,
        ghostship_width = 450,
        initial_cannon_offset = -150,
        num_cannon_volleys = 3,
        rotation_per_cannon = 12,
        rum_factor = 2,
        stun_duration = 1.2,
        tooltip_delay = 3.1,
    },
    kunkka_torrent = {
        hero = "npc_dota_hero_kunkka",
        AbilityCastPoint = 0.4,
        AbilityCastRange = 1300,
        damage_tick_interval = 0.2,
        delay = 1.6,
        movespeed_bonus = -40,
        percent_instant = 0,
        radius = 250,
        slow_duration = { 1, 2, 3, 4 },
        stun_duration = 1.4,
        torrent_damage = { 110, 180, 250, 320 },
    },
    lina_light_strike_array = {
        hero = "npc_dota_hero_lina",
        AbilityCastPoint = 0.45,
        AbilityCastRange = 700,
        light_strike_array_aoe = 250,
        light_strike_array_damage = { 80, 125, 170, 215 },
        light_strike_array_delay_time = 0.5,
        light_strike_array_stun_duration = { 1.2, 1.6, 2, 2.4 },
    },
    lion_impale = {
        hero = "npc_dota_hero_lion",
        AbilityCastPoint = 0.3,
        AbilityCastRange = 650,
        cone_shaped = 0,
        damage = { 105, 170, 235, 300 },
        duration = { 1.3, 1.6, 1.9, 2.2 },
        length_buffer = 275,
        pierces_immunity = 0,
        speed = 2800,
        width = 140,
    },
    magnataur_reverse_polarity = {
        hero = "npc_dota_hero_magnataur",
        AbilityCastPoint = 0.3,
        AbilityCastRange = 410,
        hero_stun_duration = { 2.5, 3, 3.5 },
        knockback_height = 0,
        max_knockback_distance = 0,
        polarity_damage = { 100, 200, 300 },
        pull_duration = 0,
        pull_radius = 430,
        push_radius = 0,
        stat_buff_duration = 0,
        stats_per_stack = 0,
    },
    mars_arena_of_blood = {
        hero = "npc_dota_hero_mars",
        AbilityCastPoint = 0.2,
        AbilityCastRange = 400,
        allied_reduction_pct = 0,
        arena_kill_buff_damage_pct = 0,
        arena_kill_buff_duration = 0,
        arena_kill_buff_heal_pct = 0,
        cast_around_self_and_leash = 0,
        duration = 5.5,
        first_warrior_angle = 0,
        formation_time = 0.1,
        obscure_vision = 0,
        pierces_debuff_immunity = 0,
        radius = 550,
        spear_attack_interval = 1,
        spear_damage = { 80, 170, 260 },
        spear_distance_from_wall = 160,
        warrior_count = 14,
        warrior_fade_max_dist = 450,
        warrior_fade_min_dist = 350,
        width = 100,
    },
    mars_spear = {
        hero = "npc_dota_hero_mars",
        AbilityCastPoint = 0.25,
        activity_duration = 1.7,
        damage = { 100, 175, 250, 325 },
        knockback_distance = 75,
        knockback_duration = 0.25,
        max_impale_targets = 1,
        spear_range = { 900, 1000, 1100, 1200 },
        spear_speed = 1400,
        spear_vision = 300,
        spear_width = 125,
        stun_duration = { 1.3, 1.6, 1.9, 2.2 },
    },
    mirana_arrow = {
        hero = "npc_dota_hero_mirana",
        AbilityCastPoint = 0.5,
        AbilityCastRange = 3000,
        AbilityDuration = 3.11,
        arrow_bonus_damage = 180,
        arrow_max_stun = { 2.3, 3.2, 4.1, 5 },
        arrow_max_stunrange = 1500,
        arrow_min_stun = 0.01,
        arrow_range = 3000,
        arrow_speed = 900,
        arrow_vision = 400,
        arrow_width = 115,
        pierce_units = 0,
    },
    mirana_invis = {
        hero = "npc_dota_hero_mirana",
        AbilityCastPoint = 0.5,
        AbilityCastRange = 0,
        bonus_movement_speed = { 9, 12, 15 },
        bonus_outgoing_damage_pct = { 9, 12, 15 },
        duration = 18,
        evasion = 0,
        fade_delay = { 2.5, 2, 1.5 },
    },
    monkey_king_boundless_strike = {
        hero = "npc_dota_hero_monkey_king",
        AbilityCastPoint = 0.4,
        AbilityCastRange = 1100,
        acceleration_z = 5000,
        duration = 0.2,
        max_horizontal_acceleration = 30000,
        min_height_above_highest = 150,
        min_height_above_lowest = 100,
        soldier_spawn_duration = 0,
        spring_channel_pct = 35,
        strike_cast_range = 1100,
        strike_crit_mult = { 120, 140, 160, 180 },
        strike_flat_damage = { 20, 40, 60, 80 },
        strike_radius = 150,
        stun_duration = { 0.7, 0.9, 1.1, 1.3 },
    },
    monkey_king_wukongs_command = {
        hero = "npc_dota_hero_monkey_king",
        AbilityCastPoint = 1,
        AbilityCastRange = 0,
        attack_speed = 1.1,
        attack_speed_pct = 0,
        bonus_armor = { 15, 20, 25 },
        cast_range = 625,
        damage_pct = 0,
        duration = 14,
        first_radius = 300,
        leadership_time_buffer = 0,
        move_speed = 700,
        num_first_soldiers = 5,
        num_second_soldiers = 9,
        outer_attack_buffer = 0,
        second_radius = 750,
    },
    nevermore_requiem = {
        hero = "npc_dota_hero_nevermore",
        AbilityCastPoint = 1.67,
        max_soul_release = 20,
        requiem_line_speed = 700,
        requiem_line_width_end = 300,
        requiem_line_width_start = 125,
        requiem_radius = 1000,
        requiem_reduction_mres = { -5, -10, -15 },
        requiem_reduction_ms = { -20, -25, -30 },
        requiem_slow_duration = 0.6,
        requiem_slow_duration_max = 2.15,
        requiem_soul_conversion = 1,
        soul_death_release = 0.5,
    },
    night_stalker_darkness = {
        hero = "npc_dota_hero_night_stalker",
        AbilityCastPoint = 0.3,
        bonus_damage = { 50, 100, 150 },
        duration = 30,
    },
    nyx_assassin_impale = {
        hero = "npc_dota_hero_nyx_assassin",
        AbilityCastPoint = 0.3,
        AbilityCastRange = 750,
        duration = { 1.1, 1.4, 1.7, 2 },
        impale_damage = { 100, 160, 220, 280 },
        length = 750,
        speed = 1600,
        width = 140,
    },
    nyx_assassin_vendetta = {
        hero = "npc_dota_hero_nyx_assassin",
        attack_animation_bonus = 70,
        attack_range_bonus = 75,
        bonus_damage = { 300, 400, 500 },
        break_duration = 4,
        duration = { 45, 50, 55 },
        fade_time = 0,
        free_pathing_duration = 0,
        free_pathing_movement_speed_bonus = 0,
        health_regen_rate_scepter = 3,
        mana_regen_rate_scepter = 3,
        movement_speed = { 16, 18, 20 },
    },
    phoenix_supernova = {
        hero = "npc_dota_hero_phoenix",
        AbilityCastPoint = 0.01,
        AbilityCastRange = 450,
        AbilityDuration = 6,
        aura_radius = 1200,
        damage_per_sec = { 50, 80, 110 },
        max_hero_attacks = { 6, 8, 10 },
        stun_duration = { 1.6, 2, 2.4 },
        tick_interval = 0.2,
    },
    puck_dream_coil = {
        hero = "npc_dota_hero_puck",
        AbilityCastPoint = 0.1,
        AbilityCastRange = 750,
        attack_rate_pct = 0,
        coil_break_damage = { 200, 300, 400 },
        coil_break_radius = 600,
        coil_duration = { 5, 5.5, 6 },
        coil_initial_damage = { 175, 250, 325 },
        coil_radius = 375,
        coil_rapid_fire_rate = 0,
        coil_rapid_fire_z_offset = 0,
        coil_stun_duration = { 1.5, 2, 2.5 },
        stun_duration = 0.5,
    },
    pudge_meat_hook = {
        hero = "npc_dota_hero_pudge",
        AbilityCastPoint = 0.3,
        AbilityCastRange = 1300,
        damage = { 150, 220, 290, 360 },
        hook_speed = 1600,
        hook_width = 100,
        reveal_duration = 0,
        self_stun_duration_percent = 65,
        vector_target_distance = 0,
        vision_duration = 4,
        vision_radius = 500,
    },
    rattletrap_hookshot = {
        hero = "npc_dota_hero_rattletrap",
        AbilityCastPoint = 0.3,
        AbilityCastRange = { 2000, 2500, 3000 },
        allied_armor_bonus = 0,
        ally_shield_duration = 0,
        cooldown_refund_ally = 0,
        damage = { 75, 175, 275 },
        duration = { 1.2, 1.4, 1.6 },
        latch_radius = 125,
        radius_ally = 175,
        speed = { 4000, 5000, 6000 },
        stun_radius = 175,
    },
    sandking_burrowstrike = {
        hero = "npc_dota_hero_sand_king",
        AbilityCastPoint = 0,
        AbilityCastRange = { 550, 625, 700, 775 },
        burrow_anim_time = 0.52,
        burrow_duration = { 1.2, 1.4, 1.6, 1.8 },
        burrow_speed = 2000,
        burrow_width = 150,
    },
    sandking_epicenter = {
        hero = "npc_dota_hero_sand_king",
        AbilityCastPoint = 2,
        AbilityDuration = 6,
        epicenter_damage = { 60, 70, 80 },
        epicenter_pulses = { 12, 16, 20 },
        epicenter_radius_base = 450,
        epicenter_radius_increment = 13,
        epicenter_slow = { -30, -40, -50 },
        epicenter_slow_as = { -30, -40, -50 },
        linger_duration = 3,
        proc_passively = 0,
        shard_interval = 3,
        shard_radius = 0,
    },
    silencer_global_silence = {
        hero = "npc_dota_hero_silencer",
        AbilityCastPoint = 0.3,
        AbilityDuration = { 4.5, 5.25, 6 },
    },
    snapfire_firesnap_cookie = {
        hero = "npc_dota_hero_snapfire",
        AbilityCastPoint = 0.2,
        AbilityCastRange = 650,
        impact_damage = { 60, 130, 200, 270 },
        impact_radius = 300,
        impact_stun_duration = { 1, 1.4, 1.8, 2.2 },
        jump_duration = 0.484,
        jump_height = 257,
        jump_horizontal_distance = 425,
        landing_gesture_duration = 0.6,
        pre_hop_duration = 0,
        pre_land_anim_time = 0.14,
        projectile_speed = 1200,
        self_cast_delay = 0.3,
        shard_damage_multiplier_tooltip = 40,
        target_heal = 0,
    },
    snapfire_mortimer_kisses = {
        hero = "npc_dota_hero_snapfire",
        AbilityCastPoint = 0.5,
        AbilityCastRange = 3000,
        AbilityDuration = 5.5,
        burn_damage = { 60, 80, 100 },
        burn_ground_duration = 3.5,
        burn_interval = 0.5,
        burn_linger_duration = 1,
        damage_per_impact = { 170, 250, 330 },
        delay_after_last_projectile = 0.5,
        dist_change_speed = 75,
        duration_tooltip = 5.5,
        impact_radius = 275,
        max_lob_travel_time = 2,
        min_lob_travel_time = 0.8,
        min_range = 600,
        move_slow_pct = { 15, 20, 25 },
        projectile_count = 8,
        projectile_speed = 1300,
        projectile_vision = 500,
        projectile_width = 130,
        turn_rate = 75,
    },
    spirit_breaker_charge_of_darkness = {
        hero = "npc_dota_hero_spirit_breaker",
        AbilityCastPoint = 0.1,
        AbilityCastRange = 0,
        bash_radius = 300,
        charge_for_max_linger = 0,
        guaranteed_bash_time = 0,
        linger_time_max = 0,
        linger_time_min = 0,
        min_movespeed_bonus_pct = 25,
        movement_speed = { 275, 325, 375, 425 },
        out_of_world_time = 0,
        reveal_charge = 0,
        stun_duration = { 1.3, 1.6, 1.9, 2.2 },
        vision_duration = 0.94,
        vision_radius = 400,
        windup_time = 1.5,
    },
    tidehunter_ravage = {
        hero = "npc_dota_hero_tidehunter",
        AbilityCastPoint = 0.3,
        AbilityCastRange = 0,
        duration = { 2, 2.2, 2.4 },
        radius = 1250,
        speed = 725,
    },
    tiny_avalanche = {
        hero = "npc_dota_hero_tiny",
        AbilityCastPoint = 0,
        AbilityCastRange = 600,
        avalanche_damage = { 90, 180, 270, 360 },
        projectile_speed = 1200,
        radius = { 325, 340, 355, 370 },
        stun_duration = 0.3,
        tick_count = 5,
        tick_interval = 0.3,
        total_duration = 1.5,
    },
    treant_overgrowth = {
        hero = "npc_dota_hero_treant",
        AbilityCastPoint = 0.5,
        damage = 95,
        duration = { 3, 4, 5 },
        radius = 800,
        undispellable = 0,
    },
    tusk_walrus_punch = {
        hero = "npc_dota_hero_tusk",
        AbilityCastPoint = 0,
        AbilityCastRange = 150,
        air_time = 1,
        bonus_damage = { 60, 90, 120 },
        crit_multiplier = { 200, 250, 300 },
        push_length = 1000,
    },
    venomancer_poison_nova = {
        hero = "npc_dota_hero_venomancer",
        attack_slow = 0,
        damage_base = { 35, 50, 65 },
        duration = 12,
        hp_damage = { 3, 3.5, 4 },
        magic_resist_reduce = 0,
        radius = 950,
        speed = 550,
        start_radius = 255,
    },
    void_spirit_aether_remnant = {
        hero = "npc_dota_hero_void_spirit",
        AbilityCastPoint = 0,
        AbilityCastRange = 850,
        activation_delay = 0.4,
        artifice_duration_override = 0,
        artifice_pct_effectiveness = 0,
        creep_damage_pct = 0,
        damage_tick_rate = 0,
        duration = 17,
        end_radius = 90,
        impact_damage = { 90, 140, 190, 240 },
        pierces_creeps = 0,
        projectile_speed = 900,
        pull_destination = { 44, 50, 56, 62 },
        pull_duration = { 1, 1.2, 1.4, 1.6 },
        radius = 300,
        remnant_watch_distance = 450,
        remnant_watch_radius = 130,
        rotation_speed = 0,
        start_radius = 90,
        think_interval = 0.1,
        truesight_range = 0,
        watch_path_vision_radius = 200,
    },
    warlock_rain_of_chaos = {
        hero = "npc_dota_hero_warlock",
        AbilityCastPoint = 0.5,
        AbilityCastRange = 900,
        aoe = 600,
        bonus_slow_resistance = 60,
        golem_armor = { 8, 12, 14 },
        golem_dmg = { 100, 150, 200 },
        golem_duration = 60,
        golem_gold_bounty = { 100, 150, 200 },
        golem_health_regen = { 25, 50, 75 },
        golem_hp = { 1500, 2250, 3000 },
        golem_movement_speed = { 320, 340, 360 },
        stun_delay = 0.5,
        stun_duration = 0.8,
        tooltip_golem_armor = { 8, 12, 14 },
        tooltip_manahealthboost = 0,
    },
    windrunner_powershot = {
        hero = "npc_dota_hero_windrunner",
        AbilityCastPoint = 0,
        AbilityCastRange = 3000,
        AbilityChannelTime = 1,
        arrow_range = 3000,
        arrow_speed = 3000,
        arrow_width = 125,
        damage_reduction = 15,
        max_execute_threshold = 0,
        min_execute_threshold = 0,
        powershot_damage = { 170, 270, 370, 470 },
        slow = { 22, 28, 34, 40 },
        slow_duration = 3,
        tree_width = 50,
        vision_duration = 3.34,
        vision_radius = 400,
    },
    wisp_relocate = {
        hero = "npc_dota_hero_wisp",
        AbilityCastPoint = 0,
        cast_delay = { 3.5, 3.25, 3 },
        return_time = 12,
    },
    zuus_thundergods_wrath = {
        hero = "npc_dota_hero_zuus",
        AbilityCastPoint = 0.4,
        damage = { 275, 425, 575 },
        sight_duration = 3,
        sight_radius_day = 600,
        sight_radius_night = 600,
    },
}
Изменения

Заметок к версиям нет.

Используют

Пока ни один опубликованный скрипт её не требует.

Ещё у этого автора

Ещё у этого автора

ground

от hunnyc

Ground height and high-ground level at any point of the dota map.

pack.json
"requires": { "ground": "^1.0" }
твой lua
local ground = require("lib/ground")
0 скриптов используютОпубликованных версий пока нет

Beta Tester Config

от hunnyc
Входит в доступ

Beta 0.10.54 preset: combo on F, last hit on B, every other bind moved off dota's own keys, hp cards and minimap marks on.

configcombolast hit
Оценок пока нет0 установок
v1.0.0 · Обновлён 2026-10-17✓ 0.10.70

lane_geom

от hunnyc

A lane as a polyline: the point on it nearest to a creep, the heading there, and a walk of N units along it.

pack.json
"requires": { "lane_geom": "^1.0" }
твой lua
local lane_geom = require("lib/lane_geom")
0 скриптов используютv1.0.0