Quiz jouable : budget de récompense, boîte à quiz, widget score
- 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>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
e972acf9e6
commit
b5546df044
@@ -65,6 +65,50 @@ def render_scene_object(obj):
|
||||
f'<button type="button" class="dialogueBoxNextBtn" data-dialogue-role="next-btn" onclick="forgeDialogueBoxAdvance({obj["id"]})">Suivant →</button>'
|
||||
f'</div></div>'
|
||||
)
|
||||
if obj["kind"] == "quiz_box":
|
||||
# Widget "❓ Boîte à quiz" (voir "🖥️ Interface") — réutilise le
|
||||
# MÊME style que "💬 Boîte de dialogue" (resolve_dialogue_box_style/
|
||||
# set_scene_object_dialogue_box_style, une seule "🎨 Style" pour
|
||||
# les deux) : header = la question, corps = les choix de réponse
|
||||
# (boutons remplis EN JEU par static/js/play/dialogue-box-controller.js,
|
||||
# data-quiz-role sert de sélecteur) — pas de pied (une question se
|
||||
# résout au clic sur un choix, pas de "Suivant"). Masqué par
|
||||
# défaut au jeu, comme la boîte de dialogue.
|
||||
style = resolve_dialogue_box_style(obj)
|
||||
box_style = (
|
||||
f"position:absolute; left:{obj['x']}px; top:{obj['y']}px; "
|
||||
f"width:{obj['width']}px; height:{obj['height']}px; z-index:{obj['z_index']}; "
|
||||
f"font-family:{html_lib.escape(style['font_family'])}; font-size:{style['font_size']}px; "
|
||||
f"font-weight:{style['font_weight']}; color:{html_lib.escape(style['text_color'])};"
|
||||
)
|
||||
return (
|
||||
f'<div class="quizBoxWidget" data-object-id="{obj["id"]}" data-element-id="{obj["id"]}" style="{box_style}">'
|
||||
f'<div class="quizBoxHeader" data-quiz-role="header" style="background:{html_lib.escape(style["header_bg"])}">La question s\'affiche ici.</div>'
|
||||
f'<div class="quizBoxChoices" data-quiz-role="choices" style="background:{html_lib.escape(style["body_bg"])}">'
|
||||
f'<button type="button" class="quizBoxChoiceBtn" disabled>Choix A</button>'
|
||||
f'<button type="button" class="quizBoxChoiceBtn" disabled>Choix B</button>'
|
||||
f'</div></div>'
|
||||
)
|
||||
if obj["kind"] == "score_widget":
|
||||
# Widget "🏆 Score" (voir "🖥️ Interface") — toujours VISIBLE une
|
||||
# fois posé (pas de collision/déclencheur, contrairement aux deux
|
||||
# widgets ci-dessus) : affiche en continu le score de la partie en
|
||||
# cours (voir static/js/play/dialogue-box-controller.js::
|
||||
# forgeUpdateAllScoreWidgets). Même style que les deux autres
|
||||
# widgets, header_bg sert de fond unique (pas de zone body/footer).
|
||||
style = resolve_dialogue_box_style(obj)
|
||||
box_style = (
|
||||
f"position:absolute; left:{obj['x']}px; top:{obj['y']}px; "
|
||||
f"width:{obj['width']}px; height:{obj['height']}px; z-index:{obj['z_index']}; "
|
||||
f"font-family:{html_lib.escape(style['font_family'])}; font-size:{style['font_size']}px; "
|
||||
f"font-weight:{style['font_weight']}; color:{html_lib.escape(style['text_color'])}; "
|
||||
f"background:{html_lib.escape(style['header_bg'])};"
|
||||
)
|
||||
return (
|
||||
f'<div class="scoreWidget" data-object-id="{obj["id"]}" data-element-id="{obj["id"]}" style="{box_style}">'
|
||||
f'🏆 <span data-score-role="value">0</span>'
|
||||
f'</div>'
|
||||
)
|
||||
if obj["kind"] == "personnage":
|
||||
src = resolve_personnage_idle_frame(obj)
|
||||
src_attr = f' src="{html_lib.escape(src)}"' if src else ""
|
||||
|
||||
Reference in New Issue
Block a user