Updated to 4n0n latest - object manager and unit manager updates
main
Ofrex 2 years ago
parent db4ec0ff1c
commit fef75da2a6
  1. 21
      src/Aura/Aura.lua
  2. 130
      src/AuraTable/AuraTable.lua
  3. 19
      src/Item/Item.lua
  4. 21
      src/List/List.lua
  5. 65
      src/ObjectManager/ObjectManager.lua
  6. 10
      src/Refreshable/Refreshable.lua
  7. 16
      src/Spell/Spell.lua
  8. 164
      src/Unit/Unit.lua
  9. 20
      src/UnitManager/UnitManager.lua
  10. 19
      src/_bastion.lua

@ -1,6 +1,7 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Aura class -- Create a new Aura class
---@class Aura
local Aura = {} local Aura = {}
function Aura:__index(k) function Aura:__index(k)
@ -17,6 +18,19 @@ function Aura:__index(k)
return response return response
end end
-- Equals
function Aura:__eq(other)
if getmetatable(other) == Aura then
return self:GetSpell():GetID() == other:GetSpell():GetID()
end
if getmetatable(other) == Bastion.Spell then
return self:GetSpell():GetID() == other:GetID()
end
return false
end
function Aura:__tostring() function Aura:__tostring()
return "Bastion.__Aura(" .. self:GetSpell():GetID() .. ")" .. " - " .. (self:GetName() or "''") return "Bastion.__Aura(" .. self:GetSpell():GetID() .. ")" .. " - " .. (self:GetName() or "''")
end end
@ -46,12 +60,15 @@ function Aura:New(unit, index, type)
type = nil, type = nil,
} }
if self.aura.spellId then
Bastion.SpellBook:GetSpell(self.aura.spellId) Bastion.SpellBook:GetSpell(self.aura.spellId)
end
return self return self
end end
local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal,
spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit.unit, index, type) spellId, canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit:GetOMToken(), index, type)
local self = setmetatable({}, Aura) local self = setmetatable({}, Aura)
self.aura = { self.aura = {
@ -75,7 +92,9 @@ function Aura:New(unit, index, type)
index = index, index = index,
type = type, type = type,
} }
if self.aura.spellId then
Bastion.SpellBook:GetSpell(self.aura.spellId) Bastion.SpellBook:GetSpell(self.aura.spellId)
end
return self return self
end end

@ -1,6 +1,7 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new AuraTable class -- Create a new AuraTable class
---@class AuraTable
local AuraTable = {} local AuraTable = {}
AuraTable.__index = AuraTable AuraTable.__index = AuraTable
@ -17,9 +18,10 @@ function AuraTable:New(unit)
local self = setmetatable({}, AuraTable) local self = setmetatable({}, AuraTable)
self.unit = unit self.unit = unit
self.auras = {}
self.auras = {}
self.playerAuras = {} self.playerAuras = {}
self.guid = unit:GetGUID() self.guid = unit:GetGUID()
self.instanceIDLookup = {} self.instanceIDLookup = {}
@ -27,6 +29,10 @@ function AuraTable:New(unit)
end end
function AuraTable:OnUpdate(auras) function AuraTable:OnUpdate(auras)
if not auras then
self:Update()
return
end
local isFullUpdate = auras.isFullUpdate local isFullUpdate = auras.isFullUpdate
if isFullUpdate then if isFullUpdate then
@ -51,7 +57,7 @@ function AuraTable:OnUpdate(auras)
if updatedAuras and #updatedAuras > 0 then if updatedAuras and #updatedAuras > 0 then
for i = 1, #updatedAuras do for i = 1, #updatedAuras do
local id = updatedAuras[i] local id = updatedAuras[i]
local newAura = C_UnitAuras_GetAuraDataByAuraInstanceID(self.unit.unit, id); local newAura = C_UnitAuras_GetAuraDataByAuraInstanceID(self.unit:GetOMToken(), id);
if newAura then if newAura then
local aura = Bastion.Aura:CreateFromUnitAuraInfo(newAura) local aura = Bastion.Aura:CreateFromUnitAuraInfo(newAura)
self:AddOrUpdateAuraInstanceID(aura:GetAuraInstanceID(), aura) self:AddOrUpdateAuraInstanceID(aura:GetAuraInstanceID(), aura)
@ -109,7 +115,34 @@ end
-- Get a units buffs -- Get a units buffs
function AuraTable:GetUnitBuffs() function AuraTable:GetUnitBuffs()
AuraUtil_ForEachAura(self.unit.unit, 'HELPFUL', nil, function(a) if Tinkr.classic then
for i = 1, 40 do
local aura = Bastion.Aura:New(self.unit, i, 'HELPFUL')
if not aura:IsValid() then
break
end
local spellId = aura:GetSpell():GetID()
if Bastion.UnitManager['player']:IsUnit(aura:GetSource()) then
if not self.playerAuras[spellId] then
self.playerAuras[spellId] = {}
end
table.insert(self.playerAuras[spellId], aura)
else
if not self.auras[spellId] then
self.auras[spellId] = {}
end
table.insert(self.auras[spellId], aura)
end
end
return
end
AuraUtil_ForEachAura(self.unit:GetOMToken(), 'HELPFUL', nil, function(a)
local aura = Bastion.Aura:CreateFromUnitAuraInfo(a) local aura = Bastion.Aura:CreateFromUnitAuraInfo(a)
if aura:IsValid() then if aura:IsValid() then
@ -120,7 +153,34 @@ end
-- Get a units debuffs -- Get a units debuffs
function AuraTable:GetUnitDebuffs() function AuraTable:GetUnitDebuffs()
AuraUtil_ForEachAura(self.unit.unit, 'HARMFUL', nil, function(a) if Tinkr.classic then
for i = 1, 40 do
local aura = Bastion.Aura:New(self.unit, i, 'HARMFUL')
if not aura:IsValid() then
break
end
local spellId = aura:GetSpell():GetID()
if Bastion.UnitManager['player']:IsUnit(aura:GetSource()) then
if not self.playerAuras[spellId] then
self.playerAuras[spellId] = {}
end
table.insert(self.playerAuras[spellId], aura)
else
if not self.auras[spellId] then
self.auras[spellId] = {}
end
table.insert(self.auras[spellId], aura)
end
end
return
end
AuraUtil_ForEachAura(self.unit:GetOMToken(), 'HARMFUL', nil, function(a)
local aura = Bastion.Aura:CreateFromUnitAuraInfo(a) local aura = Bastion.Aura:CreateFromUnitAuraInfo(a)
if aura:IsValid() then if aura:IsValid() then
@ -196,6 +256,7 @@ function AuraTable:Clear()
end end
-- Check if the unit has a specific aura -- Check if the unit has a specific aura
---@return Aura
function AuraTable:Find(spell) function AuraTable:Find(spell)
local auras = self:GetUnitAuras() local auras = self:GetUnitAuras()
local aurasub = auras[spell:GetID()] local aurasub = auras[spell:GetID()]
@ -205,20 +266,74 @@ function AuraTable:Find(spell)
end end
for k, a in pairs(aurasub) do for k, a in pairs(aurasub) do
print(a)
if a ~= nil then if a ~= nil then
if a:IsUp() then -- Handle expired and non refreshed dropoffs not coming in UNIT_AURA if a:IsUp() then -- Handle expired and non refreshed dropoffs not coming in UNIT_AURA
return a return a
else else
if not Tinkr.classic then
self:RemoveInstanceID(a:GetAuraInstanceID()) self:RemoveInstanceID(a:GetAuraInstanceID())
end end
end end
end end
end
return Bastion.Aura:New() return Bastion.Aura:New()
end end
---@return Aura
function AuraTable:FindMy(spell) function AuraTable:FindMy(spell)
local aurasub = self.playerAuras[spell:GetID()] local auras = self:GetMyUnitAuras()
local aurasub = auras[spell:GetID()]
if not aurasub then
return Bastion.Aura:New()
end
for k, a in pairs(aurasub) do
if a ~= nil then
if a:IsUp() then -- Handle expired and non refreshed dropoffs not coming in UNIT_AURA
return a
else
if not Tinkr.classic then
self:RemoveInstanceID(a:GetAuraInstanceID())
end
end
end
end
return Bastion.Aura:New()
end
function AuraTable:FindFrom(spell, source)
local auras = self:GetUnitAuras()
local aurasub = auras[spell:GetID()]
if not aurasub then
return Bastion.Aura:New()
end
for k, a in pairs(aurasub) do
if a ~= nil then
if a:IsUp() then -- Handle expired and non refreshed dropoffs not coming in UNIT_AURA
if a:GetSource() == source then
return a
end
else
if not Tinkr.classic then
self:RemoveInstanceID(a:GetAuraInstanceID())
end
end
end
end
return Bastion.Aura:New()
end
-- Find the aura from the current unit
function AuraTable:FindTheirs(spell)
local auras = self:GetUnitAuras()
local aurasub = auras[spell:GetID()]
if not aurasub then if not aurasub then
return Bastion.Aura:New() return Bastion.Aura:New()
@ -227,17 +342,22 @@ function AuraTable:FindMy(spell)
for k, a in pairs(aurasub) do for k, a in pairs(aurasub) do
if a ~= nil then if a ~= nil then
if a:IsUp() then -- Handle expired and non refreshed dropoffs not coming in UNIT_AURA if a:IsUp() then -- Handle expired and non refreshed dropoffs not coming in UNIT_AURA
if self.unit:IsUnit(a:GetSource()) then
return a return a
end
else else
if not Tinkr.classic then
self:RemoveInstanceID(a:GetAuraInstanceID()) self:RemoveInstanceID(a:GetAuraInstanceID())
end end
end end
end end
end
return Bastion.Aura:New() return Bastion.Aura:New()
end end
-- Find any -- Find any
---@return Aura
function AuraTable:FindAny(spell) function AuraTable:FindAny(spell)
local a = self:Find(spell) local a = self:Find(spell)
if a:IsValid() then if a:IsValid() then

@ -1,6 +1,7 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Item class -- Create a new Item class
---@class Item
local Item = { local Item = {
UsableIfFunc = false, UsableIfFunc = false,
PreUseFunc = false, PreUseFunc = false,
@ -29,6 +30,11 @@ function Item:__index(k)
return response return response
end end
-- Equals
function Item:__eq(other)
return self:GetID() == other:GetID()
end
-- tostring -- tostring
function Item:__tostring() function Item:__tostring()
return "Bastion.__Item(" .. self:GetID() .. ")" .. " - " .. self:GetName() return "Bastion.__Item(" .. self:GetID() .. ")" .. " - " .. self:GetName()
@ -110,7 +116,7 @@ function Item:Use(unit, condition)
self.wasLooking = IsMouselooking() self.wasLooking = IsMouselooking()
-- Use the Item -- Use the Item
UseItemByName(self:GetName(), unit.unit) UseItemByName(self:GetName(), unit:GetOMToken())
Bastion:Debug("Using", self) Bastion:Debug("Using", self)
@ -170,18 +176,21 @@ function Item:Usable()
end end
-- Set a script to check if the Item is Usable -- Set a script to check if the Item is Usable
---@param func fun(self:Item):boolean
function Item:UsableIf(func) function Item:UsableIf(func)
self.UsableIfFunc = func self.UsableIfFunc = func
return self return self
end end
-- Set a script to run before the Item has been Use -- Set a script to run before the Item has been Use
---@param func fun(self:Item)
function Item:PreUse(func) function Item:PreUse(func)
self.PreUseFunc = func self.PreUseFunc = func
return self return self
end end
-- Set a script to run after the Item has been Use -- Set a script to run after the Item has been Use
---@param func fun(self:Item)
function Item:OnUse(func) function Item:OnUse(func)
self.OnUseFunc = func self.OnUseFunc = func
return self return self
@ -221,9 +230,9 @@ end
function Item:IsInRange(unit) function Item:IsInRange(unit)
local name, rank, icon, UseTime, Itemmin, Itemmax, ItemID = GetItemInfo(self:GetID()) local name, rank, icon, UseTime, Itemmin, Itemmax, ItemID = GetItemInfo(self:GetID())
local them = Object(unit.unit) local them = Object(unit:GetOMToken())
local tx, ty, tz = ObjectPosition(unit.unit) local tx, ty, tz = ObjectPosition(unit:GetOMToken())
local px, py, pz = ObjectPosition('player') local px, py, pz = ObjectPosition('player')
if not them then if not them then
@ -235,7 +244,7 @@ function Item:IsInRange(unit)
end end
local combatReach = ObjectCombatReach("player") local combatReach = ObjectCombatReach("player")
local themCombatReach = ObjectCombatReach(unit.unit) local themCombatReach = ObjectCombatReach(unit:GetOMToken())
if Bastion.UnitManager['player']:InMelee(unit) and Itemmin == 0 then if Bastion.UnitManager['player']:InMelee(unit) and Itemmin == 0 then
return true return true
@ -278,6 +287,8 @@ function Item:GetChargesRemaining()
end end
-- Create a condition for the Item -- Create a condition for the Item
---@param name string
---@param func fun(self:Item)
function Item:Condition(name, func) function Item:Condition(name, func)
self.conditions[name] = { self.conditions[name] = {
func = func func = func

@ -1,6 +1,25 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
local List = {} ---@class List
local List = {
-- Add overload
---@param self List
---@param value any
---@return List
__add = function(self, value)
self:push(value)
return self
end,
-- Subtract overload
---@param self List
---@param value any
---@return List
__sub = function(self, value)
self:remove(value)
return self
end,
}
List.__index = List List.__index = List
function List:New(from) function List:New(from)

@ -1,12 +1,13 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
---@class ObjectManager
local ObjectManager = {} local ObjectManager = {}
ObjectManager.__index = ObjectManager ObjectManager.__index = ObjectManager
function ObjectManager:New() function ObjectManager:New()
local self = setmetatable({}, ObjectManager) local self = setmetatable({}, ObjectManager)
self._objects = {} self._lists = {}
self.enemies = Bastion.List:New() self.enemies = Bastion.List:New()
self.friends = Bastion.List:New() self.friends = Bastion.List:New()
@ -16,15 +17,54 @@ function ObjectManager:New()
return self return self
end end
-- Register a custom list with a callback
function ObjectManager:RegisterList(name, cb)
if self._lists[name] then
return false
end
self._lists[name] = {
list = Bastion.List:New(),
cb = cb
}
return self._lists[name].list
end
-- reset custom lists
function ObjectManager:ResetLists()
for _, list in pairs(self._lists) do
list.list:clear()
end
end
-- Refresh custom lists
function ObjectManager:EnumLists(object)
for _, list in pairs(self._lists) do
local r = list.cb(object)
if r then
list.list:push(r)
end
end
end
-- Get a list
function ObjectManager:GetList(name)
return self._lists[name].list
end
function ObjectManager:Refresh() function ObjectManager:Refresh()
self.enemies:clear() self.enemies:clear()
self.friends:clear() self.friends:clear()
self.activeEnemies:clear() self.activeEnemies:clear()
self.explosives:clear() self.explosives:clear()
self:ResetLists()
local objects = Objects() local objects = Objects()
for _, object in pairs(objects) do for _, object in pairs(objects) do
self:EnumLists(object)
if ObjectType(object) == 5 or ObjectType(object) == 6 then if ObjectType(object) == 5 or ObjectType(object) == 6 then
local unit = Bastion.UnitManager:GetObject(ObjectGUID(object)) local unit = Bastion.UnitManager:GetObject(ObjectGUID(object))
if not unit then if not unit then
@ -39,7 +79,7 @@ function ObjectManager:Refresh()
elseif unit:IsEnemy() then elseif unit:IsEnemy() then
self.enemies:push(unit) self.enemies:push(unit)
if unit:IsAffectingCombat() then if unit:InCombatOdds() > 80 then
self.activeEnemies:push(unit) self.activeEnemies:push(unit)
end end
end end
@ -48,3 +88,24 @@ function ObjectManager:Refresh()
end end
return ObjectManager return ObjectManager
-- -- Register a list of objects that are training dummies
-- local dummies = Bastion.ObjectManager:RegisterList('dummies', function(object)
-- if ObjectType(object) == 5 or ObjectType(object) == 6 then
-- local unit = Bastion.UnitManager:GetObject(ObjectGUID(object))
-- if not unit then
-- unit = Bastion.Unit:New(object)
-- Bastion.UnitManager:SetObject(unit)
-- end
-- if unit:GetID() == 198594 then
-- return unit
-- end
-- end
-- end)
-- dummies:each(function(dummy)
-- print(dummy:GetName())
-- end)

@ -1,10 +1,14 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Define a Refreshable class -- Define a Refreshable class
---@class Refreshable
local Refreshable = { local Refreshable = {
cache = nil, cache = nil,
callback = nil, callback = nil,
value = nil value = nil,
__eq = function(self, other)
return self.value.__eq(rawget(self, 'value'), other)
end
} }
-- On index check the cache to be valid and return the value or reconstruct the value and return it -- On index check the cache to be valid and return the value or reconstruct the value and return it
@ -19,7 +23,7 @@ end
-- When the object is accessed return the value -- When the object is accessed return the value
function Refreshable:__tostring() function Refreshable:__tostring()
return "Bastion.__Refreshable(" .. tostring(self.value) .. ")" return "Bastion.__Refreshable(" .. tostring(rawget(self, 'value')) .. ")"
end end
-- Create -- Create
@ -30,7 +34,7 @@ function Refreshable:New(value, cb)
self.value = value self.value = value
self.callback = cb self.callback = cb
self.cache:Set('self', self.value, 0.5) self.cache:Set('self', rawget(self, 'value'), 0.5)
return self return self
end end

@ -1,6 +1,7 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Spell class -- Create a new Spell class
---@class Spell
local Spell = { local Spell = {
CastableIfFunc = false, CastableIfFunc = false,
PreCastFunc = false, PreCastFunc = false,
@ -30,6 +31,11 @@ function Spell:__index(k)
return response return response
end end
-- Equals
function Spell:__eq(other)
return self:GetID() == other:GetID()
end
-- tostring -- tostring
function Spell:__tostring() function Spell:__tostring()
return "Bastion.__Spell(" .. self:GetID() .. ")" .. " - " .. self:GetName() return "Bastion.__Spell(" .. self:GetID() .. ")" .. " - " .. self:GetName()
@ -50,6 +56,7 @@ function Spell:GetID()
end end
-- Add post cast func -- Add post cast func
---@param func fun(self:Spell)
function Spell:PostCast(func) function Spell:PostCast(func)
self.PostCastFunc = func self.PostCastFunc = func
return self return self
@ -114,8 +121,8 @@ function Spell:Cast(unit, condition)
-- Check if the mouse was looking -- Check if the mouse was looking
self.wasLooking = IsMouselooking() self.wasLooking = IsMouselooking()
-- if unit.unit contains 'nameplate' then we need to use Object wrapper to cast -- if unit:GetOMToken() contains 'nameplate' then we need to use Object wrapper to cast
local u = unit.unit local u = unit:GetOMToken()
if type(u) == "string" and string.find(u, 'nameplate') then if type(u) == "string" and string.find(u, 'nameplate') then
u = Object(u) u = Object(u)
end end
@ -173,18 +180,21 @@ function Spell:Castable()
end end
-- Set a script to check if the spell is castable -- Set a script to check if the spell is castable
---@param func fun(spell:Spell):boolean
function Spell:CastableIf(func) function Spell:CastableIf(func)
self.CastableIfFunc = func self.CastableIfFunc = func
return self return self
end end
-- Set a script to run before the spell has been cast -- Set a script to run before the spell has been cast
---@param func fun(spell:Spell)
function Spell:PreCast(func) function Spell:PreCast(func)
self.PreCastFunc = func self.PreCastFunc = func
return self return self
end end
-- Set a script to run after the spell has been cast -- Set a script to run after the spell has been cast
---@param func fun(spell:Spell)
function Spell:OnCast(func) function Spell:OnCast(func)
self.OnCastFunc = func self.OnCastFunc = func
return self return self
@ -227,7 +237,7 @@ end
-- Check if the spell is in range of the unit -- Check if the spell is in range of the unit
function Spell:IsInRange(unit) function Spell:IsInRange(unit)
local hasRange = self:HasRange() local hasRange = self:HasRange()
local inRange = IsSpellInRange(self:GetName(), unit.unit) local inRange = IsSpellInRange(self:GetName(), unit:GetOMToken())
if hasRange == false then if hasRange == false then
return true return true

@ -1,19 +1,27 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
-- Create a new Unit class -- Create a new Unit class
---@class Unit
local Unit = { local Unit = {
cache = nil, cache = nil,
---@type AuraTable
aura_table = nil, aura_table = nil,
---@type Unit
unit = nil, unit = nil,
last_shadow_techniques = 0, last_shadow_techniques = 0,
swings_since_sht = 0, swings_since_sht = 0,
last_off_attack = 0, last_off_attack = 0,
last_main_attack = 0, last_main_attack = 0,
last_combat_time = 0,
} }
function Unit:__index(k) function Unit:__index(k)
local response = Bastion.ClassMagic:Resolve(Unit, k) local response = Bastion.ClassMagic:Resolve(Unit, k)
if k == 'unit' then
return rawget(self, k)
end
if response == nil then if response == nil then
response = rawget(self, k) response = rawget(self, k)
end end
@ -25,9 +33,14 @@ function Unit:__index(k)
return response return response
end end
-- Equals
function Unit:__eq(other)
return UnitIsUnit(self:GetOMToken(), other.unit)
end
-- tostring -- tostring
function Unit:__tostring() function Unit:__tostring()
return "Bastion.__Unit(" .. tostring(self.unit) .. ")" .. " - " .. (self:GetName() or '') return "Bastion.__Unit(" .. tostring(self:GetOMToken()) .. ")" .. " - " .. (self:GetName() or '')
end end
-- Constructor -- Constructor
@ -42,37 +55,37 @@ end
-- Check if the unit is valid -- Check if the unit is valid
function Unit:IsValid() function Unit:IsValid()
return self.unit ~= nil and self:Exists() return self:GetOMToken() ~= nil and self:Exists()
end end
-- Check if the unit exists -- Check if the unit exists
function Unit:Exists() function Unit:Exists()
return Object(self.unit) return Object(self:GetOMToken())
end end
-- Get the units token -- Get the units token
function Unit:Token() function Unit:Token()
return self.unit return self:GetOMToken()
end end
-- Get the units name -- Get the units name
function Unit:GetName() function Unit:GetName()
return UnitName(self.unit) return UnitName(self:GetOMToken())
end end
-- Get the units GUID -- Get the units GUID
function Unit:GetGUID() function Unit:GetGUID()
return ObjectGUID(self.unit) return ObjectGUID(self:GetOMToken())
end end
-- Get the units health -- Get the units health
function Unit:GetHealth() function Unit:GetHealth()
return UnitHealth(self.unit) return UnitHealth(self:GetOMToken())
end end
-- Get the units max health -- Get the units max health
function Unit:GetMaxHealth() function Unit:GetMaxHealth()
return UnitHealthMax(self.unit) return UnitHealthMax(self:GetOMToken())
end end
-- Get the units health percentage -- Get the units health percentage
@ -86,19 +99,19 @@ end
-- Get the units power type -- Get the units power type
function Unit:GetPowerType() function Unit:GetPowerType()
return UnitPowerType(self.unit) return UnitPowerType(self:GetOMToken())
end end
-- Get the units power -- Get the units power
function Unit:GetPower(powerType) function Unit:GetPower(powerType)
local powerType = powerType or self:GetPowerType() local powerType = powerType or self:GetPowerType()
return UnitPower(self.unit, powerType) return UnitPower(self:GetOMToken(), powerType)
end end
-- Get the units max power -- Get the units max power
function Unit:GetMaxPower(powerType) function Unit:GetMaxPower(powerType)
local powerType = powerType or self:GetPowerType() local powerType = powerType or self:GetPowerType()
return UnitPowerMax(self.unit, powerType) return UnitPowerMax(self:GetOMToken(), powerType)
end end
-- Get the units power percentage -- Get the units power percentage
@ -115,7 +128,7 @@ end
-- Get the units position -- Get the units position
function Unit:GetPosition() function Unit:GetPosition()
local x, y, z = ObjectPosition(self.unit) local x, y, z = ObjectPosition(self:GetOMToken())
return Bastion.Vector3:New(x, y, z) return Bastion.Vector3:New(x, y, z)
end end
@ -129,37 +142,37 @@ end
-- Is the unit dead -- Is the unit dead
function Unit:IsDead() function Unit:IsDead()
return UnitIsDeadOrGhost(self.unit) return UnitIsDeadOrGhost(self:GetOMToken())
end end
-- Is the unit alive -- Is the unit alive
function Unit:IsAlive() function Unit:IsAlive()
return not UnitIsDeadOrGhost(self.unit) return not UnitIsDeadOrGhost(self:GetOMToken())
end end
-- Is the unit a pet -- Is the unit a pet
function Unit:IsPet() function Unit:IsPet()
return UnitIsUnit(self.unit, "pet") return UnitIsUnit(self:GetOMToken(), "pet")
end end
-- Is the unit a friendly unit -- Is the unit a friendly unit
function Unit:IsFriendly() function Unit:IsFriendly()
return UnitIsFriend("player", self.unit) return UnitIsFriend("player", self:GetOMToken())
end end
-- IsEnemy -- IsEnemy
function Unit:IsEnemy() function Unit:IsEnemy()
return UnitCanAttack("player", self.unit) return UnitCanAttack("player", self:GetOMToken())
end end
-- Is the unit a hostile unit -- Is the unit a hostile unit
function Unit:IsHostile() function Unit:IsHostile()
return UnitCanAttack(self.unit, 'player') return UnitCanAttack(self:GetOMToken(), 'player')
end end
-- Is the unit a boss -- Is the unit a boss
function Unit:IsBoss() function Unit:IsBoss()
if UnitClassification(self.unit) == "worldboss" then if UnitClassification(self:GetOMToken()) == "worldboss" then
return true return true
end end
@ -174,77 +187,80 @@ function Unit:IsBoss()
return false return false
end end
function Unit:GetOMToken()
if not self.unit then
return "none"
end
return self.unit:unit()
end
-- Is the unit a target -- Is the unit a target
function Unit:IsTarget() function Unit:IsTarget()
return UnitIsUnit(self.unit, "target") return UnitIsUnit(self:GetOMToken(), "target")
end end
-- Is the unit a focus -- Is the unit a focus
function Unit:IsFocus() function Unit:IsFocus()
return UnitIsUnit(self.unit, "focus") return UnitIsUnit(self:GetOMToken(), "focus")
end end
-- Is the unit a mouseover -- Is the unit a mouseover
function Unit:IsMouseover() function Unit:IsMouseover()
return UnitIsUnit(self.unit, "mouseover") return UnitIsUnit(self:GetOMToken(), "mouseover")
end end
-- Is the unit a tank -- Is the unit a tank
function Unit:IsTank() function Unit:IsTank()
return UnitGroupRolesAssigned(self.unit) == "TANK" return UnitGroupRolesAssigned(self:GetOMToken()) == "TANK"
end end
-- Is the unit a healer -- Is the unit a healer
function Unit:IsHealer() function Unit:IsHealer()
return UnitGroupRolesAssigned(self.unit) == "HEALER" return UnitGroupRolesAssigned(self:GetOMToken()) == "HEALER"
end end
-- Is the unit a damage dealer -- Is the unit a damage dealer
function Unit:IsDamage() function Unit:IsDamage()
return UnitGroupRolesAssigned(self.unit) == "DAMAGER" return UnitGroupRolesAssigned(self:GetOMToken()) == "DAMAGER"
end end
-- Is the unit a player -- Is the unit a player
function Unit:IsPlayer() function Unit:IsPlayer()
return UnitIsPlayer(self.unit) return UnitIsPlayer(self:GetOMToken())
end end
-- Is the unit a player controlled unit -- Is the unit a player controlled unit
function Unit:IsPCU() function Unit:IsPCU()
return UnitPlayerControlled(self.unit) return UnitPlayerControlled(self:GetOMToken())
end end
-- Get if the unit is affecting combat -- Get if the unit is affecting combat
function Unit:IsAffectingCombat() function Unit:IsAffectingCombat()
return UnitAffectingCombat('player', self.unit) return UnitAffectingCombat(self:GetOMToken())
end
-- Is the unit indoors
function Unit:IsIndoors()
return IsIndoors()
end end
-- Get the units class id -- Get the units class id
function Unit:GetClass() function Unit:GetClass()
local locale, class, classID = UnitClass(self.unit) local locale, class, classID = UnitClass(self:GetOMToken())
return Bastion.Class:New(locale, class, classID) return Bastion.Class:New(locale, class, classID)
end end
-- Get the units auras -- Get the units auras
---@return AuraTable
function Unit:GetAuras() function Unit:GetAuras()
return self.aura_table return self.aura_table
end end
-- Get the raw unit -- Get the raw unit
function Unit:GetRawUnit() function Unit:GetRawUnit()
return self.unit return self:GetOMToken()
end end
local isClassicWow = select(4, GetBuildInfo()) < 40000 local isClassicWow = select(4, GetBuildInfo()) < 40000
-- Check if two units are in melee -- Check if two units are in melee
-- function Unit:InMelee(unit) -- function Unit:InMelee(unit)
-- return UnitInMelee(self.unit, unit.unit) -- return UnitInMelee(self:GetOMToken(), unit.unit)
-- end -- end
local losFlag = bit.bor(0x1, 0x10, 0x100000) local losFlag = bit.bor(0x1, 0x10, 0x100000)
@ -266,8 +282,8 @@ function Unit:CanSee(unit)
-- return false -- return false
-- end -- end
-- end -- end
local ax, ay, az = ObjectPosition(self.unit) local ax, ay, az = ObjectPosition(self:GetOMToken())
local ah = ObjectHeight(self.unit) local ah = ObjectHeight(self:GetOMToken())
local attx, atty, attz = GetUnitAttachmentPosition(unit.unit, 34) local attx, atty, attz = GetUnitAttachmentPosition(unit.unit, 34)
if (ax == 0 and ay == 0 and az == 0) or (attx == 0 and atty == 0 and attz == 0) then if (ax == 0 and ay == 0 and az == 0) or (attx == 0 and atty == 0 and attz == 0) then
@ -288,7 +304,7 @@ end
-- Check if the unit is casting a spell -- Check if the unit is casting a spell
function Unit:IsCasting() function Unit:IsCasting()
return UnitCastingInfo(self.unit) ~= nil return UnitCastingInfo(self:GetOMToken()) ~= nil
end end
-- Get Casting or channeling spell -- Get Casting or channeling spell
@ -297,7 +313,8 @@ function Unit:GetCastingOrChannelingSpell()
.unit) .unit)
if not name then if not name then
name, text, texture, startTimeMS, endTimeMS, isTradeSkill, notInterruptible, spellId = UnitChannelInfo(self.unit) name, text, texture, startTimeMS, endTimeMS, isTradeSkill, notInterruptible, spellId = UnitChannelInfo(self.unit
:unit())
end end
if name then if name then
@ -309,7 +326,7 @@ end
-- Check if the unit is channeling a spell -- Check if the unit is channeling a spell
function Unit:IsChanneling() function Unit:IsChanneling()
return UnitChannelInfo(self.unit) ~= nil return UnitChannelInfo(self:GetOMToken()) ~= nil
end end
-- Check if the unit is casting or channeling a spell -- Check if the unit is casting or channeling a spell
@ -319,7 +336,7 @@ end
-- Check if the unit can attack the target -- Check if the unit can attack the target
function Unit:CanAttack(unit) function Unit:CanAttack(unit)
return UnitCanAttack(self.unit, unit.unit) return UnitCanAttack(self:GetOMToken(), unit.unit)
end end
function Unit:GetChannelOrCastPercentComplete() function Unit:GetChannelOrCastPercentComplete()
@ -327,7 +344,8 @@ function Unit:GetChannelOrCastPercentComplete()
.unit) .unit)
if not name then if not name then
name, text, texture, startTimeMS, endTimeMS, isTradeSkill, notInterruptible, spellId = UnitChannelInfo(self.unit) name, text, texture, startTimeMS, endTimeMS, isTradeSkill, notInterruptible, spellId = UnitChannelInfo(self.unit
:unit())
end end
if name and startTimeMS and endTimeMS then if name and startTimeMS and endTimeMS then
@ -345,7 +363,8 @@ function Unit:IsInterruptible()
.unit) .unit)
if not name then if not name then
name, text, texture, startTimeMS, endTimeMS, isTradeSkill, notInterruptible, spellId = UnitChannelInfo(self.unit) name, text, texture, startTimeMS, endTimeMS, isTradeSkill, notInterruptible, spellId = UnitChannelInfo(self.unit
:unit())
end end
if name then if name then
@ -382,7 +401,7 @@ function Unit:GetEnemies(range)
Bastion.UnitManager:EnumEnemies(function(unit) Bastion.UnitManager:EnumEnemies(function(unit)
if not self:IsUnit(unit) and unit:GetDistance(self) <= range and unit:IsAlive() and self:CanSee(unit) and if not self:IsUnit(unit) and unit:GetDistance(self) <= range and unit:IsAlive() and self:CanSee(unit) and
unit:IsEnemy() and unit:IsAffectingCombat() then unit:IsEnemy() then
count = count + 1 count = count + 1
end end
end) end)
@ -402,7 +421,7 @@ function Unit:GetMeleeAttackers()
Bastion.UnitManager:EnumEnemies(function(unit) Bastion.UnitManager:EnumEnemies(function(unit)
if not self:IsUnit(unit) and unit:IsAlive() and self:CanSee(unit) and if not self:IsUnit(unit) and unit:IsAlive() and self:CanSee(unit) and
self:InMelee(unit) and unit:IsEnemy() and unit:IsAffectingCombat() then self:InMelee(unit) and unit:IsEnemy() and unit:InCombatOdds() > 80 then
count = count + 1 count = count + 1
end end
end) end)
@ -426,19 +445,19 @@ end
-- Is moving -- Is moving
function Unit:IsMoving() function Unit:IsMoving()
return GetUnitSpeed(self.unit) > 0 return GetUnitSpeed(self:GetOMToken()) > 0
end end
function Unit:IsMovingAtAll() function Unit:IsMovingAtAll()
return ObjectMovementFlag(self.unit) ~= 0 return ObjectMovementFlag(self:GetOMToken()) ~= 0
end end
function Unit:GetComboPoints() function Unit:GetComboPoints()
return UnitPower(self.unit, 4) return UnitPower(self:GetOMToken(), 4)
end end
function Unit:GetComboPointsMax() function Unit:GetComboPointsMax()
return UnitPowerMax(self.unit, 4) return UnitPowerMax(self:GetOMToken(), 4)
end end
-- Get combopoints deficit -- Get combopoints deficit
@ -448,19 +467,20 @@ end
-- IsUnit -- IsUnit
function Unit:IsUnit(unit) function Unit:IsUnit(unit)
return UnitIsUnit(self.unit, unit.unit) return UnitIsUnit(self:GetOMToken(), unit and unit:GetOMToken() or 'none')
end end
-- IsTanking -- IsTanking
function Unit:IsTanking(unit) function Unit:IsTanking(unit)
local isTanking, status, threatpct, rawthreatpct, threatvalue = UnitDetailedThreatSituation(self.unit, unit.unit) local isTanking, status, threatpct, rawthreatpct, threatvalue = UnitDetailedThreatSituation(self:GetOMToken(),
unit.unit)
return isTanking return isTanking
end end
-- IsFacing -- IsFacing
function Unit:IsFacing(unit) function Unit:IsFacing(unit)
local rot = ObjectRotation(self.unit) local rot = ObjectRotation(self:GetOMToken())
local x, y, z = ObjectPosition(self.unit) local x, y, z = ObjectPosition(self:GetOMToken())
local x2, y2, z2 = ObjectPosition(unit.unit) local x2, y2, z2 = ObjectPosition(unit.unit)
if not x or not x2 then if not x or not x2 then
@ -481,7 +501,7 @@ end
function Unit:IsBehind(unit) function Unit:IsBehind(unit)
local rot = ObjectRotation(unit.unit) local rot = ObjectRotation(unit.unit)
local x, y, z = ObjectPosition(unit.unit) local x, y, z = ObjectPosition(unit.unit)
local x2, y2, z2 = ObjectPosition(self.unit) local x2, y2, z2 = ObjectPosition(self:GetOMToken())
if not x or not x2 then if not x or not x2 then
return false return false
@ -513,7 +533,7 @@ end
-- InMelee -- InMelee
function Unit:InMelee(unit) function Unit:InMelee(unit)
local x, y, z = ObjectPosition(self.unit) local x, y, z = ObjectPosition(self:GetOMToken())
local x2, y2, z2 = ObjectPosition(unit.unit) local x2, y2, z2 = ObjectPosition(unit.unit)
if not x or not x2 then if not x or not x2 then
@ -521,7 +541,7 @@ function Unit:InMelee(unit)
end end
local dist = math.sqrt((x - x2) ^ 2 + (y - y2) ^ 2 + (z - z2) ^ 2) local dist = math.sqrt((x - x2) ^ 2 + (y - y2) ^ 2 + (z - z2) ^ 2)
local maxDist = math.max((ObjectCombatReach(self.unit) + 1.3333) + ObjectCombatReach(unit.unit), 5.0) local maxDist = math.max((ObjectCombatReach(self:GetOMToken()) + 1.3333) + ObjectCombatReach(unit.unit), 5.0)
maxDist = maxDist + 1.0 + self:GetMeleeBoost() maxDist = maxDist + 1.0 + self:GetMeleeBoost()
return dist <= maxDist return dist <= maxDist
@ -529,12 +549,12 @@ end
-- Get object id -- Get object id
function Unit:GetID() function Unit:GetID()
return ObjectID(self.unit) return ObjectID(self:GetOMToken())
end end
-- In party -- In party
function Unit:IsInParty() function Unit:IsInParty()
return UnitInParty(self.unit) return UnitInParty(self:GetOMToken())
end end
-- Linear regression between time and percent to something -- Linear regression between time and percent to something
@ -623,17 +643,20 @@ end
-- Set combat time if affecting combat and return the difference between now and the last time -- Set combat time if affecting combat and return the difference between now and the last time
function Unit:GetCombatTime() function Unit:GetCombatTime()
if self:IsAffectingCombat() then return GetTime() - self.last_combat_time
self.last_combat_time = GetTime()
elseif not self:IsAffectingCombat() and self.last_combat_time then
self.last_combat_time = nil
end end
if not self.last_combat_time then function Unit:SetLastCombatTime(time)
return 0 self.last_combat_time = time
end end
return GetTime() - self.last_combat_time -- Get combat odds (if the last combat time is less than 1 minute ago return 1 / time, else return 0)
-- the closer to 0 the more likely the unit is to be in combat (0 = 100%) 60 = 0%
function Unit:InCombatOdds()
local time = self:GetCombatTime()
local percent = 1 - (time / 60)
return percent * 100
end end
-- Get units gcd time -- Get units gcd time
@ -656,7 +679,7 @@ More than 50% Haste will drop a spell below 1 second
]] ]]
function Unit:GetMaxGCD() function Unit:GetMaxGCD()
local haste = UnitSpellHaste(self.unit) local haste = UnitSpellHaste(self:GetOMToken())
if haste > 50 then if haste > 50 then
haste = 50 haste = 50
end end
@ -679,7 +702,7 @@ end
-- Get unit swing timers -- Get unit swing timers
function Unit:GetSwingTimers() function Unit:GetSwingTimers()
local main_speed, off_speed = UnitAttackSpeed(self.unit) local main_speed, off_speed = UnitAttackSpeed(self:GetOMToken())
local main_speed = main_speed or 2 local main_speed = main_speed or 2
local off_speed = off_speed or 2 local off_speed = off_speed or 2
@ -833,4 +856,9 @@ function Unit:GetTimeToShurikenTornado(n)
end end
end end
-- Is the unit indoors
function Unit:IsIndoors()
return IsIndoors()
end
return Unit return Unit

@ -48,6 +48,7 @@ local function Validate(token)
end end
-- Create a new UnitManager class -- Create a new UnitManager class
---@class UnitManager
local UnitManager = { local UnitManager = {
units = {}, units = {},
customUnits = {}, customUnits = {},
@ -87,11 +88,14 @@ function UnitManager:__index(k)
-- end -- end
if self.objects[kguid] == nil then if self.objects[kguid] == nil then
local o = Object(k)
if o then
local unit = Unit:New(Object(k)) local unit = Unit:New(Object(k))
self:SetObject(unit) self:SetObject(unit)
end end
end
return self.objects[kguid] return self.objects['none']
end end
-- Constructor -- Constructor
@ -108,6 +112,7 @@ function UnitManager:Validate(token)
end end
-- Get or create a unit -- Get or create a unit
---@return Unit
function UnitManager:Get(token) function UnitManager:Get(token)
-- if not Validate(token) then -- if not Validate(token) then
-- error("UnitManager:Get - Invalid token: " .. token) -- error("UnitManager:Get - Invalid token: " .. token)
@ -115,19 +120,20 @@ function UnitManager:Get(token)
local tguid = ObjectGUID(token) local tguid = ObjectGUID(token)
if self.objects[tguid] == nil then if tguid and self.objects[tguid] == nil then
if token == 'none' then if token == 'none' then
self.objects[tguid] = Unit:New(token) self.objects['none'] = Unit:New()
else else
self.objects[tguid] = Unit:New(Object(tguid)) self.objects[tguid] = Unit:New(Object(tguid))
end end
end end
return Bastion.Refreshable:New(self.objects[tguid], function() return Bastion.Refreshable:New(self.objects[tguid], function()
local tguid = ObjectGUID(token) local tguid = ObjectGUID(token) or "none"
if self.objects[tguid] == nil then if self.objects[tguid] == nil then
if token == 'none' then if token == 'none' then
self.objects[tguid] = Unit:New(token) self.objects['none'] = Unit:New()
else else
self.objects[tguid] = Unit:New(Object(tguid)) self.objects[tguid] = Unit:New(Object(tguid))
end end
@ -145,6 +151,9 @@ function UnitManager:SetObject(unit)
end end
-- Create a custom unit and cache it for .5 seconds -- Create a custom unit and cache it for .5 seconds
---@param token string
---@param cb fun():Unit
---@return Unit
function UnitManager:CreateCustomUnit(token, cb) function UnitManager:CreateCustomUnit(token, cb)
local unit = cb() local unit = cb()
local cachedUnit = Bastion.Cacheable:New(unit, cb) local cachedUnit = Bastion.Cacheable:New(unit, cb)
@ -175,6 +184,7 @@ function UnitManager:EnumFriends(cb)
end end
-- Enum Enemies (object manager) -- Enum Enemies (object manager)
---@param cb fun(unit: Unit):boolean
function UnitManager:EnumEnemies(cb) function UnitManager:EnumEnemies(cb)
Bastion.ObjectManager.activeEnemies:each(function(unit) Bastion.ObjectManager.activeEnemies:each(function(unit)
if cb(unit) then if cb(unit) then

@ -42,7 +42,9 @@ Bastion.Enabled = false
Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras) Bastion.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
local u = Bastion.UnitManager[unit] local u = Bastion.UnitManager[unit]
if u then
u:GetAuras():OnUpdate(auras) u:GetAuras():OnUpdate(auras)
end
end) end)
Bastion.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...) Bastion.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...)
@ -59,6 +61,23 @@ Bastion.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...)
end end
end) end)
Bastion.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
local _, subtype, _, sourceGUID, sourceName, _, _, destGUID, destName, destFlags, _, spellID, spellName, _, amount, interrupt, a, b, c, d, offhand, multistrike = CombatLogGetCurrentEventInfo()
local u = Bastion.UnitManager[sourceGUID]
local u2 = Bastion.UnitManager[destGUID]
local t = GetTime()
if u then
u:SetLastCombatTime(t)
end
if u2 then
u2:SetLastCombatTime(t)
end
end)
Bastion.Ticker = C_Timer.NewTicker(0.1, function() Bastion.Ticker = C_Timer.NewTicker(0.1, function()
if not Bastion.CombatTimer:IsRunning() and UnitAffectingCombat("player") then if not Bastion.CombatTimer:IsRunning() and UnitAffectingCombat("player") then
Bastion.CombatTimer:Start() Bastion.CombatTimer:Start()

Loading…
Cancel
Save