diff --git a/README.md b/README.md index 3875490..cb613c6 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr - Battle HUD portrait thumbnails show the selected unit, or a hovered unit when nothing is selected. - Selected and hovered unit focus text shows combat role, movement type, current terrain move cost, terrain bonuses, core stats, and status effects. - Dialogue lines can mark speaking side for text alignment inside a fixed visual-novel-style dialogue panel with stable portrait, progress, and previous-line controls. -- Longer procedural draft menu/battle BGM plus UI, movement, attack, tactic, item, victory, and defeat SFX, with a quieter 75% default volume so first launch is less harsh. +- Named procedural draft BGM tracks for the title/camp mood (`menu_camp_dawn_theme.wav`) and the first-battle march (`battle_yingchuan_march.wav`), plus UI, movement, attack, tactic, item, victory, and defeat SFX, with a quieter 75% default volume so first launch is less harsh. - Floating combat text for damage, recovery, misses, support effects, poison ticks, action locks, level-ups, and promotions. - Short unit slide animation for board movement. - Board attacks now request class-specific motion profiles, with infantry strikes, archer traces, cavalry charges, command flashes, and heavy warrior/bandit impacts drawn by the battle scene. diff --git a/audio/bgm/battle_yingchuan_march.wav b/audio/bgm/battle_yingchuan_march.wav new file mode 100644 index 0000000..b4dfb71 Binary files /dev/null and b/audio/bgm/battle_yingchuan_march.wav differ diff --git a/audio/bgm/battle_yingchuan_march.wav.import b/audio/bgm/battle_yingchuan_march.wav.import new file mode 100644 index 0000000..adaec23 --- /dev/null +++ b/audio/bgm/battle_yingchuan_march.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://dt5dqerjssp1f" +path="res://.godot/imported/battle_yingchuan_march.wav-fc3e60dec1c23809f0b38cf91405a99c.sample" + +[deps] + +source_file="res://audio/bgm/battle_yingchuan_march.wav" +dest_files=["res://.godot/imported/battle_yingchuan_march.wav-fc3e60dec1c23809f0b38cf91405a99c.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/audio/bgm/menu_camp_dawn_theme.wav b/audio/bgm/menu_camp_dawn_theme.wav new file mode 100644 index 0000000..52d20d2 Binary files /dev/null and b/audio/bgm/menu_camp_dawn_theme.wav differ diff --git a/audio/bgm/menu_camp_dawn_theme.wav.import b/audio/bgm/menu_camp_dawn_theme.wav.import new file mode 100644 index 0000000..3280018 --- /dev/null +++ b/audio/bgm/menu_camp_dawn_theme.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://ckefe53r1vrn4" +path="res://.godot/imported/menu_camp_dawn_theme.wav-ce1d2cba4082f795366c4afbf1968152.sample" + +[deps] + +source_file="res://audio/bgm/menu_camp_dawn_theme.wav" +dest_files=["res://.godot/imported/menu_camp_dawn_theme.wav-ce1d2cba4082f795366c4afbf1968152.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 848fde1..377151f 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -15,7 +15,7 @@ - `scripts/core/campaign_state.gd`: Thin campaign save state for gold, inventory, roster, completed scenarios, and campaign flags. - `scripts/core/battle_state.gd`: Battle rules, unit state, turns, AI, and victory checks. - `scripts/scenes/battle_scene.gd`: Rendering, input handling, and HUD wiring. -- `audio/bgm/*.wav` and `audio/sfx/*.wav`: Procedural draft music loops and interface/action stingers. +- `audio/bgm/*.wav` and `audio/sfx/*.wav`: Named procedural draft music loops (`menu_camp_dawn_theme.wav`, `battle_yingchuan_march.wav`) and interface/action stingers. - `art/portraits/*.png`, `art/units/*.png`, `art/units/enemies/*.png`, `art/items/*.png`, and `art/backgrounds/*.png`: Generated visual assets used by dialogue, battle HUD, transparent board-token cutouts, generic-enemy transparent cutouts, transparent item icon cutouts, and map backdrops. - `data/campaign/campaign.json`: Campaign chapter ranges, scenario order, and scenario paths. - `data/defs/*.json`: Officers, classes, terrain, items, and skills. diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index a870f94..b37b124 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -24,8 +24,8 @@ const FORMATION_OVERLAY_COLOR := Color(0.18, 0.38, 0.34, 0.30) const OBJECTIVE_OVERLAY_COLOR := Color(0.58, 0.18, 0.12, 0.28) const THREAT_OVERLAY_COLOR := Color(0.76, 0.060, 0.035, 0.20) const THREAT_BORDER_COLOR := Color(0.86, 0.18, 0.10, 0.48) -const BGM_MENU_PATH := "res://audio/bgm/menu_theme_placeholder.wav" -const BGM_BATTLE_PATH := "res://audio/bgm/battle_loop_placeholder.wav" +const BGM_MENU_PATH := "res://audio/bgm/menu_camp_dawn_theme.wav" +const BGM_BATTLE_PATH := "res://audio/bgm/battle_yingchuan_march.wav" const TITLE_BACKGROUND_PATH := "res://art/backgrounds/title_war_camp_dawn.png" const TITLE_PORTRAIT_PATH := "res://art/portraits/cao_cao.png" const TITLE_MENU_SURFACE_PATH := "res://art/ui/panels/panel_title_command.png" @@ -3032,7 +3032,7 @@ func _create_hud() -> void: settings_bgm_toggle = CheckButton.new() settings_bgm_toggle.text = "배경 음악" settings_bgm_toggle.custom_minimum_size = Vector2(374, 30) - settings_bgm_toggle.tooltip_text = "군막과 전투에서 흐르는 음악을 켜거나 끕니다." + settings_bgm_toggle.tooltip_text = "군막의 새벽과 영천 진군 음악을 켜거나 끕니다." settings_bgm_toggle.toggled.connect(_on_settings_bgm_toggled) settings_column.add_child(settings_bgm_toggle) @@ -3054,7 +3054,7 @@ func _create_hud() -> void: settings_bgm_volume_slider.step = 5.0 settings_bgm_volume_slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL settings_bgm_volume_slider.custom_minimum_size = Vector2(194, 30) - settings_bgm_volume_slider.tooltip_text = "군막과 전투 음악의 크기를 조절합니다." + settings_bgm_volume_slider.tooltip_text = "군막의 새벽과 영천 진군 음악의 크기를 조절합니다." settings_bgm_volume_slider.value_changed.connect(_on_settings_bgm_volume_changed) settings_bgm_volume_row.add_child(settings_bgm_volume_slider) @@ -3104,7 +3104,7 @@ func _create_hud() -> void: settings_audio_reset_button = Button.new() settings_audio_reset_button.text = "소리 켜기" settings_audio_reset_button.custom_minimum_size = Vector2(374, 32) - settings_audio_reset_button.tooltip_text = "군막 음악과 전투 효과음을 켜고 기본 음량으로 되돌린 뒤 확인음을 재생합니다." + settings_audio_reset_button.tooltip_text = "군막의 새벽 음악과 전투 효과음을 켜고 기본 음량으로 되돌린 뒤 확인음을 재생합니다." settings_audio_reset_button.pressed.connect(_on_settings_audio_reset_pressed) settings_column.add_child(settings_audio_reset_button) @@ -4523,7 +4523,7 @@ func _create_hud() -> void: title_bgm_toggle.text = "군막 음악" title_bgm_toggle.custom_minimum_size = Vector2(350, 30) title_bgm_toggle.button_pressed = title_bgm_enabled - title_bgm_toggle.tooltip_text = "첫 화면과 군막에서 흐르는 음악을 켜거나 끕니다." + title_bgm_toggle.tooltip_text = "첫 화면과 군막의 새벽 음악을 켜거나 끕니다." title_bgm_toggle.toggled.connect(_on_title_bgm_toggled) title_settings_column.add_child(title_bgm_toggle) @@ -4546,7 +4546,7 @@ func _create_hud() -> void: title_bgm_volume_slider.value = float(title_bgm_volume_percent) title_bgm_volume_slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL title_bgm_volume_slider.custom_minimum_size = Vector2(172, 30) - title_bgm_volume_slider.tooltip_text = "군막 음악의 크기를 조절합니다." + title_bgm_volume_slider.tooltip_text = "군막의 새벽 음악 크기를 조절합니다." title_bgm_volume_slider.value_changed.connect(_on_title_bgm_volume_changed) title_bgm_volume_row.add_child(title_bgm_volume_slider) @@ -4601,7 +4601,7 @@ func _create_hud() -> void: "TitleAudioResetButton", "status", "소리 켜기", - "군막 음악과 전투 효과음을 켜고 기본 음량으로 되돌린 뒤 확인음을 재생합니다.", + "군막의 새벽 음악과 전투 효과음을 켜고 기본 음량으로 되돌린 뒤 확인음을 재생합니다.", Vector2(350, 32) ) title_audio_reset_button.pressed.connect(_on_title_audio_reset_pressed) diff --git a/tools/smoke_title_menu.gd b/tools/smoke_title_menu.gd index a48b6ba..e48b8e8 100644 --- a/tools/smoke_title_menu.gd +++ b/tools/smoke_title_menu.gd @@ -45,6 +45,12 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void: failures.append("title screen should start with an audible menu BGM stream") elif scene.bgm_player.volume_db < -12.0: failures.append("title menu BGM should be loud enough to hear by default: %.1fdb" % scene.bgm_player.volume_db) + if BattleSceneScript.BGM_MENU_PATH.contains("placeholder") or BattleSceneScript.BGM_BATTLE_PATH.contains("placeholder"): + failures.append("menu and battle BGM should use named mood tracks instead of placeholder assets") + if not BattleSceneScript.BGM_MENU_PATH.ends_with("menu_camp_dawn_theme.wav"): + failures.append("title menu should use the camp dawn theme, got %s" % BattleSceneScript.BGM_MENU_PATH) + if not BattleSceneScript.BGM_BATTLE_PATH.ends_with("battle_yingchuan_march.wav"): + failures.append("battle start should use the Yingchuan march theme, got %s" % BattleSceneScript.BGM_BATTLE_PATH) _check_bgm_stream_quality(failures, scene._bgm_stream_for("menu"), "menu", 20.0) _check_bgm_stream_quality(failures, scene._bgm_stream_for("battle"), "battle", 16.0) for sfx_key in [