Add placeholder battle audio
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user