Skip to content

Movement, effects & missiles in logs

Beyond damage and buffs, a modern log is full of spatial data: where every agent stood, what projectiles flew, what visual effects played. It’s the raw material for replay maps, positioning analysis, and mechanic detection. This page covers the three event families, with values observed in a real revision-1 WvW .zevtc log (arcdps build 20260114, Alpine Borderlands, ~6.7-minute fight) inspected while writing this page. Payload layouts are on the statechange payloads page.

Movement: CBTS_POSITION (19) / CBTS_VELOCITY (20) / CBTS_FACING (21)

src_agent is the agent; the coordinates are floats overlaid on dst_agent — float[3] (x/y/z) for position and velocity, float[2] for facing.

What the test log showed:

  • Volume: 18,862 position, 17,534 velocity, and 13,882 facing events — movement is roughly a third of this log’s event count.
  • Everyone is tracked, not just the squad: positions broke down as 9,285 squad, 7,203 enemy-player, 2,346 NPC, and 28 gadget samples. Enemy movement analysis is possible straight from the log.
  • Sampling rate: the busiest agent had 1,113 position samples at a 300 ms median interval — dense enough for smooth replay paths.
  • Coordinates are game-world units in map space; observed ranges in this Alpine Borderlands fight were roughly x ∈ [−22,260, 17,857], y ∈ [−35,597, 21,792], z ∈ [−6,152, 19] (a real sample: (10956.7, 15051.2, −3450.7)). The official notes don’t document the unit or axis conventions — correlating them to in-game coordinates is left to community tooling.

Related one-offs: CBTS_GLIDER (55) marks glider deploy/stow — 117 events in this WvW log (bombing keeps from the air leaves a trail).

Note the availability caveat on all of these: “evtc: limited to agent table outside instances · realtime: no” — you get them in open-world /WvW logs, but extensions never see them live through the combat callback.

Visual effects: CBTS_EFFECTGROUNDCREATE (60) / CBTS_EFFECTAGENTCREATE (62)

Effect events record visual content playing on the ground (with origin/orientation packed as int16s) or around an agent. Observed: 3,269 ground and 5,049 agent effect creates.

Two practical points, both confirmed in the test log:

Effect ids are not skill ids. The skillid field of an effect event holds a volatile effect id — none of the 671 distinct effect ids observed had a name in the log’s skill table. The official notes say to “prefer using an id to guid map via n_contentlocal”: each id is resolved by a CBTS_IDTOGUID (46) event carrying the persistent 16-byte content GUID in src_agent and the content type (n_contentlocal) in overstack_value. In the test log this resolution was complete: all 671 effect ids had a matching type-CONTENTLOCAL_EFFECT entry (keyed by the skillid field — observed, as the payload notes don’t name the id field explicitly). Build the GUID map first, then key your effect logic on GUIDs, which are stable across logs.

(The log also contained 24 IDTOGUID events with content type 3 — CONTENTLOCAL_SPECIES_NOT_GADGET, associating NPC species ids with GUIDs.)

Removes are rare; durations matter. Ground effects: 3,269 creates, zero removes. Agent effects: 5,049 creates, 41 removes. Most effects simply expire — the create event’s duration field (a uint32 overlaid at iff) plus the default duration from the IDTOGUID payload is how you know when; a remove event (trackable id in pad61) only arrives for early termination.

Missiles: CBTS_MISSILECREATE (57) / CBTS_MISSILELAUNCH (58) / CBTS_MISSILEREMOVE (59)

Projectiles are tracked as create → launch(es) → remove, with positions packed as int16 triples divided by 10 (layouts: missile events). Observed: 2,169 creates, 2,339 launches, 2,112 removes — launches exceed creates because one missile can re-launch (is_flanking flags the first launch). Unlike effect ids, missile skillids are real skills — the log’s top missile sources were Rapid Fire (140), Vicious Shot (137), Long Range Shot (102), all named in the skill table. The remove event carries a friendly-fire damage total in value.

Recipe: building a position track

To reconstruct where everyone stood, scan the event stream for CBTS_POSITION (19) events and read the float[3] x/y/z overlaid on dst_agent (payload), keying by src_agent. Accumulate one track per agent — at the observed ~300 ms sampling that’s a dense path ready to plot.

The coordinates are 12 bytes of float[3] reinterpreted starting at the dst_agent field. In the 64-byte cbtevent dst_agent sits at byte offset 16, so the three floats occupy bytes 16–27 — i.e. they spill past dst_agent (8 bytes) into the value field. Read them from the raw record rather than the parsed dst_agent integer:

import struct
from collections import defaultdict
CBTS_POSITION = 19
tracks = defaultdict(list) # src_agent -> [(time, x, y, z), ...]
for rec in records: # each rec is a raw 64-byte cbtevent; see /guides/parsing-logs/
if rec[56] != CBTS_POSITION: # is_statechange is byte 56
continue
time, src_agent = struct.unpack_from("<QQ", rec, 0) # bytes 0-15
x, y, z = struct.unpack_from("<3f", rec, 16) # float[3] at dst_agent
tracks[src_agent].append((time, x, y, z))
for agent, samples in tracks.items():
samples.sort() # by time

See parsing EVTC logs for reading the raw event stream. These events are evtc-only, so this runs offline against a .zevtc, not a live extension.

What this enables

  • Replay maps: positions at 300 ms resolution for both sides, plus facing for cone-skill analysis — see WvW allies & enemies for classifying who’s who first.
  • Mechanic/AoE detection: ground effects with orientation and scale, GUID-stable across logs.
  • Projectile analysis: per-skill missile counts and flight endpoints.

All of it is evtc-only — none of these events reach realtime extensions — and all of it is per-map-instance data, so pair it with the map id before plotting anything.