"""Fly command for aerial movement across the world."""
from typing import Any
from mudlib.commands import register
from mudlib.commands.movement import DIRECTIONS, send_nearby_message
from mudlib.effects import add_effect
from mudlib.player import Player
from mudlib.render.ansi import BOLD, BRIGHT_WHITE
# World instance will be injected by the server
world: Any = None
# how far you fly
FLY_DISTANCE = 5
# origin cloud gets the base ttl, each step toward destination adds stagger.
# trail visibly shrinks from origin toward the player, one tile at a time.
CLOUD_TTL = 1.5
CLOUD_STAGGER = 0.4 # seconds between each cloud's expiry
# ANSI color for cloud trails
CLOUD_COLOR = BOLD + BRIGHT_WHITE
async def cmd_fly(player: Player, args: str) -> None:
"""Toggle flying or move while airborne.
fly - toggle flying on/off
fly
- move 5 tiles in a direction (must be flying)
"""
direction = args.strip().lower()
# no args = toggle flying state
if not direction:
if player.flying:
player.flying = False
player.writer.write("You land.\r\n")
await player.writer.drain()
await send_nearby_message(
player,
player.x,
player.y,
f"{player.name} lands.\r\n",
)
else:
player.flying = True
player.writer.write("You fly into the air!\r\n")
await player.writer.drain()
await send_nearby_message(
player,
player.x,
player.y,
f"{player.name} lifts into the air!\r\n",
)
return
# direction given but not flying
if not player.flying:
player.writer.write("You aren't flying.\r\n")
await player.writer.drain()
return
delta = DIRECTIONS.get(direction)
if delta is None:
player.writer.write(f"'{direction}' isn't a direction.\r\n")
await player.writer.drain()
return
dx, dy = delta
start_x, start_y = player.x, player.y
# lay cloud trail at starting position and each intermediate step.
# origin cloud expires first, near-dest cloud lingers longest.
# the trail shrinks from behind toward the player over time.
for step in range(FLY_DISTANCE):
trail_x, trail_y = world.wrap(start_x + dx * step, start_y + dy * step)
ttl = CLOUD_TTL + step * CLOUD_STAGGER
add_effect(trail_x, trail_y, "~", CLOUD_COLOR, ttl=ttl)
# move player to destination
dest_x, dest_y = world.wrap(
start_x + dx * FLY_DISTANCE, start_y + dy * FLY_DISTANCE
)
player.x = dest_x
player.y = dest_y
# auto-look at new position
from mudlib.commands.look import cmd_look
await cmd_look(player, "")
register("fly", cmd_fly)