Quêtes/collision : personnages nommés, dialogues qui parlent, boîte de dialogue en jeu
- "ℹ️ Informations" (propriétés d'un personnage) : nom éditable, réutilisé comme "qui parle" dans l'éditeur de dialogue de quête (menu déroulant, plus "Joueur" toujours disponible) — remplace l'ancien choix binaire joueur/pnj. db.sanitize_quest_dialogues accepte maintenant un nom libre. - Nouveau menu "🖥️ Interface" (palette d'objets) avec le premier widget : "💬 Boîte de dialogue" (kind="dialogue_box", screens/rendering/ dialogue_box_style.py) — position/taille comme tout objet de scène, panneau "🎨 Style" dédié (police, taille, épaisseur, couleur du texte, couleur header/body/footer). Rendu en <div> à 3 zones, jamais soumis à la collision ni à l'éditeur de collision (exclu partout : obstacles, liste des règles, payload). Rendu côté jeu dans .sceneUI, une couche FIXE au viewport (jamais .sceneWorld, qui défile avec la caméra). - static/js/play/dialogue-box-controller.js : fait le lien moteur entre l'action "quete" de l'éditeur de collision et ce widget — affiche la réplique en cours du dialogue correspondant au STATUT ACTUEL de la quête (gameData.quests, désormais exposé game-wide par full_game_payload.py), avance au clic sur "Suivant" (header = qui parle, body = texte, footer = bouton), se masque à la dernière réplique. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
390ee831ca
commit
2347a70c45
@@ -0,0 +1,72 @@
|
||||
// ---------- Widget "💬 Boîte de dialogue" — moteur d'exécution ----------
|
||||
// Fait le lien entre l'éditeur de collision (action "quete", voir
|
||||
// static/js/play/collision-rules-controller.js) et le widget d'interface
|
||||
// posé par l'auteur (voir "🖥️ Interface", templates/scene_edit.html,
|
||||
// screens/rendering/dialogue_box_style.py) : à l'exécution d'une action
|
||||
// "quete", affiche la réplique en cours du dialogue correspondant au
|
||||
// STATUT ACTUEL de la quête (gameData.quests, voir full_game_payload.py),
|
||||
// avance d'une réplique à chaque clic sur "Suivant", se masque à la fin.
|
||||
// Silencieux (aucun effet) si la quête est introuvable, n'a aucune
|
||||
// réplique pour son statut, ou si l'auteur n'a posé aucun widget sur
|
||||
// l'écran — même esprit que le reste du moteur (jamais planter).
|
||||
|
||||
var forgeDialogueBoxState = {};
|
||||
|
||||
function forgeQuestById(questId) {
|
||||
return (gameData.quests || []).find(function (q) { return q.id === questId; });
|
||||
}
|
||||
|
||||
function forgeDialogueBoxWidgetOnCurrentScreen() {
|
||||
return document.querySelector('.playScreen[data-screen-id="' + window.currentScreenId + '"] .dialogueBoxWidget');
|
||||
}
|
||||
|
||||
function forgeDialogueBoxWidgetById(objectId) {
|
||||
return document.querySelector('.dialogueBoxWidget[data-object-id="' + objectId + '"]');
|
||||
}
|
||||
|
||||
function forgeRenderDialogueBoxLine(widget, line) {
|
||||
var header = widget.querySelector('[data-dialogue-role="header"]');
|
||||
var body = widget.querySelector('[data-dialogue-role="body"]');
|
||||
if (header) header.textContent = line.speaker;
|
||||
if (body) body.textContent = line.text;
|
||||
}
|
||||
|
||||
// Appelée par l'action "quete" (collision-rules-controller.js) — trouve
|
||||
// le widget posé sur l'écran ACTUELLEMENT affiché (un seul à la fois,
|
||||
// comme le reste du moteur 2D).
|
||||
function forgeShowDialogueBox(questId) {
|
||||
var quest = forgeQuestById(questId);
|
||||
if (!quest) return;
|
||||
var lines = (quest.dialogues && quest.dialogues[quest.status]) || [];
|
||||
if (!lines.length) return;
|
||||
var widget = forgeDialogueBoxWidgetOnCurrentScreen();
|
||||
if (!widget) return;
|
||||
var objectId = widget.getAttribute('data-object-id');
|
||||
forgeDialogueBoxState[objectId] = { lines: lines, index: 0 };
|
||||
forgeRenderDialogueBoxLine(widget, lines[0]);
|
||||
widget.classList.add('is-active');
|
||||
}
|
||||
|
||||
// Appelée par le bouton "Suivant →" rendu dans le widget lui-même (voir
|
||||
// render_scene_object.py, onclick="forgeDialogueBoxAdvance(<id>)").
|
||||
function forgeDialogueBoxAdvance(objectId) {
|
||||
var state = forgeDialogueBoxState[objectId];
|
||||
var widget = forgeDialogueBoxWidgetById(objectId);
|
||||
if (!state || !widget) return;
|
||||
state.index += 1;
|
||||
if (state.index >= state.lines.length) {
|
||||
widget.classList.remove('is-active');
|
||||
delete forgeDialogueBoxState[objectId];
|
||||
return;
|
||||
}
|
||||
forgeRenderDialogueBoxLine(widget, state.lines[state.index]);
|
||||
}
|
||||
|
||||
// static/js/play/__tests__/ (node:test) — même garde que les autres
|
||||
// contrôleurs de ce dossier.
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = {
|
||||
forgeQuestById, forgeShowDialogueBox, forgeDialogueBoxAdvance,
|
||||
forgeDialogueBoxWidgetOnCurrentScreen, forgeDialogueBoxWidgetById, forgeRenderDialogueBoxLine,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user