diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index b13588a..1c07ada 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -13171,6 +13171,11 @@ func _on_dialogue_requested(lines: Array) -> void: func _on_combat_feedback_requested(unit_id: String, text: String, kind: String) -> void: + if _should_suppress_floating_feedback_text(text, kind): + var quiet_sfx_key := _combat_feedback_sfx_key(text, kind) + if not quiet_sfx_key.is_empty(): + _play_sfx(quiet_sfx_key) + return var unit := state.get_unit(unit_id) if unit.is_empty(): return @@ -13185,7 +13190,7 @@ func _on_combat_feedback_requested(unit_id: String, text: String, kind: String) floating_texts.append({ "text": text, "kind": kind, - "pos": _floating_text_origin(cell) + Vector2(jitter, 0), + "pos": _floating_text_origin(cell) + Vector2(jitter, 0) + _floating_text_kind_offset(kind), "age": -delay, "duration": FLOATING_TEXT_LIFETIME, "focus_cell": cell, @@ -13200,6 +13205,10 @@ func _on_combat_feedback_requested(unit_id: String, text: String, kind: String) queue_redraw() +func _should_suppress_floating_feedback_text(text: String, kind: String) -> bool: + return kind == "progress" and text.strip_edges().begins_with("공적 +") + + func _on_combat_result_reported(report: Dictionary) -> void: if report.is_empty(): return @@ -13382,9 +13391,33 @@ func _format_combat_progress_line(progress_value, fallback_name: String, fallbac func _combat_feedback_sfx_key(text: String, kind: String) -> String: if kind == "reinforcement" or text == "증원": return "footstep" + if kind == "damage" or text.begins_with("-"): + return "hit_heavy" + if kind == "miss" or text == "헛침": + return "guard_block" + if kind == "defeat" or kind == "fade" or text == "퇴각": + return "defeat_sting" + if kind == "heal" or kind == "mp" or kind == "support": + return "skill_cast" + if kind == "item" or kind == "gold": + return "item_pickup" + if kind == "progress": + return "menu_confirm" return "" +func _floating_text_kind_offset(kind: String) -> Vector2: + if kind == "progress": + return Vector2(-30.0, 22.0) + if kind == "heal" or kind == "mp" or kind == "support" or kind == "item" or kind == "gold": + return Vector2(0.0, 18.0) + if kind == "miss" or kind == "defeat" or kind == "fade": + return Vector2(0.0, -12.0) + if kind == "reinforcement" or kind == "priority": + return Vector2(0.0, -18.0) + return Vector2.ZERO + + func _on_unit_motion_requested(unit_id: String, from_cell: Vector2i, to_cell: Vector2i) -> void: if unit_id.is_empty() or from_cell == to_cell: return diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 4ba266f..d28bc7a 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -4146,6 +4146,35 @@ func _check_ancient_ui_theme(failures: Array[String]) -> void: failures.append("reinforcement feedback should use a distinct floating text color") if scene._combat_feedback_sfx_key("증원", "reinforcement") != "footstep": failures.append("reinforcement feedback should use the footstep arrival SFX") + if scene._combat_feedback_sfx_key("-18", "damage") != "hit_heavy": + failures.append("damage feedback should play a clear impact SFX") + if scene._combat_feedback_sfx_key("헛침", "miss") != "guard_block": + failures.append("miss feedback should play a guarded/missed SFX") + if scene._combat_feedback_sfx_key("퇴각", "defeat") != "defeat_sting": + failures.append("defeat feedback should play a retreat sting SFX") + if scene._combat_feedback_sfx_key("+8 병력", "heal") != "skill_cast": + failures.append("healing feedback should play a skill SFX") + if scene._combat_feedback_sfx_key("공적 +10", "progress") != "menu_confirm": + failures.append("merit feedback should play a clear confirmation SFX") + if not scene._should_suppress_floating_feedback_text("공적 +10", "progress"): + failures.append("routine merit feedback should be shown in the combat report instead of cluttering the map") + if scene._should_suppress_floating_feedback_text("품계 2", "progress"): + failures.append("level-up feedback should still appear as a floating battlefield cue") + scene.title_sfx_enabled = true + scene.title_sfx_volume_percent = BattleSceneScript.DEFAULT_AUDIO_VOLUME_PERCENT + scene.recent_sfx_keys.clear() + var floating_count_before_merit: int = scene.floating_texts.size() + scene._on_combat_feedback_requested("cao_cao", "공적 +10", "progress") + if scene.floating_texts.size() != floating_count_before_merit: + failures.append("routine merit feedback should not add overlapping floating text") + if not scene.recent_sfx_keys.has("menu_confirm"): + failures.append("routine merit feedback should still play an audible confirmation") + var progress_popup_offset: Vector2 = scene._floating_text_kind_offset("progress") + if progress_popup_offset.x >= 0.0 or progress_popup_offset.y <= 0.0: + failures.append("merit feedback should be offset from impact text so experience remains readable: %s" % str(progress_popup_offset)) + var miss_popup_offset: Vector2 = scene._floating_text_kind_offset("miss") + if miss_popup_offset.y >= 0.0: + failures.append("miss feedback should be lifted away from merit and damage text: %s" % str(miss_popup_offset)) if not scene._combat_feedback_sfx_key("표적", "priority").is_empty(): failures.append("priority targeting feedback should not inherit reinforcement arrival SFX") scene.recent_sfx_keys.clear()