Files
wow_cyka/Autoloot.lua
2024-12-16 15:44:51 +01:00

696 lines
18 KiB
Lua

local addonname, shared = ...
---@cast shared CykaShared
---@cast addonname string
local skills = {}
---@class Autoloot
---@field Init fun()
---@class Value
---@field value any
---@field Gt fun(self:Value, other: any): boolean
---@field Lt fun(self:Value, other: any): boolean
---@field Eq fun(self:Value, other: any): boolean
---@field Ne fun(self:Value, other: any): boolean
---@field Ge fun(self:Value, other: any): boolean
---@field Le fun(self:Value, other: any): boolean
---@class NumberValue : Value
---@field value number
local NumberValue = {
---@param other number
Gt = function(self, other) return self.value > other end,
---@param other number
Lt = function(self, other) return self.value < other end,
---@param other number
Eq = function(self, other) return self.value == other end,
---@param other number
Ne = function(self, other) return self.value ~= other end,
---@param other number
Ge = function(self, other) return self.value >= other end,
---@param other number
Le = function(self, other) return self.value <= other end,
}
---@class StringValue : Value
---@field value string
local StringValue = {
---@param other string
Gt = function(self, other) return self.value > other end,
---@param other string
Lt = function(self, other) return self.value < other end,
---@param other string
Eq = function(self, other) return self.value == other end,
---@param other string
Ne = function(self, other) return self.value ~= other end,
---@param other string
Ge = function(self, other) return self.value >= other end,
---@param other string
Le = function(self, other) return self.value <= other end,
---@param other string
Matches = function(self, other) return string.match(self.value, other) end,
---@param other string
Contains = function(self, other) return string.find(self.value, other) end,
}
---@class Filter
---@field Matches fun(slot: number): boolean
shared.Autoloot = { Init = function() end }
function shared.Autoloot.Init()
if not shared.config.autoloot.enabled then
print("Cyka - Autoloot disabled")
return
end
-- ____ ____ _____ _____ ____ _____ ____ ____
-- | _ \| _ \ / _ \ \ / /_ _| _ \| ____| _ \/ ___|
-- | |_) | |_) | | | \ \ / / | || | | | _| | |_) \___ \
-- | __/| _ <| |_| |\ V / | || |_| | |___| _ < ___) |
-- |_| |_| \_\\___/ \_/ |___|____/|_____|_| \_\____/
---@param slot number
---@return StringValue, string?
local function Link(slot)
local ret = StringValue("")
if slot == nil then return ret, "slot is nil" end
local link = GetLootSlotLink(slot)
if link == nil then return ret, "link is nil" end
ret.value = link
return ret, nil
end
---@param slot number
---@return StringValue, string?
local function Name(slot)
local ret = StringValue("")
if slot == nil then return ret, "slot is nil" end
local name = select(2, GetLootSlotInfo(slot))
if name == nil then return ret, "name is nil" end
ret.value = name
return ret, nil
end
---@param slot number
---@return StringValue, string?
local function Type(slot)
local ret = StringValue("")
if slot == nil then return ret, "slot is nil" end
local type = select(6, GetItemInfo(Link(slot).value))
if type == nil then return ret, "type is nil" end
ret.value = type
return ret, nil
end
---@param slot number
---@return StringValue, string?
local function SubType(slot)
local ret = StringValue("")
if slot == nil then return ret, "slot is nil" end
local subType = select(7, GetItemInfo(Link(slot).value))
if subType == nil then return ret, "subType is nil" end
ret.value = subType
return ret, nil
end
---@param slot number
---@return NumberValue, string?
local function ItemLevel(slot)
local ret = NumberValue(0)
if slot == nil then return ret, "slot is nil" end
local itemLevel = select(4, GetItemInfo(Link(slot).value))
if itemLevel == nil then return ret, "itemLevel is nil" end
ret.value = itemLevel
return ret, nil
end
---@param slot number
---@return NumberValue, string?
local function Value(slot)
local ret = NumberValue(0)
if slot == nil then return ret, "slot is nil" end
local itemValue = select(11, GetItemInfo(Link(slot).value))
if itemValue == nil then return ret, "itemValue is nil" end
ret.value = itemValue
return ret, nil
end
---@param slot number
---@return NumberValue, string?
local function SubclassId(slot)
local ret = NumberValue(0)
if slot == nil then return ret, "slot is nil" end
local subclassId = select(13, GetItemInfo(Link(slot).value))
if subclassId == nil then return ret, "subclassId is nil" end
ret.value = subclassId
return ret, nil
end
---@param slot number
---@return NumberValue, string?
local function Quantity(slot)
local ret = NumberValue(1)
if slot == nil then return ret, "slot is nil" end
local quantity = select(3, GetItemInfo(Link(slot).value))
if quantity == nil then return ret, "quantity is nil" end
ret.value = quantity
return ret, nil
end
---@param slot number
---@return StringValue, string?
local function EquipLocation(slot)
local ret = NumberValue(0)
if slot == nil then return ret, "slot is nil" end
local equipLocation = select(9, GetItemInfo(Link(slot).value))
if equipLocation == nil then return ret, "equipLocation is nil" end
ret.value = equipLocation
return ret, nil
end
---@param slot number
---@return StringValue, string?
local function Icon(slot)
local ret = StringValue("")
if slot == nil then return ret, "slot is nil" end
local icon = select(10, GetItemInfo(Link(slot).value))
if icon == nil then return ret, "icon is nil" end
ret.value = icon
return ret, nil
end
---@param slot number
---@return NumberValue, string?
local function BindType(slot)
local ret = StringValue("")
if slot == nil then return ret, "slot is nil" end
local bindType = select(14, GetItemInfo(Link(slot).value))
if bindType == nil then return ret, "bindType is nil" end
ret.value = bindType
return ret, nil
end
---@param slot number
---@return NumberValue, string?
local function Quality(slot)
local ret = NumberValue(-1)
if slot == nil then return ret, "slot is nil" end
local quality = select(3, GetItemInfo(Link(slot).value))
if quality == nil then return ret, "quality is nil" end
ret.value = quality
return ret, nil
end
-- _____ ___ _ _____ _____ ____ ____
-- | ___|_ _| | |_ _| ____| _ \/ ___|
-- | |_ | || | | | | _| | |_) \___ \
-- | _| | || |___| | | |___| _ < ___) |
-- |_| |___|_____|_| |_____|_| \_\____/
---@class GoldFilter : Filter
local GoldFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.gold.enabled then return false end
local name = Name(slot)
return name:Contains("Gold") or name:Contains("Silver") or name:Contains("Copper")
end
}
---@class OrderResourceFilter : Filter
local OrderResourceFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.orderResource.enabled then return false end
return Name(slot):Contains("Order Resources")
end
}
---@class MountFilter : Filter
local MountFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.mount.enabled then return false end
return Type(slot):Eq("Mount")
end
}
---@class IlvlFilter : Filter
local IlvlFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.ilvl.enabled then return false end
return ItemLevel(slot):Ge(shared.config.autoloot.filter.ilvl.value)
end
}
---@class ProfessionFilter : Filter
local ProfessionFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.profession.enabled then return false end
local type = Type(slot)
if not type:Eq("Tradeskill") then return false end
local subtype = SubType(slot)
local professions = { strsplit(",", shared.config.autoloot.filter.profession.professions) }
return shared.TableContains(professions, subtype) or false
end
}
---@class ValueFilter : Filter
local ValueFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.value.enabled then return false end
local value = Value(slot)
if shared.config.autoloot.filter.value.byStack then
value = value * Quantity(slot).value
end
return value:Ge(shared.config.autoloot.filter.value.value)
end
}
---@class GreyValueFilter : Filter
local GreyValueFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.greyvalue.enabled then return false end
local quality = Quality(slot)
if not quality:Eq(0) then return false end
local value = Value(slot)
if shared.config.autoloot.filter.greyvalue.byStack then
value = value * Quantity(slot).value
end
return value:Ge(shared.config.autoloot.filter.greyvalue.value)
end
}
---@class QuestItemFilter : Filter
local QuestItemFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.questItem.enabled then return false end
return Type(slot):Eq("Quest") and SubType(slot):Eq("Quest")
end
}
---@class ClassGearFilter : Filter
local ClassGearFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.classGear.enabled then return false end
local ilvlThreshold = shared.config.autoloot.filter.classGear.ilvlThreshold
local qualityThreshold = shared.config.autoloot.filter.classGear.qualityThreshold
local isEquippable = skills[select(3, UnitClass("player"))][SubType(slot).value] or false
if not isEquippable then return false end
return ItemLevel(slot):Ge(ilvlThreshold) and Quality(slot):Ge(qualityThreshold)
end
}
---@class NameFilter : Filter
local NameFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.name.enabled then return false end
local whitelist = { strsplit(",", shared.config.autoloot.filter.name.whitelist) }
for _, name in ipairs(whitelist) do
if not shared.config.autoloot.filter.name.caseSensitive then name = name:lower() end
if shared.config.autoloot.filter.name.exact then
return Name(slot):Eq(name)
else
return Name(slot):Contains(name)
end
end
return false
end
}
---@class BoeFilter : Filter
local BoeFilter = {
types = { "Armor", "Weapon" },
equipLocs = { "INVTYPE_FINGER", "INVTYPE_TRINKET", "INVTYPE_CLOAK", "INVTYPE_NECK" },
Matches = function(self, slot)
if not shared.config.autoloot.filter.boe.enabled then return false end
local ilvlThreshold = shared.config.autoloot.filter.boe.ilvlThreshold
local qualityThreshold = shared.config.autoloot.filter.boe.qualityThreshold
local type = Type(slot)
local equipLoc = EquipLocation(slot)
if not shared.TableContains(self.types, type) or not shared.TableContains(self.equipLocs, equipLoc) then return false end
return BindType(slot):Eq(1) and ItemLevel(slot):Ge(ilvlThreshold) and Quality(slot):Ge(qualityThreshold)
end
}
---@class APFilter : Filter
local APFilter = {
Matches = function(self, slot)
if not shared.config.autoloot.filter.ap.enabled then return false end
return Value(slot):Eq(0) and Type(slot):Eq("Consumable") and SubType(slot):Eq("Other") and
SubclassId(slot):Eq(8)
end
}
---@class EverythingFilter : Filter
local EverythingFilter = {
Matches = function(self, slot)
return true
end
}
---@type Filter[]
local Filters = {
APFilter,
BoeFilter,
ClassGearFilter,
EverythingFilter,
GoldFilter,
GreyValueFilter,
IlvlFilter,
MountFilter,
NameFilter,
OrderResourceFilter,
ProfessionFilter,
QuestItemFilter,
ValueFilter,
}
-- _ ___ ___ _____ _ ___ ____ ___ ____
-- | | / _ \ / _ \_ _| | | / _ \ / ___|_ _/ ___|
-- | | | | | | | | || | | | | | | | | _ | | |
-- | |__| |_| | |_| || | | |__| |_| | |_| || | |___
-- |_____\___/ \___/ |_| |_____\___/ \____|___\____|
local lootReadyFrame = CreateFrame("Frame")
lootReadyFrame:RegisterEvent("LOOT_READY")
lootReadyFrame:SetScript("OnEvent", function()
local lootInfo = GetLootInfo()
shared.DumpTable(lootInfo, 0)
for slot = #lootInfo, 1, -1 do
for _, filter in ipairs(Filters) do
if filter.Matches(slot) then
print(string.format("Autolooting slot %s", tostring(slot)))
shared.DumpTable(filter, 0)
LootSlot(slot)
end
end
end
--aura_env.FilterService.Run(lootInfo)
--CloseLoot()
end)
print("Cyka - Autoloot loaded")
end
skills = {
--Warrior
[1] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 0,
["Mail"] = 0,
["Plate"] = 1,
["Shields"] = 1,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 1,
["Bows"] = 1,
["Guns"] = 1,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 1,
["Polearms"] = 1,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 1,
["Warglaives"] = 1,
["Staves"] = 1,
["Fist Weapons"] = 1,
["Daggers"] = 1,
["Crossbows"] = 1,
["Wands"] = 0,
},
--Paladin
[2] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 0,
["Mail"] = 0,
["Plate"] = 1,
["Shields"] = 1,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 1,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 1,
["Polearms"] = 1,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 1,
["Warglaives"] = 0,
["Staves"] = 0,
["Fist Weapons"] = 0,
["Daggers"] = 0,
["Crossbows"] = 0,
["Wands"] = 0,
},
--Hunter
[3] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 0,
["Mail"] = 1,
["Plate"] = 0,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 1,
["Bows"] = 1,
["Guns"] = 1,
["One-Handed Maces"] = 0,
["Two-Handed Maces"] = 0,
["Polearms"] = 1,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 1,
["Warglaives"] = 0,
["Staves"] = 1,
["Fist Weapons"] = 1,
["Daggers"] = 1,
["Crossbows"] = 1,
["Wands"] = 0,
},
--Rogue
[4] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 1,
["Mail"] = 0,
["Plate"] = 0,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 0,
["Polearms"] = 0,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 0,
["Warglaives"] = 0,
["Staves"] = 0,
["Fist Weapons"] = 1,
["Daggers"] = 1,
["Crossbows"] = 0,
["Wands"] = 0,
},
--Priest
[5] = {
--Armor Skills
["Cloth"] = 1,
["Leather"] = 0,
["Mail"] = 0,
["Plate"] = 0,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 0,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 0,
["Polearms"] = 0,
["One-Handed Swords"] = 0,
["Two-Handed Swords"] = 0,
["Warglaives"] = 0,
["Staves"] = 1,
["Fist Weapons"] = 0,
["Daggers"] = 1,
["Crossbows"] = 0,
["Wands"] = 1,
},
--Death Knight
[6] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 0,
["Mail"] = 0,
["Plate"] = 1,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 1,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 1,
["Polearms"] = 1,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 1,
["Warglaives"] = 0,
["Staves"] = 0,
["Fist Weapons"] = 0,
["Daggers"] = 0,
["Crossbows"] = 0,
["Wands"] = 0,
},
--Shaman
[7] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 0,
["Mail"] = 1,
["Plate"] = 0,
["Shields"] = 1,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 0,
["Polearms"] = 0,
["One-Handed Swords"] = 0,
["Two-Handed Swords"] = 0,
["Warglaives"] = 0,
["Staves"] = 1,
["Fist Weapons"] = 1,
["Daggers"] = 1,
["Crossbows"] = 0,
["Wands"] = 0,
},
--Mage
[8] = {
--Armor Skills
["Cloth"] = 1,
["Leather"] = 0,
["Mail"] = 0,
["Plate"] = 0,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 0,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 0,
["Two-Handed Maces"] = 0,
["Polearms"] = 0,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 0,
["Warglaives"] = 0,
["Staves"] = 1,
["Fist Weapons"] = 0,
["Daggers"] = 1,
["Crossbows"] = 0,
["Wands"] = 1,
},
--Warlock
[9] = {
--Armor Skills
["Cloth"] = 1,
["Leather"] = 0,
["Mail"] = 0,
["Plate"] = 0,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 0,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 0,
["Two-Handed Maces"] = 0,
["Polearms"] = 0,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 0,
["Warglaives"] = 0,
["Staves"] = 1,
["Fist Weapons"] = 0,
["Daggers"] = 1,
["Crossbows"] = 0,
["Wands"] = 1,
},
--Monk
[10] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 1,
["Mail"] = 0,
["Plate"] = 1,
["Shields"] = 1,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 0,
["Polearms"] = 1,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 0,
["Warglaives"] = 0,
["Staves"] = 1,
["Fist Weapons"] = 1,
["Daggers"] = 0,
["Crossbows"] = 0,
["Wands"] = 0,
},
--Druid
[11] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 1,
["Mail"] = 0,
["Plate"] = 0,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 0,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 1,
["Two-Handed Maces"] = 0,
["Polearms"] = 1,
["One-Handed Swords"] = 0,
["Two-Handed Swords"] = 0,
["Warglaives"] = 0,
["Staves"] = 1,
["Fist Weapons"] = 1,
["Daggers"] = 1,
["Crossbows"] = 0,
["Wands"] = 0,
},
--Demon Hunter
[12] = {
--Armor Skills
["Cloth"] = 0,
["Leather"] = 1,
["Mail"] = 0,
["Plate"] = 0,
["Shields"] = 0,
--Weapon Skills
["One-Handed Axes"] = 1,
["Two-Handed Axes"] = 0,
["Bows"] = 0,
["Guns"] = 0,
["One-Handed Maces"] = 0,
["Two-Handed Maces"] = 0,
["Polearms"] = 0,
["One-Handed Swords"] = 1,
["Two-Handed Swords"] = 0,
["Warglaives"] = 1,
["Staves"] = 0,
["Fist Weapons"] = 1,
["Daggers"] = 0,
["Crossbows"] = 0,
["Wands"] = 0,
},
}
--aura_env.qualityColors = {
-- "\124cff9d9d9d", -- Poor
-- "\124cffffffff", -- Common
-- "\124cff1eff00", -- Uncommon
-- "\124cff0070dd", -- Rare
-- "\124cffa335ee", -- Epic
-- "\124cffff8000", -- Legendary
-- "\124cffe6cc80", -- Artifact
-- "\124cff00ccff", -- Heirloom
--}