- summary: Asks the server to perform one action of one interactive element on the current map: harvest, open a door, take a zaap, use a workshop.
- area: Game.Interactive
Asks the server to perform one action of one interactive element on the current map: harvest, open a door, take a zaap, use a workshop.
Kind request · Area Game.Interactive
Asks the server to perform ONE action of ONE interactive element on the map you are standing on: harvest a resource, open a door, take a zaap, open a crafting workshop, the smithmagic table, the auction house, the crafter list or the guild creator, enter or manage a house.
YOU ARE ASKING, NOT ACTING. Nothing has happened until the server answers:
success arrives as InteractiveUsedEvent with you as its entity_id, a
refusal as InteractiveUseErrorEvent. Exactly one of the two answers each
request.
HOW TO USE AN ELEMENT - do exactly this, in this order. It is what the official client does, read from its code.
1. BE ON THE MAP. You are in the roleplay context and have received the map's
interactive snapshot (InteractiveMapUpdateEvent, kept current by
InteractiveElementUpdatedEvent). Only use elements whose
InteractiveElement.on_current_map is true.
2. PICK AN ENABLED ACTION. Take it from the element's
InteractiveElement.enabled_skills - never from disabled_skills, and
never a directional sign (skill_id 360, 361 or 362: signs are read, not
used). Keep both of its ids: skill_instance_uid is what you send,
skill_id is what you look up in the game data.
3. EXIT POINTERS ARE WALKED ONTO, NOT USED. If the element's only enabled action is "Point Out an Exit" (skill_id 339), do not send this message: walk onto the element's own cell instead - that cell is the exit.
4. READ THE ALLOWED DISTANCE FROM THE GAME DATA. Look up every enabled action
of the element in the skill table by its skill_id:
- an action whose use_range_in_client is set allows its range;
- an action without it allows 1.
The allowed distance is the SMALLEST of those values over the element's
enabled actions. Distance is |dx| + |dy| between your cell and the
element's cell in map coordinates (the coordinates derived from the cell
id), so 1 means one of the four cells that share an edge with the
element's cell.
5. WALK UNTIL YOU ARE THAT CLOSE - if you already are, skip this step.
Choose a free cell within the allowed distance (for a distance of 1, the
free cell next to the element on your side of it) and walk there with the
normal movement handshake: MapMovementRequest, follow the path the
server grants (MapMovementEvent), MapMovementConfirmRequest when
the walk is done, and WAIT FOR MapMovementConfirmResponse. Never send
two walk requests less than 250 ms apart. If the server refuses the walk
(MapMovementRefusedEvent), send no confirm, take the cell it names as
your position and carry on: the official client still sends the use
request, from wherever it stands.
6. ONLY NOW SEND THIS REQUEST, with element_id, skill_instance_uid, and
specific_instance_id for a house action only (see HOUSE DOORS). Set
nothing else.
7. WAIT FOR THE ANSWER before touching that element again:
- InteractiveUsedEvent for that element: accepted. It does NOT echo
your request: recognise it by its element_id (the element you used),
its entity_id (your character) and its skill_id - the skill_id of
the action you picked, not the skill_instance_uid you sent. If it names
YOU and its duration is above zero, the use lasts duration x 100 ms
(duration is in tenths of a second: 30 is three seconds) and you are
BUSY: send no use request at all, for any element, until
InteractiveUseEndedEvent for the element you are using arrives - or
a new StatedMapUpdateEvent snapshot. When its can_move is false
(absent on the wire), do not walk until the use is over either.
- InteractiveUseErrorEvent for that element: refused. Nothing
started and you are not busy. The official client prints the
ui.popup.impossible_action line in chat and forgets the request;
nothing else changes.
Never send a second request for an element whose first request is still
unanswered.
DO YOU HAVE TO BE NEXT TO THE DOOR? Yes - within the allowed distance of step 4, which is one cell unless the skill data says otherwise, and only after the server has confirmed the walk. Whether the server REJECTS a request sent from further away cannot be read from the client; following these steps is the safe contract.
THE TWO IDS ARE BOTH int32 AND MUST NOT BE SWAPPED
element_idInteractiveElement.element_idof the element. skill_instance_uidInteractiveElementSkill.skill_instance_uidof the chosen action in THAT element'sInteractiveElement.enabled_skills. NOTInteractiveElementSkill.skill_id: skill_id says WHAT the action is and is shared by every element offering it; skill_instance_uid says WHICH offer on this element.
HOUSE DOORS AND specific_instance_id
Leave specific_instance_id ABSENT for everything except a house action on a
house door. A house door can lead to several house instances; the house actions
are:
84 Enter any instance 97 Buy an instance for sale that is not yours 98 Sell an instance of yours that is not for sale 108 Change the price an instance of yours that is for sale 81 Add a code an instance of yours with no code lock 100 Change the code an instance of yours locked with a code
"Yours" means the instance's owner account (name and tag) is the account you are logged in with. Send the id of the house instance you act on. That is what the official client sends when the action is picked from the door's menu: the chosen instance, or the door's only instance. It also sends 0 when no instance suits the action, and sends no instance at all when the door is used by a direct click (one usable action, at most one instance). Never send -1: it is the client's internal "no instance" and means "leave the field unset".
WHAT THE GAME DATA DECIDES (skill table, by skill_id)
range, use_range_in_client the allowed distance (step 4)
level_min, parent_job_id the job and job level a job action needs; the
client uses them to explain a disabled action.
Whether an action is usable is decided by the
server's enabled_skills, not by this check
cursor, name_id,
use_animation presentation only (cursor, menu label, the
animation played when the use starts)
LIVE CAPTURES (3.6.12.16)
requests element 489389 with skill instance 14033, and element 489333
with skill instance 14004; between them they showed an
in-game message and opened a door. Neither carried
specific_instance_id.
acceptance an InteractiveUsedEvent for a character: element 537803,
skill_id 68, duration 30 (three seconds), can_move absent
(false). The request it answered is not part of that capture.
The official client also ships developer console commands that send this message
directly with fixed ids and no walk (a command literally named
sendInteractiveUseRequest, and shortcuts that open the auction house, the
craft and smithmagic windows, the crafter list and the guild creator). They are
not part of a normal session and prove nothing about what the server accepts.
The current build pads this message with an optional int32 and a nested decoy message that no client code ever writes. Never set them.
When you may send it
- Requires
roleplay_contextinferred - Raised by: a user action: the player picks one enabled action of an interactive element (a click on an element with one usable action, an entry of the element's action menu, or the client's auto-travel). The client first walks into the action's range and, when it walked, waits for
MapMovementConfirmResponsebefore sending. Never for directional signs (skills 360-362) and never for an element whose only enabled action is Point Out an Exit (skill 339), which is walked onto instead inferred
Related messages
- You will then receive
InteractiveUseEndedEventinferred — only after an acceptance whose duration is above zero (a timed use): it closes the use, and the client ends its busy state when it arrives. An untimed use gets none. Not captured yet - You will then receive
TeleportDestinationsEventobserved — when the element is a zaap, zaapi or prism: its destination list, right after the acceptance. Captured once on 3.7.4.4 (same millisecond as the acceptance) - You will receive one of
InteractiveUsedEventinferred — the acceptance, with you as entity_id, the used element_id and the action's skill_id (not the skill_instance_uid you sent); the client clears its pending request for that element when it arrives. One acceptance was captured live (duration 30, can_move false), but not together with its request - You will receive one of
InteractiveUseErrorEventinferred — the refusal, naming the element_id you sent; the client clears its pending request for that element and prints the localized ui.popup.impossible_action line in chat. Not captured yet
If you get it wrong
- a use the server will not perform (out of range, an action the element does not currently offer, another map's element) is answered by [[InteractiveUseErrorEvent]]; the client's only reaction is the chat line and dropping its pending request inferred
Fields
| # | Field | Type | Meaning | You set it |
|---|---|---|---|---|
| 1 | skill_instance_uid | int32 | Which of that element's offered actions to perform. (skill instance uid) Observed: 14033, 14004 (live capture, 3.6.12.16)Copy InteractiveElementSkill.skill_instance_uid of one action in that element's InteractiveElement.enabled_skills - NOT InteractiveElementSkill.skill_id. Both are int32: skill_id says WHAT the action is, skill_instance_uid says WHICH offer on this element.Never an action from disabled_skills, never a directional sign (skill_id 360-362), and never the lone Point Out an Exit action (skill_id 339), which is walked onto instead. | required |
| 2 | specific_instance_id | int32 | The house instance a house-door action applies to. Explicit presence: absent is not the same as zero. (house instance id) Leave it absent unless you are acting on a house. Absent means no particular instance. Send the house instance you act on: Enter (84) any; Buy (97) one for sale that is not yours; Sell (98) one of yours not for sale; Change the price (108) one of yours for sale; Add a code (81) one of yours without a code; Change the code (100) one of yours with a code. The official client sends the instance picked in the door's menu or the door's only instance, sends 0 when no instance suits the action, and sends none on a direct click. Never send -1: it is the client's internal 'no instance' and leaves the field unset. | only for a house action on a house door (Enter, Buy, Sell, Change the price, Add a code, Change the code); absent for every other use |
| 3 | element_id | int32 | The interactive element to use, by its id on the current map. (interactive element id) Observed: 489389, 489333 (live capture, 3.6.12.16)Copy InteractiveElement.element_id of an element in the current map's snapshot (InteractiveMapUpdateEvent, kept current by InteractiveElementUpdatedEvent) whose InteractiveElement.on_current_map is true.Send it unchanged, and only once you stand within the action's allowed distance of this element's cell. | required |