Hello. I decided to share my little library, containing some useful functions for both scripters and common users. The functions are not documented well (if at all), but their usage should be pretty obvious.
Note: I'm overriding the current opendepot function, you should comment it out at the end of the code if you want to use the original from Lucas Terra's library Note2: If you want to keep my version, however, you must save the library as e.g. xColandus.lua, to make sure it's loaded last!
local sphereItems = {"emerald", "amethyst", "ruby", "sapphire"}
------------------------------
-- Tibia specific functions --
------------------------------
-- Returns true if an NPC can be found near you (distance and name are optional).
function NPCAround(distance, name)
distance = distance or 3
foreach creature m 'ns' do
if(m.dist <= distance and (not name or m.name:lower() == name:lower())) then
return true
end
end
return false
end
-- Sell items by looting category.
function sellLootItems(category)
if(not NPCAround(3)) then
return
end
try($tradeopen, opentrade)
foreach lootingitem m category do
while(tradecount('sell', m.id) > 0) do
sellitems(m.id, tradecount('sell', m.id))
waitping(1.8, 2.3)
end
end
end
-- Check if at least one of specified items can be found on given position.
function isItemsOnPos(x, y, z, ...)
local args = {...}
local tile = gettile(x, y, z)
for i=1, tile.itemcount do
if(table.find(args, tile.item[i].id)) then
return tile.item[i].id
end
end
return false
end
-- Check if there is a depot around you.
function depotAround()
for x = -1, 1 do
for y = -1, 1 do
if(not(x == 0 and y == 0)) then
local posX = $posx + x
local posY = $posy + y
if(isItemsOnPos(posX, posY, $posz, unpack(depotIDs))) then
return posX, posY, $posz
end
end
end
end
return false
end
-- Get position of nearest item with specific id
function getClosestItemPosition(...)
local closestDistance, closestPos = -1
for X_OFFSET = SCREEN_LEFT, SCREEN_RIGHT do
for Y_OFFSET = SCREEN_TOP, SCREEN_BOTTOM do
if(not(x == 0 and y == 0)) then
local posX = $posx + X_OFFSET
local posY = $posy + Y_OFFSET
local item = isItemsOnPos(posX, posY, $posz, ...)
if(item) then
local distance = math.abs(X_OFFSET) + math.abs(Y_OFFSET)
if(closestDistance == -1 or distance < closestDistance or (distance == closestDistance and math.random(1, 2) == 2)) then
closestDistance = distance
closestPos = {posX, posY, $posz, item}
end
end
end
end
end
if(not closestPos) then
return
end
return unpack(closestPos)
end
-- Will rope up on closest rope hole, if no position specified.
function ropeUp(x, y, z)
if(not (x and y and z)) then
x, y, z = getClosestItemPosition(unpack(ropeHoleIDs))
if(not x) then
return false
end
end
local rope = getsetting('Cavebot/Rope')
useitemon(itemid(rope), 0, ground(x, y, z))
waitping(1.3, 1.7)
return true
end
-- Will use closest ladder, if no position specified.
function useLadder(x, y, z, itemid)
if(not (x and y and z)) then
x, y, z, itemid = getClosestItemPosition(unpack(stairIDs))
if(not x) then
return false
end
end
useitem(itemid or 0, ground(x, y, z))
waitping(1.3, 1.7)
return true
end
function openClosestDoor()
local x, y, z = getClosestItemPosition(unpack(doorIDs))
if(x) then
useitem(0, ground(x, y, z))
end
end
function clearTile(x, y, z)
local id = topitem(x, y, z).id
while(not itemproperty(id, ITEM_NOTMOVEABLE)) do
moveitems(id, ground($posx, $posy, $posz), ground(x, y, z), 100)
waitping(1.5, 2)
id = topitem(x, y, z).id
end
end
local breakableWoodenBars = {2295, 2296}
function breakWoodenBars()
local x, y, z = getClosestItemPosition(unpack(breakableWoodenBars))
if(not x) then
return false
end
local _, weapon = findweapontouse()
clearTile(x, y, z)
repeat
reachlocation(x, y, z)
waitping(1, 1.7)
useitemon(weapon, 0, ground(x, y, z))
waitping(1, 1.7)
until not isItemsOnPos(x, y, z, unpack(breakableWoodenBars))
return true
end
-- TODO: Enable walk through first, for those who don't use it...
-- Moves to closest depot despite if it's not top item
function moveToDepot()
while not depotAround() do
local closestX, closestY, closestZ = getClosestItemPosition(depotTileID)
if(closestX) then
moveto(closestX, closestY, closestZ)
end
waitping(1, 1.7)
end
end
-- Tries different methods of opening depot
function safeOpenDepot(forceBrowse)
local dpX, dpY, dpZ = depotAround()
if(not dpX) then
return
end
if(table.find(depotIDs, topitem(dpX, dpY, dpZ).id)) then
openitem("depot")
waitcontainer("Locker", false)
openitem(3502, "Locker", false)
waitcontainer("Depot Chest", false)
return
end
if(not forceBrowse) then
local tile = gettile(dpX, dpY, dpZ)
local count = tile.itemcount
if(count <= (5 + 3)) then
local expectedCount = count
repeat
if(tile.itemcount > expectedCount) then
break
end
openitem(0, "Locker", false, 0)
waitcontainer("Depot Chest", false)
end
end
function isBackpackOpen(bptype)
for i = 0, windowcount() - 1 do
local bpname = getcontainer(i).name:lower()
if(bptype:lower() == bpname) then
return true
end
end
return false
end
-- Use Sphere Machine in edron, with specified pearls.
-- usage: useSphereMachine("emerald")
function useSphereMachine(itemName)
for _, sphereItem in ipairs(sphereItems) do
if(itemName:match(sphereItem)) then
itemName = "small enchanted " .. sphereItem
break
end
end
local machineX, machineY, machineZ = 33269, 31830, 10
local machineActiveId = 847
local machineInactiveId = 843
local itemsNeeded = 20
local itemAmount = itemcount(itemName)
if(itemAmount < itemsNeeded) then
printerror('Insufficient amount of "' .. itemName .. 's"')
return
end
repeat
if(topitem(machineX, machineY, machineZ).id == machineActiveId) then
useitem(machineActiveId, ground(machineX, machineY, machineZ))
waitping()
end
useitemon(itemid(itemName), machineInactiveId, ground(machineX, machineY, machineZ))
waitping()
until (itemAmount - itemcount(itemName)) >= itemsNeeded or itemcount(itemName) == 0
while(topitem(machineX, machineY, machineZ).id == machineActiveId) do
useitem(machineActiveId, ground(machineX, machineY, machineZ))
waitping()
end
useitem(machineInactiveId, ground(machineX, machineY, machineZ))
end
function doStick()
if(not STICK_ENABLED) then
return false
end
local stickX, stickY, stickZ = unpack(STICK_POSITION)
if(tilereachable(stickX, stickY, stickZ)) then
local stickRadiusX, stickRadiusY = unpack(STICK_RADIUS)
if($posx < (stickX - stickRadiusX) or $posx > (stickX + stickRadiusX) or
$posy < (stickY - stickRadiusY) or $posy > (stickY + stickRadiusY) or
$posz ~= stickZ) then
moveto(stickX, stickY, stickZ)
wait(300, 450)
return true
end
end
return false
end
function stick(radiusX, radiusY)
STICK_POSITION = {$wptx, $wpty, $wptz}
STICK_RADIUS = {radiusX or 0, radiusY or 0}
STICK_ENABLED = true
end
function unstick()
STICK_POSITION = {0, 0, 0}
STICK_RADIUS = {0, 0}
STICK_ENABLED = false
end
------------------------------
-- Overridden functions --
------------------------------
-- NOTE: Requires library --
-- to be loaded LAST --
-- by naming it e.g. --
-- xColandus.lua --
------------------------------
-- Don't use this if you want Lucas Terra's version.
function opendepot()
moveToDepot()
safeOpenDepot()
end
-- Will make sure an NPC is near you before attempting to talk to it.
_npctalk = _npctalk or npctalk
function npctalk(...)
if(not NPCAround()) then
return
end
_npctalk(...)
end
03-18-2014, 06:57 PM
Leonardo
Cool boy, but try don't overriding existing functions. (Actually table.find will fuck up fishing scripts)
03-18-2014, 07:03 PM
mistgun
I like it, especially Npcaround func :D! Keep em coming here :]
03-18-2014, 07:17 PM
Colandus
Quote:
Originally Posted by Leonardo
Cool boy, but try don't overriding existing functions. (Actually table.find will fuck up fishing scripts)
Yeah I'll remove it, should work fine with current.
03-18-2014, 10:42 PM
Leonardo
Quote:
Originally Posted by Colandus
Yeah I'll remove it, should work fine with current.
Both npctalk and opendepot should be removed too, not that they are wrong, but ppl may want to spam it, and your code will avoid that. Also Raphael will be pissed off with that.
03-19-2014, 12:13 AM
Colandus
Quote:
Originally Posted by Leonardo
Both npctalk and opendepot should be removed too, not that they are wrong, but ppl may want to spam it, and your code will avoid that. Also Raphael will be pissed off with that.
What do you mean may want to spam it? :o It won't hurt anyone as it will only prevent it from not talking if there are no NPCs close enough! As for opendepot, I don't think it's a big issue. Both mine and Lucas' version should function properly and almost the same... Also if the lib is saved as Colandus.lua their functions will override mines anyway.
03-19-2014, 12:46 AM
Leonardo
Quote:
Originally Posted by Colandus
What do you mean may want to spam it? :o It won't hurt anyone as it will only prevent it from not talking if there are no NPCs close enough! As for opendepot, I don't think it's a big issue. Both mine and Lucas' version should function properly and almost the same... Also if the lib is saved as Colandus.lua their functions will override mines anyway.
I meant spam npctalk for example, even if there's not any NPC around. But yes they will override, but if someone paste your code on an action ? It'll run like I said and the user won't be able to spam it. And the opendepot function is already good enough and try the necessary times to reach and open it.
03-19-2014, 02:29 AM
Raphael
@Leonardo, Why do you guys always think I'll be mad at everything? I'm zen.
@Colandus
It's cool to override functions and I don't mind if you do that to mine, but avoid breaking backwards compatibility; everything that was already working should keep working. If that can't be hold, then you'd be better of writing a function with a different name. This really isn't the case for npctalk here, since I don't think anyone would want to talk to a NPC that isn't there. Actually, I might, if you allow me, add that check on my code directly. Now, as for opendepot, it seems that you completely rewrote it to work on a completely different fashion. Especially since all it does is call two other functions, this really doesn't seem necessary.
Anyway, keep up the good work, you know you rock.
03-19-2014, 02:40 AM
Leonardo
Quote:
Originally Posted by Raphael
Leonardo, Why do you guys always think I'll be mad at everything? I'm zen.
It's your standard behave.
03-19-2014, 11:28 AM
Colandus
Quote:
Originally Posted by Raphael
@Leonardo, Why do you guys always think I'll be mad at everything? I'm zen.
@Colandus
It's cool to override functions and I don't mind if you do that to mine, but avoid breaking backwards compatibility; everything that was already working should keep working. If that can't be hold, then you'd be better of writing a function with a different name. This really isn't the case for npctalk here, since I don't think anyone would want to talk to a NPC that isn't there. Actually, I might, if you allow me, add that check on my code directly. Now, as for opendepot, it seems that you completely rewrote it to work on a completely different fashion. Especially since all it does is call two other functions, this really doesn't seem necessary.
Anyway, keep up the good work, you know you rock.
About opendepot, I actually wrote that function when WindBot's opendepot was very basic, but it's not a "completely different fashion". Basically, in Lucas' lib opendepot will contains the code to reach and open a depot, whereas I however wanted a separate function to reach depot and the one to open it, in case someone (or me) might need to use them at some point separately. My method of opening the depot does contain an additional step indeed, because I favor realistic behavior, therefore it will attempt to untrash the depot if there are only a few items on top of it.
And yes, you can go ahead and add that code to your npctalk function!