Like the Lua scripts of the classic Tibia bots, but in JavaScript. Write a few lines in the Scripts tab and the bot runs them every few seconds: it reads your character and the screen, casts, uses items, attacks, walks, talks to NPCs and buys, or decides who the Target attacks and what the Loot takes.
How it works
- Open the bot, go to Scripts and press + New script, or start from one of the examples below.
- Each script runs again at the interval you choose (from 0.1 s). Turn it on with its switch, and turn the Scripts module on. While a script is on, its code is read-only: turn it off to edit it. What log() writes shows in the Console under the code (Edit).
- Scripts are saved in your profile: when you share, send or sell a profile, its scripts go with it, and whoever gets it can read and edit them. Scripts that come in a profile from someone else arrive off and blocked: they don’t run in any way (not on their own, not with Run now, not from a Script waypoint of the Cavebot) until you press Allow… in the Scripts module. Be careful: a malicious script can sell or drop your items, walk your character into monsters, log you out or talk for you. Read the code (Edit) and allow only scripts you understand, from people you trust.
- An action returns true when the bot does it and false when it can't; why() tells you why. Each script does one game action per tick: put await wait(ms) between the steps of a sequence.
Safe by design
Scripts run in a closed box inside the bot and can only use the functions on this page. They can't see the game page, your passwords or the internet, and a script stuck in a loop is stopped on its own. Every action goes through the same paths as the rest of the bot.
Your first script
Heal under 60% life, put the magic shield on when a player shows up, and write what is happening in the script's console:
if (player.hpPercent < 60) cast("exura vita")
if (players().length > 0 && !player.magicShield) cast("utamo vita")
log("HP", player.hp, "monsters", monsters().length)They are in the bot too: Scripts → + From an example.
Train magic level (utevo lux)
runs every 2 s
if (player.manaPercent >= 95 && !player.inPz && monsters().length === 0) {
cast("utevo lux")
}Magic shield when a PK shows up
runs every 0.5 s
const pk = players().find((p) => p.skull === "white" || p.skull === "red" || p.skull === "black")
if (pk && !player.magicShield) {
cast("utamo vita")
}Heal a friend with exura sio
runs every 0.5 s
const friend = findCreature("Friend Name")
if (friend && friend.hpPercent < 60 && distance(friend) <= 7) {
cast('exura sio "' + friend.name + '"')
}Alarm on low capacity
runs every 5 s
if (player.cap !== null && player.cap < 50) {
alarm()
log("Capacity:", player.cap)
}Hit the weakest monster first
runs every 0.5 s
const weakest = monsters()
.filter((m) => m.distance <= 6 && m.hpPercent !== null)
.sort((a, b) => a.hpPercent - b.hpPercent)[0]
if (weakest && (!target || target.id !== weakest.id)) {
attack(weakest)
}Haste when no monster is around
runs every 1 s
if (!player.hasted && !player.inPz && monsters().length === 0) {
cast("utani hur")
}Pause the Cavebot on few mana fluids
runs every 2 s
const VIAL = 2874
const MANA = 7
if (itemCount(VIAL, MANA) < 20) {
pause("cavebot")
warn("Few mana fluids:", itemCount(VIAL, MANA))
} else {
resume("cavebot")
}Talk to an NPC (step by step)
runs every 60 s
say("hi")
await wait(2000)
say("trade")
await wait(1500)
log("Trade window should be open now")Target: skip some, weak ones first
runs every 60 s
const NEVER = ["Rabbit", "Deer"]
onAttack((monster) => {
if (NEVER.includes(monster.name)) return false
if (monster.hpPercent !== null && monster.hpPercent < 30) return 10
if (monster.attackingMe) return 5
})Loot: skip cheap items, always take some
runs every 60 s
const ALWAYS = ["dragon ham", "platinum coin"]
onLoot((item) => {
if (ALWAYS.includes(item.name)) return true
if (item.value !== null && item.value < 50) return false
})Go refill on low supplies
runs every 60 s
const MANA_FLUIDS = itemCount(2874, 7)
if (player.cap < 100 || MANA_FLUIDS < 50) {
log("Going to refill. Cap:", player.cap, "mana fluids:", MANA_FLUIDS)
gotoLabel("Refill")
}Buy mana fluids up to 100
runs every 60 s
const WANT = 100
const have = itemCount(2874, 7)
if (have >= WANT) return
say("hi")
await wait(1500)
say("trade")
if (!(await waitUntil(() => trade, 3000))) {
warn("The shop did not open")
return
}
if (!(await buy(2874, WANT - have, 7))) warn("Could not buy:", why())
closeTrade()Sell loot to the NPC
runs every 60 s
const SELL = ["plate armor", "battle shield", "dwarven shield"]
say("hi")
await wait(1500)
say("trade")
if (!(await waitUntil(() => trade, 3000))) {
warn("The shop did not open")
return
}
for (const name of SELL) {
const item = findItem(name)
if (!item) continue
if (!(await sell(item.id, itemCount(item.id)))) warn("Could not sell", name + ":", why())
}
closeTrade()Stop hunting, log out after 2 h
runs every 10 s
const HOURS = 2
storage.start = storage.start || now
if (now - storage.start >= HOURS * 3600000) {
pause("cavebot")
pause("target")
if (!storage.warned) {
warn("Hunt time is over")
alarm()
storage.warned = true
}
if (!player.inBattle && !player.pzLocked) logout()
}Alarm on a private message
runs every 1 s
for (const m of messages()) {
if (m.type === "private") {
alarm()
warn("Private message from", m.from)
}
}Pause the Cavebot near players
runs every 1 s
const near = players().filter((p) => p.distance <= 4 && !p.party)
if (near.length > 0) {
pause("cavebot")
} else {
resume("cavebot")
}Kills per hour
runs every 60 s
storage.start = storage.start || now
storage.kills = storage.kills || 0
for (const m of messages()) {
if (m.type === "loot") storage.kills += 1
}
const hours = (now - storage.start) / 3600000
log("Kills:", storage.kills, "per hour:", hours > 0 ? Math.round(storage.kills / hours) : 0)Area spell on 3 monsters around
runs every 0.5 s
const SPELL = "exori"
const close = monsters().filter((m) => m.distance <= 1)
if (close.length >= 3 && canCast(SPELL)) {
cast(SPELL)
}