Compare commits

..

10 Commits

Author SHA1 Message Date
João Fidalgo 6280196711 feat: add spell traits 9 months ago
4n0n c0c8ab8362 Fix? 11 months ago
4n0n fad3d76d8a 11.0 ItemName 11 months ago
4n0n e6b2b8f42f Merge pull request '11.0' (#27) from 4n0n/Bastion:main into main 11 months ago
4n0n 86e7aeccec 11.0 11 months ago
4n0n f9583a85d8 11.0 11 months ago
4n0n d0cad5746d 11.0 11 months ago
4n0n 010d2b4111 11.0 11 months ago
4n0n 7442498326 11.0 11 months ago
4n0n 83086a9b57 11.0 11 months ago
  1. 34
      src/Aura/Aura.lua
  2. 41
      src/Item/Item.lua
  3. 18
      src/MythicPlusUtils/MythicPlusUtils.lua
  4. 92
      src/Spell/Spell.lua
  5. 4
      src/SpellBook/SpellBook.lua
  6. 113
      src/_bastion.lua

@ -75,6 +75,40 @@ function Aura:New(unit, index, type)
return self
end
if C_UnitAuras.GetAuraDataByIndex then
local unitAuraInfo = C_UnitAuras.GetAuraDataByIndex(unit:GetOMToken(), index, type)
if not unitAuraInfo then
local self = setmetatable({}, Aura)
self.aura = {
name = nil,
icon = nil,
count = 0,
dispelType = nil,
duration = 0,
expirationTime = 0,
source = nil,
isStealable = false,
nameplateShowPersonal = false,
spellId = 0,
canApplyAura = false,
isBossDebuff = false,
castByPlayer = false,
nameplateShowAll = false,
timeMod = 0,
index = nil,
type = nil
}
if self.aura.spellId then
Bastion.Globals.SpellBook:GetSpell(self.aura.spellId)
end
return self
end
return Aura:CreateFromUnitAuraInfo(unitAuraInfo)
end
local name, icon, count, dispelType, duration, expirationTime, source, isStealable, nameplateShowPersonal, spellId,
canApplyAura, isBossDebuff, castByPlayer, nameplateShowAll, timeMod = UnitAura(unit:GetOMToken(), index, type)

@ -51,7 +51,13 @@ function Item:New(id)
self.ItemID = id
-- Register spell in spellbook
local name, spellID = GetItemSpell(self:GetID())
local name, spellID
if C_Item.GetItemSpell then
name, spellID = C_Item.GetItemSpell(self:GetID())
else
name, spellID = GetItemSpell(self:GetID())
end
if spellID then
self.spellID = spellID
Bastion.Globals.SpellBook:GetSpell(spellID)
@ -69,18 +75,27 @@ end
-- Get the Items name
---@return string
function Item:GetName()
if C_Item.GetItemInfo then
return C_Item.GetItemInfo(self:GetID())
end
return GetItemInfo(self:GetID())
end
-- Get the Items icon
---@return number
function Item:GetIcon()
if C_Item.GetItemIconByID then
return C_Item.GetItemIconByID(self:GetID())
end
return select(3, GetItemInfo(self:GetID()))
end
-- Get the Items cooldown
---@return number
function Item:GetCooldown()
if C_Item.GetItemCooldown then
return select(2, C_Item.GetItemCooldown(self:GetID()))
end
return select(2, C_Container.GetItemCooldown(self:GetID()))
end
@ -105,6 +120,10 @@ end
-- Get the Items cooldown remaining
---@return number
function Item:GetCooldownRemaining()
if C_Item.GetItemCooldown then
local start, duration = C_Item.GetItemCooldown(self:GetID())
return start + duration - GetTime()
end
local start, duration = C_Container.GetItemCooldown(self:GetID())
return start + duration - GetTime()
end
@ -131,7 +150,11 @@ function Item:Use(unit, condition)
self.wasLooking = IsMouselooking()
-- Use the Item
if C_Item.UseItemByName then
C_Item.UseItemByName(self:GetName(), unit:GetOMToken())
else
UseItemByName(self:GetName(), unit:GetOMToken())
end
Bastion:Debug("Using", self)
@ -161,18 +184,28 @@ end
-- Check if the Item is known
---@return boolean
function Item:IsEquipped()
if C_Item.IsEquippedItem then
return C_Item.IsEquippedItem(self:GetID())
end
return IsEquippedItem(self:GetID())
end
-- Check if the Item is on cooldown
---@return boolean
function Item:IsOnCooldown()
if C_Item.GetItemCooldown then
return select(2, C_Item.GetItemCooldown(self:GetID())) > 0
end
return select(2, C_Container.GetItemCooldown(self:GetID())) > 0
end
-- Check if the Item is usable
---@return boolean
function Item:IsUsable()
if C_Item.IsUsableItem then
local usable, noMana = C_Item.IsUsableItem(self:GetID())
return usable or usableExcludes[self:GetID()]
end
local usable, noMana = IsUsableItem(self:GetID())
return usable or usableExcludes[self:GetID()]
end
@ -187,6 +220,9 @@ end
-- Is equippable
---@return boolean
function Item:IsEquippable()
if C_Item.IsEquippableItem then
return C_Item.IsEquippableItem(self:GetID())
end
return IsEquippableItem(self:GetID())
end
@ -317,6 +353,9 @@ end
-- Get the Items charges
---@return number
function Item:GetCharges()
if C_Item.GetItemCount then
return C_Item.GetItemCount(self:GetID())
end
return GetItemCharges(self:GetID())
end

@ -462,7 +462,14 @@ function MythicPlusUtils:New()
return
end
local name = GetSpellInfo(spellID)
local name
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(spellID)
name = info and info.name or ''
else
name = GetSpellInfo(spellID)
end
self.loggedCasts[spellID] = true
@ -481,7 +488,14 @@ function MythicPlusUtils:New()
return
end
local name = GetSpellInfo(spellID)
local name
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(spellID)
name = info and info.name or ''
else
name = GetSpellInfo(spellID)
end
self.loggedCasts[spellID] = true

@ -96,24 +96,53 @@ end
-- Get the spells name
---@return string
function Spell:GetName()
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(self:GetID())
return info and info.name or nil
end
return GetSpellInfo(self:GetID())
end
-- Get the spells icon
---@return number
function Spell:GetIcon()
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(self:GetID())
return info and info.iconID or nil
end
return select(3, GetSpellInfo(self:GetID()))
end
-- Get the spells cooldown
---@return number
function Spell:GetCooldown()
if C_Spell.GetSpellCooldown then
local info = C_Spell.GetSpellCooldown(self:GetID())
return info and info.duration or nil
end
return select(2, GetSpellCooldown(self:GetID()))
end
-- Get the full cooldown (time until all charges are available)
---@return number
function Spell:GetFullRechargeTime()
if C_Spell.GetSpellCooldown then
local info = C_Spell.GetSpellCooldown(self:GetID())
if info.isEnabled == 0 then
return 0
end
local chargeInfo = C_Spell.GetSpellCharges(self:GetID())
if chargeInfo.currentCharges == chargeInfo.maxCharges then
return 0
end
if chargeInfo.currentCharges == 0 then
return info.startTime + info.duration - GetTime()
end
return chargeInfo.cooldownStartTime + chargeInfo.cooldownDuration - GetTime()
end
local start, duration, enabled = GetSpellCooldown(self:GetID())
if enabled == 0 then
return 0
@ -152,6 +181,10 @@ end
-- Get the spells cooldown remaining
---@return number
function Spell:GetCooldownRemaining()
if C_Spell.GetSpellCooldown then
local info = C_Spell.GetSpellCooldown(self:GetID())
return info and info.startTime + info.duration - GetTime() or nil
end
local start, duration = GetSpellCooldown(self:GetID())
return start + duration - GetTime()
end
@ -159,6 +192,9 @@ end
-- Get the spell count
---@return number
function Spell:GetCount()
if C_Spell.GetSpellCastCount then
return C_Spell.GetSpellCastCount(self:GetID())
end
return GetSpellCount(self:GetID())
end
@ -268,6 +304,8 @@ end
-- Check if the spell is known
---@return boolean
function Spell:IsKnown()
local IsSpellKnown = C_Spell.IsSpellKnown and C_Spell.IsSpellKnown or IsSpellKnown
local IsPlayerSpell = C_Spell.IsPlayerSpell and C_Spell.IsPlayerSpell or IsPlayerSpell
local isKnown = IsSpellKnown(self:GetID())
local isPlayerSpell = IsPlayerSpell(self:GetID())
return isKnown or isPlayerSpell
@ -276,12 +314,20 @@ end
-- Check if the spell is on cooldown
---@return boolean
function Spell:IsOnCooldown()
if C_Spell.GetSpellCooldown then
local info = C_Spell.GetSpellCooldown(self:GetID())
return info and info.duration > 0
end
return select(2, GetSpellCooldown(self:GetID())) > 0
end
-- Check if the spell is usable
---@return boolean
function Spell:IsUsable()
if C_Spell.IsSpellUsable then
local usable, noMana = C_Spell.IsSpellUsable(self:GetID())
return usable or usableExcludes[self:GetID()] and not noMana
end
local usable, noMana = IsUsableSpell(self:GetID())
return usable or usableExcludes[self:GetID()] and not noMana
end
@ -403,6 +449,9 @@ end
-- Check if the spell is castable and cast it
---@return boolean
function Spell:HasRange()
if C_Spell.SpellHasRange then
return C_Spell.SpellHasRange(self:GetID())
end
return SpellHasRange(self:GetName())
end
@ -410,6 +459,10 @@ end
---@return number
---@return number
function Spell:GetRange()
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(self:GetID())
return info and info.minRange or nil, info and info.maxRange or nil
end
local name, rank, icon, castTime, minRange, maxRange, spellID, originalIcon = GetSpellInfo(self:GetID())
return maxRange, minRange
end
@ -418,6 +471,7 @@ end
---@param unit Unit
---@return boolean
function Spell:IsInRange(unit)
local IsSpellInRange = C_Spell.IsSpellInRange and C_Spell.IsSpellInRange or IsSpellInRange
local hasRange = self:HasRange()
local inRange = IsSpellInRange(self:GetName(), unit:GetOMToken())
@ -459,20 +513,50 @@ end
-- Get the spells charges
---@return number
function Spell:GetCharges()
if C_Spell.GetSpellCharges then
local info = C_Spell.GetSpellCharges(self:GetID())
return info and info.currentCharges or nil
end
return GetSpellCharges(self:GetID())
end
function Spell:GetMaxCharges()
if C_Spell.GetSpellCharges then
local info = C_Spell.GetSpellCharges(self:GetID())
return info and info.maxCharges or nil
end
return select(2, GetSpellCharges(self:GetID()))
end
function Spell:GetCastLength()
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(self:GetID())
return info and info.castTime or nil
end
return select(4, GetSpellInfo(self:GetID()))
end
-- Get the spells charges
---@return number
function Spell:GetChargesFractional()
if C_Spell.GetSpellCharges then
local info = C_Spell.GetSpellCharges(self:GetID())
if info.currentCharges == info.maxCharges then
return info.maxCharges
end
if info.currentCharges == 0 then
return 0
end
local timeSinceStart = GetTime() - info.cooldownStartTime
local timeLeft = info.cooldownDuration - timeSinceStart
local timePerCharge = info.cooldownDuration / info.maxCharges
local chargesFractional = info.currentCharges + (timeLeft / timePerCharge)
return chargesFractional
end
local charges, maxCharges, start, duration = GetSpellCharges(self:GetID())
if charges == maxCharges then
@ -494,6 +578,10 @@ end
-- Get the spells charges remaining
---@return number
function Spell:GetChargesRemaining()
if C_Spell.GetSpellCharges then
local info = C_Spell.GetSpellCharges(self:GetID())
return info and info.currentCharges or nil
end
local charges, maxCharges, start, duration = GetSpellCharges(self:GetID())
return charges
end
@ -599,6 +687,10 @@ end
-- GetCost
---@return number
function Spell:GetCost()
if C_Spell.GetSpellPowerCost then
local info = C_Spell.GetSpellPowerCost(self:GetID())
return info and info.cost or 0
end
local cost = GetSpellPowerCost(self:GetID())
return cost and cost.cost or 0
end

@ -50,6 +50,10 @@ end
---@param name string
---@return Spell
function SpellBook:GetSpellByName(name)
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(name)
return self:GetSpell(info.spellID)
end
local _, rank, icon, castTime, minRange, maxRange, spellID, originalIcon = GetSpellInfo(name)
return self:GetSpell(spellID)
end

@ -1,9 +1,9 @@
local Tinkr = ...
local Evaulator = Tinkr.Evaluator
---@class Bastion
local Bastion = {
DebugMode = false
}
local Bastion = {DebugMode = false}
Bastion.__index = Bastion
function Bastion:Require(file)
@ -50,6 +50,9 @@ function Bastion.require(class)
return Bastion:Require("~/src/" .. class .. "/" .. class)
end
-- fenv for all required files
function Bastion.Bootstrap()
Bastion.Globals = {}
---@type ClassMagic
@ -59,7 +62,8 @@ Bastion.List = Bastion.require("List")
---@type Library
Bastion.Library = Bastion.require("Library")
---@type NotificationsList, Notification
Bastion.NotificationsList, Bastion.Notification = Bastion.require("NotificationsList")
Bastion.NotificationsList, Bastion.Notification = Bastion.require(
"NotificationsList")
---@type Vector3
Bastion.Vector3 = Bastion.require("Vector3")
---@type Sequencer
@ -115,15 +119,15 @@ local MODULES = {}
Bastion.Enabled = false
Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA', function(unit, auras)
Bastion.Globals.EventManager:RegisterWoWEvent('UNIT_AURA',
function(unit, auras)
local u = Bastion.UnitManager[unit]
if u then
u:GetAuras():OnUpdate(auras)
end
if u then u:GetAuras():OnUpdate(auras) end
end)
Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED", function(...)
Bastion.Globals.EventManager:RegisterWoWEvent("UNIT_SPELLCAST_SUCCEEDED",
function(...)
local unit, castGUID, spellID = ...
local spell = Bastion.Globals.SpellBook:GetIfRegistered(spellID)
@ -140,7 +144,8 @@ end)
local pguid = UnitGUID("player")
local missed = {}
Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", function()
Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED",
function()
local args = {CombatLogGetCurrentEventInfo()}
local subEvent = args[2]
@ -161,14 +166,13 @@ Bastion.Globals.EventManager:RegisterWoWEvent("COMBAT_LOG_EVENT_UNFILTERED", fun
local t = GetTime()
if u then
u:SetLastCombatTime(t)
end
if u then u:SetLastCombatTime(t) end
if u2 then
u2:SetLastCombatTime(t)
if subEvent == "SPELL_MISSED" and sourceGUID == pguid and spellID == 408 then
if subEvent == "SPELL_MISSED" and sourceGUID == pguid and spellID ==
408 then
local missType = args[15]
if missType == "IMMUNE" then
@ -187,15 +191,14 @@ end)
Bastion.Ticker = C_Timer.NewTicker(0.1, function()
if not Bastion.CombatTimer:IsRunning() and UnitAffectingCombat("player") then
Bastion.CombatTimer:Start()
elseif Bastion.CombatTimer:IsRunning() and not UnitAffectingCombat("player") then
elseif Bastion.CombatTimer:IsRunning() and
not UnitAffectingCombat("player") then
Bastion.CombatTimer:Reset()
end
if Bastion.Enabled then
Bastion.ObjectManager:Refresh()
for i = 1, #MODULES do
MODULES[i]:Tick()
end
for i = 1, #MODULES do MODULES[i]:Tick() end
end
end)
@ -207,9 +210,7 @@ end
-- Find a module by name
function Bastion:FindModule(name)
for i = 1, #MODULES do
if MODULES[i].name == name then
return MODULES[i]
end
if MODULES[i].name == name then return MODULES[i] end
end
return nil
@ -218,21 +219,15 @@ end
function Bastion:Print(...)
local args = {...}
local str = "|cFFDF362D[Bastion]|r |cFFFFFFFF"
for i = 1, #args do
str = str .. tostring(args[i]) .. " "
end
for i = 1, #args do str = str .. tostring(args[i]) .. " " end
print(str)
end
function Bastion:Debug(...)
if not Bastion.DebugMode then
return
end
if not Bastion.DebugMode then return end
local args = {...}
local str = "|cFFDF6520[Bastion]|r |cFFFFFFFF"
for i = 1, #args do
str = str .. tostring(args[i]) .. " "
end
for i = 1, #args do str = str .. tostring(args[i]) .. " " end
print(str)
end
@ -259,21 +254,35 @@ end)
Command:Register('dumpspells', 'Dump spells to a file', function()
local i = 1
local rand = math.random(100000, 999999)
local BOOKTYPE_SPELL = BOOKTYPE_SPELL or (Enum.SpellBookSpellBank.Player and Enum.SpellBookSpellBank.Player or 'spell')
while true do
local spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_SPELL)
if not spellName then
do
break
end
local spellName, spellSubName
if C_SpellBook.GetSpellBookItemName then
spellName, spellSubName = C_SpellBook.GetSpellBookItemName(i, BOOKTYPE_SPELL)
else
spellName, spellSubName = GetSpellBookItemName(i, BOOKTYPE_SPELL)
end
if not spellName then do break end end
-- use spellName and spellSubName here
local spellID = select(7, GetSpellInfo(spellName))
local spellID
if C_Spell.GetSpellInfo then
local info = C_Spell.GetSpellInfo(spellName)
spellID = info.spellID
else
spellID = select(7, GetSpellInfo(spellName))
end
if spellID then
spellName = spellName:gsub("[%W%s]", "")
WriteFile('bastion-' .. UnitClass('player') .. '-' .. rand .. '.lua',
"local " .. spellName .. " = Bastion.Globals.SpellBook:GetSpell(" .. spellID .. ")\n", true)
WriteFile('bastion-' .. UnitClass('player') .. '-' .. rand ..
'.lua',
"local " .. spellName ..
" = Bastion.Globals.SpellBook:GetSpell(" ..
spellID .. ")\n", true)
end
i = i + 1
end
@ -297,13 +306,16 @@ Command:Register('mplus', 'Toggle m+ module on/off', function(args)
local cmd = args[2]
if cmd == 'debuffs' then
Bastion.MythicPlusUtils:ToggleDebuffLogging()
Bastion:Print("Debuff logging", Bastion.MythicPlusUtils.debuffLogging and "enabled" or "disabled")
Bastion:Print("Debuff logging", Bastion.MythicPlusUtils
.debuffLogging and "enabled" or "disabled")
return
end
if cmd == 'casts' then
Bastion.MythicPlusUtils:ToggleCastLogging()
Bastion:Print("Cast logging", Bastion.MythicPlusUtils.castLogging and "enabled" or "disabled")
Bastion:Print("Cast logging",
Bastion.MythicPlusUtils.castLogging and "enabled" or
"disabled")
return
end
@ -313,10 +325,9 @@ Command:Register('mplus', 'Toggle m+ module on/off', function(args)
Bastion:Print("casts")
end)
Command:Register('missed', 'Dump the list of immune kidney shot spells', function()
for k, v in pairs(missed) do
Bastion:Print(k)
end
Command:Register('missed', 'Dump the list of immune kidney shot spells',
function()
for k, v in pairs(missed) do Bastion:Print(k) end
end)
---@param library Library
@ -333,13 +344,16 @@ function Bastion:CheckLibraryDependencies()
if LIBRARIES[dep].dependencies then
for j = 1, #LIBRARIES[dep].dependencies do
if LIBRARIES[dep].dependencies[j] == v.name then
Bastion:Print("Circular dependency detected between " .. v.name .. " and " .. dep)
Bastion:Print(
"Circular dependency detected between " ..
v.name .. " and " .. dep)
return false
end
end
end
else
Bastion:Print("Library " .. v.name .. " depends on " .. dep .. " but it's not registered")
Bastion:Print("Library " .. v.name .. " depends on " ..
dep .. " but it's not registered")
return false
end
end
@ -352,9 +366,7 @@ end
function Bastion:Import(library)
local lib = self:GetLibrary(library)
if not lib then
error("Library " .. library .. " not found")
end
if not lib then error("Library " .. library .. " not found") end
return lib:Resolve()
end
@ -395,3 +407,6 @@ end
Load("@Libraries/")
Load("@Modules/")
Load("@")
end
Bastion.Bootstrap()

Loading…
Cancel
Save