Skip to main content

Evade Helper

Overview

The Evade Helper provides an API for adding custom danger zones to the evade system. You can define circles, rectangles, and cones that the evade system will recognize and avoid. This is useful for adding custom spell awareness, boss mechanics, or any ground effects that aren't in the default database.

Key Features:

  • Multiple Geometries - Add circles, rectangles, and cones
  • Automatic Deduplication - Safe to call every frame; entries are deduplicated by key and geometry
  • Customizable Danger Levels - Set visual, low, medium, high, or extreme danger
  • Growth Animation - Support for expanding zones over time
  • Point Safety Checks - Query if a position is safe from all danger zones

Importing The Module

---@type evade_helper
local evade = require("common/utility/evade_helper")
Method Access

Access functions with : (colon), not . (dot).


Functions

evade:add_circle

Syntax
evade:add_circle(key: string, params: table): boolean, string

Parameters

ParameterTypeDescription
keystringUnique identifier for this danger zone
paramstableCircle parameters (see below)

Params Table

FieldTypeDefaultDescription
namestringnilDisplay name
radiusnumberRequiredCircle radius in yards
time_alivenumber5.0How long the zone persists
growth_rationumber0.0Expansion rate over time
object_idintegernilUsed for deduplication with geometry
caster_idinteger0Caster identifier
danger_levelintegervisualDanger level enum value
danger_level_dropdownintegersame as danger_levelUI dropdown level
is_debugbooleanfalseEnable debug visualization
Returns
  • boolean - True if added successfully
  • string - Reason if not added

Example Usage

local evade = require("common/utility/evade_helper")
local db = require("root/core_lua/proxy/evade/danger_database")

local ok, why = evade:add_circle("my_spell_circle", {
name = "My Spell Circle",
radius = 6.5,
time_alive = 8.0,
object_id = 123456,
danger_level = db.danger_level_enum.extreme,
danger_level_dropdown = db.danger_level_enum.extreme
})

if not ok then
core.log("[evade_helper] not added: " .. why)
end

evade:add_rect

Syntax
evade:add_rect(key: string, params: table): boolean, string

Params Table

FieldTypeDefaultDescription
namestringnilDisplay name
widthnumberRequiredRectangle width in yards
lengthnumberRequiredRectangle length in yards
time_alivenumber5.0How long the zone persists
growth_rationumber0.0Expansion rate over time
is_projectilebooleanfalseWhether this is a moving projectile
object_idintegernilUsed for deduplication
caster_idinteger0Caster identifier
danger_levelintegervisualDanger level enum value
danger_level_dropdownintegersameUI dropdown level
is_debugbooleanfalseEnable debug visualization

Example Usage

evade:add_rect("boss_line_aoe", {
name = "Boss Line AOE",
width = 4.0,
length = 18.0,
time_alive = 4.0,
object_id = 998877
})

evade:add_cone

Syntax
evade:add_cone(key: string, params: table): boolean, string

Params Table

FieldTypeDefaultDescription
namestringnilDisplay name
radiusnumberRequiredCone radius (length) in yards
anglenumberRequiredCone angle in degrees
time_alivenumber3.0How long the zone persists
growth_rationumber0.0Expansion rate over time
anim_speednumber2.0Animation speed
object_idintegernilUsed for deduplication
caster_idinteger-1Caster identifier
danger_levelintegervisualDanger level enum value
danger_level_dropdownintegersameUI dropdown level
is_debugbooleanfalseEnable debug visualization

Example Usage

evade:add_cone("frontal_breath", {
name = "Frontal Breath",
radius = 12.0,
angle = 60.0,
anim_speed = 1.5,
time_alive = 3.0,
is_debug = true
})

evade:add_custom

Syntax
evade:add_custom(key: string, data: table): boolean, string

Forwards your exact table to the database. Must include geometry_type and all geometry-specific fields. Still deduplicated by key and geometry+object_id.

Example Usage

local db = require("root/core_lua/proxy/evade/danger_database")

evade:add_custom("rare_custom_shape", {
name = "Rare Shape",
geometry_type = db.geometry_type_enum.rect,
danger_level = db.danger_level_enum.visual,
danger_level_dropdown = db.danger_level_enum.extreme,
enable_check = core.menu.checkbox(true, "rare_custom_shape:enable_check"),
color = core.menu.colorpicker(db.danger_level_colors.extreme, "rare_custom_shape:color"),
object_id = -1,
caster_id = 0,
width = 3.0,
length = 9.0,
time_alive = 6.0,
is_projectile = false,
growth_ratio = 10.0,
is_debug = true
})

evade:is_point_safe

Syntax
evade:is_point_safe(point: vec3): boolean

Checks if a position is safe from all registered danger zones.

Example Usage

local safe_pos = vec3.new(100, 200, 30)
if evade:is_point_safe(safe_pos) then
core.log("Position is safe!")
end

evade:is_point_safe_full

Syntax
evade:is_point_safe_full(point: vec3, fall_threshold?: number): boolean

Extended safety check that also considers fall damage threshold.


evade:has_entry

evade:has_entry(key: string): boolean

Checks if a danger zone with the given key already exists.


evade:clear_cache

evade:clear_cache(): nil

Clears all cached danger zone entries.


Query Functions

evade:get_database_info(): any      -- Get database information
evade:get_geometry(): any -- Get geometry data
evade:get_geometry_inst(): any -- Get geometry instances
evade:get_customizations(): any -- Get customization data

evade:add_debug_spells

evade:add_debug_spells(key: string, add_cone: boolean, add_rect: boolean, add_circle: boolean): any

Adds debug visualizations for testing purposes.


Danger Level Enum

Access danger levels through the database module:

local db = require("root/core_lua/proxy/evade/danger_database")

db.danger_level_enum.visual -- Lowest, just visual indicator
db.danger_level_enum.low
db.danger_level_enum.medium
db.danger_level_enum.high
db.danger_level_enum.extreme -- Highest priority

Complete Example

Boss Mechanic Handler

local evade = require("common/utility/evade_helper")
local db = require("root/core_lua/proxy/evade/danger_database")

-- Track boss mechanics
local function on_spell_cast(data)
local spell_id = data.spell_id
local caster = data.caster

-- Boss frontal cone attack
if spell_id == 123456 then
local pos = caster:get_position()
local facing = caster:get_facing()

evade:add_cone("boss_frontal_" .. tostring(caster), {
name = "Boss Frontal",
radius = 20.0,
angle = 90.0,
time_alive = 3.0,
danger_level = db.danger_level_enum.extreme,
object_id = caster:get_id()
})
end

-- Ground circle AoE
if spell_id == 789012 then
local target_pos = data.target_position

evade:add_circle("ground_aoe_" .. core.game_time(), {
name = "Ground AoE",
radius = 8.0,
time_alive = 5.0,
growth_ratio = 2.0, -- Expands over time
danger_level = db.danger_level_enum.high
})
end
end

core.register_on_spell_cast_callback(on_spell_cast)

Safe Position Finder

local evade = require("common/utility/evade_helper")

local function find_safe_position(center, max_distance, step)
step = step or 2

for distance = step, max_distance, step do
for angle = 0, 360, 30 do
local rad = math.rad(angle)
local test_pos = vec3.new(
center.x + math.cos(rad) * distance,
center.y + math.sin(rad) * distance,
center.z
)

if evade:is_point_safe(test_pos) then
return test_pos
end
end
end

return nil -- No safe position found
end