feat(city): add bump-to-talk conversations with persistent context

Implements proximity-based street conversations between player characters and peers (human or agentic NPC). New PersonTalk model, controller, and migrations store daily message threads that persist across sessions and provide context for future interactions. Agent replies include backoff throttling and fallback persona handling to avoid dead-end chats.

Frontend changes refactor the chat panel to support both character and agent peers, opening automatically when the player moves within range, polling for replies, rendering day separators, and displaying rate-limit warnings. Styling updated to a transparent blurred panel. Translations extended with new hint text and rate-limit messages across en, es, and pt_BR.
This commit is contained in:
2026-10-31 17:59:22 -03:00
parent 50a6d40e8e
commit 59963de995
13 changed files with 1475 additions and 57 deletions
+2 -1
View File
@@ -88,7 +88,7 @@
"city.error": "Failed to load city data.",
"city.stores_count": "stores",
"city.agents_count": "agents",
"city.hint": "Click the scene to control · WASD to walk · Mouse to look · Esc to exit",
"city.hint": "Click the scene to control · WASD to walk · Mouse to look · Esc to exit · Get close to someone to talk",
"city.refresh": "Reload",
"city.selected": "Selected",
"city.open": "Open",
@@ -102,6 +102,7 @@
"city.chat_responding": "responding…",
"city.chat_accepted": "Message sent to agent.",
"city.chat_error": "Sorry, I can't reply right now. Please try again.",
"city.talk_ratelimited": "Too many messages — wait a moment and try again.",
"city.chat_send": "Send",
"city.chat_with": "Chatting with",
"city.clock": "Time",
+2 -1
View File
@@ -88,7 +88,7 @@
"city.error": "Error al cargar los datos de la ciudad.",
"city.stores_count": "tiendas",
"city.agents_count": "agentes",
"city.hint": "Haz clic en la escena para controlar · WASD para caminar · Ratón para mirar · Esc para salir",
"city.hint": "Haz clic en la escena para controlar · WASD para caminar · Ratón para mirar · Esc para salir · Acércate a alguien para hablar",
"city.refresh": "Recargar",
"city.selected": "Seleccionada",
"city.open": "Abierta",
@@ -102,6 +102,7 @@
"city.chat_responding": "respondiendo…",
"city.chat_accepted": "Mensaje enviado al agente.",
"city.chat_error": "Lo siento, no puedo responder ahora. Inténtalo de nuevo.",
"city.talk_ratelimited": "Muchos mensajes — espera un instante e inténtalo de nuevo.",
"city.chat_send": "Enviar",
"city.chat_with": "Chateando con",
"city.clock": "Hora",
+2 -1
View File
@@ -88,7 +88,7 @@
"city.error": "Falha ao carregar os dados da cidade.",
"city.stores_count": "lojas",
"city.agents_count": "agentes",
"city.hint": "Clique na tela para controlar · WASD para andar · Mouse para olhar · Esc para sair",
"city.hint": "Clique na tela para controlar · WASD para andar · Mouse para olhar · Esc para sair · Chegue perto de alguém para conversar",
"city.refresh": "Recarregar",
"city.selected": "Selecionada",
"city.open": "Aberta",
@@ -102,6 +102,7 @@
"city.chat_responding": "respondendo…",
"city.chat_accepted": "Mensagem enviada ao agente.",
"city.chat_error": "Desculpe, não consegui responder agora. Tente novamente.",
"city.talk_ratelimited": "Muitas mensagens — aguarde um instante e tente de novo.",
"city.chat_send": "Enviar",
"city.chat_with": "Conversando com",
"city.clock": "Horário",