Skip to content

Combat callback

Extension modules receive combat events through two optional callback slots in their arcdps_exports table (see Getting Started): combat (area) and combat_local (local). Both share the same call signature; they differ in scope, timing, and the skillname parameter’s constness. This page is sourced from the official arcdps API reference (https://www.deltaconnected.com/arcdps/api/README.txt).

Signature

void combat(cbtevent* ev, ag* src, ag* dst, const char* skillname,
uint64_t id, uint64_t revision);
void combat_local(cbtevent* ev, ag* src, ag* dst, char* skillname,
uint64_t id, uint64_t revision);
  • ev — a cbtevent* as defined in the evtc documentation. See the cbtevent reference for its field layout. ev may be null — see “ev == null events” below.
  • src / dstag* (agent) pointers. See the agent (ag) reference.
  • skillname — the skill’s display name. const char* for combat, non-const char* for combat_local.
  • id — use this to re-establish event order (an id of 0 means the event is unordered). Due to a historical change in how id is assigned, the first event will always have id == 2.
  • revision — the cbtevent type revision; “will most likely be 1”.

combat (area) vs combat_local

combatcombat_local
Scopearea eventschatbox/local events
Timingasynchronous, delayed roughly 2-3 secondsnot delayed
skillname typeconst char*char*

The official notes describe combat_local as “same as combat, but for chatbox events,” and are explicit that combat’s ~2-3 second delay makes it suited for statistics rather than realtime notifications:

events are delayed by ~2-3 seconds - this is intended for statistics, not realtime notifications.

If your extension needs low-latency reactions to the local player’s own events, prefer combat_local. If you’re aggregating area-wide combat statistics (e.g. a DPS meter), combat is the documented source, with the understood delay.

What the realtime feed does and doesn’t carry

The realtime API is filtered as well as delayed. Key facts:

  • Per the EVTC documentation’s per-event availability notes, many statechange types are never delivered on the realtime path (most positional, effect, missile, and metadata events are evtc-only), and most of the rest are limited to squad members. The full per-event “evtc:”/“realtime:” availability is listed on the statechange payloads page.
  • Community bindings summarize the delivery guarantee as: at least one participant of a delivered event will be a party/squad member (or minion of one, or a buff applied by the squad in the case of buff removes).
  • The retired CBTS_APIDELAYED statechange existed specifically for events “deemed unsafe for realtime” that were held back until the squad left combat — evidence that the delay/filtering is a deliberate anti-cheat design, not an implementation accident.

Two community-verified practical quirks (from working extensions, not the official notes):

  • Agent name lifetime — the char* names inside src/dst are only valid for the duration of the callback. Copy the strings; never store the pointers.
  • Non-squad hostile players are aggregated — arcdps reuses the profession id as the agent id for hostile players outside your squad, so a realtime “enemy roster” tops out at roughly one entry per profession. Per-player enemy data only exists in the written .evtc log, which appears a few seconds after combat ends.

ev == null events

ev may be null. When it is, the meaning of src/dst changes to signal agent-list events rather than a combat event:

  • If src->elite == 1, then src->id is the id of the newly targeted agent.
  • Else, if src->prof is set, src->id was added:
    • src->name — character name
    • dst->name — account name
    • src->id — agent id
    • dst->id — instance id on the map
    • dst->prof — profession
    • dst->elite — elite spec
    • dst->self — is-self flag
    • src->team — team id
    • dst->team — subgroup
  • Else, src->id was removed.

Calling order and ordering guarantees

  • Use id to re-establish the order of events; id == 0 means the event is unordered.
  • The first event delivered will always have id == 2 (a documented quirk from a past change to id assignment — not a bug to work around, it’s the expected starting value).
  • combat events are delayed ~2-3 seconds relative to the in-game event; combat_local is not.

Extensions can also inject synthetic combat events into arcdps’ processing pipeline rather than only receiving them — see e9 and e10 on the arcdps exports reference.

See also

  • cbtevent — full field layout of the event struct.
  • agent (ag) — full field layout of the src/dst struct.
  • Getting Started — the surrounding arcdps_exports contract these callbacks are registered through.