122 lines
4.2 KiB
Lua
122 lines
4.2 KiB
Lua
-- Adapted from AoELoot by Sandrea / ChatGPT for ShaguTweaks-ClassicAPI.
|
|
|
|
local T = ShaguTweaks.T
|
|
local API = ShaguTweaks.API
|
|
|
|
local module = ShaguTweaks:register({
|
|
title = T["AoE Loot"],
|
|
description = T["Automatically loots all nearby corpses using ClassicAPI without confirmation prompts. Leaves Master Loot untouched."],
|
|
expansions = { ["vanilla"] = true },
|
|
category = T["Loot"],
|
|
enabled = nil,
|
|
})
|
|
|
|
module.enable = function(self)
|
|
-- AoE Loot relies entirely on ClassicAPI's native corpse walker,
|
|
-- container classification and timer. Do not keep partial legacy behavior
|
|
-- when those capabilities are unavailable.
|
|
if not API or not API.aoeloot or not API.containeropenable or not API.timer then return end
|
|
|
|
local frame = CreateFrame("Frame", "ShaguTweaksAoELoot")
|
|
local pending = false
|
|
local containerLootDeadline = 0
|
|
local takeoverGeneration = 0
|
|
local TAKEOVER_DELAY = 0.3
|
|
|
|
local function CancelTakeover()
|
|
takeoverGeneration = takeoverGeneration + 1
|
|
pending = false
|
|
end
|
|
|
|
local function TrackContainerUse(bag, slot)
|
|
local isOpenable, canOpen = API.IsContainerItemOpenable(bag, slot)
|
|
if isOpenable and canOpen then
|
|
-- LOOT_OPENED is also fired by clams, lockboxes and similar bag items.
|
|
-- Mark that session before UseContainerItem runs so it remains under the
|
|
-- normal client handling and the consumed container can leave the bag.
|
|
containerLootDeadline = GetTime() + 3
|
|
end
|
|
end
|
|
|
|
-- Use the ShaguTweaks hook explicitly because its prepend mode records the
|
|
-- bag item before UseContainerItem can synchronously fire LOOT_OPENED.
|
|
ShaguTweaks.hooksecurefunc("UseContainerItem", TrackContainerUse, true)
|
|
|
|
local function IsMasterLootActive()
|
|
if not GetLootMethod then return false end
|
|
return GetLootMethod() == "master"
|
|
end
|
|
|
|
local function CanStartAoELoot()
|
|
if IsMasterLootActive() then return false end
|
|
if API.IsLootScanInProgress() then return false end
|
|
return true
|
|
end
|
|
|
|
local function HasNearbyLootableCorpse()
|
|
local units = API.GetNearbyLootableUnits()
|
|
return type(units) == "table" and table.getn(units) > 0
|
|
end
|
|
|
|
local function StartAoELoot(generation)
|
|
if generation ~= takeoverGeneration or not pending then return end
|
|
|
|
pending = false
|
|
if CanStartAoELoot() then
|
|
API.LootAllCorpses()
|
|
end
|
|
end
|
|
|
|
local function TakeOverLootSession()
|
|
-- AoE Loot owns corpse sessions while enabled. Close the normal client
|
|
-- window immediately so Vanilla autoloot, SuperAPI SetAutoloot modes and
|
|
-- quickloot-patched clients cannot keep control of the session.
|
|
takeoverGeneration = takeoverGeneration + 1
|
|
local generation = takeoverGeneration
|
|
pending = true
|
|
CloseLoot()
|
|
|
|
-- Native autoloot may already have emitted loot packets before LOOT_OPENED
|
|
-- reaches Lua. ClassicAPI's own loot test uses the same 0.3s settling
|
|
-- window between loot operations; after it expires the native corpse walker
|
|
-- becomes the sole owner of all remaining nearby corpse loot.
|
|
C_Timer.After(TAKEOVER_DELAY, function()
|
|
StartAoELoot(generation)
|
|
end)
|
|
end
|
|
|
|
frame:RegisterEvent("LOOT_OPENED")
|
|
|
|
frame:SetScript("OnEvent", function()
|
|
if event ~= "LOOT_OPENED" then return end
|
|
|
|
-- Inventory containers use the same loot event as corpses. Let the normal
|
|
-- client finish them instead of treating them as an AoE-loot trigger.
|
|
if containerLootDeadline > 0 then
|
|
local isContainerLoot = GetTime() <= containerLootDeadline
|
|
containerLootDeadline = 0
|
|
if isContainerLoot then
|
|
CancelTakeover()
|
|
return
|
|
end
|
|
end
|
|
|
|
-- The master looter must keep the normal window to inspect and assign loot.
|
|
if IsMasterLootActive() then
|
|
CancelTakeover()
|
|
return
|
|
end
|
|
|
|
-- Chests, fishing nodes and other non-corpse sources also emit LOOT_OPENED.
|
|
-- Only take over when ClassicAPI can see at least one nearby lootable unit.
|
|
if not HasNearbyLootableCorpse() then return end
|
|
|
|
-- A queued takeover already owns this interaction. ClassicAPI suppresses
|
|
-- its own LOOT_OPENED/LOOT_CLOSED events while walking corpses, so no
|
|
-- additional session needs to be stacked here.
|
|
if pending then return end
|
|
|
|
TakeOverLootSession()
|
|
end)
|
|
end
|