feat(city): add east shore beach leisure activity

Characters can now relax on the beach sand to recover energy and
health. The server clamps position to the shoreline, exposes beach
geometry in the city payload, and the client renders animated waves,
sand, stalls, chairs, and ambient NPCs.

Includes Beach support class, new beach action endpoint, localization
strings, and feature tests.
This commit is contained in:
2026-10-31 20:35:22 -03:00
parent 4b71a9d0ff
commit b8c31e7be4
12 changed files with 827 additions and 5 deletions
+7
View File
@@ -212,6 +212,13 @@
"city.exercise_active": "Exercising",
"city.exercise_stopHint": "to stop",
"city.exercise_ok": "Nice! +2 health.",
"city.beach_need": "To relax, head to the beach.",
"city.beach_ok": "You relaxed at the beach and recovered energy!",
"city.beach_full": "Energy and health are already at max.",
"city.beach_busy": "Finish your current exercise first.",
"city.beach_start": "Resting on the sand…",
"city.beach_prompt": "Relax at the beach",
"city.beach_active": "Relaxing at the beach",
"city.exercise_need_equipment": "Get closer to plaza gym equipment.",
"city.exercise_need_awake": "You must be awake to exercise.",
"city.exercise_tired": "You are too tired to exercise.",
+7
View File
@@ -212,6 +212,13 @@
"city.exercise_active": "Ejercitándose",
"city.exercise_stopHint": "para parar",
"city.exercise_ok": "¡Bien! +2 de salud.",
"city.beach_need": "Para relajar, ve a la playa.",
"city.beach_ok": "¡Relajaste en la playa y recuperaste energía!",
"city.beach_full": "La energía y la salud ya están al máximo.",
"city.beach_busy": "Termina el ejercicio actual primero.",
"city.beach_start": "Descansando en la arena…",
"city.beach_prompt": "Relajar en la playa",
"city.beach_active": "Relajándote en la playa",
"city.exercise_need_equipment": "Acérquese a un equipo de la plaza.",
"city.exercise_need_awake": "Debe estar despierto para ejercitarse.",
"city.exercise_tired": "Está demasiado cansado para ejercitarse.",
+7
View File
@@ -212,6 +212,13 @@
"city.exercise_active": "Exercitando",
"city.exercise_stopHint": "para parar",
"city.exercise_ok": "Boa! +2 de saúde.",
"city.beach_need": "Para relaxar, vá até a praia.",
"city.beach_ok": "Você relaxou na praia e recuperou ânimo!",
"city.beach_full": "Energia e saúde já estão no máximo.",
"city.beach_busy": "Termine o exercício atual primeiro.",
"city.beach_start": "Descansando na areia…",
"city.beach_prompt": "Relaxar na praia",
"city.beach_active": "Relaxando na praia",
"city.exercise_need_equipment": "Aproxime-se de um equipamento da praça.",
"city.exercise_need_awake": "Você precisa estar acordado para se exercitar.",
"city.exercise_tired": "Você está cansado demais para se exercitar.",