WIP: main #2

Closed
RexUK wants to merge 6 commits from Bastion:main into main
  1. 4
      scripts/subtlety.lua
  2. 7
      src/Aura/Aura.lua
  3. 126
      src/AuraTable/AuraTable.lua
  4. 6
      src/Cacheable/Cacheable.lua
  5. 8
      src/Item/Item.lua
  6. 20
      src/List/List.lua
  7. 64
      src/ObjectManager/ObjectManager.lua
  8. 6
      src/Refreshable/Refreshable.lua
  9. 6
      src/Spell/Spell.lua
  10. 147
      src/Unit/Unit.lua
  11. 14
      src/UnitManager/UnitManager.lua
  12. 19
      src/_bastion.lua

@ -1402,7 +1402,7 @@ CDsAPL:AddSpell(
function(self) function(self)
return Player:IsAffectingCombat() and Player:GetAuras():FindMy(Vanish):IsUp() and self:IsKnownAndUsable() and return Player:IsAffectingCombat() and Player:GetAuras():FindMy(Vanish):IsUp() and self:IsKnownAndUsable() and
Player:GetAuras():FindMy(DanseMacabre):GetCount() > 3 and Player:GetAuras():FindMy(DanseMacabre):GetCount() > 3 and
DefaultAPL:GetVariable('effective_combo_points') <= 2 DefaultAPL:GetVariable('effective_combo_points') <= 2 and Vanish:GetTimeSinceLastCast() > 2
end end
):SetTarget(Player) ):SetTarget(Player)
) )
@ -1764,7 +1764,7 @@ StealthCDsAPL:AddSpell(
self:IsKnownAndUsable() and self:IsKnownAndUsable() and
(not DanseMacabre:IsKnown() or Player:GetEnemies(10) >= 3) and (not DanseMacabre:IsKnown() or Player:GetEnemies(10) >= 3) and
not StealthCDsAPL:GetVariable('shd_threshold') and not StealthCDsAPL:GetVariable('shd_threshold') and
Player:GetComboPointsDeficit() > 1 Player:GetComboPointsDeficit() > 1 and Vanish:GetTimeSinceLastCast() > 2
end end
):SetTarget(Target) ):SetTarget(Target)
) )

@ -60,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 = {
@ -89,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

@ -18,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 = {}
@ -28,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
@ -52,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)
@ -110,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
@ -121,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
@ -207,21 +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 ---@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()
@ -230,12 +342,16 @@ 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

@ -6,9 +6,9 @@ local Cacheable = {
cache = nil, cache = nil,
callback = nil, callback = nil,
value = nil, value = nil,
__eq = function(self, other) -- __eq = function(self, other)
return self.value.__eq(self.value, other) -- return self.value.__eq(self.value, other)
end -- 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

@ -116,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)
@ -230,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
@ -244,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

@ -1,7 +1,25 @@
local Tinkr, Bastion = ... local Tinkr, Bastion = ...
---@class List ---@class List
local 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)

@ -7,7 +7,7 @@ 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()
@ -17,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
@ -40,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
@ -49,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)

@ -7,7 +7,7 @@ local Refreshable = {
callback = nil, callback = nil,
value = nil, value = nil,
__eq = function(self, other) __eq = function(self, other)
return self.value.__eq(self.value, other) return self.value.__eq(rawget(self, 'value'), other)
end end
} }
@ -23,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
@ -34,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

@ -121,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
@ -237,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

@ -12,11 +12,16 @@ local Unit = {
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
@ -30,12 +35,12 @@ end
-- Equals -- Equals
function Unit:__eq(other) function Unit:__eq(other)
return UnitIsUnit(self.unit, other.unit) return UnitIsUnit(self:GetOMToken(), other.unit)
end 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
@ -50,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
@ -94,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
@ -123,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
@ -137,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
@ -182,54 +187,61 @@ 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(self.unit) return UnitAffectingCombat(self:GetOMToken())
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
@ -241,14 +253,14 @@ 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)
@ -270,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
@ -292,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
@ -301,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
@ -313,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
@ -323,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()
@ -331,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
@ -349,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
@ -386,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)
@ -406,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)
@ -430,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
@ -452,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
@ -485,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
@ -517,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
@ -525,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
@ -533,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
@ -627,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
@ -660,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
@ -683,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

@ -88,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
@ -117,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

@ -66,7 +66,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(...)
@ -83,6 +85,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