I'm using this one for when our team does WZ. Might be better ones out there though.
Code:
-----------------------------------------------
-------------------- CONFIG -------------------
-----------------------------------------------
 
LootGold            = false
LootAboveValue      = 1000 -- Will loot any item with an NPC price greater or equal to this.
LootAboveValueRatio = 5    -- Will loot any stackable item with a NPC price to weight ratio greater or equal to this.
LootList =                 -- Will loot all items on this list even if they don't meet any of the above criteria.
{
    "Shiny Blade",
    "Crystalline Axe",
    "Decorative Ribbon",
    "Abyssador's Lash",
    "Deathstrike's Snippet",
    "Gnomevil's Hat",
    "Crystalline Sword",
    "Mycological Mace",
    "Mycological Bow",
    "Crystal Crossbow"
}
 
-- You need to open your backpacks on your own. 0 is your main backpack.
BpStacks = 1
BpRares  = 2
BpGold   = 3 -- Not needed it not looting gold.
 
-- Increase these if the script misses loot. Decrease them to increase speed.
MinWait = 15
MaxWait = 40
 
OpenCorpses  = true
CloseCorpses = true -- The corpse opener works better if you also let it close corpses.
LootFirst    = true -- Only relevant if OpenCorpses is true.
 
-----------------------------------------------
----------------- DESCRIPTION -----------------
-----------------------------------------------
--[[
	This script will open and loot corpses within 1sqm of your character.
	It will also loot any corpse that you open manually.
	Known issues:
		- The script is only able to open very fresh corpses.
		- The script will not retry opening a corpse if you walk away
		  while it is being looted.
		- The script cannot open corpses on top of ladders and rope spots.
]]
-----------------------------------------------
-----------------------------------------------
-----------------------------------------------
 
-- CONVERT CONFIG
local LootAboveValue = LootAboveValue
local LootAboveValueRatio = LootAboveValueRatio
OldLootList = LootList
local LootList = {}
for _, name in ipairs(OldLootList) do
    LootList[Item.GetItemIDFromDualInput(name)] = true
end
 
local BpStacks = BpStacks
local BpRares = BpRares
local BpGold = BpGold
 
-- POSITION HASHING
local function ToNumber(pos)
    return 10000000000*pos.x+100000*pos.y+pos.z
end
 
local function ToPos(num)
    local x = math.floor(num/10000000000)
    local y = math.floor(num/100000)%100000
    local z = num%100000
    return {x=x, y=y, z=z}
end
 
-- WAITING
local MinWait = MinWait
local MaxWait = MaxWait
local function Wait()
    wait(MinWait, MaxWait)
end
 
-- LOOTER
local Corpses = {}
local Monsters = {}
 
 
Module("Find Corpses", function(find)
    local UpdatedMonsters = {}
    for pos, monster in pairs(Monsters) do
        if monster:isAlive() and monster:DistanceFromSelf() < 20 then
            UpdatedMonsters[ToNumber(monster:Position())] = monster
        elseif Corpses[ToNumber(monster:Position())] then
            Corpses[ToNumber(monster:Position())] = Corpses[ToNumber(monster:Position())] + 1
        else
            Corpses[ToNumber(monster:Position())] = 1
        end
    end
     
    for _, monster in Creature.iMonsters(7) do
        UpdatedMonsters[ToNumber(monster:Position())] = monster
    end
     
    Monsters = UpdatedMonsters
end)
 
local function GetBp(id)
    return (id==3031 and BpGold) or (Item.isStackable(id) and BpStacks) or BpRares
end
 
local function GetSlot(id)
    local bp = Container(GetBp(id))
    if bp:isOpen() then
        if Item.isStackable(id) then
            for Spot = 0, bp:ItemCount() - 1 do
                local item = bp:GetItemData(Spot)
                if id == item.id and item.count ~= 100 then
                    return bp:Index(), Spot, (100-item.count)
                end
            end
		end
		if bp:isFull() then
			if Item.isContainer(bp:GetItemData(bp:ItemCount()-1).id) then
				local tries = 0
				while not bp:UseItem(bp:ItemCount()-1, true) and tries < 10 do
					Wait() 
					tries = tries + 1 
				end
				if tries < 10 then
					return GetSlot(id)
				end
			else
				print("Error: "..bp:Name().." is full and has no container in its last slot.")
			end
		else
			return bp:Index(), bp:ItemCount(), (Item.isStackable(id) and 100) or 1
		end
    else
        print("Error: All backpacks aren't open.")
    end
end
 
local function MoveToSelf(Corpse, Spot)
    local item = Corpse:GetItemData(Spot)
    if Self.Cap() >= Item.GetWeight(item.id)*item.count then
        local index, slot, count = GetSlot(item.id)
        if index then
            local tries = 0
            local LCount = Corpse:ItemCount()
            while Corpse:isOpen() and Corpse:ItemCount() == LCount and tries < 10 do
                Corpse:MoveItemToContainer(Spot, index, slot, math.min(item.count, count))
                Wait()
                tries = tries + 1 
            end
            Wait()
            if Corpse:isOpen() and Corpse:ItemCount() ~= LCount and count == item.count then
                return true
            end
            if Corpse:isOpen() and count < item.count then
                return MoveToSelf(Corpse, Spot)
            end
        end
    else
        print("Error: Not enough capacity.")
    end
    return false
end
 
local function IsLoot(id)
    return ((Item.GetValue(id) >= LootAboveValue) or
            (Item.isStackable(id) and (Item.GetValue(id)/Item.GetWeight(id)) > LootAboveValueRatio) or
		     LootList[id]) and (LootGold or id ~= 3031)
end

local CorpseNames = {"The", "Demonic", "Dead", "Slain", "Dissolved", "Remains", "Elemental"}
local function IsCorpseByName(name)
	for _, CPartName in ipairs(CorpseNames) do
		if name:find(CPartName) then
			return true
		end
	end
	return false
end

local function GrabItems(Corpse)
    local success = true
    if (Item.isCorpse(Corpse:ID()) or IsCorpseByName(Corpse:Name())) then
        for Spot = Corpse:ItemCount() - 1, 0, -1 do
            if IsLoot(Corpse:GetItemData(Spot).id) then
                success = success and MoveToSelf(Corpse, Spot)
                Wait()
            end
        end
    end
    return success
end

local function OpenCorpse(pos, count)
    if Item.isCorpse(Map.GetTopUseItem(pos.x, pos.y, pos.z).id) and count == 1 then
        local tries = 0
		-- We need slightly longer waits when opening corpses, or the script falls apart. However, I'd still like the user to be able to slow down the looter. Thus we use both a static wait and a user configured wait.
        while tries < 10 and not (Self.UseItemFromGround(pos.x, pos.y, pos.z) and (wait(40, 50) or Wait() or true) and Item.isCorpse(Container.GetLast():ID())) do
            tries = tries + 1
        end
        Wait()
        return tries < 10
    else
        local Browse = Container.GetByName("Browse Field")
        local tries = 0
        while (not Browse:isOpen() and tries < 10) do
            Self.BrowseField(pos.x, pos.y, pos.z)
            Wait()
            Browse = Container.GetByName("Browse Field")
            tries = tries + 1
        end
        Wait()
        local success = true
        for Spot = Browse:ItemCount() - 1, 0, -1 do
            if Item.isCorpse(Browse:GetItemData(Spot).id) then
                local tries = 0
                while tries < 10 and not (Browse:UseItem(Spot) and (wait(40, 50) or Wait() or true) and Item.isCorpse(Container.GetLast():ID())) do
                    tries = tries + 1
                end
                Wait()
                success = success and tries < 10
                count = count - 1
            end
            if count == 0 then break end
        end
        return success
    end
end
 
if OpenCorpses then
	Module("Open Corpses", function(open)
		local UpdatedCorpses = {}
		for numPos, count in pairs(Corpses) do
			local pos = ToPos(numPos)
			if Self.DistanceFromPosition(pos.x, pos.y, pos.z) <= 1 and (LootFirst or Self.TargetID() == 0) then
				if not OpenCorpse(pos, count) then
					UpdatedCorpses[ToNumber(pos)] = count
				else
					GrabItems(Container.GetLast())
				end
			else
				UpdatedCorpses[ToNumber(pos)] = count
			end
			Corpses = UpdatedCorpses
		end
	end)
end

Module("Loot Corpses", function(loot)
    for _, c in Container.iContainers() do
        if (Item.isCorpse(c:ID()) or IsCorpseByName(c:Name())) and c:isOpen() then
            if GrabItems(c) then 
				Wait() 
				if CloseCorpses then c:Close() end
			end
        end
    end
end)