Supprime le concept de "quête" au profit d'un onglet unique "Déclencheurs"
portant toute la logique (dialogue, condition, marquage terminé) directement
sur l'objet de scène. Ajoute une nouvelle action "Modifier une variable"
(réutilisant le vocabulaire du graphe de flow) utilisable après une
collision, une interaction ou une branche de condition, ainsi qu'un
chaînage d'actions ("then") permettant d'enchaîner plusieurs actions à la
suite et d'étendre un déclencheur déjà posé sans le recréer.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
SCORM/xAPI :
- Ajoute l'export SCORM 2004 (3rd/4th edition) au choix, en plus du 1.2
par défaut : sépare completion_status/success_status (un échec reste
"completed" au lieu de retomber à tort en "incomplete" comme force la
1.2), remonte aussi cmi.interactions.n.* par question répondue.
- Fournit cmi.core.score.min/max (1.2 et 2004), calculé depuis les
récompenses de quiz du jeu, pour que le LMS affiche un vrai pourcentage
au lieu du score brut à tort étiqueté "%".
- Libellés de verbes xAPI en français en plus de l'anglais.
Accessibilité (RGAA/WCAG 2.1 AA) sur le player :
- Navigation clavier des objets de scène "au clic"/"au survol"
(tabindex, role, Entrée/Espace, focus/blur).
- alt sur les images (nom auteur ou décoratif), aria-hidden sur les
icônes seules, role="dialog"/aria-live sur les boîtes de dialogue/quiz.
- Landmark <main> + titre de page, respect de prefers-reduced-motion.
- Le quiz n'avance plus automatiquement après un délai fixe : bouton
"Continuer →" explicite (RGAA 2.2.1).
- Avertissement de contraste dans l'éditeur de style de dialogue.
- Déclaration d'accessibilité téléchargeable depuis la modale d'export.
Greffe l'envoi de statements xAPI vers un LRS configurable par le
créateur du jeu, en parallèle du reporting SCORM existant : réglages
stockés en base (_meta), formulaire dans la modale d'export, injection
dans le paquet exporté. Relié aussi bien à l'action de flow "Modifier
un score/statut" qu'au parcours quête/quiz (qui alimentait déjà le
SCORM classique via un chemin séparé).
L'export ne se lance plus automatiquement à l'ouverture de la modale,
pour laisser le temps d'enregistrer les réglages xAPI avant de générer
le paquet.
Les quêtes/quiz mettaient à jour l'état local (statut, score) sans
jamais toucher gameData.scoring, que scorm-api.js interroge déjà pour
reporter Completion/Success/Score au LMS. Ajoute forgeSyncQuizScoreToScorm,
forgeSyncQuestStartedToScorm et forgeSyncAllQuestsCompletionToScorm,
appelées lors d'un bon score, de l'acceptation d'une quête et de la
complétion de toutes les quêtes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Bug corrigé : les panneaux flottants "🧩 Objets"/"⚙️ Propriétés" sont en
position:fixed (hors du flux flex de .builder3) — ils flottaient
PAR-DESSUS le canevas sans jamais réduire sa largeur, rendant sa
partie droite/gauche inaccessible au clic/glisser tant qu'un panneau
restait ouvert. .builderCanvasArea réserve maintenant leur largeur
(marge) dès qu'un panneau est ouvert (:has()).
- Boîte à quiz : header = "Quête : <titre>" (au lieu du texte de la
question), corps = la question ET ses choix ensemble.
- Mauvaise réponse : ne bloque plus JAMAIS la progression (bug signalé :
"je suis obligé de bien répondre sinon j'avance pas") — surligne la
bonne réponse en vert (le choix cliqué en rouge s'il était faux) puis
avance automatiquement après un court délai, sans jamais octroyer de
points. Un second clic pendant la révélation est ignoré.
- Animations : la boîte à quiz rejoue une entrée (pop-in) à CHAQUE
nouvelle question, la bonne réponse pulse en vert, une mauvaise
réponse "secoue" en rouge.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Récompense d'une quête = budget MAXIMUM pour ses questions : la somme
des points des "❓ Question" ne peut plus dépasser recompense_score
(routes/quests/quest_dialogues.py à l'enregistrement des dialogues,
quest_update.py si on abaisse la récompense sous ce qui est déjà
réparti) — message d'erreur explicite (400) dans les deux sens,
affiché via alert() côté éditeur (quest-editor.js), jamais enregistré
silencieusement dans un état incohérent.
- Nombre de choix par question plafonné à 4 (au lieu de 8).
- Deux nouveaux widgets "🖥️ Interface" (mêmes fondations que "💬 Boîte
de dialogue" — screens/rendering/dialogue_box_style.py, même panneau
"🎨 Style") :
- "❓ Boîte à quiz" : affiche la question et ses choix, sans pied (une
question se résout au clic sur un choix, pas de "Suivant").
- "🏆 Score" : affiche en continu les points gagnés, TOUJOURS visible
une fois posé (contrairement aux boîtes de dialogue/quiz, masquées
par défaut).
- Moteur d'exécution (static/js/play/dialogue-box-controller.js,
refonte) : une conversation de quête alterne maintenant répliques
(boîte de dialogue) et questions (boîte à quiz) selon le type de
chaque ligne. Bonne réponse -> crédite le score (compteur runtime
dédié, jamais lié au score du moteur document) et avance ; mauvaise
réponse -> rien, la question reste affichée pour réessayer ; aucune
boîte à quiz posée -> la question est ignorée plutôt que de bloquer
la conversation. Le dialogue "en_cours" épuisé (donc, s'il contenait
des questions, toutes répondues) fait passer la quête "terminee" (en
mémoire seulement, comme le reste de ce système — voir accepter/
refuser une offre de quête) : le joueur peut alors quitter la scène
normalement, ces widgets n'étant jamais des obstacles.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Une fois le dialogue épuisé, si la quête est encore "nouvelle", la
boîte de dialogue bascule sur un écran d'offre au lieu de se masquer :
header "Quête : <titre>", body l'objectif, pied deux boutons.
- Accepter -> la quête passe "en_cours" (en MÉMOIRE seulement,
gameData.quests — jamais persisté en base : le statut en base est
celui de DÉPART pour toute nouvelle partie, pas un état de partie en
cours, voir PLAYER_SHARED/full_game_payload.py).
- Refuser -> la boîte se referme SANS toucher au statut, qui reste
"nouvelle" : la prochaine interaction rejoue exactement le même
dialogue depuis le début — impossible d'avancer la quête sans
l'accepter un jour.
Pour tout autre statut (déjà "en_cours"/"terminee"), la boîte se
masque normalement à la fin du dialogue, comme avant.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- "ℹ️ 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>