Éditeur de quêtes : titre/objectif/récompense/statut/résultat + dialogue à 3 colonnes
Build and deploy / test-python (push) Successful in 6m14s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped

Nouvel espace "🗺️ Quêtes" (game-wide, comme les événements
personnalisés) : liste de cartes + "+ Nouvelle quête", chaque carte
ouvrant une modale d'arbre de dialogue en bulles de théâtre
("speaker: texte"), une colonne par statut de quête (nouvelle/en
cours/terminée) puisque le dialogue joué dépend de l'état de la
quête au moment où le joueur parle au PNJ. Bulles alternées
joueur/PNJ, couleur différente selon qui parle.

L'action "Déclencher une quête" de l'éditeur de collision n'est plus
un champ texte libre : elle ouvre directement CETTE MÊME modale
(picker de quêtes existantes + création à la volée), et finalise la
règle avec l'id numérique de la quête choisie — collision_rules.py
migré en conséquence (quete_id devient un entier, comme evenement_id).

Corrige aussi la miniature d'objet de la carte "🧩 Collision", 3× plus
grande (120px) comme demandé.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
william
2026-09-02 20:24:57 +02:00
co-authored by Claude Sonnet 5
parent 4391b36d45
commit 51427b5297
28 changed files with 881 additions and 29 deletions
+1 -1
View File
@@ -1 +1 @@
from . import auth, games, objects, screens, elements, legacy_actions, flow, element_types, uploads, play, animations, global_vars, publish, custom_events, flow_blocks, scenes, onboarding
from . import auth, games, objects, screens, elements, legacy_actions, flow, element_types, uploads, play, animations, global_vars, publish, custom_events, flow_blocks, scenes, onboarding, quests
+1
View File
@@ -0,0 +1 @@
from . import quests_view, quests_list_json, quest_new, quest_update, quest_delete, quest_dialogues
+11
View File
@@ -0,0 +1,11 @@
from flask import jsonify
import db
from core.flask_app import app
@app.route("/game/<slug>/quests/<int:quest_id>/delete", methods=["POST"])
def quest_delete(slug, quest_id):
db.delete_quest(slug, quest_id)
return jsonify({"ok": True})
+17
View File
@@ -0,0 +1,17 @@
from flask import jsonify, request
import db
from core.flask_app import app
@app.route("/game/<slug>/quests/<int:quest_id>/dialogues", methods=["POST"])
def quest_dialogues(slug, quest_id):
"""Toujours les 3 colonnes ENTIÈRES (voir db.set_quest_dialogues) —
le client (renderQuestDialogueColumns, quest-editor.js) poste l'objet
complet à chaque modification plutôt qu'une réplique isolée."""
body = request.get_json(silent=True) or {}
dialogues = db.set_quest_dialogues(slug, quest_id, body.get("dialogues"))
if dialogues is None:
return jsonify({"error": "quête introuvable"}), 404
return jsonify({"dialogues": dialogues})
+12
View File
@@ -0,0 +1,12 @@
from flask import jsonify, request
import db
from core.flask_app import app
@app.route("/game/<slug>/quests/new", methods=["POST"])
def quest_new(slug):
body = request.get_json(silent=True) or {}
quest = db.create_quest(slug, body.get("title"))
return jsonify({"quest": quest})
+14
View File
@@ -0,0 +1,14 @@
from flask import jsonify, request
import db
from core.flask_app import app
@app.route("/game/<slug>/quests/<int:quest_id>", methods=["POST"])
def quest_update(slug, quest_id):
body = request.get_json(silent=True) or {}
quest = db.update_quest(slug, quest_id, body)
if quest is None:
return jsonify({"error": "quête introuvable"}), 404
return jsonify({"quest": quest})
+14
View File
@@ -0,0 +1,14 @@
from flask import jsonify
import db
from core.flask_app import app
@app.route("/game/<slug>/quests/list.json")
def quests_list_json(slug):
"""Utilisé par l'assistant "+ Action" de l'éditeur de collision (voir
collision-rules-editor.js) pour lister les quêtes existantes sans
quitter la modale déjà ouverte — même contenu que quests_view, en JSON
seul plutôt qu'une page complète."""
return jsonify({"quests": db.list_quests(slug)})
+20
View File
@@ -0,0 +1,20 @@
import json
from flask import render_template
import db
from core.flask_app import app
@app.route("/game/<slug>/quests")
def quests_view(slug):
"""Éditeur de quêtes (voir db/quests/) — page dédiée game-wide, dans le
même esprit que game_dashboard.html : une liste de cartes + un bouton
"+ Nouvelle quête" au-dessus, chaque carte ouvrant une modale avec
l'arbre de dialogue (static/js/quests/quest-editor.js — même module
JS que celui rendu depuis l'assistant "+ Action" de l'éditeur de
collision, voir collision-rules-editor.js)."""
game = db.game_meta(slug)
quests = db.list_quests(slug)
return render_template("quests.html", game=game, quests_json=json.dumps(quests))
+6
View File
@@ -128,4 +128,10 @@ def render_scene_edit(slug, screen_id, game):
collision_rule_objects_json=json.dumps(collision_rule_objects),
collision_action_types=screens.ACTION_TYPES, collision_trigger_types=screens.TRIGGER_TYPES,
collision_default_perimetre_px=screens.DEFAULT_PERIMETRE_PX,
# Éditeur de quêtes (voir db/quests/) : préchargées ici pour que
# collisionRuleActionSummary (collision-rules-editor.js) affiche
# tout de suite le TITRE de la quête référencée par une règle
# existante, sans attendre l'ouverture de l'assistant "+ Action"
# (seul moment où questPickerHtml irait la chercher sinon).
quests_json=json.dumps(db.list_quests(slug)),
)