Home API Manuals About Forum
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Events

What Are Events / Что такое события

Events allow handling incoming game data (packets, timers, messages) in a decentralized way — independently from the main script logic.

For example: while your crafting macro runs, an anti-macro gump may appear. Without events, you would need to check for the gump at every step. With events, the gump is handled by a separate handler function automatically.

Another common use: monitoring connection state, reacting to incoming speech, tracking buff/debuff changes — all without polluting the main script loop with checks.

События позволяют обрабатывать входящие игровые данные (пакеты, таймеры, сообщения) децентрализованно — независимо от основной логики скрипта.

Например: пока работает макрос крафта, может появиться антимакро-гамп. Без событий пришлось бы проверять наличие гампа на каждом шаге. С событиями гамп обрабатывается отдельной функцией автоматически.

Другие типичные применения: мониторинг состояния подключения, реакция на входящую речь, отслеживание бафов/дебафов — всё это без засорения основного цикла проверками.


How Events Work / Как работают события

Event handlers are not executed in parallel. They are called from within the Wait method (and WaitForEvent in Python). When an event fires, it is added to an internal queue and executed in the script one by one during the next Wait call.

Important rules:

  • Never put heavy operations in event handlers: no movement (MoveXY), no waiting (WaitForTarget), no long loops. Only lightweight and fast code.
  • Events are available for all internal (Pascal) and external (Python) scripts. They work the same everywhere.
  • Events triggered by network packets require an active connection. No connection → no packets → no packet-based events. Timer events (evTimer1, evTimer2) are internal and do not depend on packets.

Обработчики событий выполняются не параллельно. Они вызываются изнутри метода WaitWaitForEvent в Python). При наступлении события оно добавляется во внутреннюю очередь и выполняется в скрипте по одному во время следующего вызова Wait.

Важные правила:

  • Никогда не размещайте тяжёлые операции в обработчиках: никакого перемещения (MoveXY), ожидания (WaitForTarget), длинных циклов. Только лёгкий и быстрый код.
  • События доступны для всех внутренних (Pascal) и внешних (Python) скриптов. Работают одинаково везде.
  • События от сетевых пакетов требуют активного подключения. Нет подключения → нет пакетов → нет пакетных событий. Таймерные события (evTimer1, evTimer2) — внутренние и не зависят от пакетов.

Pascal Usage / Использование в Pascal

Register a handler with SetEventProc:

SetEventProc(evSpeech, 'OnSpeech');

Unregister by passing an empty string:

SetEventProc(evSpeech, '');

If a handler is already registered for an event and you set a different one without clearing first, a warning is logged. Always unregister the old handler before setting a new one.

Зарегистрируйте обработчик через SetEventProc:

SetEventProc(evSpeech, 'OnSpeech');

Снятие обработчика — передайте пустую строку:

SetEventProc(evSpeech, '');

Если обработчик уже назначен и вы устанавливаете другой без предварительного снятия — выводится предупреждение. Всегда снимайте старый обработчик перед установкой нового.


Python Usage / Использование в Python

Python offers two modes for working with events.

В Python есть два режима работы с событиями.

Callback Mode (classic) / Режим callback (классический)

Register a handler function via SetEventProc. The handler is called automatically during Wait.

Зарегистрируйте функцию-обработчик через SetEventProc. Обработчик вызывается автоматически во время Wait.

def speech_handler(text, sender_name, sender_id):
    AddToSystemJournal(f'Speech {sender_name}({sender_id}): {text}')

SetEventProc(EventType.EvSpeech, speech_handler)

while True:
    Wait(100)

Unregister by calling without callback:

SetEventProc(EventType.EvSpeech)

If the callback accepts fewer parameters than the event provides, extra arguments are silently truncated. For example, a handler def on_speech(text): will work for evSpeech — only the first argument (text) will be passed.

Если callback принимает меньше параметров, чем предоставляет событие, лишние аргументы отбрасываются. Например, обработчик def on_speech(text): будет работать для evSpeech — передастся только первый аргумент (text).

Polling Mode (new) / Режим polling (новый)

Subscribe to events via SetEventCallback, then poll with WaitForEvent. No callback function needed.

Подпишитесь на события через SetEventCallback, затем опрашивайте через WaitForEvent. Callback-функция не нужна.

SetEventCallback(EventType.EvSpeech)
SetEventCallback(EventType.EvItemInfo)

while True:
    event = WaitForEvent(100)
    if event:
        print(event)

WaitForEvent(timeout_ms) returns a StealthEvent object or None on timeout. If timeout_ms is 0 or omitted — waits indefinitely.

WaitForEvent(timeout_ms) возвращает объект StealthEvent или None при таймауте. Если timeout_ms равен 0 или не указан — ожидание бесконечное.

Unsubscribe:

ClearEventCallback(EventType.EvSpeech)

Event Type Specification / Указание типа события

SetEventProc accepts event type as:

  • EventType enum: EventType.EvSpeech
  • String: 'EvSpeech' (case-insensitive)
  • Integer: 2

SetEventCallback / ClearEventCallback accept EventType enum or integer only.

SetEventProc принимает тип события как:

  • Перечисление EventType: EventType.EvSpeech
  • Строку: 'EvSpeech' (регистронезависимо)
  • Целое число: 2

SetEventCallback / ClearEventCallback принимают только перечисление EventType или целое число.

Typed Event Objects / Типизированные объекты событий

WaitForEvent returns typed dataclass objects for many event types. Each has an id field (EventType), an arguments list (raw values), and named fields for convenience:

WaitForEvent возвращает типизированные dataclass-объекты для многих типов событий. Каждый содержит поле id (EventType), список arguments (сырые значения) и именованные поля для удобства:

@dataclass
class StealthEvent:            # base: id, arguments[]
class SpeechEvent:             # text, sender_name, serial
class ItemInfoEvent:           # serial
class ItemDeletedEvent:        # serial
class DrawObjectEvent:         # serial
class DrawContainerEvent:      # serial, graphic_id
class AddItemToContainerEvent: # serial, container_serial
class AddMultipleItemsInContEvent: # container_serial
class RejectMoveItemEvent:     # reason
class IncomingGumpEvent:       # serial, gump_id, x, y
class MenuEvent:               # serial, menu_id
class ContextMenuEvent:        # serial
class SoundEvent:              # sound_id, x, y, z
class CharAnimationEvent:      # serial, action
class MoveRejectionEvent:      # x_src, y_src, direction, x_dst, y_dst

Events without a typed subclass are returned as base StealthEvent with raw values in arguments[].

События без типизированного подкласса возвращаются как базовый StealthEvent с сырыми значениями в arguments[].


Event Reference / Справочник событий

evItemInfo

Incoming item (not a mobile).

Входящий предмет (не мобайл).

Pascal:  procedure OnItemInfo(ID: Cardinal);
Python:  def on_item_info(id: int)
         → ItemInfoEvent(serial)

evItemDeleted

Item deleted from the world.

Предмет удалён из мира.

Pascal:  procedure OnItemDeleted(ID: Cardinal);
Python:  def on_item_deleted(id: int)
         → ItemDeletedEvent(serial)

evSpeech

Incoming speech message (includes regular speech, party messages prefixed with PartyPrivateMsg: / PartyChatMsg:, and Unicode speech).

Входящее речевое сообщение (включая обычную речь, сообщения группы с префиксом PartyPrivateMsg: / PartyChatMsg:, и Unicode-речь).

Pascal:  procedure OnSpeech(Text: String; SenderName: String; SenderID: Cardinal);
Python:  def on_speech(text: str, sender_name: str, sender_id: int)
         → SpeechEvent(text, sender_name, serial)

evMoveRejection

Server rejected the movement step.

Сервер отклонил шаг перемещения.

Pascal:  procedure OnMoveRejection(Xorig, Yorig: Word; Dir: Byte; X, Y: Word);
Python:  def on_move_rejection(x_orig: int, y_orig: int, dir: int, x: int, y: int)
         → MoveRejectionEvent(x_src, y_src, direction, x_dst, y_dst)

evDrawContainer

Container being opened/drawn.

Контейнер открывается/отрисовывается.

Pascal:  procedure OnDrawContainer(ID: Cardinal; ModelGump: Word);
Python:  def on_draw_container(id: int, model_gump: int)
         → DrawContainerEvent(serial, graphic_id)

evAddItemToContainer

Item added to a container.

Предмет добавлен в контейнер.

Pascal:  procedure OnAddItemToContainer(ObjID: Cardinal; ContainerID: Cardinal);
Python:  def on_add_item(obj_id: int, container_id: int)
         → AddItemToContainerEvent(serial, container_serial)

evAddMultipleItemsInCont

Multiple items added to a container (packet 0x3C).

Несколько предметов добавлены в контейнер (пакет 0x3C).

Pascal:  procedure OnAddMultipleItems(ContainerID: Cardinal);
Python:  def on_add_multiple(container_id: int)
         → AddMultipleItemsInContEvent(container_serial)

evRejectMoveItem

Drag/drop operation rejected by the server.

Операция перетаскивания отклонена сервером.

Pascal:  procedure OnRejectMoveItem(Reason: Byte);
Python:  def on_reject_move_item(reason: int)
         → RejectMoveItemEvent(reason)

evDrawObject

Any mobile (character or NPC) drawn/updated.

Любой мобайл (персонаж или NPC) отрисован/обновлён.

Pascal:  procedure OnDrawObject(ID: Cardinal);
Python:  def on_draw_object(id: int)
         → DrawObjectEvent(serial)

evMenu

A menu appeared.

Появилось меню.

Pascal:  procedure OnMenu(Serial: Cardinal; ID: Word; Name: String);
Python:  def on_menu(serial: int, id: int, name: str)
         → MenuEvent(serial, menu_id)

Note: Pascal handler receives 3 parameters. The Name field contains the menu title.

Обработчик в Pascal получает 3 параметра. Поле Name содержит заголовок меню.

evMapMessage

Map/treasure message received.

Получено сообщение о карте/сокровище.

Pascal:  procedure OnMapMessage(ID: Cardinal; CenterX, CenterY: Word);
Python:  def on_map_message(id: int, center_x: int, center_y: int)
         → StealthEvent (no typed subclass)

evAllow_RefuseAttack

Attack permission response.

Ответ на разрешение атаки.

Pascal:  procedure OnAllowRefuseAttack(ID: Cardinal; AttackAllowed: Boolean);
Python:  def on_allow_refuse(id: int, attack_allowed: bool)
         → StealthEvent

ID is 0 if AttackAllowed is False.

ID равен 0, если AttackAllowed = False.

evClilocSpeech

Cliloc (localized) speech message.

Клилок-сообщение (локализованная речь).

Pascal:  procedure OnClilocSpeech(SenderID: Cardinal; SenderName: String;
                                  ClilocID: Cardinal; Text: String);
Python:  def on_cliloc(sender_id: int, sender_name: str, cliloc_id: int, text: str)
         → StealthEvent

evBuff_DebuffSystem

A buff or debuff was activated/deactivated on the player.

Баф или дебаф активирован/деактивирован на игроке.

Pascal:  procedure OnBuffDebuff(PlayerID: Cardinal; IconID: Word; IsEnabled: Boolean);
Python:  def on_buff(player_id: int, icon_id: int, is_enabled: bool)
         → StealthEvent

evClientSendResync

Stealth (or the client through it) sent a resync request. No parameters.

Stealth (или клиент через него) отправил запрос ресинхронизации. Без параметров.

Pascal:  procedure OnResync;
Python:  def on_resync()
         → StealthEvent

evCharAnimation

Character animation played.

Анимация персонажа воспроизведена.

Pascal:  procedure OnCharAnimation(ID: Cardinal; Action: Word);
Python:  def on_animation(id: int, action: int)
         → CharAnimationEvent(serial, action)

evIncomingGump

A gump was received from the server.

Гамп получен от сервера.

Pascal:  procedure OnIncomingGump(Serial: Cardinal; GumpID: Cardinal; X, Y: Integer);
Python:  def on_gump(serial: int, gump_id: int, x: int, y: int)
         → IncomingGumpEvent(serial, gump_id, x, y)

evTimer1

Internal timer, fires every ~100ms. No parameters.

Not called while the script is paused (including pause-on-disconnect). Events accumulate in the queue during the 100ms interval; they are consumed when the script calls Wait.

Внутренний таймер, срабатывает каждые ~100мс. Без параметров.

Не вызывается, пока скрипт на паузе (включая паузу при отключении). События накапливаются в очереди с интервалом 100мс; они обрабатываются при вызове скриптом Wait.

Pascal:  procedure OnTimer1;
Python:  def on_timer1()
         → StealthEvent

evTimer2

Same as evTimer1 — a second independent timer channel.

Аналогичен evTimer1 — второй независимый канал таймера.

Pascal:  procedure OnTimer2;
Python:  def on_timer2()
         → StealthEvent

evSound

Sound played at coordinates.

Звук воспроизведён по координатам.

Pascal:  procedure OnSound(Sound_ID: Word; X, Y: Word; Z: ShortInt);
Python:  def on_sound(sound_id: int, x: int, y: int, z: int)
         → SoundEvent(sound_id, x, y, z)

evDeath

Character died or was resurrected.

Персонаж умер или воскрешён.

Pascal:  procedure OnDeath(Dead: Boolean);
Python:  def on_death(dead: bool)
         → StealthEvent

evQuestArrow

Quest arrow appeared, moved, or disappeared.

Стрелка квеста появилась, переместилась или исчезла.

Pascal:  procedure OnQuestArrow(X, Y: Word; Active: Boolean);
Python:  def on_quest_arrow(x: int, y: int, active: bool)
         → StealthEvent

evPartyInvite

Party invitation received.

Получено приглашение в группу.

Pascal:  procedure OnPartyInvite(Inviter_ID: Cardinal);
Python:  def on_party_invite(inviter_id: int)
         → StealthEvent

evMapPin

Map pin action (marked point on a cartography map item).

Действие с маркером на карте (отмеченная точка на картографическом предмете).

Pascal:  procedure OnMapPin(ID: Cardinal; Action, PinID: Byte; X, Y: Word);
Python:  def on_map_pin(id: int, action: int, pin_id: int, x: int, y: int)
         → StealthEvent

evGumpTextEntry

Text entry dialog (looks like a gump, but technically is not).

Диалог ввода текста (выглядит как гамп, но технически им не является).

Pascal:  procedure OnGumpTextEntry(Serial: Cardinal; Title: String;
                                   InputStyle: Byte; MaxLength: Cardinal; Desc: String);
Python:  def on_text_entry(serial: int, title: str, input_style: int,
                           max_length: int, desc: str)
         → StealthEvent

evGraphicalEffect

Graphical effect displayed (from packets 0x70 and 0xC0).

Графический эффект отображён (из пакетов 0x70 и 0xC0).

Pascal:  procedure OnGraphicalEffect(SrcID: Cardinal; SrcX, SrcY: Word; SrcZ: SmallInt;
                                     DstID: Cardinal; DstX, DstY: Word; DstZ: SmallInt;
                                     EffectType: Byte; ItemID: Word; FixedDir: Byte);
Python:  def on_effect(src_id: int, src_x: int, src_y: int, src_z: int,
                       dst_id: int, dst_x: int, dst_y: int, dst_z: int,
                       effect_type: int, item_id: int, fixed_dir: int)
         → StealthEvent

evMessengerEvent

Event from Telegram or Discord messenger bot.

Событие от мессенджер-бота Telegram или Discord.

In Pascal (internal scripts), Sender is a TMessenger object — you can call methods on it directly. In Python (external scripts), the object cannot be transferred via IPC, so the messenger code is passed instead (see Messenger enum: 1 = Telegram, 3 = Discord).

В Pascal (внутренние скрипты) Sender — это объект TMessenger, на котором можно напрямую вызывать методы. В Python (внешние скрипты) объект не может быть передан через IPC, поэтому передаётся код мессенджера (см. Messenger enum: 1 = Telegram, 3 = Discord).

Pascal:  procedure OnMessengerEvent(Sender: TMessenger; SenderNickName: String;
                                    SenderId, ChatId: String;
                                    EventMsg: String; EventCode: Byte);
Python:  def on_messenger(mes_id: int, sender_name: str, sender_id: str,
                          chat_id: str, event_msg: str, event_code: int)
         → StealthEvent

evSetGlobalVar

Triggered when a global variable is set via SetGlobal('stealth', ...) or from an external script.

Срабатывает при установке глобальной переменной через SetGlobal('stealth', ...) или из внешнего скрипта.

Pascal:  procedure OnSetGlobalVar(VarName: String; VarValue: String);
Python:  def on_global_var(var_name: str, var_value: str)
         → StealthEvent

evUpdateObjStats

Fired when any mobile’s stats change. Values of -1 indicate that particular stat was not updated in this event (data comes from different packets: 0x2D provides all stats, 0xA1 only HP, 0xA2 only Mana, 0xA3 only Stamina).

Срабатывает при изменении статов любого мобайла. Значение -1 означает, что данный стат не обновлялся в этом событии (данные приходят из разных пакетов: 0x2D содержит все статы, 0xA1 — только HP, 0xA2 — только Mana, 0xA3 — только Stamina).

Pascal:  procedure OnUpdateObjStats(ID: Cardinal; CurLife, MaxLife,
                                    CurMana, MaxMana,
                                    CurStam, MaxStam: Integer);
Python:  def on_stats(id: int, cur_life: int, max_life: int,
                      cur_mana: int, max_mana: int,
                      cur_stam: int, max_stam: int)
         → StealthEvent

evGlobalChat

Global chat action/message.

Действие/сообщение глобального чата.

Pascal:  procedure OnGlobalChat(MsgNum: Word; Param1, Param2: String);
Python:  def on_global_chat(msg_num: int, param1: str, param2: str)
         → StealthEvent

evWarDamage

Damage applied to a mobile.

Урон, нанесённый мобайлу.

Pascal:  procedure OnWarDamage(ID: Cardinal; Damage: Word);
Python:  def on_damage(id: int, damage: int)
         → StealthEvent

evContextMenu

Context menu received for an object.

Получено контекстное меню для объекта.

Pascal:  procedure OnContextMenu(ID: Cardinal);
Python:  def on_context_menu(id: int)
         → ContextMenuEvent(serial)

Deprecated Events / Устаревшие события

Event Status Replacement
evUnicodeSpeech Deprecated Use evSpeech
evClilocSpeechAffix Deprecated Use evClilocSpeech
evDrawGamePlayer Deprecated Use evDrawObject
evUpdateChar Deprecated Use evDrawObject
evICQDisconnect Removed
evICQConnect Removed
evICQIncomingText Removed
evICQError Removed
evIRCIncomingText Removed
evWindowsMessage Removed

Event Type Enum Reference / Справочник перечисления EventType

Pascal Name Python EventType Value
evItemInfo EvItemInfo 0
evItemDeleted EvItemDeleted 1
evSpeech EvSpeech 2
evMoveRejection EvMoveRejection 4
evDrawContainer EvDrawContainer 5
evAddItemToContainer EvAddItemToContainer 6
evAddMultipleItemsInCont EvAddMultipleItemsInCont 7
evRejectMoveItem EvRejectMoveItem 8
evDrawObject EvDrawObject 10
evMenu EvMenu 11
evMapMessage EvMapMessage 12
evAllow_RefuseAttack EvAllowRefuseAttack 13
evClilocSpeech EvClilocSpeech 14
evBuff_DebuffSystem EvBuffDebuffSystem 17
evClientSendResync EvClientSendResync 18
evCharAnimation EvCharAnimation 19
evIncomingGump EvIncomingGump 24
evTimer1 EvTimer1 25
evTimer2 EvTimer2 26
evSound EvSound 28
evDeath EvDeath 29
evQuestArrow EvQuestArrow 30
evPartyInvite EvPartyInvite 31
evMapPin EvMapPin 32
evGumpTextEntry EvGumpTextEntry 33
evGraphicalEffect EvGraphicalEffect 34
evMessengerEvent EvMessengerEvent 36
evSetGlobalVar EvSetGlobalVar 37
evUpdateObjStats EvUpdateObjStats 38
evGlobalChat EvGlobalChat 39
evWarDamage EvWarDamage 40
evContextMenu EvContextMenu 41

Examples / Примеры

Pascal Example

Program EventDemo;

procedure OnSpeech(Text, SenderName: String; SenderID: Cardinal);
begin
  AddToSystemJournal('Speech from ' + SenderName + ': ' + Text);
end;

procedure OnCharAnimation(ID: Cardinal; Action: Word);
begin
  AddToSystemJournal('Animation: ID=$' + IntToHex(ID, 8) +
    ' Action=' + IntToStr(Action));
end;

procedure OnMultipleItems(ContainerID: Cardinal);
begin
  AddToSystemJournal('Multiple items added to $' + IntToHex(ContainerID, 8));
end;

procedure OnUpdateStats(ID: Cardinal; CurLife, MaxLife, CurMana, MaxMana,
  CurStam, MaxStam: Integer);
begin
  if CurLife >= 0 then
    AddToSystemJournal('HP update for $' + IntToHex(ID, 8) + ': ' +
      IntToStr(CurLife) + '/' + IntToStr(MaxLife));
end;

begin
  SetEventProc(evSpeech, 'OnSpeech');
  SetEventProc(evCharAnimation, 'OnCharAnimation');
  SetEventProc(evAddMultipleItemsInCont, 'OnMultipleItems');
  SetEventProc(evUpdateObjStats, 'OnUpdateStats');

  while True do
    Wait(50);
end.

Python — Callback Mode

from py_astealth.stealth_enums import EventType

def speech_handler(text, sender_name, sender_id):
    AddToSystemJournal(f'Speech {sender_name}({sender_id}): {text}')

def item_handler(item_id):
    AddToSystemJournal(f'ItemInfo {item_id}')

SetEventProc(EventType.EvSpeech, speech_handler)
SetEventProc(EventType.EvItemInfo, item_handler)

while True:
    Wait(100)

Python — Polling Mode

from py_astealth.stealth_enums import EventType
from py_astealth.stealth_events import SpeechEvent, ItemInfoEvent

SetEventCallback(EventType.EvSpeech)
SetEventCallback(EventType.EvItemInfo)

while True:
    event = WaitForEvent(100)
    if event is None:
        continue

    if isinstance(event, SpeechEvent):
        AddToSystemJournal(f'Speech {event.sender_name}: {event.text}')
    elif isinstance(event, ItemInfoEvent):
        AddToSystemJournal(f'Item: {event.serial}')
    else:
        AddToSystemJournal(f'Event {event.id}: {event.arguments}')

See Also

SetEventProc, Wait, ConstantsAndEnums