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