Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -----------------------------------------------
- -------------------- CONFIG -------------------
- -----------------------------------------------
- LootGold = false
- LootAboveValue = 1000000 -- Will loot any item with an NPC price greater or equal to this.
- LootAboveValueRatio = 50000 -- 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.
- {
- "Glooth Capsule",
- "Tainted Glooth Capsule",
- "Crude Umbral Spellbook",
- "Gold Nugget",
- 4061,
- 11328,
- 10027,
- 22656
- }
- -- You need to open your backpacks on your own. 0 is your main backpack.
- BpStacks = 0
- BpRares = 0
- BpGold = 0 -- Not needed it not looting gold.
- -- Increase these if the script misses loot. Decrease them to increase speed.
- MinWait = 1000
- MaxWait = 1100
- OpenCorpses = 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()
- local ping = 0 --Self.Ping()
- wait(MinWait + ping, MaxWait + ping)
- end
- -- LOOTER
- local Corpses = {}
- local Monsters = {}
- Module("Find Corpses", function(find)
- for _, monster in pairs(Monsters) do
- if not monster:isAlive() and monster:DistanceFromSelf() <= 1 and Self.Position().z == monster:Position().z then
- local posHash = ToNumber(monster:Position())
- Corpses[posHash] = (Corpses[posHash] or 0) + 1
- end
- end
- Monsters = {}
- for _, monster in Creature.iMonsters(7) do
- Monsters[ToNumber(monster:Position())] = monster
- end
- 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 bp isn't full, place it in the last slot.
- if bp:ItemCount() < bp:ItemCapacity() then return bp:Index(), bp:ItemCapacity()-1, (Item.isStackable(id) and 100) or 1 end
- -- If it is full and the item is stackable, try to fit it into an existing slot.
- 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 it's full and we couldn't fit it into an existing slot, try open a new bp.
- 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
- 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", "Split", "dead", "a dead"}
- local function IsCorpseByName(name)
- for _, CPartName in ipairs(CorpseNames) do
- if name:find(CPartName) then
- return true
- end
- end
- return false
- end
- local function CotainerIsCorpse(c)
- return Item.isCorpse(c:ID()) or IsCorpseByName(c:Name())
- 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
- -- 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.
- local success = Self.UseItemFromGround(pos.x, pos.y, pos.z)
- return 0
- else
- -- Open the browse field container
- local Browse = Container.GetByName("Browse Field")
- Self.BrowseField(pos.x, pos.y, pos.z)
- Wait()
- if not Browse:isOpen() then return count end
- -- For each corpse in the browse, loot it
- for Spot = Browse:ItemCount() - 1, 0, -1 do
- if Item.isCorpse(Browse:GetItemData(Spot).id) then
- if not Browse:UseItem(Spot) then
- Browse:Close()
- return count
- end
- wait(40, 50)
- Wait()
- count = count - 1
- end
- if count == 0 then break end
- end
- Browse:Close()
- return 0
- 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 Self.Position().z == pos.z then
- local remaining = OpenCorpse(pos, count)
- if remaining > 0 then
- UpdatedCorpses[numPos] = remaining
- else
- GrabItems(Container:GetLast())
- end
- else
- UpdatedCorpses[numPos] = count
- end
- end
- Corpses = UpdatedCorpses
- end)
- end
- Module("Loot Corpses", function(loot)
- local Browse = Container.GetByName("Browse Field")
- for _, c in Container.iContainers() do
- if (Item.isCorpse(c:ID()) or IsCorpseByName(c:Name())) and c:isOpen() then
- if GrabItems(c) then
- Wait()
- c:Close()
- Browse:Close()
- end
- end
- end
- end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement