Each cloud in the trail gets a slightly longer TTL than the one before it (0.15s stagger). The origin cloud dissolves first, then each subsequent tile follows. Two consecutive flights produce a trail where the oldest clouds are already gone.
94 lines
2.8 KiB
Python
94 lines
2.8 KiB
Python
"""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 <dir> - 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)
|