Brodgar client

hafen.event: The Character and the Rosters

What one character’s own HUD reports: bars and buffs, food and study, equipment and hotbar, wounds, kin, quests, map pins and the radial menu. Every key hands the thing it is about and that character’s Session last, except MarkerChanged (the recorded map is one database for the client). Part of the catalogue.

hafen.event():on("BuffAdded", function(buff, session)
  hafen.log():write(session:character() .. " gained " .. (buff:name() or buff:res()))
end)

Rule Detail
The session argument nil where the client cannot name the login the widget stands in. A handler that took the parameter guards it.
Diff, one frame The client marks the subject dirty when the server messages about it and re-reads once on the next step. A value that changes and reverts inside that frame fires nothing. State the server never messages about (a buff’s meter running down against a clock) moves silently and is announced by the next message that arrives. Read such a number live off the object.
List keys For StudyChanged, EquipChanged, KinChanged, WoundChanged the payload is the full new list, not a delta. Read the initial state once with the section’s own :list(), then listen. A list key covers adds, removals and changes: WoundChanged fires for a wound appearing, healing and worsening. A buff arrives one at a time, and its edge is named.

Character and status

From the HUD’s own widgets, so they start once the HUD is up. Attributes, learning points, weight, skills, credos and lore have no key: session:char() reads them after the action that changes them.

Event Payload Fires
MeterAdded Meter A HUD meter bar appears.
MeterRemoved Meter A HUD meter bar goes away. The object still reads, :exists() is false.
MeterChanged Meter A meter bar’s value or colour changes.
BuffAdded Buff A buff appears on the buff bar.
BuffRemoved Buff A buff leaves the bar. The object still reads, :exists() is false.
BuffChanged Buff A bar buff’s content updates.
FepChanged Food FEP or hunger changes.
StudyChanged StudySlot[] The study slots change: an add, a removal, or data resolving.
EquipChanged Item[] Worn equipment changes.
ActionbarChanged Slot An action-bar slot is set, cleared or changed.
WoundChanged Wound[] A wound is added or healed, or its severity changes.
Rule Detail
Containers are not here A chest is not a global fact: subscribe to the container with widget:on("ItemAdded"/"ItemRemoved"/"Removed", fn). EquipChanged is global because worn gear is one fixed surface.
ActionbarChanged payload The changed slot as the interned Slot session:actionbar():get(n) returns, so payload and session:actionbar():get(payload:index()) are one object. Fires on a set, a clear, a drag, or a slot’s data resolving, not on :cooldown() ticking. At login the occupied slots stream in as a burst, one fire each.
A held slot fires on both edges Once when the hold takes the slot, once when it ends and the server’s content returns. While held, slot:res() is the entry’s identity.

Roster, quests, markers

Event Payload Fires
KinChanged Kin[] A kin is added, removed or edited, or flips online or offline.
QuestAdded Quest A new active quest appears.
QuestCompleted Quest An active quest is completed.
QuestFailed Quest An active quest is failed.
MarkerChanged The marker collection A map marker is added or removed.
Rule Detail
KinChanged payload The whole roster as the interned Kin objects session:kin():list() returns, in Kin-window sort order, so payload[1] and session:kin():get(payload[1]:id()) are one object. It says that the roster changed, not what. Keep your own map of the last state, keyed by the Kin itself rather than :name(). A rename then does not read as one kin leaving and another arriving. kin:info() is the plain table.
The outcome is the key QuestCompleted on done, QuestFailed on failed: a handler for success is one subscription and no if. Subscribe to both for either. A finished status the client does not recognise fires neither.
The quest payload The Quest itself: a handler that keeps it goes on reading it, quest:status() included.

The radial menu

Event Payload Fires
FlowerMenuAdded Petal[], in ring order A right-click puts up a radial menu.
FlowerMenuRemoved string \| nil, the label picked That menu goes away.

Every FlowerMenuAdded is followed by exactly one FlowerMenuRemoved (a pick, Esc, a click away, a dropped connection). The payload is nil for everything but a pick. Both cover the client’s own menus (the Kin window’s) as well as the server’s. Read the ring from the payload or from session:flowermenu(), which also names the object it was opened on. session is the event’s last argument. A ring goes up on the character the pointer is on and stays up, readable, if you tab away.

Steam

Event Payload Fires
SteamStatsLoaded — The Steam client has finished loading the player’s stats and achievements, so hafen.steam() reads them.
AchievementUnlocked Achievement An achievement is stored as unlocked.

Both are the Steam client’s moments, not a character’s. They fire once per client, whichever session is on screen, and not at all on a client started outside Steam.


See Also