evtc/state_change.rs
1use num_enum::{FromPrimitive, IntoPrimitive};
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6#[cfg(feature = "strum")]
7use strum::{Display, EnumCount, EnumIter, IntoStaticStr, VariantNames};
8
9/// Combat state change kinds.
10#[derive(
11 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, FromPrimitive,
12)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14#[cfg_attr(
15 feature = "strum",
16 derive(Display, EnumCount, EnumIter, IntoStaticStr, VariantNames)
17)]
18#[repr(u8)]
19pub enum StateChange {
20 /// Not used, different kind of event.
21 None = 0,
22
23 /// Agent entered combat.
24 ///
25 /// `src_agent` entered combat.
26 /// `dst_agent` contains the subgroup.
27 /// `value` contains the Profession id.
28 /// `buff_dmg` contains the Elite Specialization id.
29 ///
30 /// EVTC: yes, limited to agent table outside instances.
31 ///
32 /// Realtime: yes, limited to squad.
33 EnterCombat = 1,
34
35 /// Agent left combat.
36 ///
37 /// `src_agent` left combat.
38 ///
39 /// EVTC: yes, limited to agent table outside instances.
40 ///
41 /// Realtime: yes, limited to squad.
42 ExitCombat = 2,
43
44 /// Agent is now alive.
45 ///
46 /// `src_agent` is alive.
47 ///
48 /// EVTC: yes, limited to agent table outside instances.
49 ///
50 /// Realtime: yes, limited to squad.
51 ChangeUp = 3,
52
53 /// Agent is now dead.
54 ///
55 /// `src_agent` is dead.
56 ///
57 /// EVTC: yes, limited to agent table outside instances.
58 ///
59 /// Realtime: yes, limited to squad.
60 ChangeDead = 4,
61
62 /// Agent is now downed.
63 ///
64 /// `src_agent` is down.
65 ///
66 /// EVTC: yes, limited to agent table outside instances.
67 ///
68 /// Realtime: yes, limited to squad.
69 ChangeDown = 5,
70
71 /// Agent is now in game tracking range.
72 ///
73 /// `src_agent` is now tracked.
74 ///
75 /// EVTC: yes, limited to agent table outside instances.
76 ///
77 /// Realtime: no
78 Spawn = 6,
79
80 /// Source agent is no longer being tracked or out of game tracking range.
81 ///
82 /// `src_agent` is no longer tracked.
83 ///
84 /// EVTC: yes, limited to agent table outside instances.
85 ///
86 /// Realtime: no
87 Despawn = 7,
88
89 /// Agent health change.
90 ///
91 /// `src_agent` health changed.
92 /// `dst_agent` contains percentage as `percent * 10000`.
93 /// For example 99.5% will be `9950`.
94 ///
95 /// EVTC: yes, limited to agent table outside instances.
96 ///
97 /// Realtime: no
98 HealthUpdate = 8,
99
100 /// Squad combat start, first player entered combat. Logging has started.
101 ///
102 /// `value` contains the server Unix timestamp as `u32`.
103 /// `buff_dmg` contains the local Unix timestamp.
104 ///
105 /// `src_agent` is `0x637261` (ArcDPS id) if log EVTC and species id if realtime API.
106 ///
107 /// EVTC: yes
108 ///
109 /// Realtime: yes
110 SquadCombatStart = 9,
111
112 /// Squad combat end, last player has left combat. Logging has ended.
113 ///
114 /// `value` contains the server Unix timestamp as `u32`.
115 /// `buff_dmg` contains the local Unix timestamp.
116 ///
117 /// `src_agent` is `0x637261` (ArcDPS id) if log EVTC and species id if realtime API.
118 ///
119 /// EVTC: yes
120 ///
121 /// Realtime: yes
122 SquadCombatEnd = 10,
123
124 /// Agent swapped weapon set.
125 ///
126 /// `src_agent` swapped weapons.
127 /// `dst_agent` contains the new weapon set id.
128 /// `value` contains the previous weapon set id.
129 ///
130 /// `0`/`1` for underwater weapon sets and `4`/`5` for land weapon sets.
131 /// `2` is bundle/kit weapon set and `3` transform weapon set.
132 ///
133 /// EVTC: yes
134 ///
135 /// Realtime: yes
136 WeaponSwap = 11,
137
138 /// Agent maximum health change.
139 ///
140 /// `src_agent` changed max health.
141 /// `dst_agent` contains the new maximum health.
142 ///
143 /// EVTC: yes, limited to non-players.
144 ///
145 /// Realtime: no
146 MaxHealthUpdate = 12,
147
148 /// Player recording the log.
149 ///
150 /// `src_agent` is point of view
151 ///
152 /// EVTC: yes
153 ///
154 /// Realtime: no
155 PointOfView = 13,
156
157 /// Game text language.
158 ///
159 /// `src_agent` contains the text language id.
160 ///
161 /// EVTC: yes
162 ///
163 /// Realtime: no
164 Language = 14,
165
166 /// Game build.
167 ///
168 /// `src_agent` contains the game build.
169 ///
170 /// EVTC: yes
171 ///
172 /// Realtime: no
173 GWBuild = 15,
174
175 /// Sever shard id.
176 ///
177 /// `src_agent` contains the shard id.
178 ///
179 /// EVTC: yes
180 ///
181 /// Realtime: no
182 ShardId = 16,
183
184 /// Source agent got a reward chest.
185 ///
186 /// `src_agent` is always self.
187 /// `dst_agent` contains the reward id.
188 /// `value` contains the reward type.
189 ///
190 /// EVTC: yes
191 ///
192 /// Realtime: yes
193 Reward = 17,
194
195 /// Initially present buffs.
196 ///
197 /// Identical to buff application event.
198 /// Appears once per buff per agent on logging start.
199 ///
200 /// EVTC: yes, limited to squad outside instances.
201 ///
202 /// Realtime: yes, limited to squad.
203 BuffInitial = 18,
204
205 /// Agent position change.
206 ///
207 /// `src_agent` changed position.
208 /// `dst_agent` contains XYZ coordinates as `[f32; 3]`.
209 ///
210 /// EVTC: yes, limited to agent table outside instances.
211 ///
212 /// Realtime: no
213 Position = 19,
214
215 /// Agent velocity change.
216 ///
217 /// `src_agent` changed position.
218 /// `dst_agent` contains XYZ velocity as `[f32; 3]`.
219 ///
220 /// EVTC: yes, limited to agent table outside instances.
221 ///
222 /// Realtime: no
223 Velocity = 20,
224
225 /// Agent facing change.
226 ///
227 /// `src_agent` changed position.
228 /// `dst_agent` contains XY direction as `[f32; 2]`.
229 ///
230 /// EVTC: yes, limited to agent table outside instances.
231 ///
232 /// Realtime: no
233 Facing = 21,
234
235 /// Agent team change.
236 ///
237 /// `src_agent` changed team.
238 /// `dst_agent` contains the new team id.
239 /// `value` contains the previous team id.
240 ///
241 /// EVTC: yes, limited to agent table outside instances.
242 ///
243 /// Realtime: yes, limited to squad.
244 TeamChange = 22,
245
246 /// Agent is an attack target of parent gadget.
247 ///
248 /// `src_agent` is the attack target.
249 /// `dst_agent` is the parent gadget.
250 /// `value` contains the current targetable state.
251 ///
252 /// EVTC: yes, limited to agent table outside instances.
253 ///
254 /// Realtime: no
255 AttackTarget = 23,
256
257 /// Agent changed targetable state.
258 ///
259 /// `src_agent` changed targetable state.
260 /// `dst_agent` contains the new targetable state.
261 /// `0` for no, `1` for yes. Default is yes.
262 ///
263 /// EVTC: yes, limited to agent table outside instances.
264 ///
265 /// Realtime: no
266 Targetable = 24,
267
268 /// Map id.
269 ///
270 /// `src_agent` contains the map id.
271 ///
272 /// EVTC: yes
273 ///
274 /// Realtime: no
275 MapId = 25,
276
277 /// Used internally by ArcDPS.
278 /// Should not appear anywhere.
279 ReplInfo = 26,
280
281 /// Buff stack is now active.
282 ///
283 /// `src_agent` has the buff.
284 /// `dst_agent` contains the buff stack id marked active.
285 /// `value` contains the current buff duration.
286 ///
287 /// EVTC: yes, limited to squad outside instances.
288 ///
289 /// Realtime: yes, limited to squad.
290 StackActive = 27,
291
292 /// Buff stack duration changed.
293 ///
294 /// `src_agent` has the buff.
295 /// `value` contains the new duration to reset to (also marks inactive).
296 /// `pad61-64` contains the stack id.
297 ///
298 /// EVTC: yes, limited to squad outside instances.
299 ///
300 /// Realtime: yes, limited to squad.
301 StackReset = 28,
302
303 /// Agent is in guild.
304 ///
305 /// `src_agent` is in guild.
306 /// `dst_agent` contains the guild guid as [u8; 16].
307 ///
308 /// Given in client form, needs minor rearrange for API form.
309 ///
310 /// EVTC: yes, limited to squad outside instances.
311 ///
312 /// Realtime: yes, limited to squad.
313 Guild = 29,
314
315 /// Buff information.
316 ///
317 /// `skill_id` is skilldef id of buff.
318 /// `is_offcycle` contains the category.
319 /// `pad61` contains the stacking type.
320 /// `src_master_instance_id` contains the max stacks.
321 /// `overstack_value` contains the duration cap.
322 ///
323 /// If `is_flanking` probably invulnerability-like.
324 /// If `is_shields` probably invert-like.
325 /// If `pad62` probably resistance-like.
326 ///
327 /// One event per buff.
328 ///
329 /// EVTC: yes
330 ///
331 /// Realtime: no
332 BuffInfo = 30,
333
334 /// Buff formula.
335 ///
336 /// `skill_id` is skilldef id of buff.
337 /// `time` contains `type`, `attr1`, `attr2`, `param1`, `param2`, `param3`, `trait_condition_src` and `trait_condition_self`, `content_reference` as `[f32; 9]`.
338 /// `src_instance_id` contains `buff_condition_src` and `buff_condition_self` as `[f32; 2]`.
339 ///
340 /// If `is_flanking` not NPC.
341 /// If `is_shields` not player.
342 /// If `is_offcycle` break.
343 ///
344 /// `overstack_value` is value of type determined by `pad61`.
345 ///
346 /// One event per buff formula.
347 ///
348 /// EVTC: yes
349 ///
350 /// Realtime: no
351 BuffFormula = 31,
352
353 /// Skill information.
354 ///
355 /// `skill_id` is skilldef id of ability.
356 /// `time` contains `recharge`, `range0`, `range1` and `tooltiptime` as `[f32; 4]`.
357 ///
358 /// One event per ability.
359 ///
360 /// EVTC: yes
361 ///
362 /// Realtime: no
363 SkillInfo = 32,
364
365 /// Skill action.
366 ///
367 /// `skill_id` is skilldef id of ability.
368 /// `src_agent` contains the action type.
369 /// `dst_agent` contains the time since activation in milliseconds.
370 ///
371 /// One event per ability timing.
372 ///
373 /// EVTC: yes
374 ///
375 /// Realtime: no
376 SkillTiming = 33,
377
378 /// Agent breakbar state change.
379 ///
380 /// `src_agent` changed breakbar state.
381 /// `value` contains the new breakbar state as [`u16`] (game enum: active, recover, immune, none).
382 ///
383 /// EVTC: yes, limited to agent table outside instances.
384 ///
385 /// Realtime: no
386 BreakbarState = 34,
387
388 /// Breakbar percentage.
389 ///
390 /// `src_agent` has breakbar percentage.
391 /// `value` contains percentage as [`f32`].
392 ///
393 /// EVTC: yes, limited to agent table outside instances.
394 ///
395 /// Realtime: no
396 BreakbarPercent = 35,
397
398 /// Message with log integrity information.
399 ///
400 /// `time` contains the message as a null-terminated C string.
401 ///
402 /// EVTC: yes
403 ///
404 /// Realtime: no
405 Integrity = 36,
406
407 /// Agent has a marker.
408 ///
409 /// `src_agent` has the marker.
410 /// `value` contains the markerdef id (volatile, depends on game build).
411 /// If `buff`, marker is a commander tag.
412 ///
413 /// A marker id of `0` indicates a remove.
414 ///
415 /// EVTC: yes, limited to agent table outside instances.
416 ///
417 /// Realtime: no
418 Marker = 37,
419
420 /// Agent barrier change.
421 ///
422 /// `src_agent` has barrier percentage.
423 /// `dst_agent` contains percentage as `percent * 10000`.
424 /// For example 99.5% will be `9950`.
425 ///
426 /// EVTC: yes, limited to agent table outside instances.
427 ///
428 /// Realtime: no
429 BarrierUpdate = 38,
430
431 /// Arc UI stats reset.
432 ///
433 /// `src_agent` contains the species id of the agent triggering the reset, for example boss species id.
434 ///
435 /// EVTC: yes
436 ///
437 /// Realtime: yes
438 StatReset = 39,
439
440 /// A custom event created by an extension (addon/plugin).
441 Extension = 40,
442
443 /// Delayed combat event.
444 ///
445 /// Event deemed "unsafe" for realtime that was held back until after squad left combat.
446 ///
447 /// EVTC: no
448 ///
449 /// Realtime: yes
450 ApiDelayed = 41,
451
452 /// Map instance start timestamp.
453 ///
454 /// `src_agent` contains the time in milliseconds since the instance was started.
455 ///
456 /// EVTC: yes
457 ///
458 /// Realtime: yes
459 InstanceStart = 42,
460
461 /// Tick rate health.
462 ///
463 /// `src_agent` is `25 - tickrate` when `tickrate < 21`.
464 /// Every 500ms.
465 ///
466 /// EVTC: yes
467 ///
468 /// Realtime: no
469 RateHealth = 43,
470
471 /// Retired since 230716.
472 ///
473 /// Previously: *Last 90% before down.*
474 ///
475 /// *`src_agent` is enemy agent that went down, `dst_agent` is time in ms since last 90%.
476 /// For downs contribution.*
477 Last90BeforeDown = 44,
478
479 /// Retired since 230716.
480 ///
481 /// Previously: *Effect created or ended.*
482 ///
483 /// *`skill_id` contains the effect id.*
484 /// *`src_agent` is the effect owner.*
485 /// *`dst_agent` if effect located at agent.*
486 /// *Otherwise `value` contains XYZ position as `[f32; 3]`, `affinity` contains XY orientation as `[f32; 2]`, `pad61` contains Z orientation as [`f32`].*
487 /// *`is_shields` contains duration as [`u16`].*
488 /// *If `is_flanking`, duration is a tracking id.*
489 /// *If effect id is `0`, effect ended and `is_shields` contains tracking id.*
490 Effect45 = 45,
491
492 /// Content id to GUID.
493 ///
494 /// `skill_id` is the content id.
495 /// `src_agent` contains the persistent content guid as `[u8; 16]`.
496 /// `overstack_value` contains a variant of [`ContentLocal`](crate::guid::ContentLocal).
497 ///
498 /// *Not used in realtime API.*
499 IdToGUID = 46,
500
501 /// Log boss agent changed.
502 ///
503 /// `src_agent` contains the species id of the agent.
504 /// `dst_agent` is the boss agent.
505 /// `value` contains the server Unix timestamp as `u32`.
506 /// `buff_dmg` contains the local Unix timestamp.
507 ///
508 /// EVTC: yes
509 ///
510 /// Realtime: yes
511 LogNPCUpdate = 47,
512
513 /// Used internally by ArcDPS.
514 /// Should not appear anywhere.
515 IdleEvent = 48,
516
517 /// A custom combat event created by an extension (addon/plugin).
518 ///
519 /// `skill_id` is treated as skill id and will be added to the EVTC skill table.
520 ExtensionCombat = 49,
521
522 /// Fractal scale.
523 ///
524 /// `src_agent` contains the scale.
525 ///
526 /// EVTC: yes
527 ///
528 /// Realtime: no
529 FractalScale = 50,
530
531 /// Visual effect created or ended.
532 ///
533 /// `skill_id` contains the effect id.
534 /// `src_agent` is the effect owner (if any).
535 /// `dst_agent` if effect located at agent.
536 /// Otherwise `value` contains XYZ location as `[f32; 3]`.
537 /// `affinity` contains duration as [`u32`].
538 /// `is_buffremove` contains trackable id as [`u32`].
539 /// `is_shields` contains orientation as `[i16; 3]`.
540 /// Orientation values are `original * 1000` or [`i16::MIN`]/[`i16::MAX`] if out of bounds.
541 ///
542 /// EVTC: yes, limited to agent table outside instances
543 ///
544 /// Realtime: no
545 Effect51 = 51,
546
547 /// Combat ruleset.
548 ///
549 /// `src_agent` has bit 0 set if PvE rules, bit 1 if WvW rules and bit 2 if PvP rules.
550 ///
551 /// EVTC: yes
552 ///
553 /// Realtime: no
554 Ruleset = 52,
555
556 /// Squad ground marker placed or removed.
557 ///
558 /// `src_agent` contains XYZ location as `[f32; 3]` or [`f32::INFINITY`] if removed.
559 /// `skill_id` contains the index of the squad marker, for example `0` for Arrow marker.
560 ///
561 /// EVTC: yes
562 ///
563 /// Realtime: no
564 SquadMarker = 53,
565
566 /// ArcDPS build information.
567 ///
568 /// `src_agent` contains ArcDPS build as null-terminated C string.
569 ///
570 /// EVTC: yes
571 ///
572 /// Realtime: no
573 ArcBuild = 54,
574
575 /// Agent gliding state change.
576 ///
577 /// `src_agent` changed gliding state.
578 /// `value` contains `1` if deployed and `0` if stowed.
579 ///
580 /// EVTC: yes, limited to agent table outside instances.
581 ///
582 /// Realtime: no
583 Glider = 55,
584
585 /// Disable stopped early.
586 ///
587 /// `src_agent` stopped the disable.
588 /// `value` contains duration remaining.
589 ///
590 /// EVTC: yes, limited to agent table outside instances
591 ///
592 /// Realtime: no
593 Stunbreak = 56,
594
595 /// Missile created.
596 ///
597 /// `src_agent` contains the source agent.
598 /// `value` contains the location x/y/z as `[i16; 3]` divided by 10.
599 /// `overstack_value` contains the skin id (player only).
600 /// `skill_id` contains the associated skill id.
601 /// `pad61` contains the trackable missile id as [`u32`].
602 ///
603 /// EVTC: yes, limited to agent table outside instances
604 ///
605 /// Realtime: no
606 MissileCreate = 57,
607
608 /// Missile launched or relaunched.
609 ///
610 /// `src_agent` contains the source agent.
611 /// `dst_agent` contains the target agent, if set and in range.
612 /// `value` contains the target x/y/z and current x/y/z as `[i16; 6]` divided by 10.
613 /// `skill_id` contains the associated skill id.
614 /// `affinity` contains the launch motion as [`u8`]. Unknown values, directly from client.
615 /// `result` contains the motion radius/range as [`i16`].
616 /// `is_buffremove` contains the launch flags as [`u32`]. Unknown values, directly from client.
617 /// `is_shields` contains the missile speed as [`i16`].
618 /// `pad61` contains the trackable missile id as [`u32`].
619 ///
620 /// EVTC: yes, limited to agent table outside instances
621 ///
622 /// Realtime: no
623 MissileLaunch = 58,
624
625 /// Missile removed or destroyed.
626 ///
627 /// `src_agent` contains the related agent.
628 /// `value` contains the total friendly fire damage.
629 /// `skill_id` contains the associated skill id.
630 /// `is_src_flanking` if at least one enemy was hit along the way.
631 /// `pad61` contains the trackable missile id as [`u32`].
632 ///
633 /// EVTC: yes, limited to agent table outside instances
634 ///
635 /// Realtime: no
636 MissileRemove = 59,
637
638 /// Ground effect created.
639 ///
640 /// `src_agent` contains the owner agent.
641 /// `dst_agent` contains the origin x/y/z divided by 10 and orient x/y/z multiplied by 1000 as `[i16; 6]`.
642 /// `skill_id` contains the volatile effect content id, map to stable GUID via [`StateChange::IdToGUID`] event.
643 /// `affinity` contains the effect duration as [`u32`]. If the duration is zero, it may be a fixed length duration (see [`StateChange::IdToGUID`] event).
644 /// `is_buffremove` contains the flags.
645 /// `is_flanking` if effect is located on a non-static platform.
646 /// `is_shields` contains the scale (if zero, assume 1) multiplied by 1000 as `i16`.
647 /// `pad61` contains the trackable effect id as [`u32`].
648 ///
649 /// EVTC: yes, limited to agent table outside instances
650 ///
651 /// Realtime: no
652 EffectGroundCreate = 60,
653
654 /// Ground effect removed.
655 ///
656 /// `pad61` contains the trackable effect id as [`u32`].
657 ///
658 /// EVTC: yes
659 ///
660 /// Realtime: no
661 EffectGroundRemove = 61,
662
663 /// Effect atttached to agent created.
664 ///
665 /// `src_agent` contains the related agent.
666 /// `skill_id` contains the volatile effect content id, map to stable GUID via [`StateChange::IdToGUID`] event.
667 /// `affinity` contains effect duration as [`u32`]. If the duration is zero, it may be a fixed length duration (see [`StateChange::IdToGUID`] event).
668 /// `pad61` contains the trackable effect id as [`u32`].
669 ///
670 /// EVTC: yes, limited to agent table outside instances
671 ///
672 /// Realtime: no
673 EffectAgentCreate = 62,
674
675 /// Effect attached to agent removed.
676 ///
677 /// `src_agent` contains the related agent.
678 /// `pad61` contains the trackable effect id as [`u32`].
679 ///
680 /// EVTC: yes, limited to agent table outside instances
681 ///
682 /// Realtime: no
683 EffectAgentRemove = 63,
684
685 /// Unknown or invalid.
686 #[num_enum(catch_all)]
687 Unknown(u8),
688}
689
690impl StateChange {
691 /// Checks whether the statechange has an associated timestamp.
692 #[inline]
693 pub fn has_time(&self) -> bool {
694 matches!(
695 self,
696 Self::None
697 | Self::EnterCombat
698 | Self::ExitCombat
699 | Self::ChangeUp
700 | Self::ChangeDead
701 | Self::ChangeDown
702 | Self::Spawn
703 | Self::Despawn
704 | Self::HealthUpdate
705 | Self::SquadCombatStart
706 | Self::SquadCombatEnd
707 | Self::WeaponSwap
708 | Self::MaxHealthUpdate
709 | Self::Reward
710 | Self::BuffInitial
711 | Self::Position
712 | Self::Velocity
713 | Self::Facing
714 | Self::TeamChange
715 | Self::AttackTarget
716 | Self::Targetable
717 | Self::StackActive
718 | Self::StackReset
719 | Self::BreakbarState
720 | Self::BreakbarPercent
721 | Self::BarrierUpdate
722 | Self::StatReset
723 | Self::Extension
724 | Self::ApiDelayed
725 | Self::Last90BeforeDown
726 | Self::Effect45
727 | Self::LogNPCUpdate
728 | Self::ExtensionCombat
729 | Self::Effect51
730 | Self::SquadMarker
731 | Self::Glider
732 | Self::Stunbreak
733 | Self::MissileCreate
734 | Self::MissileLaunch
735 | Self::MissileRemove
736 | Self::EffectGroundCreate
737 | Self::EffectGroundRemove
738 | Self::EffectAgentCreate
739 | Self::EffectAgentRemove
740 )
741 }
742}