Gate Rz Coins on correct-first-try-within-time-limit; match coin-flight animation to it

Credits were previously awarded on any first attempt regardless of
correctness or timing. The award now requires the first-ever attempt
to be correct (record.Attempt.IsCorrect) and submitted before the
adaptive per-question timer expired (new MetTimeLimit request field,
computed client-side from the same elapsed/target comparison that
already drives the visible countdown bar). The coin-flight animation
in question_player.gd now only plays when both conditions are met
(BlockSessionService.submit_core_attempt's existing "mastered" flag
plus met_time_limit), so the effect never promises a coin that isn't
actually earned.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
hz
2026-07-28 20:17:07 -05:00
co-authored by Claude Sonnet 5
parent efae7e0b2b
commit 6f41906101
8 changed files with 88 additions and 13 deletions
+27 -2
View File
@@ -8,6 +8,8 @@ var icon_panel: PanelContainer
var icon_texture: TextureRect
var value_label: Label
var caption_label: Label
var displayed_value := 0
var _initialized := false
func _ready() -> void:
@@ -17,6 +19,7 @@ func _ready() -> void:
refresh_theme_controls()
_on_credits_changed()
CreditsService.credits_changed.connect(_on_credits_changed)
resized.connect(func(): pivot_offset = size * 0.5)
func _build_ui() -> void:
@@ -50,7 +53,7 @@ func _build_ui() -> void:
value_label.add_theme_font_size_override("font_size", 15)
copy.add_child(value_label)
caption_label = Label.new()
caption_label.text = "RZ Points"
caption_label.text = "Rz Coins"
caption_label.add_theme_font_override("font", Brand.font)
caption_label.add_theme_font_size_override("font_size", 10)
copy.add_child(caption_label)
@@ -75,8 +78,30 @@ func refresh_theme_controls() -> void:
caption_label.add_theme_color_override("font_color", Brand.muted_color(dark))
func bump() -> void:
var tween := create_tween()
tween.tween_property(self, "scale", Vector2(1.12, 1.12), 0.12).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
tween.tween_property(self, "scale", Vector2.ONE, 0.18).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
func _on_credits_changed() -> void:
value_label.text = _format_thousands(CreditsService.credits) if CreditsService.loaded else "--"
if not CreditsService.loaded:
_initialized = false
displayed_value = 0
value_label.text = "--"
return
if not _initialized:
_initialized = true
displayed_value = CreditsService.credits
value_label.text = _format_thousands(displayed_value)
return
var tween := create_tween()
tween.tween_method(_set_displayed_value, displayed_value, CreditsService.credits, 0.5).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
func _set_displayed_value(value: int) -> void:
displayed_value = value
value_label.text = _format_thousands(value)
func _format_thousands(value: int) -> String: