442 lines
15 KiB
GDScript
442 lines
15 KiB
GDScript
extends Node
|
|
|
|
# This script handles overall game management tasks, including audio management and UI interactions.
|
|
var config = ConfigFile.new()
|
|
|
|
# Sound manager reference
|
|
var sound_manager: Node
|
|
|
|
var music_player: AudioStreamPlayer
|
|
var building_sfx: AudioStreamPlayer
|
|
var construction_sfx: AudioStreamPlayer
|
|
|
|
@onready var generic_text_panel = $CanvasLayer/GenericTextPanel
|
|
|
|
# Export variables for intro and outro resource
|
|
@export var intro_text_resource: GenericText
|
|
@export var outro_text_resource: GenericText
|
|
|
|
# Node references
|
|
@onready var building_selector = get_node_or_null("CanvasLayer/BuildingSelector")
|
|
@onready var resource_display = get_node_or_null("CanvasLayer/ResourceDisplay")
|
|
@onready var game_menu = get_node_or_null("CanvasLayer/GameMenu")
|
|
|
|
func _ready():
|
|
print("GameManager: Initializing...")
|
|
# Load data from a file.
|
|
var err = config.load("user://config.cfg")
|
|
# If the file didn't load, ignore it.
|
|
if err != OK:
|
|
print("GameManager: No config file found, using defaults")
|
|
config = ConfigFile.new()
|
|
|
|
# Get sound manager reference
|
|
sound_manager = get_node_or_null("/root/SoundManager")
|
|
if sound_manager:
|
|
print("GameManager: Found sound manager, connecting signals")
|
|
# Connect to sound manager signals
|
|
sound_manager.music_volume_changed.connect(_on_music_volume_changed)
|
|
sound_manager.sfx_volume_changed.connect(_on_sfx_volume_changed)
|
|
sound_manager.music_muted_changed.connect(_on_music_muted_changed)
|
|
sound_manager.sfx_muted_changed.connect(_on_sfx_muted_changed)
|
|
|
|
# Load saved volume settings
|
|
var saved_music_volume = config.get_value("audio", "music_volume", 0.1)
|
|
var saved_sfx_volume = config.get_value("audio", "sfx_volume", 0.1)
|
|
var saved_music_muted = config.get_value("audio", "music_muted", false)
|
|
var saved_sfx_muted = config.get_value("audio", "sfx_muted", false)
|
|
|
|
print("GameManager: Loading saved settings - Music: ", saved_music_volume, " SFX: ", saved_sfx_volume)
|
|
print("GameManager: Loading saved mute states - Music: ", saved_music_muted, " SFX: ", saved_sfx_muted)
|
|
|
|
# Apply saved settings
|
|
sound_manager.music_volume = saved_music_volume
|
|
sound_manager.sfx_volume = saved_sfx_volume
|
|
sound_manager.music_muted = saved_music_muted
|
|
sound_manager.sfx_muted = saved_sfx_muted
|
|
else:
|
|
print("GameManager: Warning - Sound manager not found!")
|
|
|
|
# Register SoundManager in the main loop for JavaScript bridge to find
|
|
Engine.get_main_loop().set_meta("sound_manager", sound_manager)
|
|
|
|
# Reference to the controls panel and HUD
|
|
var controls_panel = get_node_or_null("CanvasLayer/ControlsPanel")
|
|
var hud = get_node_or_null("CanvasLayer/HUD")
|
|
|
|
# Set up the HUD's reference to the panels
|
|
if hud and controls_panel:
|
|
hud.controls_panel = controls_panel
|
|
|
|
# Show intro text if available
|
|
#if generic_text_panel and intro_text_resource:
|
|
#generic_text_panel.apply_resource_data(intro_text_resource)
|
|
#generic_text_panel.show_panel()
|
|
#
|
|
#generic_text_panel.closed.connect(func():
|
|
#if generic_text_panel and generic_text_panel.resource_data and generic_text_panel.resource_data.panel_type == 0 and controls_panel:
|
|
#controls_panel.show_panel()
|
|
#)
|
|
|
|
# Connect controls panel closed signal
|
|
if controls_panel:
|
|
controls_panel.closed.connect(_on_controls_panel_closed)
|
|
|
|
# Check for audio initialization status (important for web)
|
|
var can_initialize_audio = true
|
|
|
|
if OS.has_feature("web") and sound_manager:
|
|
can_initialize_audio = sound_manager.audio_initialized
|
|
|
|
if not can_initialize_audio:
|
|
# For web, wait for the audio_ready signal before initializing audio
|
|
sound_manager.audio_ready.connect(_initialize_game_audio)
|
|
|
|
# Set up audio if allowed (immediate for desktop, after interaction for web)
|
|
if can_initialize_audio:
|
|
_initialize_game_audio()
|
|
|
|
# Find the builder and connect to it
|
|
var builder = get_node_or_null("/root/Main/Builder")
|
|
if builder:
|
|
builder.structure_placed.connect(_on_structure_placed)
|
|
print("GameManager: Connected to Builder signals")
|
|
|
|
# Connect to construction signals via deferred call to make sure everything is ready
|
|
call_deferred("_setup_construction_signals")
|
|
|
|
# Make sure sound buses are properly configured
|
|
call_deferred("_setup_sound_buses")
|
|
|
|
# Connect the building selector to the builder
|
|
if building_selector:
|
|
if builder:
|
|
building_selector.builder = builder
|
|
print("GameManager: Connected BuildingSelector to Builder")
|
|
else:
|
|
print("GameManager: Warning - Builder not found!")
|
|
else:
|
|
print("GameManager: Warning - BuildingSelector not found!")
|
|
|
|
# Connect builder's cash display to HUD
|
|
if builder and hud:
|
|
builder.cash_display = hud.get_node("HBoxContainer/CashItem/CashLabel")
|
|
|
|
# Start background music
|
|
_start_background_music()
|
|
|
|
# Connect economy manager signals to HUD
|
|
var economy_manager = get_node_or_null("EconomyManager")
|
|
var hud_manager = get_node_or_null("CanvasLayer/HUD")
|
|
|
|
if economy_manager and hud_manager:
|
|
economy_manager.money_changed.connect(hud_manager.update_money)
|
|
economy_manager.population_changed.connect(hud_manager.update_population_count)
|
|
economy_manager.energy_balance_changed.connect(hud_manager.update_energy_balance)
|
|
|
|
# Initialize managers
|
|
_initialize_managers()
|
|
|
|
# Connect signals
|
|
_connect_signals()
|
|
|
|
# Initialize game state
|
|
_initialize_game_state()
|
|
|
|
# Start the game
|
|
start_game()
|
|
|
|
func _on_music_volume_changed(new_volume: float):
|
|
print("GameManager: Music volume changed to ", new_volume)
|
|
config.set_value("audio", "music_volume", new_volume)
|
|
var err = config.save("user://config.cfg")
|
|
if err != OK:
|
|
print("GameManager: Error saving music volume: ", err)
|
|
|
|
func _on_sfx_volume_changed(new_volume: float):
|
|
print("GameManager: SFX volume changed to ", new_volume)
|
|
config.set_value("audio", "sfx_volume", new_volume)
|
|
var err = config.save("user://config.cfg")
|
|
if err != OK:
|
|
print("GameManager: Error saving SFX volume: ", err)
|
|
|
|
func _on_music_muted_changed(is_muted: bool):
|
|
print("GameManager: Music mute changed to ", is_muted)
|
|
config.set_value("audio", "music_muted", is_muted)
|
|
var err = config.save("user://config.cfg")
|
|
if err != OK:
|
|
print("GameManager: Error saving music mute: ", err)
|
|
|
|
func _on_sfx_muted_changed(is_muted: bool):
|
|
print("GameManager: SFX mute changed to ", is_muted)
|
|
config.set_value("audio", "sfx_muted", is_muted)
|
|
var err = config.save("user://config.cfg")
|
|
if err != OK:
|
|
print("GameManager: Error saving SFX mute: ", err)
|
|
|
|
# Initialize all game audio - called immediately on desktop, after user interaction for web
|
|
func _initialize_game_audio():
|
|
# Set up all audio systems
|
|
setup_background_music()
|
|
setup_building_sfx()
|
|
setup_construction_sfx()
|
|
|
|
# This function is called when the controls panel is closed
|
|
func _on_controls_panel_closed():
|
|
pass
|
|
|
|
# Function to set up the sound buses
|
|
func _setup_sound_buses():
|
|
# Wait a moment to ensure SoundManager is ready
|
|
await get_tree().process_frame
|
|
|
|
# Get reference to SoundManager singleton
|
|
var sound_manager = get_node_or_null("/root/SoundManager")
|
|
if !sound_manager:
|
|
return
|
|
|
|
# Move audio players to the appropriate buses
|
|
if music_player:
|
|
music_player.bus = "Music"
|
|
|
|
if building_sfx:
|
|
building_sfx.bus = "SFX"
|
|
|
|
if construction_sfx:
|
|
construction_sfx.bus = "SFX"
|
|
|
|
# Setup background music player
|
|
func setup_background_music():
|
|
music_player = AudioStreamPlayer.new()
|
|
add_child(music_player)
|
|
|
|
# Set this to make the music player ignore the game tree's pause state
|
|
music_player.process_mode = Node.PROCESS_MODE_ALWAYS
|
|
|
|
# Use a direct file path for the music file to avoid any loading issues
|
|
var music_path = "res://sounds/jazz_new_orleans.mp3"
|
|
|
|
# Try both direct preload and load for maximum compatibility
|
|
var music = null
|
|
|
|
# Try preload first - this ensures MP3 is pre-decoded
|
|
music = preload("res://sounds/jazz_new_orleans.mp3")
|
|
|
|
# If preload failed, try regular load
|
|
if !music:
|
|
music = load(music_path)
|
|
|
|
# Continue setup if we have the music file
|
|
if music:
|
|
# Set looping on the AudioStreamMP3 itself
|
|
if music is AudioStreamMP3:
|
|
music.loop = true
|
|
|
|
music_player.stream = music
|
|
music_player.bus = "Music" # Use the Music bus
|
|
|
|
# Set initial volume
|
|
if sound_manager:
|
|
music_player.volume_db = sound_manager.linear_to_db(sound_manager.music_volume)
|
|
|
|
# Check if we can play audio immediately (desktop) or need to wait (web)
|
|
var can_play_now = true
|
|
if OS.has_feature("web"):
|
|
var sound_manager = get_node_or_null("/root/SoundManager")
|
|
if sound_manager:
|
|
can_play_now = sound_manager.audio_initialized
|
|
|
|
# If not initialized, connect to the ready signal
|
|
if not can_play_now:
|
|
sound_manager.audio_ready.connect(_start_background_music)
|
|
|
|
# Play immediately if allowed
|
|
if can_play_now:
|
|
_start_background_music()
|
|
else:
|
|
print("GameManager: Warning - Could not load music file!")
|
|
# Try a fallback sound as music
|
|
var fallback_sound = load("res://sounds/building_placing.wav")
|
|
if fallback_sound:
|
|
music_player.stream = fallback_sound
|
|
music_player.bus = "Music"
|
|
|
|
# Set initial volume
|
|
if sound_manager:
|
|
music_player.volume_db = sound_manager.linear_to_db(sound_manager.music_volume)
|
|
|
|
# Check if we can play immediately
|
|
var can_play_now = true
|
|
if OS.has_feature("web"):
|
|
var sound_manager = get_node_or_null("/root/SoundManager")
|
|
if sound_manager:
|
|
can_play_now = sound_manager.audio_initialized
|
|
|
|
if can_play_now:
|
|
music_player.play()
|
|
else:
|
|
print("GameManager: Error - Could not load fallback sound!")
|
|
|
|
# Start background music playing (called directly or via signal)
|
|
func _start_background_music():
|
|
if music_player and music_player.stream and not music_player.playing:
|
|
# For web builds, use a simple approach to starting audio
|
|
if OS.has_feature("web"):
|
|
# Make sure we start from the beginning
|
|
music_player.stop()
|
|
music_player.seek(0.0)
|
|
|
|
# Play the music
|
|
music_player.play()
|
|
|
|
# Simple JavaScript to ensure audio context is running
|
|
if Engine.has_singleton("JavaScriptBridge"):
|
|
var js = Engine.get_singleton("JavaScriptBridge")
|
|
js.eval("""
|
|
(function() {
|
|
try {
|
|
if (window._godotAudioContext && window._godotAudioContext.state === 'suspended') {
|
|
console.log('GameManager: Resuming audio context');
|
|
window._godotAudioContext.resume();
|
|
}
|
|
} catch(e) {
|
|
console.error('GameManager: Error in audio context check:', e);
|
|
}
|
|
})()
|
|
""")
|
|
else:
|
|
# Standard approach for desktop builds
|
|
music_player.play()
|
|
|
|
# Setup building sound effects
|
|
func setup_building_sfx():
|
|
building_sfx = AudioStreamPlayer.new()
|
|
add_child(building_sfx)
|
|
|
|
# Set this to make the sound effects player ignore the game tree's pause state
|
|
building_sfx.process_mode = Node.PROCESS_MODE_ALWAYS
|
|
|
|
var sfx = load("res://sounds/building_placing.wav")
|
|
if sfx:
|
|
building_sfx.stream = sfx
|
|
building_sfx.volume_db = -5
|
|
building_sfx.bus = "SFX" # Use the SFX bus
|
|
|
|
# Setup construction sound effects
|
|
# Note: Now mainly used for backward compatibility
|
|
# Individual workers handle their own construction sounds
|
|
func setup_construction_sfx():
|
|
construction_sfx = AudioStreamPlayer.new()
|
|
add_child(construction_sfx)
|
|
|
|
# Set this to make the sound effects player ignore the game tree's pause state
|
|
construction_sfx.process_mode = Node.PROCESS_MODE_ALWAYS
|
|
|
|
var sfx = load("res://sounds/construction.wav")
|
|
if sfx:
|
|
construction_sfx.stream = sfx
|
|
construction_sfx.volume_db = -8 # Reduced volume since workers have their own sounds
|
|
construction_sfx.bus = "SFX" # Use the SFX bus
|
|
|
|
# Play the building sound effect when a structure is placed
|
|
func _on_structure_placed(structure_index, position):
|
|
# Check web audio initialized status if needed
|
|
var can_play_audio = true
|
|
if OS.has_feature("web"):
|
|
var sound_manager = get_node_or_null("/root/SoundManager")
|
|
if sound_manager:
|
|
can_play_audio = sound_manager.audio_initialized
|
|
|
|
# Only play if audio is initialized (always true on desktop, depends on user interaction for web)
|
|
if can_play_audio and building_sfx and building_sfx.stream:
|
|
if building_sfx.playing:
|
|
building_sfx.stop()
|
|
building_sfx.play()
|
|
|
|
# Variables for construction sound looping
|
|
var construction_active = false
|
|
var construction_sound_timer = null
|
|
|
|
# These functions remain for backward compatibility with mission logic
|
|
# but they don't actually play sounds anymore since workers handle their own sounds
|
|
|
|
# Compatibility function for mission triggers
|
|
func play_construction_sound():
|
|
# We don't play any sounds from here anymore - workers handle their own sounds
|
|
# but we need to keep this function for backward compatibility
|
|
pass
|
|
|
|
# Compatibility function for mission triggers
|
|
func _loop_construction_sound():
|
|
# This function exists only for backward compatibility
|
|
pass
|
|
|
|
# Compatibility function for mission triggers
|
|
func stop_construction_sound():
|
|
# We don't stop any sounds from here anymore - workers handle their own sounds
|
|
# but we need to keep this function for backward compatibility
|
|
pass
|
|
|
|
# Setup construction signals properly
|
|
func _setup_construction_signals():
|
|
var builder = get_node_or_null("/root/Main/Builder")
|
|
|
|
if builder and builder.has_method("get") and builder.get("construction_manager"):
|
|
var construction_manager = builder.construction_manager
|
|
|
|
if construction_manager:
|
|
# Disconnect any existing connections first to avoid duplicates
|
|
if construction_manager.worker_construction_started.is_connected(play_construction_sound):
|
|
construction_manager.worker_construction_started.disconnect(play_construction_sound)
|
|
|
|
if construction_manager.worker_construction_ended.is_connected(stop_construction_sound):
|
|
construction_manager.worker_construction_ended.disconnect(stop_construction_sound)
|
|
|
|
# Connect signals
|
|
construction_manager.worker_construction_started.connect(play_construction_sound)
|
|
construction_manager.worker_construction_ended.connect(stop_construction_sound)
|
|
|
|
|
|
func _on_mission_manager_all_missions_completed() -> void:
|
|
if generic_text_panel and outro_text_resource:
|
|
generic_text_panel.apply_resource_data(outro_text_resource)
|
|
generic_text_panel.show_panel()
|
|
|
|
|
|
func _on_mission_manager_mission_started(mission: MissionData) -> void:
|
|
var mission_manager: Node = get_node_or_null("/root/Main/MissionManager")
|
|
if mission_manager and mission_manager.mission_ui:
|
|
mission_manager.mission_ui.update_mission_display(mission)
|
|
|
|
var mission_text = GenericText.new()
|
|
mission_text.panel_type = 2
|
|
mission_text.title = mission.title
|
|
mission_text.body_text = mission.description
|
|
mission_text.button_text = "Start Mission"
|
|
|
|
print(generic_text_panel)
|
|
if generic_text_panel:
|
|
generic_text_panel.apply_resource_data(mission_text)
|
|
generic_text_panel.show_panel()
|
|
|
|
|
|
func _initialize_managers():
|
|
print("GameManager: Initializing managers")
|
|
# Initialize any required managers here
|
|
pass
|
|
|
|
func _connect_signals():
|
|
print("GameManager: Connecting signals")
|
|
# Connect any required signals here
|
|
pass
|
|
|
|
func _initialize_game_state():
|
|
print("GameManager: Initializing game state")
|
|
# Initialize game state here
|
|
pass
|
|
|
|
func start_game():
|
|
print("GameManager: Starting game")
|
|
# Start game logic here
|
|
pass
|