diff --git a/libs/gw2_analytics/src/gw2_analytics/rotation.py b/libs/gw2_analytics/src/gw2_analytics/rotation.py index 04138008..56dbbf2a 100644 --- a/libs/gw2_analytics/src/gw2_analytics/rotation.py +++ b/libs/gw2_analytics/src/gw2_analytics/rotation.py @@ -154,6 +154,7 @@ 62769: 62861, 13135: 13106, 77265: 76730, + 29502: -41, # Berserk (end): BuffLossCastFinder(BerserkEndSkill, BerserkBuff) } _BUFF_GIVE_CASTS = { 41815: 45789, @@ -292,7 +293,7 @@ #: strip is not a cast. Only the entries verified against Elite Insights are #: listed; the rest keep the historical "any removal" behaviour until they #: are checked the same way. -_BUFF_LOSS_REMOVE_ALL_ONLY = {29446, 62769} +_BUFF_LOSS_REMOVE_ALL_ONLY = {29446, 62769, 29502} #: BuffGainCastFinder books the buff gained by the player itself; arcdps #: also re-emits these buffs with ``src=0`` (env) for trait/sigil pulses, #: which EI excludes via ``!bae.Initial``. Self-apply gating reproduces @@ -880,7 +881,8 @@ def add_instant(source: int, skill_id: int, time_ms: int, icd: int = 50) -> None and elite_specs.get(event.target_agent_id) is EliteSpec.WEAVER ) or ( - event.skill_id in _BUFF_GAIN_SELF_ONLY + event.kind == "apply" + and event.skill_id in _BUFF_GAIN_SELF_ONLY and event.source_agent_id != event.target_agent_id ) or ( diff --git a/libs/gw2_analytics/tests/test_rotation.py b/libs/gw2_analytics/tests/test_rotation.py index 0f7c60f6..7d4fa5ee 100644 --- a/libs/gw2_analytics/tests/test_rotation.py +++ b/libs/gw2_analytics/tests/test_rotation.py @@ -1568,3 +1568,34 @@ def casts(**kwargs: Any) -> list[int]: assert casts() == [5492] assert casts(elite_specs={7: EliteSpec.TEMPEST}) == [5492] assert casts(elite_specs={7: EliteSpec.WEAVER}) == [43470] + + +def test_berserk_loss_is_booked_as_berserk_end() -> None: + """EI books ``BerserkEndSkill`` (-41) when the Berserk buff is fully removed.""" + origin = 42_000_000 + + def casts(*events: Event) -> list[int]: + return [ + cast.skill_id + for cast in build_skill_rotation(list(events), duration_ms=1_000, start_time_ms=origin) + ] + + gain = BoonApplyEvent( + time_ms=origin + 100, + source_agent_id=7, + target_agent_id=7, + skill_id=29502, + duration_ms=5_000, + stacks=1, + ) + end = BoonApplyEvent( + time_ms=origin + 5_100, + source_agent_id=0, + target_agent_id=7, + skill_id=29502, + duration_ms=0, + stacks=0, + kind="remove_all", + ) + assert casts(gain) == [30435] + assert casts(gain, end) == [30435, -41]