Add placeholder battle audio

This commit is contained in:
2026-06-18 03:04:18 +09:00
parent 1857d45b52
commit b0d26530f2
19 changed files with 193 additions and 4 deletions

View File

@@ -13,6 +13,24 @@ const SKILL_OVERLAY_COLOR := Color(0.56, 0.28, 0.95, 0.28)
const ITEM_OVERLAY_COLOR := Color(0.24, 0.74, 0.34, 0.30)
const FORMATION_OVERLAY_COLOR := Color(0.95, 0.76, 0.25, 0.34)
const OBJECTIVE_OVERLAY_COLOR := Color(1.0, 0.78, 0.18, 0.30)
const BGM_MENU := preload("res://audio/bgm/menu_theme_placeholder.wav")
const BGM_BATTLE := preload("res://audio/bgm/battle_loop_placeholder.wav")
const SFX_BOW_RELEASE := preload("res://audio/sfx/bow_release_01.wav")
const SFX_DEFEAT_STING := preload("res://audio/sfx/defeat_sting_01.wav")
const SFX_FIRE_SKILL := preload("res://audio/sfx/fire_skill_01.wav")
const SFX_FOOTSTEP := preload("res://audio/sfx/footstep_armor_01.wav")
const SFX_GUARD_BLOCK := preload("res://audio/sfx/guard_block_01.wav")
const SFX_HIT_HEAVY := preload("res://audio/sfx/hit_heavy_01.wav")
const SFX_ITEM_PICKUP := preload("res://audio/sfx/item_pickup_01.wav")
const SFX_MENU_CANCEL := preload("res://audio/sfx/menu_cancel_01.wav")
const SFX_MENU_CONFIRM := preload("res://audio/sfx/menu_confirm_01.wav")
const SFX_SKILL_CAST := preload("res://audio/sfx/skill_cast_01.wav")
const SFX_SLASH := preload("res://audio/sfx/slash_01.wav")
const SFX_UI_CLICK := preload("res://audio/sfx/ui_click_01.wav")
const SFX_VICTORY_STING := preload("res://audio/sfx/victory_sting_01.wav")
const BGM_VOLUME_DB := -14.0
const SFX_VOLUME_DB := -4.0
const UI_SFX_VOLUME_DB := -8.0
var state: BattleState = BattleStateScript.new()
var campaign_state: CampaignState = CampaignStateScript.new()
@@ -83,10 +101,14 @@ var log_box: RichTextLabel
var dialogue_queue: Array = []
var active_dialogue_lines: Array = []
var active_dialogue_index := 0
var bgm_player: AudioStreamPlayer
var current_bgm_key := ""
var last_announced_battle_status := ""
func _ready() -> void:
_create_hud()
_create_audio()
state.changed.connect(_on_state_changed)
state.log_added.connect(_on_log_added)
state.dialogue_requested.connect(_on_dialogue_requested)
@@ -447,6 +469,130 @@ func _create_hud() -> void:
result_column.add_child(next_battle_button)
func _create_audio() -> void:
bgm_player = AudioStreamPlayer.new()
bgm_player.name = "BgmPlayer"
bgm_player.volume_db = BGM_VOLUME_DB
bgm_player.finished.connect(_on_bgm_finished)
add_child(bgm_player)
func _on_bgm_finished() -> void:
if current_bgm_key.is_empty() or bgm_player == null or bgm_player.stream == null:
return
bgm_player.play()
func _play_bgm(key: String) -> void:
if bgm_player == null:
return
if current_bgm_key == key and bgm_player.playing:
return
var stream = _bgm_stream_for(key)
if stream == null:
return
current_bgm_key = key
bgm_player.stop()
bgm_player.stream = stream
bgm_player.play()
func _bgm_stream_for(key: String):
if key == "battle":
return BGM_BATTLE
if key == "menu":
return BGM_MENU
return null
func _play_sfx(key: String, volume_db := SFX_VOLUME_DB) -> void:
var stream = _sfx_stream_for(key)
if stream == null:
return
var player := AudioStreamPlayer.new()
player.name = "Sfx_%s" % key
player.stream = stream
player.volume_db = volume_db
player.finished.connect(player.queue_free)
add_child(player)
player.play()
func _sfx_stream_for(key: String):
if key == "bow_release":
return SFX_BOW_RELEASE
if key == "defeat_sting":
return SFX_DEFEAT_STING
if key == "fire_skill":
return SFX_FIRE_SKILL
if key == "footstep":
return SFX_FOOTSTEP
if key == "guard_block":
return SFX_GUARD_BLOCK
if key == "hit_heavy":
return SFX_HIT_HEAVY
if key == "item_pickup":
return SFX_ITEM_PICKUP
if key == "menu_cancel":
return SFX_MENU_CANCEL
if key == "menu_confirm":
return SFX_MENU_CONFIRM
if key == "skill_cast":
return SFX_SKILL_CAST
if key == "slash":
return SFX_SLASH
if key == "ui_click":
return SFX_UI_CLICK
if key == "victory_sting":
return SFX_VICTORY_STING
return null
func _play_ui_click() -> void:
_play_sfx("ui_click", UI_SFX_VOLUME_DB)
func _play_ui_confirm() -> void:
_play_sfx("menu_confirm", UI_SFX_VOLUME_DB)
func _play_ui_cancel() -> void:
_play_sfx("menu_cancel", UI_SFX_VOLUME_DB)
func _play_log_sfx(message: String) -> void:
if message.contains(" but misses."):
_play_sfx("guard_block")
elif message.contains(" attacks ") or message.contains(" counterattacks "):
if message.contains(" for "):
_play_sfx("hit_heavy")
elif message.contains(" casts "):
if message.contains("restoring"):
_play_sfx("skill_cast")
else:
_play_sfx("fire_skill")
elif message.contains(" moved to ") or message.contains(" advances to ") or message.contains(" takes formation at ") or message.contains(" arrives at "):
_play_sfx("footstep")
elif message.contains(" uses ") or message.contains(" equips ") or message.begins_with("Bought "):
_play_sfx("item_pickup")
elif message.contains(" reaches Lv.") or message.contains(" promotes to "):
_play_sfx("menu_confirm")
func _announce_battle_status_audio() -> void:
if state.battle_status == BattleState.STATUS_ACTIVE:
last_announced_battle_status = ""
return
if last_announced_battle_status == state.battle_status:
return
last_announced_battle_status = state.battle_status
_play_bgm("menu")
if state.battle_status == BattleState.STATUS_VICTORY:
_play_sfx("victory_sting")
elif state.battle_status == BattleState.STATUS_DEFEAT:
_play_sfx("defeat_sting")
func _handle_board_click(screen_position: Vector2) -> void:
if formation_menu != null and formation_menu.visible:
_handle_formation_board_click(screen_position)
@@ -500,6 +646,9 @@ func _handle_board_click(screen_position: Vector2) -> void:
return
if not clicked_unit.is_empty() and clicked_unit.get("team", "") != selected_unit.get("team", ""):
var attack_sfx := "bow_release" if int(selected_unit.get("range", 1)) > 1 else "slash"
if attack_cells.has(clicked_unit.get("pos", Vector2i(-1, -1))):
_play_sfx(attack_sfx)
if state.try_attack_selected(clicked_unit["id"]):
selected_skill_id = ""
selected_item_id = ""
@@ -928,6 +1077,7 @@ func _update_item_forecast(selected: Dictionary) -> void:
func _update_result_panel() -> void:
if result_panel == null:
return
_announce_battle_status_audio()
if campaign_complete_screen:
_clear_dialogue()
_clear_result_choices()
@@ -989,6 +1139,7 @@ func _on_state_changed() -> void:
func _on_log_added(message: String) -> void:
_play_log_sfx(message)
if log_box == null:
return
log_box.append_text(message + "\n")
@@ -1069,6 +1220,7 @@ func _render_dialogue_line() -> void:
func _advance_dialogue() -> void:
if not _is_dialogue_visible():
return
_play_ui_click()
active_dialogue_index += 1
if active_dialogue_index < active_dialogue_lines.size():
_render_dialogue_line()
@@ -1103,10 +1255,13 @@ func _on_wait_pressed() -> void:
_hide_tactic_menu()
_hide_item_menu()
_hide_equip_menu()
state.try_wait_selected()
if state.try_wait_selected():
_play_ui_confirm()
func _on_end_turn_pressed() -> void:
if state.can_player_act():
_play_ui_confirm()
selected_skill_id = ""
selected_item_id = ""
_hide_tactic_menu()
@@ -1119,6 +1274,7 @@ func _on_tactic_pressed() -> void:
var selected := state.get_selected_unit()
if selected.is_empty():
return
_play_ui_click()
if tactic_menu != null and tactic_menu.visible:
_hide_tactic_menu()
else:
@@ -1135,6 +1291,7 @@ func _on_item_pressed() -> void:
var selected := state.get_selected_unit()
if selected.is_empty():
return
_play_ui_click()
if item_menu != null and item_menu.visible:
_hide_item_menu()
else:
@@ -1153,6 +1310,7 @@ func _on_equip_pressed() -> void:
return
if selected.get("moved", false) or selected.get("acted", false):
return
_play_ui_click()
if equip_menu != null and equip_menu.visible:
_hide_equip_menu()
else:
@@ -1169,6 +1327,7 @@ func _on_equip_pressed() -> void:
func _on_restart_pressed() -> void:
if campaign_complete_screen:
return
_play_ui_confirm()
if log_box != null:
log_box.clear()
battle_started = false
@@ -1197,6 +1356,8 @@ func _load_pending_post_battle_choice() -> void:
post_battle_dialogue_started = true
battle_result_summary = campaign_state.get_pending_post_battle_choice_summary()
state.battle_status = BattleState.STATUS_VICTORY
last_announced_battle_status = BattleState.STATUS_VICTORY
_play_bgm("menu")
if briefing_panel != null:
briefing_panel.visible = false
if log_box != null:
@@ -1206,6 +1367,7 @@ func _load_pending_post_battle_choice() -> void:
func _load_scenario(scenario_id: String) -> void:
campaign_complete_screen = false
active_scenario_id = scenario_id
last_announced_battle_status = ""
var scenario_path := campaign_state.get_scenario_path(active_scenario_id)
if scenario_path.is_empty():
push_error("Missing scenario path for %s." % active_scenario_id)
@@ -1234,6 +1396,7 @@ func _load_scenario(scenario_id: String) -> void:
func _show_briefing() -> void:
_play_bgm("menu")
var briefing := state.get_briefing()
if briefing.is_empty():
_start_battle_from_briefing()
@@ -1269,11 +1432,13 @@ func _show_briefing() -> void:
func _on_begin_battle_pressed() -> void:
_play_ui_confirm()
_start_battle_from_briefing()
func _start_battle_from_briefing() -> void:
battle_started = true
_play_bgm("battle")
if briefing_panel != null:
briefing_panel.visible = false
_hide_shop_menu()
@@ -1288,6 +1453,7 @@ func _start_battle_from_briefing() -> void:
func _on_shop_pressed() -> void:
if battle_started or _is_prebattle_prep_locked() or briefing_panel == null or not briefing_panel.visible:
return
_play_ui_click()
if shop_menu != null and shop_menu.visible:
_hide_shop_menu()
else:
@@ -1308,6 +1474,7 @@ func _hide_shop_menu() -> void:
func _on_armory_pressed() -> void:
if battle_started or _is_prebattle_prep_locked() or briefing_panel == null or not briefing_panel.visible:
return
_play_ui_click()
if armory_menu != null and armory_menu.visible:
_hide_armory_menu()
else:
@@ -1328,6 +1495,7 @@ func _hide_armory_menu() -> void:
func _on_roster_pressed() -> void:
if battle_started or _is_prebattle_prep_locked() or not state.has_deployment_roster() or briefing_panel == null or not briefing_panel.visible:
return
_play_ui_click()
if roster_menu != null and roster_menu.visible:
_hide_roster_menu()
else:
@@ -1348,6 +1516,7 @@ func _hide_roster_menu() -> void:
func _on_formation_pressed() -> void:
if battle_started or _is_prebattle_prep_locked() or briefing_panel == null or not briefing_panel.visible:
return
_play_ui_click()
if formation_menu != null and formation_menu.visible:
_hide_formation_menu()
else:
@@ -1434,6 +1603,7 @@ func _on_roster_unit_pressed(unit_id: String) -> void:
return
var next_deployed := not bool(unit.get("deployed", true))
if state.try_set_unit_deployed(unit_id, next_deployed):
_play_ui_confirm()
if not state.get_unit(formation_unit_id).get("deployed", false):
formation_unit_id = ""
if not state.get_unit(armory_unit_id).get("deployed", false):
@@ -1498,6 +1668,7 @@ func _format_cell_label(value) -> String:
func _on_formation_unit_pressed(unit_id: String) -> void:
_play_ui_click()
formation_unit_id = unit_id
_rebuild_formation_menu()
_update_hud()
@@ -1511,6 +1682,7 @@ func _handle_formation_board_click(screen_position: Vector2) -> void:
if not state.is_inside(cell):
return
if state.try_set_prebattle_formation(formation_unit_id, cell):
_play_ui_confirm()
_rebuild_formation_menu()
_update_hud()
queue_redraw()
@@ -1598,6 +1770,7 @@ func _format_armory_unit_button_text(unit: Dictionary) -> String:
func _on_armory_unit_pressed(unit_id: String) -> void:
_play_ui_click()
armory_unit_id = unit_id
_rebuild_armory_menu()
_update_hud()
@@ -1613,6 +1786,7 @@ func _on_armory_equip_pressed(item_id: String) -> void:
if campaign_state.try_save_prebattle_loadout(state.get_player_roster_snapshot(), state.get_inventory_snapshot()):
_on_log_added("Saved pre-battle equipment.")
else:
_play_ui_cancel()
_on_log_added("Could not save pre-battle equipment.")
_load_scenario(active_scenario_id)
_show_briefing()
@@ -1701,6 +1875,7 @@ func _on_shop_item_pressed(item_id: String) -> void:
state.set_inventory_snapshot(campaign_state.get_inventory_snapshot())
_on_log_added("Bought %s for %d gold." % [item_name, price])
else:
_play_ui_cancel()
_on_log_added("Could not buy %s." % item_name)
_rebuild_shop_menu()
_update_hud()
@@ -1775,6 +1950,7 @@ func _on_post_battle_choice_pressed(choice: Dictionary) -> void:
return
var scenario_id := str(battle_result_summary.get("scenario_id", state.battle_id))
if campaign_state.try_apply_post_battle_choice(choice, scenario_id):
_play_ui_confirm()
battle_result_summary["choice_applied"] = true
battle_result_summary["saved"] = true
battle_result_summary["choice_label"] = str(choice.get("label", choice.get("id", "")))
@@ -1782,6 +1958,7 @@ func _on_post_battle_choice_pressed(choice: Dictionary) -> void:
_append_unique_result_values("left_officers", choice.get("leave_officers", []))
_on_log_added("Campaign choice saved: %s." % battle_result_summary["choice_label"])
else:
_play_ui_cancel()
_on_log_added("Could not save campaign choice.")
_rebuild_result_choices()
_update_hud()
@@ -1959,6 +2136,7 @@ func _on_next_battle_pressed() -> void:
var next_scenario_id := str(battle_result_summary.get("next_scenario_id", ""))
if next_scenario_id.is_empty():
return
_play_ui_confirm()
if log_box != null:
log_box.clear()
_load_scenario(next_scenario_id)
@@ -1968,6 +2146,7 @@ func _on_next_battle_pressed() -> void:
func _show_campaign_complete() -> void:
campaign_complete_screen = true
_play_bgm("menu")
battle_started = false
battle_result_applied = true
battle_result_summary.clear()
@@ -1994,6 +2173,7 @@ func _show_campaign_complete() -> void:
func _on_new_campaign_pressed() -> void:
_play_ui_confirm()
if log_box != null:
log_box.clear()
if not campaign_state.reset_save(campaign_state.get_start_scenario_id()):
@@ -2116,6 +2296,7 @@ func _format_tactic_range_text(skill: Dictionary) -> String:
func _on_tactic_skill_pressed(skill_id: String) -> void:
_play_ui_confirm()
selected_skill_id = skill_id
selected_item_id = ""
_hide_tactic_menu()
@@ -2127,6 +2308,7 @@ func _on_tactic_skill_pressed(skill_id: String) -> void:
func _on_tactic_cancel_pressed() -> void:
_play_ui_cancel()
selected_skill_id = ""
_hide_tactic_menu()
_refresh_ranges()
@@ -2228,6 +2410,7 @@ func _format_item_effect_text(item: Dictionary) -> String:
func _on_item_selected_pressed(item_id: String) -> void:
_play_ui_confirm()
selected_item_id = item_id
selected_skill_id = ""
_hide_item_menu()
@@ -2239,6 +2422,7 @@ func _on_item_selected_pressed(item_id: String) -> void:
func _on_item_cancel_pressed() -> void:
_play_ui_cancel()
selected_item_id = ""
_hide_item_menu()
_refresh_ranges()
@@ -2355,6 +2539,7 @@ func _on_equip_item_pressed(item_id: String) -> void:
func _on_equip_cancel_pressed() -> void:
_play_ui_cancel()
_hide_equip_menu()
_update_hud()
queue_redraw()