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) return shared.config.autoloot.filter.profession.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 = ItemValue(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 = ItemValue(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 --}