diff --git a/libs/gw2_analytics/src/gw2_analytics/buff_state.py b/libs/gw2_analytics/src/gw2_analytics/buff_state.py index 0d4ca75c..4d0d28cd 100644 --- a/libs/gw2_analytics/src/gw2_analytics/buff_state.py +++ b/libs/gw2_analytics/src/gw2_analytics/buff_state.py @@ -424,7 +424,7 @@ def process( # noqa: PLR0912, PLR0915 ( i for i, stack_id in enumerate(target_tracker.stack_ids) - if event.stack_id and stack_id == event.stack_id + if event.stack_id is not None and stack_id == event.stack_id ), None, ) @@ -446,7 +446,7 @@ def process( # noqa: PLR0912, PLR0915 ( i for i, stack_id in enumerate(target_tracker.stack_ids) - if event.stack_id and stack_id == event.stack_id + if event.stack_id is not None and stack_id == event.stack_id ), 0, ) diff --git a/libs/gw2_analytics/src/gw2_analytics/ei_compare.py b/libs/gw2_analytics/src/gw2_analytics/ei_compare.py index 25453baf..66758fc1 100644 --- a/libs/gw2_analytics/src/gw2_analytics/ei_compare.py +++ b/libs/gw2_analytics/src/gw2_analytics/ei_compare.py @@ -808,6 +808,7 @@ def player_agent_ids(agent: Agent, slice_lo: int = 0, slice_hi: int = 0) -> set[ agent_id_by_instance={ agent.instance_id: agent.id for agent in fight.agents if agent.instance_id }, + squad_agent_ids={agent.id for agent in fight.agents if agent.is_player}, ) has_downed_buff_applies = any( isinstance(event, BoonApplyEvent) and event.kind == "apply" and event.skill_id == 770 diff --git a/libs/gw2_analytics/src/gw2_analytics/rotation.py b/libs/gw2_analytics/src/gw2_analytics/rotation.py index 56dbbf2a..9cf244d6 100644 --- a/libs/gw2_analytics/src/gw2_analytics/rotation.py +++ b/libs/gw2_analytics/src/gw2_analytics/rotation.py @@ -576,6 +576,7 @@ def build_skill_rotation( # noqa: PLR0912, PLR0915 elite_specs: Mapping[int, EliteSpec] | None = None, agent_id_by_instance: Mapping[int, int] | None = None, ownership_resolver: Callable[[int, int], int | None] | None = None, + squad_agent_ids: Collection[int] = (), ) -> list[SkillCast]: """Return completed, clipped casts ordered by fight-relative start time. @@ -997,12 +998,13 @@ def add_instant(source: int, skill_id: int, time_ms: int, icd: int = 50) -> None elif (isinstance(event, HealingEvent) and event.skill_id in _HEALING_CASTS) or ( isinstance(event, MissileEvent) and event.skill_id in _MISSILE_CASTS ): - if ( - isinstance(event, HealingEvent) - and event.skill_id in _HEALING_CASTS_SQUAD_ONLY - and not event.src_is_peer - ): - continue + if isinstance(event, HealingEvent) and event.skill_id in _HEALING_CASTS_SQUAD_ONLY: + # EI EXTHealingCastFinder: only book if caster is in squad. + # If squad set is available, require membership; else fall back to src_is_peer. + if squad_agent_ids and event.source_agent_id not in squad_agent_ids: + continue + if not squad_agent_ids and not event.src_is_peer: + continue add_instant( event.source_agent_id, event.skill_id, diff --git a/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py b/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py index 2a8bd2ac..1f54d9e9 100644 --- a/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py +++ b/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py @@ -840,7 +840,7 @@ def parse_events(source: BinaryIO | bytes) -> Iterator[Event]: # noqa: PLR0912, if _ev_buff != 0 and value == 0 and buff_dmg < 0 else 0 ) - src_is_peer = bool(is_offcycle & 0x80) or not bool(is_offcycle & 0xC0) + src_is_peer = bool(is_offcycle & 0x80) if magnitude > 0 and src_is_peer: yield HealingEvent( time_ms=time_ms, @@ -852,7 +852,7 @@ def parse_events(source: BinaryIO | bytes) -> Iterator[Event]: # noqa: PLR0912, iff=_iff & 0xFF, src_master_instid=src_master_inst, dst_master_instid=dst_master_inst, - src_is_peer=bool(is_offcycle & 0x80), + src_is_peer=True, ) continue if is_statechange == 6: diff --git a/libs/gw2_evtc_parser/tests/test_parser.py b/libs/gw2_evtc_parser/tests/test_parser.py index 0c8f13a1..e7671550 100644 --- a/libs/gw2_evtc_parser/tests/test_parser.py +++ b/libs/gw2_evtc_parser/tests/test_parser.py @@ -1040,6 +1040,7 @@ def test_parse_events_2025_healing_extension_combat_round_trips() -> None: 13980, is_statechange=49, pad=0x9C9B3C99, + is_offcycle=0x80, ), _build_event_record_2025( 43_500, @@ -1050,6 +1051,7 @@ def test_parse_events_2025_healing_extension_combat_round_trips() -> None: is_statechange=49, is_shields=1, pad=0x9C9B3C99, + is_offcycle=0x80, ), ], )