Documentation › Lua
Game events
An event calls one of your functions when something happens: someone speaks in chat, an effect shows on the screen, you press a key, the CaveBot reaches a label. This way the script reacts right away, without checking in a loop.
How to register#
Game.registerEvent(event, function) binds the function to the event and returns the function itself. Game.unregisterEvent(event, function) unbinds it. Keep the function in a variable if you want to unbind it later. A script can have several functions on the same event: all of them are called, in the order they were registered.
-- Registers, uses and unbinds an event
local function onTalk(name, level, mode, x, y, z, text)
print(name .. ": " .. text)
end
Game.registerEvent(Game.Events.TALK, onTalk)
-- 60 s later, stops listening to the chat
Timer.new("stop", function()
Game.unregisterEvent(Game.Events.TALK, onTalk)
destroyTimer("stop")
end, 60000)-- The same code runs on ZeroBot and on DrenoxBot.
-- Here wait() does not block events: they keep arriving while it waits.
Game.registerEvent(Game.Events.TEXT_MESSAGE, function(msg)
if msg.messageType == Enums.MessageTypes.MESSAGE_LOOT then
print(msg.text)
end
end)
while true do
wait(1000)
endHow events arrive#
- Each script runs on its own thread. Events go into a queue and run on that thread, one at a time, so two events of the same script never run at the same time.
- The bot only sends an event to a script that has a function registered on it. HUD and window click events go only to the script that created the HUD or the window.
- An error inside the function shows in the Console as
event <number>: <error>and the script keeps running. wait(ms)does not block events: while the script waits, the queued events and timers keep running.
Summary#
| Event | Number | When it fires |
|---|---|---|
TALK | 0 | Someone speaks (Default, channels, PM, NPC) |
MAGIC_EFFECT | 1 | A magic effect shows on a tile |
HUD_CLICK | 2 | You click a HUD of the script |
HOTKEY_SHORTCUT_PRESS | 3 | You press a key with the client in focus |
TEXT_MESSAGE | 4 | The server sends a text message (loot, damage, warnings...) |
MODAL_WINDOW | 5 | The server opens a window with buttons |
CUSTOM_MODAL_WINDOW_BUTTON_CLICK | 6 | You click a button in a window of the script |
QUEST_LOG | 9 | The quest list arrives |
QUEST_LINES | 10 | The missions of a quest arrive |
DISTANCE_SHOOT_EFFECT | 11 | A projectile flies from one tile to another |
LABEL | 13 | The CaveBot reaches a Label waypoint |
OPEN_STASH | 14 | The server sends the stash contents |
HUD_DRAG | 15 | You drag a HUD of the script |
ALARM | 20 | An alarm from the Tools tab fires |
CREATURE_HEALTH | 100 | A creature's HP changes (DrenoxBot extra) |
PLAYER_DATA | 101 | Your HP and mana data arrives (DrenoxBot extra) |
TALK#
Fires for every speech message the server sends: Default, yell, whisper, channels, PMs and NPC speech.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | name | text | Who spoke (empty if the server does not send it) |
| 2 | level | number | Level of who spoke (0 if not sent) |
| 3 | mode | number | Speech type, as in Enums.TalkTypes |
| 4 | x | number | Position of who spoke (0 when the speech has no position, as in PM and channel) |
| 5 | y | number | |
| 6 | z | number | |
| 7 | text | text | What was said |
| 8 | channel | number | Channel id (0 outside a channel) |
-- Flashes the window when someone says your name
Game.registerEvent(Game.Events.TALK, function(name, level, mode, x, y, z, text)
if text:lower():find(Player.getName():lower(), 1, true) then
print(name .. " (" .. level .. "): " .. text)
Client.flashWindow()
end
end)MAGIC_EFFECT#
Fires for each magic effect (not projectile) the server draws on a tile.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | id | number | Effect id |
| 2 | x | number | Effect position |
| 3 | y | number | |
| 4 | z | number |
-- Shows in the Console the effects around you
Game.registerEvent(Game.Events.MAGIC_EFFECT, function(id, x, y, z)
local p = Player.getPosition()
if z == p.z and math.abs(x - p.x) <= 1 and math.abs(y - p.y) <= 1 then
print("effect " .. id .. " at " .. x .. "," .. y)
end
end)HUD_CLICK#
Fires when you click a HUD created by the script. Only the script that owns the HUD receives it. Before the registered functions, the bot calls the HUD's own callback (hud:setCallback), if there is one.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | hudId | number | Id of the clicked HUD (the same as hud:getId()) |
local button = HUD.new(20, 100, "[ CaveBot ]")
Game.registerEvent(Game.Events.HUD_CLICK, function(hudId)
if hudId == button:getId() then
Engine.enableCaveBot(not Engine.isCaveBotEnabled())
end
end)HOTKEY_SHORTCUT_PRESS#
Fires when a key is pressed (not while it is held) and the client window is in focus. Modifier keys alone (Ctrl, Alt, Shift, Win, Num Lock) do not fire it: they only go into the mask.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | key | number | Windows virtual key code (A = 65, F1 = 112...) |
| 2 | modifiers | number | Sum of Enums.FlagModifiers: Ctrl 1, Alt 2, Shift 4, Num Lock on 8 |
local ok, mods, key = HotkeyManager.parseKeyCombination("Ctrl+F5")
Game.registerEvent(Game.Events.HOTKEY_SHORTCUT_PRESS, function(k, m)
if k == key and bit.band(m, 7) == mods then
Engine.enableTargeting(not Engine.isTargetingEnabled())
end
end)TEXT_MESSAGE#
Fires for every text message from the server: loot, damage, healing, experience, green and red warnings, look.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | message | table | The fields below |
| Field | Type | Description |
|---|---|---|
messageType | number | Message type, as in Enums.MessageTypes |
text | text | The text |
channelId | number | Message channel |
position | table or nil | {x, y, z} when the message has a position (damage, healing) |
value | number | First value (damage, healing, xp) |
secondValue | number | Second value |
color | number | Color of the first value |
secondColor | number | Color of the second value |
-- Adds up the damage taken
local total = 0
Game.registerEvent(Game.Events.TEXT_MESSAGE, function(msg)
if msg.messageType == Enums.MessageTypes.MESSAGE_DAMAGE_RECEIVED then
total = total + (msg.value or 0)
print("total damage: " .. total)
end
end)MODAL_WINDOW#
Fires when the server opens a window with buttons and choices (NPCs, quests, OT systems). Answer with Game.modalWindowAnswer.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | window | table | The fields below |
| Field | Type | Description |
|---|---|---|
id | number | Window id, for Game.modalWindowAnswer |
title | text | Title |
message | text | Window text |
buttons | list | Buttons {id, text} |
choices | list | List options {id, text} |
defaultEnterButton | number | Enter button |
defaultEscapeButton | number | Esc button |
priority | boolean | Whether the window has priority |
-- Presses "Yes" on every window that has that button
Game.registerEvent(Game.Events.MODAL_WINDOW, function(window)
for _, b in ipairs(window.buttons) do
if b.text == "Yes" then
Game.modalWindowAnswer(window.id, b.id, 0)
end
end
end)CUSTOM_MODAL_WINDOW_BUTTON_CLICK#
Fires when you click a button in a window created by the script with CustomModalWindow. The window closes with the click. Only the owner script receives it, and the window's callback (setCallback) is called first.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | windowId | number | Window id (window:getId()) |
| 2 | button | number | Button index, starting at 0, in addButton order |
local window = CustomModalWindow.new("Refill", "Go back to town?")
window:addButton("Yes") -- 0
window:addButton("No") -- 1
Game.registerEvent(Game.Events.CUSTOM_MODAL_WINDOW_BUTTON_CLICK, function(id, button)
if id == window:getId() and button == 0 then
CaveBot.GoTo("refill")
end
end)QUEST_LOG#
Fires when the server sends the quest list, for example after Game.requestQuestLog().
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | quests | list | One table per quest: id, name, completed (boolean) and state (1 completed, 0 pending, as Enums.QuestState) |
Game.registerEvent(Game.Events.QUEST_LOG, function(quests)
for _, q in ipairs(quests) do
if not q.completed then print("pending: " .. q.name) end
end
end)
Game.requestQuestLog()QUEST_LINES#
Fires when the server sends the missions of a quest, for example after Game.requestQuestLines(id).
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | questId | number | Quest id |
| 2 | missions | list | One table per mission: id, name, description |
Game.registerEvent(Game.Events.QUEST_LINES, function(questId, missions)
for _, m in ipairs(missions) do
print(m.name .. ": " .. m.description)
end
end)DISTANCE_SHOOT_EFFECT#
Fires for each projectile (arrow, rune, distance spell) the server draws.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | id | number | Projectile id |
| 2 | fromX | number | Start position |
| 3 | fromY | number | |
| 4 | fromZ | number | |
| 5 | toX | number | End position |
| 6 | toY | number | |
| 7 | toZ | number |
-- Warns when a projectile lands on your tile
Game.registerEvent(Game.Events.DISTANCE_SHOOT_EFFECT, function(id, fx, fy, fz, tx, ty, tz)
local p = Player.getPosition()
if tx == p.x and ty == p.y and tz == p.z then
print("projectile " .. id .. " on you")
end
end)LABEL#
Fires when the CaveBot reaches a Label waypoint, and only if some script has a function registered on this event. The CaveBot pauses before sending the event and stays stopped until a script calls CaveBot.pause(0). If the script that registered the event stops, the pause ends by itself.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | index | number | Waypoint position in the route, starting at 0 |
| 2 | label | text | Label text |
-- At label "check": under 50 mana potions, go to label "refill"
Game.registerEvent(Game.Events.LABEL, function(index, label)
if label == "check" and Game.getItemCount(268) < 50 then -- 268 = mana potion
CaveBot.GoTo("refill")
end
CaveBot.pause(0) -- releases the route
end)OPEN_STASH#
Fires when the server sends the contents of your stash (supply stash).
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | stash | table | stashItems: list of {itemId, count}; freeSlots: free slots |
Game.registerEvent(Game.Events.OPEN_STASH, function(stash)
for _, item in ipairs(stash.stashItems) do
print(item.itemId .. " x" .. item.count)
end
end)HUD_DRAG#
Fires when you drop a draggable HUD (hud:setDraggable(true)) of the script at a new position. The HUD's position is already updated when the event arrives.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | hudId | number | HUD id |
| 2 | x | number | New x position |
| 3 | y | number | New y position |
local hud = HUD.new(20, 60, "Drag me")
hud:setDraggable(true)
Game.registerEvent(Game.Events.HUD_DRAG, function(id, x, y)
if id == hud:getId() then print("HUD now at " .. x .. ", " .. y) end
end)ALARM#
Fires together with an alarm from the Tools tab (the same one that shows in the Console as [ALARM]). If alarms are turned off with Engine.allAlarmsEnable(false), the event does not fire either.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | type | number | Which alarm, as in Enums.AlarmType |
| Type | When |
|---|---|
DISCONNECTED (0) | You disconnected |
DAMAGE_TAKEN (1) | You took damage (at most every 3 s) |
LOW_HEALTH (2) | HP dropped below the configured limit |
PRIVATE_MESSAGE (3) | A PM arrived |
MONSTER_DETECTED / MONSTER_ON_SCREEN (4 / 5) | A monster showed up on the map / on your floor |
PLAYER_ATTACK (6) | A player attacked you |
PLAYER_DETECTED / PLAYER_ON_SCREEN (7 / 8) | A player outside the party showed up |
PLAYER_STUCK (9) | The CaveBot is on and you have not moved |
SKULL_DETECTED / SKULL_ON_SCREEN (10 / 11) | A player with a skull showed up |
ENEMY_DETECTED / ENEMY_ON_SCREEN (12 / 13) | An enemy (guild or list) showed up |
GM_DETECTED (14) | A GM showed up |
LOW_CAP (15) | Cap dropped below the limit |
PLAYER_IDLE (16) | You stood still without gaining xp for the configured time |
Game.registerEvent(Game.Events.ALARM, function(alarmType)
if alarmType == Enums.AlarmType.PLAYER_ON_SCREEN then
Engine.enableCaveBot(false)
Sound.play("alarm.wav", true)
end
end)CREATURE_HEALTH#
DrenoxBot extra (does not exist in ZeroBot). Fires when the server sends a creature's new HP.
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | creatureId | number | Creature id |
| 2 | hp | number | HP in percent (0 to 100) |
local hud = HUD.new(20, 60, "Target: -")
Game.registerEvent(Game.Events.CREATURE_HEALTH, function(id, hp)
if id == Player.getTargetId() then
hud:setText(Creature.new(id):getName() .. " " .. hp .. "%")
end
end)PLAYER_DATA#
DrenoxBot extra (does not exist in ZeroBot). Fires every time the server sends the packet with your status data (HP, mana, cap, level...).
| # | Parameter | Type | Description |
|---|---|---|---|
| 1 | health | number | Current HP |
| 2 | maxHealth | number | Max HP |
| 3 | mana | number | Current mana |
| 4 | maxMana | number | Max mana |
Game.registerEvent(Game.Events.PLAYER_DATA, function(hp, maxHp, mana, maxMana)
if hp < maxHp * 0.3 then
Client.showMessage("Low HP!")
end
end)ZeroBot events that do not fire yet#
Game.Events has all of ZeroBot's names, so registering the events below does not raise an error. But DrenoxBot does not fire any of them yet: the function stays registered and is never called.
| Event | Number |
|---|---|
IMBUEMENT_DATA | 7 |
IMBUEMENT_OPEN_WINDOW | 8 |
PARTY_HUNT | 12 |
STORE_CATEGORIES | 16 |
STORE_OFFERS | 17 |
OPEN_DAILY_REWARD | 18 |
DAILY_REWARD_DAYS_DATA | 19 |
TASK_HUNTING_DATA | 21 |
TASK_BOARD_DATA | 22 |
See also: Scripting and the function reference.
Comments
to comment.