fly <direction> moves the player 5 tiles, ignoring terrain. Leaves a trail of bright white ~ clouds that fade after 2 seconds. Effects system supports arbitrary timed visual overlays on the viewport. TinTin aliases: fn/fs/fe/fw/fne/fnw/fse/fsw.
46 lines
1.2 KiB
Python
46 lines
1.2 KiB
Python
"""Temporary visual effects that appear on the map and fade over time."""
|
|
|
|
import time
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass
|
|
class Effect:
|
|
"""A temporary visual overlay on the world map."""
|
|
|
|
x: int
|
|
y: int
|
|
char: str
|
|
color: str # ANSI color code
|
|
expires_at: float # monotonic time when this effect disappears
|
|
|
|
|
|
# Global list of active effects
|
|
active_effects: list[Effect] = []
|
|
|
|
|
|
def add_effect(x: int, y: int, char: str, color: str, ttl: float) -> None:
|
|
"""Add a temporary visual effect at (x, y).
|
|
|
|
Args:
|
|
x: World X coordinate
|
|
y: World Y coordinate
|
|
char: Character to display
|
|
color: ANSI color code for rendering
|
|
ttl: Time to live in seconds
|
|
"""
|
|
active_effects.append(
|
|
Effect(x=x, y=y, char=char, color=color, expires_at=time.monotonic() + ttl)
|
|
)
|
|
|
|
|
|
def get_effects_at(x: int, y: int) -> list[Effect]:
|
|
"""Get all non-expired effects at a given position."""
|
|
now = time.monotonic()
|
|
return [e for e in active_effects if e.x == x and e.y == y and e.expires_at > now]
|
|
|
|
|
|
def clear_expired() -> None:
|
|
"""Remove all expired effects from the active list."""
|
|
now = time.monotonic()
|
|
active_effects[:] = [e for e in active_effects if e.expires_at > now]
|