events.pyΒΆ

Part of Dungeon Explorer.

 1"""Typed event dataclasses for the Dungeon Explorer game.
 2
 3Events are emitted via ``self.tree.events.publish(EventCls(...))`` from producers
 4and consumed via ``self.tree.events.subscribe(EventCls, handler)`` in
 5handlers' ``ready()``. The :class:`~simvx.core.event_bus.EventBus` holds
 6``WeakMethod`` references so handlers automatically detach when the owning
 7node is freed -- no explicit ``disconnect`` is required when nodes leave the
 8tree.
 9
10Per the engine "one obvious way" rule: each game situation maps to **one**
11event. Handlers infer related state (e.g. XP/gold) from the event payload
12or the player node, rather than receiving multiple parallel events for the
13same kill.
14"""
15
16from __future__ import annotations
17
18from dataclasses import dataclass
19from typing import TYPE_CHECKING
20
21if TYPE_CHECKING:
22    from simvx.core import Node
23
24    from .nodes.boss_enemy import BossEnemy
25    from .nodes.player import Player
26
27
28@dataclass(frozen=True)
29class PlayerDied:
30    """Emitted by :class:`Player` when ``hp`` first reaches zero."""
31
32    player: Player
33
34
35@dataclass(frozen=True)
36class PlayerLevelledUp:
37    """Emitted by :class:`Player` when XP crosses a level boundary."""
38
39    player: Player
40    new_level: int
41
42
43@dataclass(frozen=True)
44class HotbarSlotClicked:
45    """Emitted by :class:`PlayerHUD` on a short hotbar click."""
46
47    slot: int
48
49
50@dataclass(frozen=True)
51class HotbarSlotLongPressed:
52    """Emitted by :class:`PlayerHUD` on a long hotbar press / right-click."""
53
54    slot: int
55
56
57@dataclass(frozen=True)
58class BossDefeated:
59    """Emitted by :class:`BossEnemy` when its hp drops to zero.
60
61    Distinct from regular enemy death because the game ends the run on this
62    event (victory screen). Carries the boss reference so subscribers can
63    snapshot final stats before the node is freed.
64    """
65
66    boss: BossEnemy
67
68
69@dataclass(frozen=True)
70class BossPhaseChanged:
71    """Emitted by :class:`BossEnemy` when its hp ratio crosses a phase break."""
72
73    boss: BossEnemy
74    new_phase: int
75
76
77@dataclass(frozen=True)
78class EnemyKilled:
79    """Emitted by :class:`EnemyBase` when its hp first reaches zero.
80
81    Distinct from :class:`BossDefeated` -- regular enemy deaths do not end the
82    run. The ``enemy`` reference lets subscribers snapshot stats (archetype,
83    xp_reward, position) before the node's death animation completes and the
84    node is destroyed.
85    """
86
87    enemy: Node