Hints used to be 11 hardcoded PHP strings/thresholds in
SendMainframeHintsCommand, walked through a fixed if/else chain. They
are now Hint rows (game, condition, thresholdSeconds, message,
sortOrder) manageable at /admin/games/{game}/hints - freely
addable, removable, and reorderable per game, which sets up exactly
what's needed for difficulty-dependent hint timing later (Easy/Medium/
Hard are separate games, so each gets its own hint set).
The condition a hint fires behind (e.g. "hasn't used help yet",
"isn't verified yet") is still a fixed, code-defined check
(HintCondition enum) tied to real game state - a true free-form
condition editor would need a full rules engine, which is out of
scope. What's fully free-form is which hints exist, in what order,
gated behind which of those conditions, with what wording and timing.
SendMainframeHintsCommand now reads hints from the DB: walking them in
sortOrder, it finds the first distinct condition still unresolved for
a player, fires the most-escalated hint sharing that condition whose
threshold has passed, and stops - matching the original "stop at the
first unresolved, dependent step" behavior.
Migration seeds every existing game with the previous hardcoded
hints so behavior doesn't regress on deploy. Two minor fidelity
simplifications from the original hardcoded logic, called out here
since they're easy to miss: the "go to rapports directory" hint no
longer additionally checks whether the player is already in that
folder, and the two chat hints are now independent conditions
(broadcast done / contacted everyone privately) instead of one
combined check - both are edge-case-only behavior changes, not
regressions in the common path.
66 lines
3.7 KiB
Twig
66 lines
3.7 KiB
Twig
{% extends 'game/admin/base.html.twig' %}
|
|
|
|
{% block title %}Edit Hint — {{ game.name }} — Admin{% endblock %}
|
|
|
|
{% block admin_body %}
|
|
<div style="margin-bottom: 1.5rem;">
|
|
<a href="{{ path('game_admin_hints', {game: game.id}) }}" style="color: #64748b; text-decoration: none; font-size: 0.9rem;">← Hints — {{ game.name }}</a>
|
|
</div>
|
|
|
|
<h1 style="margin: 0 0 1.5rem; font-size: 1.5rem; color: #0f172a;">Edit hint</h1>
|
|
|
|
<div style="background: #fff; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,.07); padding: 1.5rem; max-width: 560px;">
|
|
{{ form_start(form, {attr: {style: 'display: flex; flex-direction: column; gap: 1.25rem;'}}) }}
|
|
|
|
<div>
|
|
{{ form_label(form.condition, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }}
|
|
{{ form_widget(form.condition, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }}
|
|
{{ form_errors(form.condition) }}
|
|
</div>
|
|
|
|
<div>
|
|
{{ form_label(form.thresholdSeconds, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }}
|
|
{{ form_widget(form.thresholdSeconds, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }}
|
|
<small style="color: #64748b; font-size: 0.8rem;">Seconds since the game started — e.g. 300 = 5 minutes</small>
|
|
{{ form_errors(form.thresholdSeconds) }}
|
|
</div>
|
|
|
|
<div>
|
|
{{ form_label(form.message, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }}
|
|
{{ form_widget(form.message, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }}
|
|
{{ form_errors(form.message) }}
|
|
</div>
|
|
|
|
<div>
|
|
{{ form_label(form.sortOrder, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }}
|
|
{{ form_widget(form.sortOrder, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }}
|
|
<small style="color: #64748b; font-size: 0.8rem;">Hints are evaluated in ascending order — use gaps (10, 20, 30…) to leave room to insert later</small>
|
|
{{ form_errors(form.sortOrder) }}
|
|
</div>
|
|
|
|
<div style="display: flex; gap: 0.75rem; margin-top: 0.5rem;">
|
|
<button type="submit" style="
|
|
padding: 0.6rem 1.25rem;
|
|
background: #3b82f6;
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 6px;
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
">Save changes</button>
|
|
<a href="{{ path('game_admin_hints', {game: game.id}) }}" style="
|
|
padding: 0.6rem 1.25rem;
|
|
background: #f1f5f9;
|
|
color: #475569;
|
|
border-radius: 6px;
|
|
font-size: 0.9rem;
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
">Cancel</a>
|
|
</div>
|
|
|
|
{{ form_end(form) }}
|
|
</div>
|
|
{% endblock %}
|