Skip to main content

Virtual Units

Virtual Units provide a way to dynamically reference units based on roles or other criteria. They automatically resolve to the appropriate unit based on your current group composition and context.

Basic Usage

local tank = Aurora.UnitManager.tank
local healer = Aurora.UnitManager.healer

-- Use virtual units like normal units
if tank.exists then
print("Tank is " .. tank.name)
end

Built-in Virtual Units

Tank

The tank virtual unit resolves in the following order:

  1. Assigned Main Tank in raid
  2. Player with Tank role in group
  3. Player if they are a tank
  4. Returns none unit if no tank is found
local tank = Aurora.UnitManager.tank

-- Examples
if tank.exists then
if tank.hp < 50 then
-- Heal the tank
end

if tank.distanceto(player) < 40 then
-- Stay close to tank
end
end

Healer

The healer virtual unit resolves in the following order:

  1. Player with Healer role in group
  2. Player if they are a healer
  3. Returns none unit if no healer is found
local healer = Aurora.UnitManager.healer

if healer.exists and healer.manapct < 20 then
-- Help conserve healer's mana
end

Target

The target property returns a virtual unit representing any unit's current target:

local myTarget = player.target
local tankTarget = tank.target
local healerTarget = healer.target

-- Chain targeting
local targetsTarget = player.target.target -- returns target's target as a unit

This allows you to:

  1. Access all unit properties on the target
  2. Chain target references (target of target)
  3. Handle non-existent targets safely (returns none unit if no target)

Example usage:

local unit = Aurora.UnitManager:Get("player")

-- Check if target exists and is an enemy
if unit.target.exists and unit.target.enemy then
-- Do something with the target
end

-- Check target's target
if unit.target.target.exists then
print("My target is targeting " .. unit.target.target.name)
end

-- Check if tank's target matches your target
if tank.target.guid == player.target.guid then
print("We're targeting the same unit!")
end

Custom Virtual Units

You can register your own virtual units:

-- Register a virtual unit for the lowest health party member
Aurora.UnitManager:RegisterVirtualUnit("lowestHealth", function(self)
local lowest = nil
local lowestHP = 100

Aurora.fgroup:each(function(unit)
if unit.alive and unit.hp < lowestHP then
lowest = unit
lowestHP = unit.hp
end
return false
end)

return lowest or self:Get("none")
end)

-- Use it like any other unit
local needsHealing = Aurora.UnitManager.lowestHealth
if needsHealing.exists and needsHealing.hp < 50 then
-- Heal them
end

Best Practices

Usage
  • Virtual units are recalculated each time they're accessed
  • Use them when you need dynamic unit resolution
  • Cache the result if you need to use it multiple times in quick succession
Performance
  • Avoid accessing virtual units in tight loops
  • Don't create virtual units for static references
  • Remember that resolution order matters

Common Use Cases

Tank Swapping

local tank = Aurora.UnitManager.tank
local offtank = Aurora.UnitManager:RegisterVirtualUnit("offtank", function(self)
if IsInRaid() then
for i = 1, GetNumGroupMembers() do
local unit = self:Get("raid" .. i)
if unit.exists and unit.guid ~= tank.guid and
unit.role == "TANK" then
return unit
end
end
end
return self:Get("none")
end)

Emergency Healing

local criticalHealth = Aurora.UnitManager:RegisterVirtualUnit("criticalHealth", function(self)
local critical = nil
local lowestHP = 30 -- Critical threshold

Aurora.fgroup:each(function(unit)
if unit.alive and unit.hp < lowestHP then
critical = unit
lowestHP = unit.hp
end
return false
end)

return critical or self:Get("none")
end)