### Complete Spell Scripting Example with Callbacks Source: https://github.com/less-nefariousness5/ufo/blob/main/spell.md A comprehensive example demonstrating spell definition, setting up default and named callbacks for 'fireball', 'fire_blast', and 'blizzard', and integrating them into the main update loop for rotation management. Includes AoE and single-target logic. ```lua -- Define spells ufo.define({ fireball = { 133, range = 40, projectile_speed = 24 }, fire_blast = { 108853, range = 40 }, blizzard = { 10, radius = 8, range = 30, geometry = "circle" } }) -- Fireball default callback fireball:Callback(function(spell) if not target or not target.exists or target.dead then return end if spell.cd > 0 then return end if not spell:Castable(target) then return end return spell:Cast(target) end) -- Fireball AoE callback fireball:Callback("aoe", function(spell) local enemies = ufo.enemies.circle(spell) if enemies.count >= 3 then local pos = enemies.lowest.position() return spell:AoECastPosition(pos) end end) -- Fire Blast callback (off-GCD) fire_blast:Callback(function(spell) if not target or not target.exists or target.dead then return end if spell.charges < 1 then return end if not spell:Castable(target) then return end return spell:CastFast(target) end) -- Blizzard callback blizzard:Callback(function(spell) if spell.cd > 0 then return end local enemies = ufo.enemies.circle(spell) if enemies.count >= 5 then local pos = enemies.lowest.position() return spell:AoECastPosition(pos) end end) -- Main rotation ufo.on_update(function() player = ufo.player target = ufo.target if not target or not target.exists then return end -- Off-GCD first fire_blast() -- Main rotation blizzard() fireball() fireball("aoe") end) ``` -------------------------------- ### Get Cooldown Start Time - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/spell.md Provides an example of accessing the game time when a spell's cooldown began using the `spell.cdstart` property. This can be useful for calculating precise cooldown remaining. ```lua -- Example usage might involve calculating difference from current time ``` -------------------------------- ### Trinket Management Example - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Illustrates how to manage trinkets, including checking usability and cooldowns, and using them during combat phases like a burst window. ```lua -- Create trinket items by slot local trinket1 = ufo.item(13) -- Trinket slot 1 local trinket2 = ufo.item(14) -- Trinket slot 2 ufo.on_update(function() player = ufo.player target = ufo.target if not target or not target.exists then return end -- Use trinket on burst if player.buffFrom(burst_buffs) then if trinket1.usable and trinket1.cd == 0 then trinket1.use() end if trinket2.usable and trinket2.cd == 0 then trinket2.use() end end end) ``` -------------------------------- ### Basic Item Usage Example - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Demonstrates a common scripting pattern for using healthstones and healing potions based on player health and cooldowns within an update loop. ```lua -- Create item objects local healthstone = ufo.item(5512) local healing_potion = ufo.item(191380) ufo.on_update(function() player = ufo.player -- Use healthstone at low health if player.hp < 0.3 and healthstone.usable and healthstone.cd == 0 then healthstone.use() end -- Use healing potion if healthstone is on cooldown if player.hp < 0.35 and healing_potion.usable and healthstone.cd > 0 then healing_potion.use() end end) ``` -------------------------------- ### Defensive Item Usage Example - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Shows how to implement defensive item usage, such as using a PvP trinket to break CC or an armor kit when under heavy attack, by monitoring player status and combat events. ```lua local defensive_trinket = ufo.item(14) -- PvP trinket local armor_kit = ufo.item(12345) ufo.on_update(function() player = ufo.player -- Use PvP trinket on hard CC if player.stun or player.incap then if defensive_trinket.usable and defensive_trinket.cd == 0 then defensive_trinket.use() end end -- Use armor kit when taking heavy damage local total, melee, ranged, cds = player.v2attackers() if cds >= 2 and armor_kit.usable then armor_kit.use() end end) ``` -------------------------------- ### Main Combat Rotation with Spell Callbacks Source: https://github.com/less-nefariousness5/ufo/blob/main/events.md This example illustrates setting up a main combat rotation using the UFO framework. It defines spells, registers general callbacks for each spell's logic, and then utilizes an update loop to execute abilities based on priority and availability. ```lua -- Define spells ufo.define({ fireball = 133, fire_blast = 108853, phoenix_flames = 257541, pyroblast = 11366 }) -- Setup callbacks fireball:Callback(function(spell) if not target or not target.exists then return end if spell.cd > 0 then return end if not spell:Castable(target) then return end return spell:Cast(target) end) fire_blast:Callback(function(spell) if not target or not target.exists then return end if spell.charges < 1 then return end return spell:CastFast(target) end) -- Main update loop ufo.on_update(function() player = ufo.player target = ufo.target if not target or not target.exists then return end -- Off-GCD abilities first fire_blast() phoenix_flames() -- Main rotation pyroblast() fireball() end) ``` -------------------------------- ### Get Screen Dimensions Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Retrieves the current width and height of the game screen. This function takes no arguments and returns two numbers. ```lua ufo.screensize() ``` -------------------------------- ### Draw Filled Rectangle Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Draws a solid, filled rectangle on the screen. Requires the starting position, dimensions, color, and rounding. ```lua ufo.drawrectfilled(start, width, height, color, rounding) ``` -------------------------------- ### Basic unit filtering example (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Demonstrates chaining multiple filters (within, alive, los) and a custom filter function to select nearby, low-health, visible enemies for execution. ```lua -- Get nearby low health enemies local executeTargets = ufo.enemies .within(40) .alive .los .filter(function(enemy) return enemy.hp < 0.2 end) if executeTargets.count > 0 then execute.Cast(executeTargets.first) end ``` -------------------------------- ### Draw Rectangle Border Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Draws the outline of a rectangle on the screen. Requires the starting position, dimensions, color, border thickness, and rounding. ```lua ufo.drawrect(start, width, height, color, thickness, rounding) ``` -------------------------------- ### Spell Interrupt Logic Setup Source: https://github.com/less-nefariousness5/ufo/blob/main/message (4).txt Sets up a table to manage interrupt triggers for spells like 'disrupt'. It defines conditions for when an interrupt should occur, such as checking enemy existence, casting status, interrupt immunity, cast timing, and whether the target is a high-priority spell. Requires 'disrupt' spell object, 'ufo' library, and lists of high-priority interrupt spell IDs. ```lua local interrupt_triggers = { disrupt = { spell = disrupt, conditions = { -- "generic" is just a key name - you can use any name for conditions generic = function(unit) -- Early exit checks - fail fast if not unit.exists or not unit.casting then return false end -- Don't kick if they have interrupt immunity if unit.buffFrom(IMMUNE_BUFFS) then return false end -- Check cast timing - interrupt near the end -- unit.castRemains = time remaining on current cast in seconds if unit.castRemains > 0.3 + ufo.buffer() then return false end -- Get the spell ID they're casting local castId = unit.castid if not castId then return false end -- Check if it's a spell we want to interrupt local shouldKick = false for _, spellID in ipairs(HIGH_PRIORITY_INTERRUPTS) do if castId == spellID then shouldKick = true break end end if not shouldKick then return false end -- Final check: can we actually cast the interrupt? -- Params: target, ignore_facing, ignore_range -- true for ignore_facing since it's instant cast return disrupt:Castable(unit, true, false) end, } } } ``` -------------------------------- ### Get Buff Description - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Fetches the descriptive text for a buff using its pointer. This is useful for displaying buff information to the user. ```lua unit.buffdesc(buff_ptr) ``` -------------------------------- ### Create and Use Delay Utility with ufo.delay Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Creates a delay utility object that can generate random delays within a specified range or execute functions after a delay. It provides methods to get random delay times and schedule asynchronous execution. ```lua local delay = ufo.delay(0.1, 0.3) -- Get random delay local randomTime = delay() local randomTime2 = delay.get() local exactTime = delay.now() -- Execute after delay delay.after(function() fireball.Cast(target) end) ``` -------------------------------- ### Reactive Defensive Item Usage (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Provides an example of using defensive items reactively. The code checks for player status effects like stun or incapacitation and uses a PvP trinket accordingly. This logic is crucial for timely defensive measures in combat scenarios. ```lua -- React to CC or burst damage if player.stun or player.incap then pvp_trinket.use() end ``` -------------------------------- ### Chain Filters for Clarity in Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Demonstrates chaining multiple filter methods on a collection in Lua for improved readability. This example chains `within`, `alive`, `los`, and `attackable` filters to a collection of enemies. ```lua local validTargets = ufo.enemies .within(40) .alive .los .attackable ``` -------------------------------- ### AoE decision making example (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Shows logic for choosing between single-target and AoE abilities based on the number of nearby, alive, visible enemies. It uses the 'circle' filter for AoE targeting. ```lua -- Decide between single target and AoE local nearbyEnemies = ufo.enemies.within(40).alive.los if nearbyEnemies.count >= 3 then -- Use AoE rotation local aoeTargets = nearbyEnemies.circle(flamestrike) if aoeTargets.count >= 3 then local position = aoeTargets.lowest.position() flamestrike.AoECastPosition(position) end else -- Use single target rotation fireball.Cast(target) end ``` -------------------------------- ### Common Equipment Slot Item References (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Provides examples of how to reference items by their equipment slot, specifically for trinkets, gloves, and belts. This is useful for interacting with equipment that doesn't rely on a specific item ID but rather its position. ```lua -- Trinkets (by slot, not item ID) local trinket1 = ufo.item(13) -- Top trinket slot local trinket2 = ufo.item(14) -- Bottom trinket slot -- Other slots local gloves = ufo.item(10) -- Gloves slot (for engineering) local belt = ufo.item(6) -- Belt slot ``` -------------------------------- ### Get Spell Cost Information - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/spell.md Illustrates how to retrieve detailed cost information for a spell, including resource type and amount, by calling the `spell.cost()` method. This allows for resource management before casting. ```lua local costInfo = fireball.cost() if player.mana < costInfo.amount then -- Not enough mana return end ``` -------------------------------- ### Healing priority example (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Implements a function to find the most critical healing target within a group. It first checks for critically low health allies and falls back to the lowest health ally if none are critical. ```lua -- Find most critical healing target local function findHealingTarget() -- Check for critically low health local critical = ufo.fgroup.within(40).alive.find(function(unit) return unit.hpa < 0.3 end) if critical then return critical end -- Otherwise find lowest health return ufo.fgroup.within(40).alive.los.lowest end ufo.on_update(function() local healTarget = findHealingTarget() if healTarget then heal_spell.Cast(healTarget) end end) ``` -------------------------------- ### Get the first unit in a collection (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Retrieves the first unit from a collection. Often used after sorting to get the closest or highest priority unit. ```lua local firstEnemy = ufo.enemies.within(40).sort_distance.first -- Returns the closest enemy ``` -------------------------------- ### Get Remaining Cooldown - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/spell.md Demonstrates how to get the remaining cooldown time in seconds for a spell using the `spell.cd` property. This is crucial for managing spell rotations and timing. ```lua if fireball.cd == 0 then -- Fireball is off cooldown fireball.Cast(target) end if fireball.cd < 1.5 then -- Fireball will be ready soon end ``` -------------------------------- ### Coordinating Item Usage with Spell Cooldowns (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Shows how to coordinate item usage with major spell cooldowns. This example checks if `combustion` is off cooldown or has been recently used within the last 10 seconds, and if so, uses a trinket. This ensures powerful combinations are utilized effectively. ```lua -- Use trinket with major cooldowns if combustion.cd == 0 or combustion.recentlyused(10) then trinket.use() end ``` -------------------------------- ### Lua UFO Menu System Initialization Source: https://github.com/less-nefariousness5/ufo/blob/main/message (4).txt Initializes a menu system using UFO's UI elements, including tree nodes, checkboxes, and sliders. This allows users to configure various aspects of the Havoc DH rotation and behavior, such as enabling rotations, defensives, interrupts, and setting HP thresholds for defensive spell usage. ```lua -- UFO uses a menu system with checkboxes, sliders, trees, etc. -- Store menu elements in a table for easy access local menu = { -- Tree nodes create collapsible sections main_tree = core.menu.tree_node(), -- Checkboxes for on/off options enable_rotation = core.menu.checkbox(true, "enable_rotation"), enable_defensives = core.menu.checkbox(true, "enable_defensives"), enable_interrupts = core.menu.checkbox(true, "enable_interrupts"), enable_cc = core.menu.checkbox(true, "enable_cc"), -- Sliders for numeric values (min, max, default, unique_id) blur_hp = core.menu.slider_int(0, 100, 60, "blur_hp"), darkness_hp = core.menu.slider_int(0, 100, 35, "darkness_hp"), netherwalk_hp = core.menu.slider_int(0, 100, 20, "netherwalk_hp"), } ``` -------------------------------- ### Get Debuff Uptime - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Calculates the elapsed time in seconds since a specific debuff was applied to the unit. ```lua unit.debuffuptime(12345) ``` -------------------------------- ### Get Buff Uptime - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Calculates the elapsed time in seconds since a specific buff was applied to the unit. ```lua unit.buffuptime(12345) ``` -------------------------------- ### Use AoE Geometry Methods in Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Explains how to use AoE geometry methods in Lua to let the UFO addon calculate optimal AoE spell positions. This example uses `ufo.enemies.circle` to find targets and then `blizzard.AoECastPosition` to cast a spell at the optimal location. ```lua -- Let UFO calculate optimal AoE position local targets = ufo.enemies.circle(blizzard) if targets.count >= 4 then blizzard.AoECastPosition(targets.lowest.position()) end ``` -------------------------------- ### Get Unit Name - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Retrieves the name of a unit as a string. This is useful for identifying specific units in the game. ```lua local targetName = target.name ``` -------------------------------- ### Use Descriptive Predicates in Lua Filters Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Shows how to use descriptive lambda functions (predicates) within Lua `filter` methods for clear condition checking. This example filters for enemies with low health (`hp < 0.3`) and without a specific buff (`not unit.bcc`). ```lua local lowHealthEnemies = enemies.filter(function(unit) return unit.hp < 0.3 and not unit.bcc end) ``` -------------------------------- ### Netherwalk Defensive Cooldown Implementation Source: https://github.com/less-nefariousness5/ufo/blob/main/message (4).txt Implements Netherwalk, a defensive ability providing 6 seconds of full immunity. It checks menu settings, spell readiness, player health percentage, and ensures no other major defensives are active before casting. Dependencies include menu states, player health/buff status, and predefined immune/defensive buff lists. ```lua netherwalk:Callback("defensive", function(spell) if not menu.enable_defensives:get_state() then return false end if not spellReady(spell, player) then return false end local netherwalk_threshold = menu.netherwalk_hp:get() / 100 if player.hpa > netherwalk_threshold then return false end -- Netherwalk is the ultimate defensive, save it for dire situations -- Only use if we're not already in a big defensive if player.buffFrom(IMMUNE_BUFFS) then return false end if player.buffFrom(BIG_DEFENSIVES) then return false end return spell:Cast(player) end) ``` -------------------------------- ### Lua Spell Casting and Update Loop Source: https://github.com/less-nefariousness5/ufo/blob/main/message (4).txt This snippet demonstrates a spell casting function and the main update loop for a game or simulation. It includes checks for player status, PvP instances, and executes spells in a prioritized order: defensives, interrupts, crowd control (CC), and rotation spells. It also shows how to cache frequently used units for performance. ```lua if not inMeleeRange(target) then return false end return spell:Cast(target) end) -- ============================================================================ -- MAIN UPDATE LOOP -- ============================================================================ -- This runs every frame - keep it lightweight ufo.on_update(function() -- Cache commonly used units at start of frame player = ufo.player target = ufo.target -- Basic sanity checks if not player.exists then return end if player.dead then return end if player.mounted then return end -- Only run in PvP instances if not ufo.pvp() then return end -- Execute in priority order -- Defensives first (highest priority) netherwalk("defensive") darkness("defensive") blur("defensive") -- Interrupts second - use the tryInterrupts() function -- This checks if menu is enabled inside the function if menu.enable_interrupts:get_state() then tryInterrupts() end -- CC third fel_eruption("cc_healer") chaos_nova("cc_multi") -- Rotation last vengeful_retreat("defensive_mobility") the_hunt("burst") eye_beam("burst") blade_dance("aoe") chaos_strike("filler") fel_blade("builder") immolation_aura("maintenance") demons_bite("generator") end) -- ============================================================================ -- KEY CONCEPTS DEMONSTRATED: -- ============================================================================ -- 1. ufo.define() - Register spells with geometry data -- 2. :Callback(key, function) - Register spell callbacks -- 3. Spell methods: :Cast(), :CastFast(), :AoECast(), :Castable() -- 4. Unit properties: .exists, .dead, .cc, .hpa, .distance, .buff() -- NOTE: .position is a property (no parentheses), not a method -- 5. Collections: ufo.enemies.within(range).loop(callback) -- 6. Menu system: checkboxes, sliders, tree nodes -- 7. Helper functions: isValidEnemy(), canCast(), spellReady() -- 8. Priority system: use early returns and callback ordering -- 9. Interrupt pattern: organize as tables with conditions for easy maintenance -- 10. Performance: cache units, avoid redundant checks -- 11. Safety: always check existence, state, cooldowns, range -- ============================================================================ ``` -------------------------------- ### Get Item Count in Inventory - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Returns the number of units of a specific item the player has in their inventory. This is a read-only numerical property. ```lua if healing_potion.count > 0 then -- Have at least one potion healing_potion.use() end ``` -------------------------------- ### Lua UFO Menu Rendering Callback Source: https://github.com/less-nefariousness5/ufo/blob/main/message (4).txt Registers a callback function to render the UFO addon's menu. This function defines the structure and content of the menu, including enabling/disabling various features like rotation and defensives, and displaying HP percentage sliders for defensive spells, conditionally shown based on the 'Enable Defensives' checkbox state. ```lua -- Menu render callback - called when menu is drawn core.register_on_render_menu_callback(function() menu.main_tree:render("UFO Tutorial - Havoc DH", function() -- Render each menu element with label and tooltip menu.enable_rotation:render("Enable Rotation", "Turn on/off damage rotation") menu.enable_defensives:render("Enable Defensives", "Automatic defensive cooldown usage") menu.enable_interrupts:render("Enable Interrupts", "Automatically interrupt enemy casts") menu.enable_cc:render("Enable Crowd Control", "Automatically CC enemy healer") -- Only show HP sliders if defensives are enabled if menu.enable_defensives:get_state() then menu.blur_hp:render("Blur HP %", "Use Blur below this HP percentage") menu.darkness_hp:render("Darkness HP %", "Use Darkness below this HP percentage") menu.netherwalk_hp:render("Netherwalk HP %", "Use Netherwalk below this HP percentage") end end) end) ``` -------------------------------- ### Line of Sight & Position API Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Functions for checking line of sight, cursor position, world-to-screen conversion, and screen visibility. ```APIDOC ## `ufo.traceline(start, finish, flags)` ### Description Check line of sight between two points. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **start** (Vector3) - Required - Starting position - **finish** (Vector3) - Required - Ending position - **flags** (number) - Required - Trace flags ### Request Example ```lua local visible = ufo.traceline(Vector3.new(0,0,0), Vector3.new(100,0,0), 1) ``` ### Response #### Success Response - **boolean** - True if LOS exists ``` ```APIDOC ## `ufo.losLiteral(start, finish)` ### Description Check direct line of sight between positions. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters - **start** (Vector3) - Required - Starting position - **finish** (Vector3) - Required - Ending position ### Request Example ```lua local direct_visible = ufo.losLiteral(Vector3.new(0,0,0), Vector3.new(50,0,0)) ``` ### Response #### Success Response - **boolean** - True if LOS exists ``` ```APIDOC ## `ufo.cursorposition()` ### Description Get cursor world position. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters None ### Request Example ```lua local cursor_pos = ufo.cursorposition() ``` ### Response #### Success Response - **Vector3** - Cursor position in world space ``` ```APIDOC ## `ufo.worldtoscreen(position)` ### Description Convert 3D world position to 2D screen coordinates. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters - **position** (Vector3) - Required - World position ### Request Example ```lua local screen_coords = ufo.worldtoscreen(Vector3.new(10, 20, 30)) ``` ### Response #### Success Response - **Vector2** - Screen coordinates ``` ```APIDOC ## `ufo.isonscreen(position)` ### Description Check if a position is visible on screen. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters - **position** (Vector3) - Required - World position ### Request Example ```lua local is_visible = ufo.isonscreen(Vector3.new(5, 5, 5)) ``` ### Response #### Success Response - **boolean** - True if visible ``` ```APIDOC ## `ufo.screensize()` ### Description Get screen dimensions. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters None ### Request Example ```lua local width, height = ufo.screensize() ``` ### Response #### Success Response - **number, number** - Width and height ``` -------------------------------- ### Utility Functions Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md General utility functions for logging and conditional checks. ```APIDOC ## ufo.log(msg) ### Description Log a message. ### Method `ufo.log(msg)` ### Parameters #### Path Parameters - **msg** (string) - Message to log ``` ```APIDOC ## ufo.warn(msg) ### Description Log a warning message. ### Method `ufo.warn(msg)` ### Parameters #### Path Parameters - **msg** (string) - Warning message ``` ```APIDOC ## ufo.error(msg) ### Description Log an error message. ### Method `ufo.error(msg)` ### Parameters #### Path Parameters - **msg** (string) - Error message ``` ```APIDOC ## ufo.bin(condition) ### Description Convert boolean to binary (1 or 0). ### Method `ufo.bin(condition)` ### Parameters #### Path Parameters - **condition** (boolean) - Condition to evaluate ### Response #### Success Response (200) - **number** - 1 if true, 0 if false ### Request Example ```lua local isMovingBinary = ufo.bin(player.moving) -- Returns 1 or 0 ``` ``` ```APIDOC ## ufo.pvp() ### Description Check if player is in PvP. ### Method `ufo.pvp()` ### Response #### Success Response (200) - **boolean** - True if in PvP ``` -------------------------------- ### Get Buff Remaining Duration - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Returns the remaining duration in seconds for a specified buff. If the buff is not present, it returns 0. ```lua if player.buffremains(1459) < 60 then -- Buff expires soon end ``` -------------------------------- ### Spell & Item Creation Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Functions for creating spells and items within the framework. ```APIDOC ## ufo.spell(id) ### Description Create a spell object by ID or table of properties. ### Method `ufo.spell(id)` ### Parameters #### Path Parameters - **id** (number|table) - Spell ID or configuration table ### Response #### Success Response (200) - **Spell** - Spell object ### Request Example ```lua -- Simple spell creation local fireball = ufo.spell(133) -- Spell with properties local blizzard = ufo.spell({ 10, -- Spell ID range = 30, -- Range in yards radius = 8, -- AOE radius geometry = "circle", -- AOE shape (circle, cone, rectangle) projectile_speed = 0, -- Projectile speed prediction = "most_hits" -- Prediction type }) ``` ``` ```APIDOC ## ufo.item(id) ### Description Create an item object by ID. ### Method `ufo.item(id)` ### Parameters #### Path Parameters - **id** (number) - Item ID ### Response #### Success Response (200) - **Item** - Item object ### Request Example ```lua local healthstone = ufo.item(5512) ``` ``` ```APIDOC ## ufo.define(table) ### Description Define multiple spells/items and make them globally accessible. ### Method `ufo.define(table)` ### Parameters #### Path Parameters - **table** (table) - Table of spell/item definitions ### Request Example ```lua ufo.define({ auto_attack = 6603, fireball = { 133, range = 40, radius = 0, geometry = "circle" }, frostbolt = 116, ice_lance = 30455 }) -- Now accessible globally fireball.Cast(target) ``` ``` -------------------------------- ### Get Distance to Unit - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Calculates the distance in yards between the player and a target unit. Used for range checks and engagement logic. ```lua if target.distance < 5 then -- Target is in melee range end ``` -------------------------------- ### Get Spell Name - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/spell.md Demonstrates retrieving the in-game name of a spell using the `spell.name` property. This can be used for display purposes or debugging. ```lua ufo.log(fireball.name) -- "Fireball" ``` -------------------------------- ### Pet Controls API Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Commands for controlling player-owned pets, including movement, attack, and stance settings. ```APIDOC ## Pet Controls These methods only work for player-owned pets. ### `unit.move(position)` Move pet to a specific position. **Parameters:** - `position` (Vector3) - Target position **Aliases:** `unit.moveto(position)` ### `unit.attack(target)` Command pet to attack a target. **Parameters:** - `target` (Unit) - Target to attack ### `unit.wait()` Command pet to wait/stay. ### `unit.follow()` Command pet to follow player. **Aliases:** `unit.setFollow()` ### `unit.assist()` Command pet to assist. ### `unit.passive()` Set pet to passive stance. ### `unit.defensive()` Set pet to defensive stance. ### `unit.aggressive()` Set pet to aggressive stance. ``` -------------------------------- ### Draw Line Between Two Positions Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Draws a line between two 3D positions in the world. It requires start and end positions, color, and thickness. ```lua ufo.drawline(start, finish, color, thickness) ``` -------------------------------- ### Event System for Spell Casts Source: https://context7.com/less-nefariousness5/ufo/llms.txt This Lua code demonstrates the event system for handling spell casts. It includes callbacks for all spell casts to react to enemy cooldown usage and specific spell casts like 'Blind'. It also logs important cooldown usage with timestamps, caster names, and spell names. ```lua -- Register callback for all spell casts ufo.on_spell_cast(function(data) local spellId = data.spell_id local caster = data.caster if caster and caster.enemy then if spellId == 12472 then -- Icy Veins -- Enemy used cooldown, react defensively defensive_cooldown.Cast(player) end end end) -- Register callback for specific spell ufo.events.onSpellCast(2094, function(caster, spellId) if caster and caster.enemy then -- Enemy used Blind ufo.log("Enemy used Blind!") end end) -- Track cooldown usage local cooldownLog = {} ufo.events.onSpellCast(0, function(caster, spellId) if not caster then return end local importantCDs = { [12472] = "Icy Veins", [190319] = "Combustion" } if importantCDs[spellId] then table.insert(cooldownLog, { time = ufo.time(), caster = caster.name, spell = importantCDs[spellId] }) end end) ``` -------------------------------- ### Get Debuff Stack Count - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Retrieves the number of stacks for a specified debuff ID. Returns 0 if the debuff is absent or has no stacks. ```lua unit.debuffstacks(12345) ``` -------------------------------- ### Event Registration API Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Functions for registering callbacks for game events like updates and spell casts. ```APIDOC ## `ufo.on_update(fn)` ### Description Register a function to run on every game frame. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters - **fn** (function) - Required - Callback function ### Request Example ```lua ufo.on_update(function() -- Main rotation logic player = ufo.player target = ufo.target if target and target.exists then -- Do something end end) ``` ### Response None ``` ```APIDOC ## `ufo.on_spell_cast(fn)` ### Description Register a function to run when any spell is cast. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters - **fn** (function) - Required - Callback function receiving cast data ### Request Example ```lua ufo.on_spell_cast(function(data) local spellId = data.spell_id local caster = data.caster -- Handle spell cast end) ``` ### Response None ``` ```APIDOC ## `ufo.pre_tick(fn)` ### Description Register a function to run before the game tick. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters - **fn** (function) - Required - Callback function ### Request Example ```lua ufo.pre_tick(function() -- Code to run before game tick end) ``` ### Response None ``` -------------------------------- ### Get Debuff Remaining Duration - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Returns the remaining duration in seconds for a given debuff ID. If the debuff is not present, it returns 0. ```lua unit.debuffremains(12345) ``` -------------------------------- ### Create Item Object with ufo.item Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Creates an item object by providing its unique item ID. This is a straightforward utility for item instantiation within the framework. ```lua local healthstone = ufo.item(5512) ``` -------------------------------- ### Get Time Standing Still - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Returns the duration in seconds that a unit has remained stationary. Useful for mechanics that trigger after a period of inactivity. ```lua if target.timestandingstill > 2 then -- Target hasn't moved for 2 seconds end ``` -------------------------------- ### Utility Functions Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Utility functions for spell cache cleanup and menu status. ```APIDOC ## `ufo.cleanup_spell_cache()` ### Description Clean up the spell cache. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters None ### Request Example ```lua ufo.cleanup_spell_cache() ``` ### Response None ``` ```APIDOC ## `ufo.isMenuOpen()` ### Description Check if the menu is currently open. ### Method N/A (Function Call) ### Endpoint N/A ### Parameters None ### Request Example ```lua if ufo.isMenuOpen() then print("Menu is open") end ``` ### Response #### Success Response - **boolean** - True if menu is open ``` -------------------------------- ### Get Unit Movement Speed - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Retrieves the current movement speed of a unit. This value can be used in various game logic calculations. ```lua local speed = unit.speed ``` -------------------------------- ### Implement Demon's Bite Fury Generator - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/message (4).txt Implements Demon's Bite as a basic fury generator. It checks for player's ability to cast, target validity, and spell readiness before execution. Uses `spell:Cast`. ```lua demons_bite:Callback("generator", function(spell) if not menu.enable_rotation:get_state() then return false end if not isValidEnemy(target) then return false end if not spellReady(spell, target) then return false end ``` -------------------------------- ### Get Missing Health - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Calculates the amount of health a unit is missing. This can be useful for determining healing requirements or understanding damage dealt. ```lua local healing_needed = unit.hpdeficit ``` -------------------------------- ### Draw 2D Text on Screen Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Renders 2D text directly onto the screen at a specified screen coordinate. Requires text content, position, size, and color. ```lua ufo.drawtext2d(text, position, size, color) ``` -------------------------------- ### Get Buff Stack Count - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Retrieves the current number of stacks for a given buff ID. Returns 0 if the buff is not present or has no stacks. ```lua if player.buffstacks(12345) >= 5 then -- Buff at 5+ stacks end ``` -------------------------------- ### Get Unit Position - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Retrieves the unit's current position in world coordinates as a Vector3 object. This is fundamental for spatial calculations and targeting. ```lua local pos = target.position() blizzard.AoECastPosition(pos) ``` -------------------------------- ### Register Pre-Tick Callback Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Registers a function to be executed just before the game tick occurs. This allows for actions to be performed at the very beginning of a game cycle. ```lua ufo.pre_tick(fn) ``` -------------------------------- ### Get Health With Absorbs - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/unit.md Returns the unit's effective health percentage, including any absorption shields. This provides a more accurate representation of survivability. ```lua if unit.hpa < 0.5 then -- Unit below 50% effective health end ``` -------------------------------- ### Lua Rotation Logic with UFO Framework Source: https://context7.com/less-nefariousness5/ufo/llms.txt This Lua script defines various spells with their properties, sets up individual casting conditions and actions using callbacks, and implements a main update loop for executing the rotation based on priorities and target status. It requires the UFO Framework and assumes the existence of player and target objects. ```lua -- Define all spells ufo.define({ fireball = {133, range = 40, projectile_speed = 24}, fire_blast = {108853, range = 40}, pyroblast = 11366, blizzard = {10, radius = 8, range = 30, geometry = "circle"}, combustion = 190319, ice_block = 45438 }) -- Setup callbacks fireball:Callback(function(spell) if not target or not target.exists or target.dead then return end if spell.cd > 0 then return end if not spell:Castable(target) then return end return spell:Cast(target) end) fire_blast:Callback(function(spell) if not target or not target.exists or target.dead then return end if spell.charges < 1 then return end if not spell:Castable(target) then return end return spell:CastFast(target) end) pyroblast:Callback(function(spell) if not player.buff(48108) then return end -- Hot Streak if not target or not target.exists then return end if not spell:Castable(target) then return end return spell:Cast(target) end) blizzard:Callback(function(spell) if spell.cd > 0 then return end local enemies = ufo.enemies.circle(spell) if enemies.count >= 5 then return spell:AoECastPosition(enemies.lowest.position()) end end) combustion:Callback(function(spell) if spell.cd > 0 then return end if not target or not target.exists then return end local enemies = ufo.enemies.within(40).count if enemies >= 1 and target.hpa > 0.3 then return spell:Cast(player) end end) ice_block:Callback(function(spell) if player.hpa > 0.15 then return end if spell.cd > 0 then return end return spell:Cast(player) end) -- Main loop ufo.on_update(function() player = ufo.player target = ufo.target if not target or not target.exists then return end if player.dead or player.mounted then return end -- Defensives (highest priority) ice_block() -- Cooldowns combustion() -- Off-GCD abilities fire_blast() -- Main rotation blizzard() pyroblast() fireball() end) ``` -------------------------------- ### Get Current Game Time with ufo.time Source: https://github.com/less-nefariousness5/ufo/blob/main/main.md Returns the current game time in seconds. This is a fundamental utility for time-based calculations or event scheduling within the game. ```lua local currentTime = ufo.time() ``` -------------------------------- ### Get the unit with lowest health (Lua) Source: https://github.com/less-nefariousness5/ufo/blob/main/collections.md Returns the unit with the lowest health percentage from a collection. Useful for prioritizing targets for finishing blows or specific abilities. ```lua local lowestEnemy = ufo.enemies.within(40).lowest if lowestEnemy and lowestEnemy.hp < 0.2 then execute.Cast(lowestEnemy) end ``` -------------------------------- ### Organize Spell Rotation Using Callbacks in Main Loop Source: https://github.com/less-nefariousness5/ufo/blob/main/spell.md Illustrates how to structure a spell rotation within the `ufo.on_update` function using callbacks. It shows the order of operations, including refreshing references, casting off-GCD abilities, and then executing main rotation spells and utilities. ```lua ufo.on_update(function() -- Refresh references player = ufo.player target = ufo.target focus = ufo.focus -- Off-GCD abilities (put at top for priority) fire_blast() -- Main rotation fireball() fireball("aoe") -- Utility polymorph("focus") counterspell("interrupt") end) ``` -------------------------------- ### Get Item Cooldown Remaining - Lua Source: https://github.com/less-nefariousness5/ufo/blob/main/item.md Retrieves the remaining cooldown time for an item in seconds. A value of 0 indicates the item is off cooldown and ready to be used. ```lua if healing_potion.cd == 0 then -- Item is off cooldown healing_potion.use() end if trinket.cd < 10 then -- Trinket will be ready soon end ```