resolving merge conflicts
parent
e6a0cdfbbb
commit
5b35561ce2
@ -0,0 +1 @@
|
||||
uid://dh1kcnetfc7is
|
||||
@ -0,0 +1 @@
|
||||
uid://cy2u2bghkbn5y
|
||||
@ -0,0 +1 @@
|
||||
uid://bndyjskd5fqfr
|
||||
Binary file not shown.
@ -0,0 +1 @@
|
||||
uid://cv86hhyvcveeg
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,39 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bg21cb3aolpll"
|
||||
path.s3tc="res://.godot/imported/building-small-a_colormap.png-5c3df3cd6e4a6c3a9b3ecf5882af7d0c.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/building-small-a_colormap.png-5c3df3cd6e4a6c3a9b3ecf5882af7d0c.etc2.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "007d2d2af08d0a09042bcd8910fe8d8f"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://models/building-small-a_colormap.png"
|
||||
dest_files=["res://.godot/imported/building-small-a_colormap.png-5c3df3cd6e4a6c3a9b3ecf5882af7d0c.s3tc.ctex", "res://.godot/imported/building-small-a_colormap.png-5c3df3cd6e4a6c3a9b3ecf5882af7d0c.etc2.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dq26m4wm2ukpf"
|
||||
path="res://.godot/imported/grass-trees-tall_colormap.png-039581d4038a95a52ec1edb7e14a14ad.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "007d2d2af08d0a09042bcd8910fe8d8f"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://models/grass-trees-tall_colormap.png"
|
||||
dest_files=["res://.godot/imported/grass-trees-tall_colormap.png-039581d4038a95a52ec1edb7e14a14ad.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cucaawfsny5n6"
|
||||
path="res://.godot/imported/road-straight_colormap.png-b6a117d52548e61c263bb6e65713a481.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "007d2d2af08d0a09042bcd8910fe8d8f"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://models/road-straight_colormap.png"
|
||||
dest_files=["res://.godot/imported/road-straight_colormap.png-b6a117d52548e61c263bb6e65713a481.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@ -0,0 +1,131 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="Starter Kit City Builder"
|
||||
config/tags=PackedStringArray("starterkit")
|
||||
run/main_scene="res://scenes/main.tscn"
|
||||
config/features=PackedStringArray("4.4", "Forward Plus")
|
||||
boot_splash/bg_color=Color(0.92549, 0.92549, 0.960784, 1)
|
||||
boot_splash/image="res://splash-screen.png"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[audio]
|
||||
|
||||
general/default_playback_type.web=0
|
||||
|
||||
[autoload]
|
||||
|
||||
SoundManager="*res://scripts/sound_manager.gd"
|
||||
<<<<<<< Updated upstream
|
||||
EventBus="*res://global/event_bus.gd"
|
||||
Globals="*res://global/globals.gd"
|
||||
=======
|
||||
WebSaveManager="*res://scripts/web_save_manager.gd"
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=1920
|
||||
window/size/viewport_height=1080
|
||||
|
||||
[dotnet]
|
||||
|
||||
project/assembly_name="Starter Kit City Builder"
|
||||
|
||||
[editor]
|
||||
|
||||
movie_writer/movie_file="D:/Godot/recording.avi"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray()
|
||||
|
||||
[global_classes]
|
||||
|
||||
LearningPanel="*res://scripts/mission/learning_panel.gd"
|
||||
|
||||
[input]
|
||||
|
||||
build={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(91, 24),"global_position":Vector2(95, 67),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_forward={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_back={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
rotate={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(213, 17),"global_position":Vector2(217, 60),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
demolish={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194308,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_rotate={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":4,"position":Vector2(107, 17),"global_position":Vector2(111, 60),"factor":1.0,"button_index":3,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
structure_next={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
structure_previous={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
save={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
load={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_center={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
textures/vram_compression/import_etc2_astc=true
|
||||
anti_aliasing/quality/msaa_3d=2
|
||||
debug/shapes/navigation/enable_edge_lines=false
|
||||
debug/shapes/navigation/enable_edge_lines.web=false
|
||||
debug/shapes/navigation/enable_geometry_face_random_color=false
|
||||
debug/shapes/navigation/enable_edge_connections=false
|
||||
@ -0,0 +1,131 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=5
|
||||
|
||||
[application]
|
||||
|
||||
config/name="Starter Kit City Builder"
|
||||
config/tags=PackedStringArray("starterkit")
|
||||
run/main_scene="res://scenes/main.tscn"
|
||||
config/features=PackedStringArray("4.4", "Forward Plus")
|
||||
boot_splash/bg_color=Color(0.92549, 0.92549, 0.960784, 1)
|
||||
boot_splash/image="res://splash-screen.png"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[audio]
|
||||
|
||||
general/default_playback_type.web=0
|
||||
|
||||
[autoload]
|
||||
|
||||
SoundManager="*res://scripts/sound_manager.gd"
|
||||
<<<<<<< Updated upstream
|
||||
EventBus="*res://global/event_bus.gd"
|
||||
Globals="*res://global/globals.gd"
|
||||
=======
|
||||
WebSaveManager="*res://scripts/web_save_manager.gd"
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
[display]
|
||||
|
||||
window/size/viewport_width=1920
|
||||
window/size/viewport_height=1080
|
||||
|
||||
[dotnet]
|
||||
|
||||
project/assembly_name="Starter Kit City Builder"
|
||||
|
||||
[editor]
|
||||
|
||||
movie_writer/movie_file="D:/Godot/recording.avi"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray()
|
||||
|
||||
[global_classes]
|
||||
|
||||
LearningPanel="*res://scripts/mission/learning_panel.gd"
|
||||
|
||||
[input]
|
||||
|
||||
build={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(91, 24),"global_position":Vector2(95, 67),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_forward={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_back={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
rotate={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(213, 17),"global_position":Vector2(217, 60),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
demolish={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194308,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_rotate={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":4,"position":Vector2(107, 17),"global_position":Vector2(111, 60),"factor":1.0,"button_index":3,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||
]
|
||||
}
|
||||
structure_next={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
structure_previous={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
save={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194332,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
load={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
camera_center={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
textures/vram_compression/import_etc2_astc=true
|
||||
anti_aliasing/quality/msaa_3d=2
|
||||
debug/shapes/navigation/enable_edge_lines=false
|
||||
debug/shapes/navigation/enable_edge_lines.web=false
|
||||
debug/shapes/navigation/enable_geometry_face_random_color=false
|
||||
debug/shapes/navigation/enable_edge_connections=false
|
||||
@ -0,0 +1 @@
|
||||
uid://n26k1k7243dd
|
||||
@ -0,0 +1,233 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://b4k3xfm8pd8qw"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bsjmj0qu3xfrr" path="res://scripts/building_selector.gd" id="1_yvr4p"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_button_hover"]
|
||||
bg_color = Color(0.3, 0.3, 0.3, 0.9)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.5, 0.5, 0.5, 1)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_button_pressed"]
|
||||
bg_color = Color(0.4, 0.4, 0.4, 1)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.6, 0.6, 0.6, 1)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_button"]
|
||||
bg_color = Color(0.2, 0.2, 0.2, 0.8)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.4, 0.4, 0.4, 1)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_panel"]
|
||||
bg_color = Color(0.145098, 0.172549, 0.231373, 0.941176)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(0.356863, 0.670588, 0.768627, 1)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
|
||||
[node name="BuildingSelector" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 1
|
||||
script = ExtResource("1_yvr4p")
|
||||
|
||||
[node name="MainButton" type="Button" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 20.0
|
||||
offset_top = 20.0
|
||||
offset_right = 170.0
|
||||
offset_bottom = 60.0
|
||||
mouse_filter = 1
|
||||
theme_override_font_sizes/font_size = 16
|
||||
theme_override_styles/hover = SubResource("StyleBoxFlat_button_hover")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxFlat_button_pressed")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_button")
|
||||
text = "Select Building"
|
||||
|
||||
[node name="SelectionPanel" type="Panel" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 20.0
|
||||
offset_top = 70.0
|
||||
offset_right = 380.0
|
||||
offset_bottom = 620.0
|
||||
mouse_filter = 1
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_panel")
|
||||
|
||||
[node name="SearchBar" type="LineEdit" parent="SelectionPanel"]
|
||||
layout_mode = 0
|
||||
offset_left = 10.0
|
||||
offset_top = 10.0
|
||||
offset_right = 350.0
|
||||
offset_bottom = 40.0
|
||||
placeholder_text = "Search buildings..."
|
||||
clear_button_enabled = true
|
||||
|
||||
[node name="FilterButtons" type="HBoxContainer" parent="SelectionPanel"]
|
||||
layout_mode = 0
|
||||
offset_left = 10.0
|
||||
offset_top = 50.0
|
||||
offset_right = 350.0
|
||||
offset_bottom = 90.0
|
||||
theme_override_constants/separation = 5
|
||||
|
||||
[node name="AllButton" type="Button" parent="SelectionPanel/FilterButtons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_styles/hover = SubResource("StyleBoxFlat_button_hover")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxFlat_button_pressed")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_button")
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "All"
|
||||
|
||||
[node name="ResidentialButton" type="Button" parent="SelectionPanel/FilterButtons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_styles/hover = SubResource("StyleBoxFlat_button_hover")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxFlat_button_pressed")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_button")
|
||||
toggle_mode = true
|
||||
text = "Residential"
|
||||
|
||||
[node name="CommercialButton" type="Button" parent="SelectionPanel/FilterButtons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_styles/hover = SubResource("StyleBoxFlat_button_hover")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxFlat_button_pressed")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_button")
|
||||
toggle_mode = true
|
||||
text = "Commercial"
|
||||
|
||||
[node name="IndustrialButton" type="Button" parent="SelectionPanel/FilterButtons"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_styles/hover = SubResource("StyleBoxFlat_button_hover")
|
||||
theme_override_styles/pressed = SubResource("StyleBoxFlat_button_pressed")
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_button")
|
||||
toggle_mode = true
|
||||
text = "Industrial"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="SelectionPanel"]
|
||||
layout_mode = 0
|
||||
offset_left = 10.0
|
||||
offset_top = 100.0
|
||||
offset_right = 350.0
|
||||
offset_bottom = 510.0
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="SelectionPanel/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="GroundSection" type="VBoxContainer" parent="SelectionPanel/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="Label" type="Label" parent="SelectionPanel/ScrollContainer/VBoxContainer/GroundSection"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Ground Types"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="GroundOptions" type="GridContainer" parent="SelectionPanel/ScrollContainer/VBoxContainer/GroundSection"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 10
|
||||
theme_override_constants/v_separation = 10
|
||||
columns = 2
|
||||
|
||||
[node name="BuildingSection" type="VBoxContainer" parent="SelectionPanel/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="Label" type="Label" parent="SelectionPanel/ScrollContainer/VBoxContainer/BuildingSection"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Buildings"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="BuildingOptions" type="GridContainer" parent="SelectionPanel/ScrollContainer/VBoxContainer/BuildingSection"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 10
|
||||
theme_override_constants/v_separation = 10
|
||||
columns = 2
|
||||
|
||||
[node name="DescriptionPanel" type="Panel" parent="SelectionPanel"]
|
||||
layout_mode = 0
|
||||
offset_left = 10.0
|
||||
offset_top = 520.0
|
||||
offset_right = 350.0
|
||||
offset_bottom = 610.0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_panel")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="SelectionPanel/DescriptionPanel"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="SelectionPanel/DescriptionPanel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "No Building Selected"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="DescriptionLabel" type="Label" parent="SelectionPanel/DescriptionPanel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "Select a building to view its details"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="StatsContainer" type="HBoxContainer" parent="SelectionPanel/DescriptionPanel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="PriceLabel" type="Label" parent="SelectionPanel/DescriptionPanel/VBoxContainer/StatsContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "Price: $0"
|
||||
|
||||
[node name="PopulationLabel" type="Label" parent="SelectionPanel/DescriptionPanel/VBoxContainer/StatsContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "Population: 0"
|
||||
|
||||
[node name="PowerLabel" type="Label" parent="SelectionPanel/DescriptionPanel/VBoxContainer/StatsContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 14
|
||||
text = "Power: 0 kW"
|
||||
@ -0,0 +1,9 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://c03crmaif3bss"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bat3h7fhpdh7" path="res://scripts/economy_manager.gd" id="1_abcde"]
|
||||
|
||||
[node name="EconomyManager" type="Node"]
|
||||
script = ExtResource("1_abcde")
|
||||
|
||||
[node name="EconomyTimer" type="Timer" parent="."]
|
||||
autostart = true
|
||||
@ -0,0 +1 @@
|
||||
uid://c7qrkyfuarnfa
|
||||
@ -0,0 +1,438 @@
|
||||
[gd_scene load_steps=64 format=3 uid="uid://vgwrcfy1qawf"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://c37h6na3e4twn" path="res://scripts/builder.gd" id="1_jybm7"]
|
||||
[ext_resource type="Environment" uid="uid://jbptgqvstei3" path="res://scenes/main-environment.tres" id="1_yndf3"]
|
||||
[ext_resource type="Script" uid="uid://uxn26t1x4ehr" path="res://scripts/structure.gd" id="2_54v6r"]
|
||||
[ext_resource type="Resource" uid="uid://dv14kkhb6umkv" path="res://structures/road-straight.tres" id="2_bwyku"]
|
||||
[ext_resource type="Texture2D" uid="uid://cbk07cxgshg26" path="res://sprites/selector.png" id="4_wr1wv"]
|
||||
[ext_resource type="Resource" uid="uid://cntgl86ianngh" path="res://structures/building-small-a.tres" id="5_v5o2m"]
|
||||
<<<<<<< Updated upstream
|
||||
[ext_resource type="Resource" uid="uid://ccb475jeg7ym5" path="res://structures/grass-trees.tres" id="6_fwsy4"]
|
||||
[ext_resource type="Script" uid="uid://d3n8yylhejdoh" path="res://scripts/view.gd" id="8_yovpv"]
|
||||
[ext_resource type="Resource" uid="uid://tm532uesguhk" path="res://structures/grass.tres" id="9_2t3p4"]
|
||||
[ext_resource type="Resource" uid="uid://d2jplegnkl6u2" path="res://structures/road-corner.tres" id="10_ii8xx"]
|
||||
[ext_resource type="Script" uid="uid://otnxt4e77gmc" path="res://scripts/mission/mission_manager.gd" id="10_oe3re"]
|
||||
[ext_resource type="Resource" uid="uid://mxrnqinnsqnt" path="res://structures/road-straight-lightposts.tres" id="11_20frt"]
|
||||
[ext_resource type="Resource" uid="uid://c4qbn3d85prxx" path="res://structures/power-plant.tres" id="12_xtc7p"]
|
||||
[ext_resource type="PackedScene" uid="uid://dmsy06s02tcw4" path="res://scenes/generic_text_panel.tscn" id="13_7i6dj"]
|
||||
[ext_resource type="Script" uid="uid://ctqqmg4ydlbse" path="res://scripts/mission/mission_ui.gd" id="13_xvw5w"]
|
||||
[ext_resource type="Script" uid="uid://bt3emc1vt40gq" path="res://resources/generic_text_panel.resource.gd" id="14_76jlq"]
|
||||
[ext_resource type="Script" uid="uid://dnquivpg0ead" path="res://scripts/mission/learning_panel.gd" id="14_q2ymb"]
|
||||
[ext_resource type="Script" uid="uid://cjaik5ku37xqx" path="res://scripts/mission/mission_data.gd" id="14_vcrh8"]
|
||||
[ext_resource type="Resource" uid="uid://x5h4xutbldq3" path="res://mission/unit_1.02/census_planning_1.tres" id="15_obmwc"]
|
||||
[ext_resource type="Resource" uid="uid://cjr36hqnmyn0x" path="res://mission/unit_1.02/census_planning_2.tres" id="16_rl54y"]
|
||||
[ext_resource type="Resource" uid="uid://dykbopx8n3c3v" path="res://mission/unit_1.02/census_planning_3.tres" id="17_rrdy6"]
|
||||
=======
|
||||
[ext_resource type="Resource" uid="uid://d2jplegnkl6u2" path="res://structures/road-corner.tres" id="7_2wyq8"]
|
||||
[ext_resource type="Script" uid="uid://cu76h00erned0" path="res://scripts/view.gd" id="8_yovpv"]
|
||||
[ext_resource type="Script" uid="uid://bnpqjt5n1s20m" path="res://scripts/mission/mission_manager.gd" id="10_oe3re"]
|
||||
[ext_resource type="PackedScene" uid="uid://c03crmaif3bss" path="res://scenes/economy_manager.tscn" id="11_2f3dj"]
|
||||
[ext_resource type="PackedScene" uid="uid://dmsy06s02tcw4" path="res://scenes/generic_text_panel.tscn" id="13_7i6dj"]
|
||||
[ext_resource type="Script" uid="uid://bxuxhmlcqp64g" path="res://scripts/mission/mission_ui.gd" id="13_xvw5w"]
|
||||
[ext_resource type="Script" uid="uid://d1rme8o0ewiet" path="res://resources/generic_text_panel.resource.gd" id="14_76jlq"]
|
||||
[ext_resource type="Script" uid="uid://52tdmmosdbpa" path="res://scripts/mission/learning_panel.gd" id="14_q2ymb"]
|
||||
[ext_resource type="Script" uid="uid://c6f12a8vs3hp6" path="res://scripts/mission/mission_data.gd" id="14_vcrh8"]
|
||||
[ext_resource type="Resource" uid="uid://x5h4xutbldq3" path="res://mission/first_mission.tres" id="15_obmwc"]
|
||||
[ext_resource type="Resource" uid="uid://cjr36hqnmyn0x" path="res://mission/second_mission.tres" id="16_rl54y"]
|
||||
>>>>>>> Stashed changes
|
||||
[ext_resource type="FontFile" uid="uid://d0cxd77jybrcn" path="res://fonts/lilita_one_regular.ttf" id="17_vlub6"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4gkfwf4i3ydl" path="res://scenes/character.tscn" id="18_8lrh8"]
|
||||
[ext_resource type="PackedScene" uid="uid://cgk66f6rg03mj" path="res://scenes/hud.tscn" id="18_hud"]
|
||||
[ext_resource type="PackedScene" uid="uid://bqjnp7uypupog" path="res://scenes/controls_panel.tscn" id="19_controls"]
|
||||
<<<<<<< Updated upstream
|
||||
[ext_resource type="Script" uid="uid://b5nubrdeseay4" path="res://scripts/game_manager.gd" id="20_game_manager"]
|
||||
[ext_resource type="Resource" uid="uid://442cwthak2pa" path="res://mission/unit_1.02/market_research_1.tres" id="20_ngu16"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4s46k58ddpyc" path="res://scenes/sound_panel.tscn" id="21_sound_panel"]
|
||||
[ext_resource type="Resource" uid="uid://dtal0tl2ee336" path="res://structures/store.tres" id="21_y11qv"]
|
||||
[ext_resource type="Resource" uid="uid://bom5bu47dy5kp" path="res://mission/unit_1.02/market_research_2.tres" id="24_xud6a"]
|
||||
[ext_resource type="Resource" uid="uid://csrqvfwp63ygr" path="res://mission/unit_1.02/market_research_3.tres" id="25_6hx7u"]
|
||||
[ext_resource type="Resource" uid="uid://qwiwim2pg88f" path="res://mission/unit_1.02/market_research_4.tres" id="26_lvk23"]
|
||||
[ext_resource type="PackedScene" uid="uid://cb2rylpbex3ep" path="res://models/building-arcology.glb" id="27_m8wco"]
|
||||
[ext_resource type="Resource" uid="uid://cfgw8dblm55c5" path="res://mission/unit_1.03_1.05/grid_growth_1.tres" id="27_s0e58"]
|
||||
[ext_resource type="Resource" uid="uid://ba3ndftq7dht7" path="res://mission/unit_1.03_1.05/grid_growth_2.tres" id="28_hurxs"]
|
||||
[ext_resource type="Resource" uid="uid://dgimr2v12rjqu" path="res://mission/unit_1.03_1.05/grid_growth_3.tres" id="29_rhn1n"]
|
||||
[ext_resource type="Resource" uid="uid://dm2o4dq2oml53" path="res://mission/unit_1.03_1.05/grid_growth_4.tres" id="30_4rwkv"]
|
||||
[ext_resource type="Resource" uid="uid://btwrfq37q8vey" path="res://mission/unit_1.03_1.05/traffic_flow_1.tres" id="31_j2idb"]
|
||||
[ext_resource type="Resource" uid="uid://cf7gpb4j7gq1g" path="res://mission/unit_1.03_1.05/traffic_flow_2.tres" id="32_ipu0c"]
|
||||
[ext_resource type="Resource" uid="uid://ddmxjjyxgxyxo" path="res://mission/unit_1.03_1.05/traffic_flow_3.tres" id="33_c0l5e"]
|
||||
[ext_resource type="Resource" uid="uid://doxd30r8qbgdq" path="res://mission/unit_1.03_1.05/traffic_flow_4.tres" id="34_21t20"]
|
||||
[ext_resource type="Resource" uid="uid://duaxn13myfx22" path="res://mission/unit_1.06/sustainable_dev_1.tres" id="35_o0bjh"]
|
||||
[ext_resource type="Resource" uid="uid://fuxb3pfbbwjm" path="res://mission/unit_1.06/sustainable_dev_2.tres" id="36_2wodh"]
|
||||
[ext_resource type="Resource" uid="uid://byd5jxiutxpky" path="res://mission/unit_1.06/sustainable_dev_3.tres" id="37_psgx1"]
|
||||
[ext_resource type="Resource" uid="uid://daug1o7kppqit" path="res://mission/unit_1.06/sustainable_dev_4.tres" id="38_hw762"]
|
||||
[ext_resource type="Resource" uid="uid://cp7tcpktwlrkt" path="res://mission/unit_1.06/urban_planning_1.tres" id="39_ymw5p"]
|
||||
[ext_resource type="Resource" uid="uid://c3q1afcvwi4rk" path="res://mission/unit_1.06/urban_planning_2.tres" id="40_uggp1"]
|
||||
[ext_resource type="Resource" uid="uid://ct1k7n2oopwdu" path="res://mission/unit_1.06/urban_planning_3.tres" id="41_f0dxf"]
|
||||
[ext_resource type="Resource" uid="uid://d1fykuxfmh2q1" path="res://mission/unit_1.06/urban_planning_4.tres" id="42_fv8gl"]
|
||||
[ext_resource type="Resource" uid="uid://detwnqsq87r30" path="res://mission/unit_1.07/economic_forecast_1.tres" id="43_qvne6"]
|
||||
[ext_resource type="Resource" uid="uid://bj7tjuknfaeyg" path="res://mission/unit_1.07/economic_forecast_2.tres" id="44_haub2"]
|
||||
[ext_resource type="Resource" uid="uid://ctyrlnq5cxuiu" path="res://mission/unit_1.07/economic_forecast_3.tres" id="45_xs8xk"]
|
||||
[ext_resource type="Resource" uid="uid://ct45gjmw5b7pa" path="res://mission/unit_1.07/economic_forecast_4.tres" id="46_pob6d"]
|
||||
[ext_resource type="Resource" uid="uid://bwrkqv42wk8f" path="res://mission/unit_1.07/resource_alloc_1.tres" id="47_6w4y8"]
|
||||
[ext_resource type="Resource" uid="uid://d0nblitd4ixir" path="res://mission/unit_1.07/resource_alloc_2.tres" id="48_ck35a"]
|
||||
[ext_resource type="Resource" uid="uid://cxh8dgf54oimx" path="res://mission/unit_1.07/resource_alloc_3.tres" id="49_cvgxw"]
|
||||
[ext_resource type="Resource" uid="uid://cpfr2xnjtpcog" path="res://mission/unit_1.07/resource_alloc_4.tres" id="50_6ke0d"]
|
||||
=======
|
||||
[ext_resource type="Script" uid="uid://dlqco4kmwr3er" path="res://scripts/game_manager.gd" id="20_game_manager"]
|
||||
[ext_resource type="Resource" uid="uid://bv4r7ebpjdce4" path="res://mission/sixth_mission.tres" id="20_r0ysx"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4s46k58ddpyc" path="res://scenes/sound_panel.tscn" id="21_sound_panel"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4k3xfm8pd8qw" path="res://scenes/building_selector.tscn" id="22_building_selector"]
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
[sub_resource type="Resource" id="Resource_1gdbm"]
|
||||
script = ExtResource("14_76jlq")
|
||||
panel_type = 0
|
||||
title = "Welcome to Stem City "
|
||||
body_text = "Welcome to Stem City!
|
||||
|
||||
Your goal is to build a thriving community from the ground up. As you complete missions, you'll unlock new structures to expand and improve your city.
|
||||
|
||||
As the new city planner, you need to establish a baseline understanding of your growing community. The mayor has requested a comprehensive census to guide future development.
|
||||
|
||||
|
||||
|
||||
|
||||
Ready to start planning your city? Click Close to see the controls and begin your first mission!
|
||||
|
||||
|
||||
"
|
||||
button_text = "Close"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_ja86h"]
|
||||
script = ExtResource("14_76jlq")
|
||||
panel_type = 1
|
||||
title = "Welcome to Stem City"
|
||||
body_text = "Congratulations, City Planner!
|
||||
|
||||
You've completed all the guided missions and unlocked the full potential of Stem City. Your understanding of urban planning and STEM concepts has helped create a thriving community.
|
||||
|
||||
But the journey doesn't end here! Continue expanding your city using all the structures you've unlocked. Experiment with different layouts, create new neighborhoods, and see how large you can grow your population.
|
||||
|
||||
The future of Stem City is now in your hands - keep building and exploring!
|
||||
"
|
||||
button_text = "Close"
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mission"]
|
||||
bg_color = Color(0.145098, 0.172549, 0.231373, 0.941176)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(0.356863, 0.670588, 0.768627, 1)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
shadow_size = 5
|
||||
shadow_offset = Vector2(2, 2)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lsmd5"]
|
||||
bg_color = Color(0.196078, 0.196078, 0.196078, 0.960784)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(0.294118, 0.478431, 0.729412, 1)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
shadow_size = 5
|
||||
shadow_offset = Vector2(3, 3)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_description"]
|
||||
bg_color = Color(0.145098, 0.145098, 0.164706, 0.768627)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.294118, 0.478431, 0.729412, 0.301961)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_graph"]
|
||||
bg_color = Color(0.117647, 0.137255, 0.160784, 0.768627)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.294118, 0.478431, 0.729412, 0.301961)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[node name="Main" type="Node3D"]
|
||||
script = ExtResource("20_game_manager")
|
||||
intro_text_resource = SubResource("Resource_1gdbm")
|
||||
outro_text_resource = SubResource("Resource_ja86h")
|
||||
|
||||
[node name="Builder" type="Node3D" parent="." node_paths=PackedStringArray("selector", "selector_container", "view_camera", "gridmap")]
|
||||
script = ExtResource("1_jybm7")
|
||||
<<<<<<< Updated upstream
|
||||
structures = Array[ExtResource("2_54v6r")]([ExtResource("2_bwyku"), ExtResource("5_v5o2m"), ExtResource("6_fwsy4"), ExtResource("21_y11qv"), ExtResource("9_2t3p4"), ExtResource("10_ii8xx"), ExtResource("11_20frt"), ExtResource("12_xtc7p")])
|
||||
=======
|
||||
structures = Array[ExtResource("2_54v6r")]([ExtResource("2_bwyku"), ExtResource("5_v5o2m"), ExtResource("7_2wyq8")])
|
||||
>>>>>>> Stashed changes
|
||||
selector = NodePath("Selector")
|
||||
selector_container = NodePath("Selector/Container")
|
||||
view_camera = NodePath("../View/Camera")
|
||||
gridmap = NodePath("../GridMap")
|
||||
|
||||
[node name="Selector" type="Node3D" parent="Builder"]
|
||||
|
||||
[node name="Sprite" type="Sprite3D" parent="Builder/Selector"]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.06, 0)
|
||||
texture = ExtResource("4_wr1wv")
|
||||
|
||||
[node name="Container" type="Node3D" parent="Builder/Selector"]
|
||||
|
||||
[node name="View" type="Node3D" parent="."]
|
||||
transform = Transform3D(0.707107, -0.40558, 0.579228, 0, 0.819152, 0.573576, -0.707107, -0.40558, 0.579228, 0, 0, 0)
|
||||
script = ExtResource("8_yovpv")
|
||||
|
||||
[node name="Camera" type="Camera3D" parent="View"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 7.15256e-07, 0, 0, 1, 0, 27.98, 49.5918)
|
||||
environment = ExtResource("1_yndf3")
|
||||
fov = 20.0
|
||||
|
||||
[node name="EconomyManager" parent="." instance=ExtResource("11_2f3dj")]
|
||||
|
||||
[node name="GridMap" type="GridMap" parent="."]
|
||||
cell_size = Vector3(1, 1, 1)
|
||||
cell_center_x = false
|
||||
cell_center_y = false
|
||||
cell_center_z = false
|
||||
|
||||
[node name="Sun" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.642788, 0.766044, 0, -0.766045, 0.642787, 0, 0, 0)
|
||||
light_energy = 2.0
|
||||
light_indirect_energy = 3.0
|
||||
light_volumetric_fog_energy = 3.07
|
||||
shadow_enabled = true
|
||||
shadow_opacity = 0.75
|
||||
|
||||
[node name="CanvasLayer" type="CanvasLayer" parent="."]
|
||||
|
||||
[node name="HUD" parent="CanvasLayer" instance=ExtResource("18_hud")]
|
||||
|
||||
[node name="BuildingSelector" parent="CanvasLayer" instance=ExtResource("22_building_selector")]
|
||||
anchors_preset = 0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
offset_left = 20.0
|
||||
offset_top = 100.0
|
||||
offset_right = 220.0
|
||||
offset_bottom = 200.0
|
||||
grow_horizontal = 1
|
||||
grow_vertical = 1
|
||||
|
||||
[node name="ControlsPanel" parent="CanvasLayer" instance=ExtResource("19_controls")]
|
||||
|
||||
[node name="SoundPanel" parent="CanvasLayer" instance=ExtResource("21_sound_panel")]
|
||||
anchors_preset = 8
|
||||
|
||||
[node name="GenericTextPanel" parent="CanvasLayer" instance=ExtResource("13_7i6dj")]
|
||||
resource_data = ExtResource("14_76jlq")
|
||||
|
||||
[node name="MissionManager" type="Node" parent="." node_paths=PackedStringArray("mission_ui", "builder")]
|
||||
script = ExtResource("10_oe3re")
|
||||
<<<<<<< Updated upstream
|
||||
missions = Array[ExtResource("14_vcrh8")]([ExtResource("15_obmwc"), ExtResource("16_rl54y"), ExtResource("17_rrdy6"), ExtResource("20_ngu16"), ExtResource("24_xud6a"), ExtResource("25_6hx7u"), ExtResource("26_lvk23"), ExtResource("27_s0e58"), ExtResource("28_hurxs"), ExtResource("29_rhn1n"), ExtResource("30_4rwkv"), ExtResource("31_j2idb"), ExtResource("32_ipu0c"), ExtResource("33_c0l5e"), ExtResource("34_21t20"), ExtResource("35_o0bjh"), ExtResource("36_2wodh"), ExtResource("37_psgx1"), ExtResource("38_hw762"), ExtResource("39_ymw5p"), ExtResource("40_uggp1"), ExtResource("41_f0dxf"), ExtResource("42_fv8gl"), ExtResource("43_qvne6"), ExtResource("44_haub2"), ExtResource("45_xs8xk"), ExtResource("46_pob6d"), ExtResource("47_6w4y8"), ExtResource("48_ck35a"), ExtResource("49_cvgxw"), ExtResource("50_6ke0d")])
|
||||
=======
|
||||
missions = Array[ExtResource("14_vcrh8")]([ExtResource("15_obmwc"), ExtResource("16_rl54y"), ExtResource("18_h4fpv"), ExtResource("20_r0ysx")])
|
||||
>>>>>>> Stashed changes
|
||||
mission_ui = NodePath("MissionPanel")
|
||||
builder = NodePath("../Builder")
|
||||
character_scene = ExtResource("18_8lrh8")
|
||||
|
||||
[node name="MissionPanel" type="PanelContainer" parent="MissionManager" node_paths=PackedStringArray("mission_title_label", "mission_description_label", "objectives_container")]
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -450.0
|
||||
offset_top = 20.0
|
||||
offset_right = -20.0
|
||||
grow_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_mission")
|
||||
script = ExtResource("13_xvw5w")
|
||||
mission_title_label = NodePath("MarginContainer/VBoxContainer/MissionTitleLabel")
|
||||
mission_description_label = NodePath("MarginContainer/VBoxContainer/MissionDescriptionLabel")
|
||||
objectives_container = NodePath("MarginContainer/VBoxContainer/ObjectivesContainer")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MissionManager/MissionPanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 20
|
||||
theme_override_constants/margin_top = 20
|
||||
theme_override_constants/margin_right = 20
|
||||
theme_override_constants/margin_bottom = 20
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MissionManager/MissionPanel/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 15
|
||||
|
||||
[node name="MissionTitleLabel" type="Label" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("17_vlub6")
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Mission Title"
|
||||
horizontal_alignment = 1
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MissionDescriptionLabel" type="Label" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 1
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "Mission description goes here..."
|
||||
autowrap_mode = 2
|
||||
text_overrun_behavior = 4
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ObjectivesLabel" type="Label" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.678431, 0.847059, 1, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Objectives:"
|
||||
|
||||
[node name="ObjectivesContainer" type="VBoxContainer" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="LearningPanel" type="PanelContainer" parent="MissionManager"]
|
||||
visible = false
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 50.0
|
||||
offset_top = 50.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = -50.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_lsmd5")
|
||||
script = ExtResource("14_q2ymb")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MissionManager/LearningPanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 30
|
||||
theme_override_constants/margin_top = 30
|
||||
theme_override_constants/margin_right = 30
|
||||
theme_override_constants/margin_bottom = 30
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MissionManager/LearningPanel/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("17_vlub6")
|
||||
theme_override_font_sizes/font_size = 32
|
||||
text = "Learning Module"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="DescriptionPanel" type="PanelContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
size_flags_stretch_ratio = 0.5
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_description")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/DescriptionPanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 15
|
||||
theme_override_constants/margin_top = 15
|
||||
theme_override_constants/margin_right = 15
|
||||
theme_override_constants/margin_bottom = 15
|
||||
|
||||
[node name="DescriptionLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/DescriptionPanel/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "Description goes here..."
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="GraphTitle" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Graph:"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="GraphContainer" type="Panel" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
custom_minimum_size = Vector2(0, 300)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_graph")
|
||||
|
||||
[node name="AnswerContainer" type="VBoxContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="QuestionLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "How many workers do we need to build 10 houses in a week?"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="AnswerField" type="LineEdit" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_font_sizes/font_size = 18
|
||||
placeholder_text = "Enter answer"
|
||||
alignment = 1
|
||||
max_length = 5
|
||||
|
||||
[node name="CheckButton" type="Button" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "Check Answer"
|
||||
|
||||
[node name="FeedbackLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 18
|
||||
horizontal_alignment = 1
|
||||
autowrap_mode = 2
|
||||
text_overrun_behavior = 3
|
||||
max_lines_visible = 6
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="CompleteButton" type="Button" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(200, 50)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 18
|
||||
disabled = true
|
||||
text = "Complete"
|
||||
|
||||
[node name="ObjectiveLabel" type="Label" parent="MissionManager"]
|
||||
offset_right = 40.0
|
||||
offset_bottom = 23.0
|
||||
|
||||
[node name="building-arcology2" parent="." instance=ExtResource("27_m8wco")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10, -16, -14)
|
||||
|
||||
[connection signal="all_missions_completed" from="MissionManager" to="." method="_on_mission_manager_all_missions_completed"]
|
||||
[connection signal="mission_started" from="MissionManager" to="." method="_on_mission_manager_mission_started"]
|
||||
[connection signal="pressed" from="MissionManager/LearningPanel/MarginContainer/VBoxContainer/HBoxContainer/CompleteButton" to="MissionManager/LearningPanel" method="_on_complete_button_pressed"]
|
||||
@ -0,0 +1,438 @@
|
||||
[gd_scene load_steps=64 format=3 uid="uid://vgwrcfy1qawf"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://c37h6na3e4twn" path="res://scripts/builder.gd" id="1_jybm7"]
|
||||
[ext_resource type="Environment" uid="uid://jbptgqvstei3" path="res://scenes/main-environment.tres" id="1_yndf3"]
|
||||
[ext_resource type="Script" uid="uid://uxn26t1x4ehr" path="res://scripts/structure.gd" id="2_54v6r"]
|
||||
[ext_resource type="Resource" uid="uid://dv14kkhb6umkv" path="res://structures/road-straight.tres" id="2_bwyku"]
|
||||
[ext_resource type="Texture2D" uid="uid://cbk07cxgshg26" path="res://sprites/selector.png" id="4_wr1wv"]
|
||||
[ext_resource type="Resource" uid="uid://cntgl86ianngh" path="res://structures/building-small-a.tres" id="5_v5o2m"]
|
||||
<<<<<<< Updated upstream
|
||||
[ext_resource type="Resource" uid="uid://ccb475jeg7ym5" path="res://structures/grass-trees.tres" id="6_fwsy4"]
|
||||
[ext_resource type="Script" uid="uid://d3n8yylhejdoh" path="res://scripts/view.gd" id="8_yovpv"]
|
||||
[ext_resource type="Resource" uid="uid://tm532uesguhk" path="res://structures/grass.tres" id="9_2t3p4"]
|
||||
[ext_resource type="Resource" uid="uid://d2jplegnkl6u2" path="res://structures/road-corner.tres" id="10_ii8xx"]
|
||||
[ext_resource type="Script" uid="uid://otnxt4e77gmc" path="res://scripts/mission/mission_manager.gd" id="10_oe3re"]
|
||||
[ext_resource type="Resource" uid="uid://mxrnqinnsqnt" path="res://structures/road-straight-lightposts.tres" id="11_20frt"]
|
||||
[ext_resource type="Resource" uid="uid://c4qbn3d85prxx" path="res://structures/power-plant.tres" id="12_xtc7p"]
|
||||
[ext_resource type="PackedScene" uid="uid://dmsy06s02tcw4" path="res://scenes/generic_text_panel.tscn" id="13_7i6dj"]
|
||||
[ext_resource type="Script" uid="uid://ctqqmg4ydlbse" path="res://scripts/mission/mission_ui.gd" id="13_xvw5w"]
|
||||
[ext_resource type="Script" uid="uid://bt3emc1vt40gq" path="res://resources/generic_text_panel.resource.gd" id="14_76jlq"]
|
||||
[ext_resource type="Script" uid="uid://dnquivpg0ead" path="res://scripts/mission/learning_panel.gd" id="14_q2ymb"]
|
||||
[ext_resource type="Script" uid="uid://cjaik5ku37xqx" path="res://scripts/mission/mission_data.gd" id="14_vcrh8"]
|
||||
[ext_resource type="Resource" uid="uid://x5h4xutbldq3" path="res://mission/unit_1.02/census_planning_1.tres" id="15_obmwc"]
|
||||
[ext_resource type="Resource" uid="uid://cjr36hqnmyn0x" path="res://mission/unit_1.02/census_planning_2.tres" id="16_rl54y"]
|
||||
[ext_resource type="Resource" uid="uid://dykbopx8n3c3v" path="res://mission/unit_1.02/census_planning_3.tres" id="17_rrdy6"]
|
||||
=======
|
||||
[ext_resource type="Resource" uid="uid://d2jplegnkl6u2" path="res://structures/road-corner.tres" id="7_2wyq8"]
|
||||
[ext_resource type="Script" uid="uid://cu76h00erned0" path="res://scripts/view.gd" id="8_yovpv"]
|
||||
[ext_resource type="Script" uid="uid://bnpqjt5n1s20m" path="res://scripts/mission/mission_manager.gd" id="10_oe3re"]
|
||||
[ext_resource type="PackedScene" uid="uid://c03crmaif3bss" path="res://scenes/economy_manager.tscn" id="11_2f3dj"]
|
||||
[ext_resource type="PackedScene" uid="uid://dmsy06s02tcw4" path="res://scenes/generic_text_panel.tscn" id="13_7i6dj"]
|
||||
[ext_resource type="Script" uid="uid://bxuxhmlcqp64g" path="res://scripts/mission/mission_ui.gd" id="13_xvw5w"]
|
||||
[ext_resource type="Script" uid="uid://d1rme8o0ewiet" path="res://resources/generic_text_panel.resource.gd" id="14_76jlq"]
|
||||
[ext_resource type="Script" uid="uid://52tdmmosdbpa" path="res://scripts/mission/learning_panel.gd" id="14_q2ymb"]
|
||||
[ext_resource type="Script" uid="uid://c6f12a8vs3hp6" path="res://scripts/mission/mission_data.gd" id="14_vcrh8"]
|
||||
[ext_resource type="Resource" uid="uid://x5h4xutbldq3" path="res://mission/first_mission.tres" id="15_obmwc"]
|
||||
[ext_resource type="Resource" uid="uid://cjr36hqnmyn0x" path="res://mission/second_mission.tres" id="16_rl54y"]
|
||||
>>>>>>> Stashed changes
|
||||
[ext_resource type="FontFile" uid="uid://d0cxd77jybrcn" path="res://fonts/lilita_one_regular.ttf" id="17_vlub6"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4gkfwf4i3ydl" path="res://scenes/character.tscn" id="18_8lrh8"]
|
||||
[ext_resource type="PackedScene" uid="uid://cgk66f6rg03mj" path="res://scenes/hud.tscn" id="18_hud"]
|
||||
[ext_resource type="PackedScene" uid="uid://bqjnp7uypupog" path="res://scenes/controls_panel.tscn" id="19_controls"]
|
||||
<<<<<<< Updated upstream
|
||||
[ext_resource type="Script" uid="uid://b5nubrdeseay4" path="res://scripts/game_manager.gd" id="20_game_manager"]
|
||||
[ext_resource type="Resource" uid="uid://442cwthak2pa" path="res://mission/unit_1.02/market_research_1.tres" id="20_ngu16"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4s46k58ddpyc" path="res://scenes/sound_panel.tscn" id="21_sound_panel"]
|
||||
[ext_resource type="Resource" uid="uid://dtal0tl2ee336" path="res://structures/store.tres" id="21_y11qv"]
|
||||
[ext_resource type="Resource" uid="uid://bom5bu47dy5kp" path="res://mission/unit_1.02/market_research_2.tres" id="24_xud6a"]
|
||||
[ext_resource type="Resource" uid="uid://csrqvfwp63ygr" path="res://mission/unit_1.02/market_research_3.tres" id="25_6hx7u"]
|
||||
[ext_resource type="Resource" uid="uid://qwiwim2pg88f" path="res://mission/unit_1.02/market_research_4.tres" id="26_lvk23"]
|
||||
[ext_resource type="PackedScene" uid="uid://cb2rylpbex3ep" path="res://models/building-arcology.glb" id="27_m8wco"]
|
||||
[ext_resource type="Resource" uid="uid://cfgw8dblm55c5" path="res://mission/unit_1.03_1.05/grid_growth_1.tres" id="27_s0e58"]
|
||||
[ext_resource type="Resource" uid="uid://ba3ndftq7dht7" path="res://mission/unit_1.03_1.05/grid_growth_2.tres" id="28_hurxs"]
|
||||
[ext_resource type="Resource" uid="uid://dgimr2v12rjqu" path="res://mission/unit_1.03_1.05/grid_growth_3.tres" id="29_rhn1n"]
|
||||
[ext_resource type="Resource" uid="uid://dm2o4dq2oml53" path="res://mission/unit_1.03_1.05/grid_growth_4.tres" id="30_4rwkv"]
|
||||
[ext_resource type="Resource" uid="uid://btwrfq37q8vey" path="res://mission/unit_1.03_1.05/traffic_flow_1.tres" id="31_j2idb"]
|
||||
[ext_resource type="Resource" uid="uid://cf7gpb4j7gq1g" path="res://mission/unit_1.03_1.05/traffic_flow_2.tres" id="32_ipu0c"]
|
||||
[ext_resource type="Resource" uid="uid://ddmxjjyxgxyxo" path="res://mission/unit_1.03_1.05/traffic_flow_3.tres" id="33_c0l5e"]
|
||||
[ext_resource type="Resource" uid="uid://doxd30r8qbgdq" path="res://mission/unit_1.03_1.05/traffic_flow_4.tres" id="34_21t20"]
|
||||
[ext_resource type="Resource" uid="uid://duaxn13myfx22" path="res://mission/unit_1.06/sustainable_dev_1.tres" id="35_o0bjh"]
|
||||
[ext_resource type="Resource" uid="uid://fuxb3pfbbwjm" path="res://mission/unit_1.06/sustainable_dev_2.tres" id="36_2wodh"]
|
||||
[ext_resource type="Resource" uid="uid://byd5jxiutxpky" path="res://mission/unit_1.06/sustainable_dev_3.tres" id="37_psgx1"]
|
||||
[ext_resource type="Resource" uid="uid://daug1o7kppqit" path="res://mission/unit_1.06/sustainable_dev_4.tres" id="38_hw762"]
|
||||
[ext_resource type="Resource" uid="uid://cp7tcpktwlrkt" path="res://mission/unit_1.06/urban_planning_1.tres" id="39_ymw5p"]
|
||||
[ext_resource type="Resource" uid="uid://c3q1afcvwi4rk" path="res://mission/unit_1.06/urban_planning_2.tres" id="40_uggp1"]
|
||||
[ext_resource type="Resource" uid="uid://ct1k7n2oopwdu" path="res://mission/unit_1.06/urban_planning_3.tres" id="41_f0dxf"]
|
||||
[ext_resource type="Resource" uid="uid://d1fykuxfmh2q1" path="res://mission/unit_1.06/urban_planning_4.tres" id="42_fv8gl"]
|
||||
[ext_resource type="Resource" uid="uid://detwnqsq87r30" path="res://mission/unit_1.07/economic_forecast_1.tres" id="43_qvne6"]
|
||||
[ext_resource type="Resource" uid="uid://bj7tjuknfaeyg" path="res://mission/unit_1.07/economic_forecast_2.tres" id="44_haub2"]
|
||||
[ext_resource type="Resource" uid="uid://ctyrlnq5cxuiu" path="res://mission/unit_1.07/economic_forecast_3.tres" id="45_xs8xk"]
|
||||
[ext_resource type="Resource" uid="uid://ct45gjmw5b7pa" path="res://mission/unit_1.07/economic_forecast_4.tres" id="46_pob6d"]
|
||||
[ext_resource type="Resource" uid="uid://bwrkqv42wk8f" path="res://mission/unit_1.07/resource_alloc_1.tres" id="47_6w4y8"]
|
||||
[ext_resource type="Resource" uid="uid://d0nblitd4ixir" path="res://mission/unit_1.07/resource_alloc_2.tres" id="48_ck35a"]
|
||||
[ext_resource type="Resource" uid="uid://cxh8dgf54oimx" path="res://mission/unit_1.07/resource_alloc_3.tres" id="49_cvgxw"]
|
||||
[ext_resource type="Resource" uid="uid://cpfr2xnjtpcog" path="res://mission/unit_1.07/resource_alloc_4.tres" id="50_6ke0d"]
|
||||
=======
|
||||
[ext_resource type="Script" uid="uid://dlqco4kmwr3er" path="res://scripts/game_manager.gd" id="20_game_manager"]
|
||||
[ext_resource type="Resource" uid="uid://bv4r7ebpjdce4" path="res://mission/sixth_mission.tres" id="20_r0ysx"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4s46k58ddpyc" path="res://scenes/sound_panel.tscn" id="21_sound_panel"]
|
||||
[ext_resource type="PackedScene" uid="uid://b4k3xfm8pd8qw" path="res://scenes/building_selector.tscn" id="22_building_selector"]
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
[sub_resource type="Resource" id="Resource_1gdbm"]
|
||||
script = ExtResource("14_76jlq")
|
||||
panel_type = 0
|
||||
title = "Welcome to Stem City "
|
||||
body_text = "Welcome to Stem City!
|
||||
|
||||
Your goal is to build a thriving community from the ground up. As you complete missions, you'll unlock new structures to expand and improve your city.
|
||||
|
||||
As the new city planner, you need to establish a baseline understanding of your growing community. The mayor has requested a comprehensive census to guide future development.
|
||||
|
||||
|
||||
|
||||
|
||||
Ready to start planning your city? Click Close to see the controls and begin your first mission!
|
||||
|
||||
|
||||
"
|
||||
button_text = "Close"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_ja86h"]
|
||||
script = ExtResource("14_76jlq")
|
||||
panel_type = 1
|
||||
title = "Welcome to Stem City"
|
||||
body_text = "Congratulations, City Planner!
|
||||
|
||||
You've completed all the guided missions and unlocked the full potential of Stem City. Your understanding of urban planning and STEM concepts has helped create a thriving community.
|
||||
|
||||
But the journey doesn't end here! Continue expanding your city using all the structures you've unlocked. Experiment with different layouts, create new neighborhoods, and see how large you can grow your population.
|
||||
|
||||
The future of Stem City is now in your hands - keep building and exploring!
|
||||
"
|
||||
button_text = "Close"
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mission"]
|
||||
bg_color = Color(0.145098, 0.172549, 0.231373, 0.941176)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(0.356863, 0.670588, 0.768627, 1)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
shadow_size = 5
|
||||
shadow_offset = Vector2(2, 2)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lsmd5"]
|
||||
bg_color = Color(0.196078, 0.196078, 0.196078, 0.960784)
|
||||
border_width_left = 2
|
||||
border_width_top = 2
|
||||
border_width_right = 2
|
||||
border_width_bottom = 2
|
||||
border_color = Color(0.294118, 0.478431, 0.729412, 1)
|
||||
corner_radius_top_left = 8
|
||||
corner_radius_top_right = 8
|
||||
corner_radius_bottom_right = 8
|
||||
corner_radius_bottom_left = 8
|
||||
shadow_size = 5
|
||||
shadow_offset = Vector2(3, 3)
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_description"]
|
||||
bg_color = Color(0.145098, 0.145098, 0.164706, 0.768627)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.294118, 0.478431, 0.729412, 0.301961)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_graph"]
|
||||
bg_color = Color(0.117647, 0.137255, 0.160784, 0.768627)
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
border_color = Color(0.294118, 0.478431, 0.729412, 0.301961)
|
||||
corner_radius_top_left = 4
|
||||
corner_radius_top_right = 4
|
||||
corner_radius_bottom_right = 4
|
||||
corner_radius_bottom_left = 4
|
||||
|
||||
[node name="Main" type="Node3D"]
|
||||
script = ExtResource("20_game_manager")
|
||||
intro_text_resource = SubResource("Resource_1gdbm")
|
||||
outro_text_resource = SubResource("Resource_ja86h")
|
||||
|
||||
[node name="Builder" type="Node3D" parent="." node_paths=PackedStringArray("selector", "selector_container", "view_camera", "gridmap")]
|
||||
script = ExtResource("1_jybm7")
|
||||
<<<<<<< Updated upstream
|
||||
structures = Array[ExtResource("2_54v6r")]([ExtResource("2_bwyku"), ExtResource("5_v5o2m"), ExtResource("6_fwsy4"), ExtResource("21_y11qv"), ExtResource("9_2t3p4"), ExtResource("10_ii8xx"), ExtResource("11_20frt"), ExtResource("12_xtc7p")])
|
||||
=======
|
||||
structures = Array[ExtResource("2_54v6r")]([ExtResource("2_bwyku"), ExtResource("5_v5o2m"), ExtResource("7_2wyq8")])
|
||||
>>>>>>> Stashed changes
|
||||
selector = NodePath("Selector")
|
||||
selector_container = NodePath("Selector/Container")
|
||||
view_camera = NodePath("../View/Camera")
|
||||
gridmap = NodePath("../GridMap")
|
||||
|
||||
[node name="Selector" type="Node3D" parent="Builder"]
|
||||
|
||||
[node name="Sprite" type="Sprite3D" parent="Builder/Selector"]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.06, 0)
|
||||
texture = ExtResource("4_wr1wv")
|
||||
|
||||
[node name="Container" type="Node3D" parent="Builder/Selector"]
|
||||
|
||||
[node name="View" type="Node3D" parent="."]
|
||||
transform = Transform3D(0.707107, -0.40558, 0.579228, 0, 0.819152, 0.573576, -0.707107, -0.40558, 0.579228, 0, 0, 0)
|
||||
script = ExtResource("8_yovpv")
|
||||
|
||||
[node name="Camera" type="Camera3D" parent="View"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 7.15256e-07, 0, 0, 1, 0, 27.98, 49.5918)
|
||||
environment = ExtResource("1_yndf3")
|
||||
fov = 20.0
|
||||
|
||||
[node name="EconomyManager" parent="." instance=ExtResource("11_2f3dj")]
|
||||
|
||||
[node name="GridMap" type="GridMap" parent="."]
|
||||
cell_size = Vector3(1, 1, 1)
|
||||
cell_center_x = false
|
||||
cell_center_y = false
|
||||
cell_center_z = false
|
||||
|
||||
[node name="Sun" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.642788, 0.766044, 0, -0.766045, 0.642787, 0, 0, 0)
|
||||
light_energy = 2.0
|
||||
light_indirect_energy = 3.0
|
||||
light_volumetric_fog_energy = 3.07
|
||||
shadow_enabled = true
|
||||
shadow_opacity = 0.75
|
||||
|
||||
[node name="CanvasLayer" type="CanvasLayer" parent="."]
|
||||
|
||||
[node name="HUD" parent="CanvasLayer" instance=ExtResource("18_hud")]
|
||||
|
||||
[node name="BuildingSelector" parent="CanvasLayer" instance=ExtResource("22_building_selector")]
|
||||
anchors_preset = 0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
offset_left = 20.0
|
||||
offset_top = 100.0
|
||||
offset_right = 220.0
|
||||
offset_bottom = 200.0
|
||||
grow_horizontal = 1
|
||||
grow_vertical = 1
|
||||
|
||||
[node name="ControlsPanel" parent="CanvasLayer" instance=ExtResource("19_controls")]
|
||||
|
||||
[node name="SoundPanel" parent="CanvasLayer" instance=ExtResource("21_sound_panel")]
|
||||
anchors_preset = 8
|
||||
|
||||
[node name="GenericTextPanel" parent="CanvasLayer" instance=ExtResource("13_7i6dj")]
|
||||
resource_data = ExtResource("14_76jlq")
|
||||
|
||||
[node name="MissionManager" type="Node" parent="." node_paths=PackedStringArray("mission_ui", "builder")]
|
||||
script = ExtResource("10_oe3re")
|
||||
<<<<<<< Updated upstream
|
||||
missions = Array[ExtResource("14_vcrh8")]([ExtResource("15_obmwc"), ExtResource("16_rl54y"), ExtResource("17_rrdy6"), ExtResource("20_ngu16"), ExtResource("24_xud6a"), ExtResource("25_6hx7u"), ExtResource("26_lvk23"), ExtResource("27_s0e58"), ExtResource("28_hurxs"), ExtResource("29_rhn1n"), ExtResource("30_4rwkv"), ExtResource("31_j2idb"), ExtResource("32_ipu0c"), ExtResource("33_c0l5e"), ExtResource("34_21t20"), ExtResource("35_o0bjh"), ExtResource("36_2wodh"), ExtResource("37_psgx1"), ExtResource("38_hw762"), ExtResource("39_ymw5p"), ExtResource("40_uggp1"), ExtResource("41_f0dxf"), ExtResource("42_fv8gl"), ExtResource("43_qvne6"), ExtResource("44_haub2"), ExtResource("45_xs8xk"), ExtResource("46_pob6d"), ExtResource("47_6w4y8"), ExtResource("48_ck35a"), ExtResource("49_cvgxw"), ExtResource("50_6ke0d")])
|
||||
=======
|
||||
missions = Array[ExtResource("14_vcrh8")]([ExtResource("15_obmwc"), ExtResource("16_rl54y"), ExtResource("18_h4fpv"), ExtResource("20_r0ysx")])
|
||||
>>>>>>> Stashed changes
|
||||
mission_ui = NodePath("MissionPanel")
|
||||
builder = NodePath("../Builder")
|
||||
character_scene = ExtResource("18_8lrh8")
|
||||
|
||||
[node name="MissionPanel" type="PanelContainer" parent="MissionManager" node_paths=PackedStringArray("mission_title_label", "mission_description_label", "objectives_container")]
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -450.0
|
||||
offset_top = 20.0
|
||||
offset_right = -20.0
|
||||
grow_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_mission")
|
||||
script = ExtResource("13_xvw5w")
|
||||
mission_title_label = NodePath("MarginContainer/VBoxContainer/MissionTitleLabel")
|
||||
mission_description_label = NodePath("MarginContainer/VBoxContainer/MissionDescriptionLabel")
|
||||
objectives_container = NodePath("MarginContainer/VBoxContainer/ObjectivesContainer")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MissionManager/MissionPanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 20
|
||||
theme_override_constants/margin_top = 20
|
||||
theme_override_constants/margin_right = 20
|
||||
theme_override_constants/margin_bottom = 20
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MissionManager/MissionPanel/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 15
|
||||
|
||||
[node name="MissionTitleLabel" type="Label" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("17_vlub6")
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Mission Title"
|
||||
horizontal_alignment = 1
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MissionDescriptionLabel" type="Label" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 1
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "Mission description goes here..."
|
||||
autowrap_mode = 2
|
||||
text_overrun_behavior = 4
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ObjectivesLabel" type="Label" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(0.678431, 0.847059, 1, 1)
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "Objectives:"
|
||||
|
||||
[node name="ObjectivesContainer" type="VBoxContainer" parent="MissionManager/MissionPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="LearningPanel" type="PanelContainer" parent="MissionManager"]
|
||||
visible = false
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = 50.0
|
||||
offset_top = 50.0
|
||||
offset_right = -50.0
|
||||
offset_bottom = -50.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_lsmd5")
|
||||
script = ExtResource("14_q2ymb")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MissionManager/LearningPanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 30
|
||||
theme_override_constants/margin_top = 30
|
||||
theme_override_constants/margin_right = 30
|
||||
theme_override_constants/margin_bottom = 30
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MissionManager/LearningPanel/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="TitleLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_fonts/font = ExtResource("17_vlub6")
|
||||
theme_override_font_sizes/font_size = 32
|
||||
text = "Learning Module"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="DescriptionPanel" type="PanelContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
size_flags_stretch_ratio = 0.5
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_description")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/DescriptionPanel"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 15
|
||||
theme_override_constants/margin_top = 15
|
||||
theme_override_constants/margin_right = 15
|
||||
theme_override_constants/margin_bottom = 15
|
||||
|
||||
[node name="DescriptionLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/DescriptionPanel/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 20
|
||||
text = "Description goes here..."
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="GraphTitle" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 24
|
||||
text = "Graph:"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="GraphContainer" type="Panel" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
custom_minimum_size = Vector2(0, 300)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_graph")
|
||||
|
||||
[node name="AnswerContainer" type="VBoxContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="QuestionLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 18
|
||||
text = "How many workers do we need to build 10 houses in a week?"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="AnswerField" type="LineEdit" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_font_sizes/font_size = 18
|
||||
placeholder_text = "Enter answer"
|
||||
alignment = 1
|
||||
max_length = 5
|
||||
|
||||
[node name="CheckButton" type="Button" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
custom_minimum_size = Vector2(150, 40)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
theme_override_font_sizes/font_size = 16
|
||||
text = "Check Answer"
|
||||
|
||||
[node name="FeedbackLabel" type="Label" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/AnswerContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_font_sizes/font_size = 18
|
||||
horizontal_alignment = 1
|
||||
autowrap_mode = 2
|
||||
text_overrun_behavior = 3
|
||||
max_lines_visible = 6
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="CompleteButton" type="Button" parent="MissionManager/LearningPanel/MarginContainer/VBoxContainer/HBoxContainer"]
|
||||
custom_minimum_size = Vector2(200, 50)
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 18
|
||||
disabled = true
|
||||
text = "Complete"
|
||||
|
||||
[node name="ObjectiveLabel" type="Label" parent="MissionManager"]
|
||||
offset_right = 40.0
|
||||
offset_bottom = 23.0
|
||||
|
||||
[node name="building-arcology2" parent="." instance=ExtResource("27_m8wco")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10, -16, -14)
|
||||
|
||||
[connection signal="all_missions_completed" from="MissionManager" to="." method="_on_mission_manager_all_missions_completed"]
|
||||
[connection signal="mission_started" from="MissionManager" to="." method="_on_mission_manager_mission_started"]
|
||||
[connection signal="pressed" from="MissionManager/LearningPanel/MarginContainer/VBoxContainer/HBoxContainer/CompleteButton" to="MissionManager/LearningPanel" method="_on_complete_button_pressed"]
|
||||
@ -0,0 +1 @@
|
||||
uid://buvxhq2ipa8gt
|
||||
@ -0,0 +1 @@
|
||||
uid://b1014mouu2vqu
|
||||
@ -0,0 +1 @@
|
||||
uid://csqc100kx2nsm
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
||||
uid://cklb2ypicv33a
|
||||
@ -0,0 +1,279 @@
|
||||
extends Control
|
||||
|
||||
@onready var main_button = $MainButton
|
||||
@onready var selection_panel = $SelectionPanel
|
||||
@onready var ground_options = $SelectionPanel/ScrollContainer/VBoxContainer/GroundSection/GroundOptions
|
||||
@onready var building_options = $SelectionPanel/ScrollContainer/VBoxContainer/BuildingSection/BuildingOptions
|
||||
@onready var search_bar = $SelectionPanel/SearchBar
|
||||
@onready var filter_buttons = $SelectionPanel/FilterButtons
|
||||
@onready var description_panel = $SelectionPanel/DescriptionPanel
|
||||
@onready var title_label = $SelectionPanel/DescriptionPanel/VBoxContainer/TitleLabel
|
||||
@onready var description_label = $SelectionPanel/DescriptionPanel/VBoxContainer/DescriptionLabel
|
||||
@onready var price_label = $SelectionPanel/DescriptionPanel/VBoxContainer/StatsContainer/PriceLabel
|
||||
@onready var population_label = $SelectionPanel/DescriptionPanel/VBoxContainer/StatsContainer/PopulationLabel
|
||||
@onready var power_label = $SelectionPanel/DescriptionPanel/VBoxContainer/StatsContainer/PowerLabel
|
||||
|
||||
@export var builder: Node:
|
||||
set(value):
|
||||
_builder = value
|
||||
if is_inside_tree(): # Only create buttons if node is ready
|
||||
_create_option_buttons()
|
||||
get:
|
||||
return _builder
|
||||
|
||||
var _builder: Node
|
||||
var current_selection: int = 0
|
||||
var is_panel_visible: bool = false
|
||||
var current_filter: String = "All"
|
||||
var search_text: String = ""
|
||||
|
||||
func _ready():
|
||||
# Connect the main button signal
|
||||
main_button.pressed.connect(_on_main_button_pressed)
|
||||
|
||||
# Connect search bar signal
|
||||
search_bar.text_changed.connect(_on_search_text_changed)
|
||||
|
||||
# Connect filter button signals
|
||||
for button in filter_buttons.get_children():
|
||||
if button is Button:
|
||||
button.pressed.connect(_on_filter_button_pressed.bind(button.text))
|
||||
|
||||
# Initially hide the selection panel
|
||||
selection_panel.visible = false
|
||||
|
||||
# Make sure the panel doesn't pass through mouse events
|
||||
selection_panel.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
ground_options.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
building_options.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
|
||||
# Create the building and ground option buttons
|
||||
_create_option_buttons()
|
||||
|
||||
func _create_option_buttons():
|
||||
# Clear existing buttons
|
||||
for child in ground_options.get_children():
|
||||
child.queue_free()
|
||||
for child in building_options.get_children():
|
||||
child.queue_free()
|
||||
|
||||
# Get structures from builder
|
||||
if not _builder or not _builder.structures:
|
||||
return
|
||||
|
||||
# Create ground options (grass, pavement, etc.)
|
||||
var ground_structures = []
|
||||
var building_structures = []
|
||||
|
||||
# Sort structures by type and apply filters
|
||||
for structure in _builder.structures:
|
||||
# Apply search filter
|
||||
if search_text != "" and not structure.title.to_lower().contains(search_text.to_lower()):
|
||||
continue
|
||||
|
||||
# Apply type filter
|
||||
if current_filter != "All":
|
||||
match current_filter:
|
||||
"Residential":
|
||||
if structure.type != Structure.StructureType.RESIDENTIAL_BUILDING:
|
||||
continue
|
||||
"Commercial":
|
||||
if structure.type != Structure.StructureType.COMMERCIAL_BUILDING:
|
||||
continue
|
||||
"Industrial":
|
||||
if structure.type != Structure.StructureType.INDUSTRIAL_BUILDING:
|
||||
continue
|
||||
|
||||
if structure.type == Structure.StructureType.TERRAIN:
|
||||
ground_structures.append(structure)
|
||||
else:
|
||||
building_structures.append(structure)
|
||||
|
||||
# Set up grid layout for ground options
|
||||
ground_options.columns = 4 # Set number of columns
|
||||
ground_options.add_theme_constant_override("h_separation", 10) # Horizontal spacing
|
||||
ground_options.add_theme_constant_override("v_separation", 10) # Vertical spacing
|
||||
|
||||
# Create buttons for ground structures
|
||||
for i in range(ground_structures.size()):
|
||||
var button = _create_option_button(ground_structures[i], i)
|
||||
ground_options.add_child(button)
|
||||
|
||||
# Set up grid layout for building options
|
||||
building_options.columns = 4 # Set number of columns
|
||||
building_options.add_theme_constant_override("h_separation", 10) # Horizontal spacing
|
||||
building_options.add_theme_constant_override("v_separation", 10) # Vertical spacing
|
||||
|
||||
# Create buttons for building structures
|
||||
for i in range(building_structures.size()):
|
||||
var button = _create_option_button(building_structures[i], i + ground_structures.size())
|
||||
building_options.add_child(button)
|
||||
|
||||
# Hide sections if they have no options
|
||||
$SelectionPanel/ScrollContainer/VBoxContainer/GroundSection.visible = ground_structures.size() > 0
|
||||
$SelectionPanel/ScrollContainer/VBoxContainer/BuildingSection.visible = building_structures.size() > 0
|
||||
|
||||
func _create_option_button(structure: Structure, index: int) -> Button:
|
||||
var button = Button.new()
|
||||
button.custom_minimum_size = Vector2(70, 70) # Reduced from 80x80
|
||||
button.toggle_mode = true
|
||||
button.button_group = ButtonGroup.new()
|
||||
button.tooltip_text = structure.description
|
||||
|
||||
# Create container for button contents
|
||||
var container = VBoxContainer.new()
|
||||
container.alignment = BoxContainer.AlignmentMode.ALIGNMENT_CENTER
|
||||
container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
container.add_theme_constant_override("separation", 2) # Reduce spacing between elements
|
||||
button.add_child(container)
|
||||
|
||||
# Create preview container
|
||||
var preview_container = Control.new()
|
||||
preview_container.custom_minimum_size = Vector2(50, 50) # Reduced from 64x64
|
||||
container.add_child(preview_container)
|
||||
|
||||
# Add preview image or model
|
||||
if structure.thumbnail and structure.thumbnail != "Thumbnail" and ResourceLoader.exists(structure.thumbnail):
|
||||
var preview = TextureRect.new()
|
||||
var texture = load(structure.thumbnail)
|
||||
preview.texture = texture
|
||||
preview.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
preview.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
preview.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED
|
||||
preview.custom_minimum_size = Vector2(50, 50) # Force minimum size
|
||||
preview.expand_mode = TextureRect.EXPAND_FIT_WIDTH_PROPORTIONAL # Maintain aspect ratio while fitting width
|
||||
preview_container.add_child(preview)
|
||||
else:
|
||||
var viewport = SubViewport.new()
|
||||
viewport.size = Vector2i(50, 50) # Reduced from 64x64
|
||||
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||||
viewport.transparent_bg = true
|
||||
preview_container.add_child(viewport)
|
||||
|
||||
var camera = Camera3D.new()
|
||||
camera.position = Vector3(0, 0, 2)
|
||||
camera.look_at(Vector3.ZERO)
|
||||
viewport.add_child(camera)
|
||||
|
||||
if structure.model:
|
||||
var model = structure.model.instantiate()
|
||||
viewport.add_child(model)
|
||||
|
||||
# Add structure name
|
||||
var name_label = Label.new()
|
||||
name_label.text = structure.title
|
||||
name_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
name_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
name_label.autowrap_mode = TextServer.AUTOWRAP_WORD
|
||||
name_label.max_lines_visible = 2
|
||||
name_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
name_label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
container.add_child(name_label)
|
||||
|
||||
# Add price label
|
||||
var price_label = Label.new()
|
||||
price_label.text = "$" + str(structure.price)
|
||||
price_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
price_label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
container.add_child(price_label)
|
||||
|
||||
# Add lock overlay if structure is locked
|
||||
if not structure.unlocked:
|
||||
var lock_overlay = ColorRect.new()
|
||||
lock_overlay.color = Color(0, 0, 0, 0.5)
|
||||
lock_overlay.size = preview_container.size
|
||||
preview_container.add_child(lock_overlay)
|
||||
|
||||
var lock_icon = TextureRect.new()
|
||||
lock_icon.texture = load("res://textures/lock.png")
|
||||
lock_icon.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
lock_icon.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
lock_icon.stretch_mode = TextureRect.StretchMode.STRETCH_KEEP_ASPECT_CENTERED
|
||||
lock_icon.size = Vector2(30, 30) # Reduced from 40x40
|
||||
lock_icon.position = Vector2(10, 10) # Adjusted position
|
||||
preview_container.add_child(lock_icon)
|
||||
|
||||
# Disable button if structure is locked
|
||||
button.disabled = true
|
||||
|
||||
button.pressed.connect(_on_option_selected.bind(index))
|
||||
return button
|
||||
|
||||
func _on_main_button_pressed():
|
||||
is_panel_visible = !is_panel_visible
|
||||
selection_panel.visible = is_panel_visible
|
||||
|
||||
if is_panel_visible:
|
||||
# Update button states to show current selection
|
||||
_update_button_states()
|
||||
|
||||
func _on_search_text_changed(new_text: String):
|
||||
search_text = new_text
|
||||
_create_option_buttons()
|
||||
|
||||
func _on_filter_button_pressed(filter_name: String):
|
||||
# Update filter buttons
|
||||
for button in filter_buttons.get_children():
|
||||
if button is Button:
|
||||
button.button_pressed = (button.text == filter_name)
|
||||
|
||||
current_filter = filter_name
|
||||
_create_option_buttons()
|
||||
|
||||
func _on_option_selected(index: int):
|
||||
if not _builder:
|
||||
print("ERROR: No builder reference in building selector")
|
||||
return
|
||||
|
||||
if not _builder.structures or index < 0 or index >= _builder.structures.size():
|
||||
print("ERROR: Invalid structure index: ", index)
|
||||
return
|
||||
|
||||
current_selection = index
|
||||
_update_button_states()
|
||||
|
||||
# Update the builder's current selection
|
||||
_builder.index = index
|
||||
_builder.update_structure()
|
||||
|
||||
# Update the main button text
|
||||
main_button.text = "Selected: " + _get_structure_name(index)
|
||||
|
||||
# Update description panel
|
||||
_update_description_panel(index)
|
||||
|
||||
func _update_button_states():
|
||||
# Update all buttons to show which one is selected
|
||||
var all_buttons = ground_options.get_children() + building_options.get_children()
|
||||
for i in range(all_buttons.size()):
|
||||
all_buttons[i].button_pressed = (i == current_selection)
|
||||
|
||||
func _get_structure_name(index: int) -> String:
|
||||
if _builder and _builder.structures and index >= 0 and index < _builder.structures.size():
|
||||
var structure = _builder.structures[index]
|
||||
return structure.title
|
||||
return "Unknown"
|
||||
|
||||
func _update_description_panel(index: int):
|
||||
if not _builder or not _builder.structures or index < 0 or index >= _builder.structures.size():
|
||||
title_label.text = "No Building Selected"
|
||||
description_label.text = "Select a building to view its details"
|
||||
price_label.text = "Price: $0"
|
||||
population_label.text = "Population: 0"
|
||||
power_label.text = "Power: 0 kW"
|
||||
return
|
||||
|
||||
var structure = _builder.structures[index]
|
||||
title_label.text = structure.title
|
||||
description_label.text = structure.description
|
||||
price_label.text = "Price: $" + str(structure.price)
|
||||
population_label.text = "Population: " + str(structure.population_count)
|
||||
|
||||
var power_text = "Power: "
|
||||
if structure.kW_production > 0:
|
||||
power_text += "+" + str(structure.kW_production) + " kW"
|
||||
elif structure.kW_usage > 0:
|
||||
power_text += "-" + str(structure.kW_usage) + " kW"
|
||||
else:
|
||||
power_text += "0 kW"
|
||||
power_label.text = power_text
|
||||
@ -0,0 +1 @@
|
||||
uid://bsjmj0qu3xfrr
|
||||
@ -0,0 +1 @@
|
||||
uid://b2vlnidm83s8y
|
||||
@ -0,0 +1 @@
|
||||
uid://pwnd0fyfkjed
|
||||
@ -0,0 +1 @@
|
||||
uid://3r6pls585y3h
|
||||
@ -0,0 +1,93 @@
|
||||
extends Node
|
||||
|
||||
# Resource parameters
|
||||
var money: float = 1000.0
|
||||
var population: int = 0
|
||||
var energy_consumption: float = 0.0
|
||||
var energy_production: float = 0.0
|
||||
|
||||
# Economic parameters
|
||||
var money_per_population: float = 1.0 # Money earned per population per second
|
||||
var base_energy_cost: float = 0.1 # Base energy cost per population
|
||||
var tax_rate: float = 0.1 # Tax rate on population income
|
||||
|
||||
# Building costs
|
||||
var building_costs := {
|
||||
"small_house": 100,
|
||||
"medium_house": 250,
|
||||
"large_house": 500,
|
||||
"power_plant": 1000,
|
||||
"road": 50
|
||||
}
|
||||
|
||||
# Building effects
|
||||
var building_population := {
|
||||
"small_house": 10,
|
||||
"medium_house": 25,
|
||||
"large_house": 50
|
||||
}
|
||||
|
||||
var building_energy := {
|
||||
"power_plant": 100.0, # Energy produced per second
|
||||
"small_house": 5.0, # Energy consumed per second
|
||||
"medium_house": 12.0,
|
||||
"large_house": 25.0
|
||||
}
|
||||
|
||||
# Signals
|
||||
signal money_changed(new_amount: float)
|
||||
signal population_changed(new_population: int)
|
||||
signal energy_balance_changed(production: float, consumption: float)
|
||||
|
||||
func _ready():
|
||||
# Start the economy tick
|
||||
$EconomyTimer.start()
|
||||
|
||||
func _process(_delta):
|
||||
# Update energy balance
|
||||
energy_consumption = calculate_total_energy_consumption()
|
||||
emit_signal("energy_balance_changed", energy_production, energy_consumption)
|
||||
|
||||
func calculate_total_energy_consumption() -> float:
|
||||
var total := 0.0
|
||||
for building_type in building_energy:
|
||||
if building_type != "power_plant": # Skip power plants as they produce energy
|
||||
total += building_energy[building_type] * get_building_count(building_type)
|
||||
return total
|
||||
|
||||
func get_building_count(building_type: String) -> int:
|
||||
var builder = get_node_or_null("/root/Main/Builder")
|
||||
if not builder:
|
||||
return 0
|
||||
|
||||
var count = 0
|
||||
for structure in builder.structures:
|
||||
if structure.model and structure.model.resource_path.contains(building_type):
|
||||
count += 1
|
||||
return count
|
||||
|
||||
func can_afford_building(building_type: String) -> bool:
|
||||
return money >= building_costs.get(building_type, 0)
|
||||
|
||||
func purchase_building(building_type: String) -> bool:
|
||||
if can_afford_building(building_type):
|
||||
money -= building_costs[building_type]
|
||||
emit_signal("money_changed", money)
|
||||
|
||||
# Update population if it's a house
|
||||
if building_type in building_population:
|
||||
population += building_population[building_type]
|
||||
emit_signal("population_changed", population)
|
||||
|
||||
# Update energy if it's a power plant
|
||||
if building_type == "power_plant":
|
||||
energy_production += building_energy["power_plant"]
|
||||
|
||||
return true
|
||||
return false
|
||||
|
||||
func _on_economy_timer_timeout():
|
||||
# Calculate income from population
|
||||
var income = population * money_per_population * tax_rate
|
||||
money += income
|
||||
emit_signal("money_changed", money)
|
||||
@ -0,0 +1 @@
|
||||
uid://bat3h7fhpdh7
|
||||
@ -0,0 +1 @@
|
||||
uid://b50gqdyny3llp
|
||||
@ -0,0 +1 @@
|
||||
uid://7upjj8h5aqo6
|
||||
@ -0,0 +1,244 @@
|
||||
extends Node
|
||||
|
||||
# Signals
|
||||
|
||||
signal electricity_updated(usage, production)
|
||||
# Variables
|
||||
var total_population: int = 0
|
||||
var total_kW_usage: float = 0.0
|
||||
var total_kW_production: float = 0.0
|
||||
var current_money: float = 0.0
|
||||
|
||||
# References
|
||||
var buildeJuj
|
||||
var building_construction_manager
|
||||
var population_label: Label
|
||||
var electricity_label: Label
|
||||
var electricity_indicator: ColorRect
|
||||
var population_tooltip: Control
|
||||
var electricity_tooltip: Control
|
||||
var controls_panel: PanelContainer
|
||||
var sound_panel: PanelContainer
|
||||
<<<<<<< Updated upstream
|
||||
var builder:Node
|
||||
=======
|
||||
var cash_label: Label
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
func _ready():
|
||||
# Connect to signals from the builder
|
||||
builder = get_node_or_null("/root/Main/Builder")
|
||||
if builder:
|
||||
builder.structure_placed.connect(_on_structure_placed)
|
||||
builder.structure_removed.connect(_on_structure_removed)
|
||||
|
||||
|
||||
# EventBus.population_update.connect(set_population_count)
|
||||
|
||||
# Initialize UI elements
|
||||
population_label = $HBoxContainer/PopulationItem/PopulationLabel
|
||||
if not population_label:
|
||||
push_error("Population label not found in HUD!")
|
||||
return
|
||||
|
||||
electricity_label = $HBoxContainer/ElectricityItem/ElectricityContainer/ElectricityValues/ElectricityLabel
|
||||
if not electricity_label:
|
||||
push_error("Electricity label not found in HUD!")
|
||||
return
|
||||
|
||||
electricity_indicator = $HBoxContainer/ElectricityItem/ElectricityContainer/ElectricityValues/ElectricityIndicator
|
||||
if not electricity_indicator:
|
||||
push_error("Electricity indicator not found in HUD!")
|
||||
return
|
||||
|
||||
population_tooltip = $PopulationTooltip
|
||||
if not population_tooltip:
|
||||
push_error("Population tooltip not found in HUD!")
|
||||
return
|
||||
|
||||
electricity_tooltip = $ElectricityTooltip
|
||||
<<<<<<< Updated upstream
|
||||
|
||||
|
||||
=======
|
||||
if not electricity_tooltip:
|
||||
push_error("Electricity tooltip not found in HUD!")
|
||||
return
|
||||
|
||||
cash_label = $HBoxContainer/CashItem/CashLabel
|
||||
if not cash_label:
|
||||
push_error("Cash label not found in HUD!")
|
||||
return
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
# Ensure electricity indicator starts with red color
|
||||
electricity_indicator.color = Color(1, 0, 0) # Start with red
|
||||
|
||||
# Hide the electricity label for now (keeping implementation for later)
|
||||
electricity_label.visible = false
|
||||
|
||||
# Set tooltips
|
||||
population_tooltip.visible = false
|
||||
electricity_tooltip.visible = false
|
||||
|
||||
# Update HUD
|
||||
update_hud()
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Update the population label if it changes
|
||||
if population_label and Globals.population != total_population:
|
||||
total_population = Globals.population
|
||||
population_label.text = str(total_population)
|
||||
|
||||
|
||||
# Called when a structure is placed
|
||||
func _on_structure_placed(structure_index, position):
|
||||
if !builder or structure_index < 0 or structure_index >= builder.structures.size():
|
||||
return
|
||||
|
||||
var structure = builder.structures[structure_index]
|
||||
|
||||
# Only update population for non-residential buildings or if we're NOT in the construction mission
|
||||
var is_residential = structure.type == Structure.StructureType.RESIDENTIAL_BUILDING
|
||||
var mission_manager = get_node_or_null("/root/Main/MissionManager")
|
||||
var using_construction = false
|
||||
if mission_manager and mission_manager.current_mission:
|
||||
var mission_id = mission_manager.current_mission.id
|
||||
using_construction = (mission_id == "3" or mission_id == "1")
|
||||
|
||||
# Always update electricity usage/production
|
||||
total_kW_usage += structure.kW_usage
|
||||
total_kW_production += structure.kW_production
|
||||
|
||||
# Update HUD
|
||||
update_hud()
|
||||
|
||||
# Emit signals
|
||||
electricity_updated.emit(total_kW_usage, total_kW_production)
|
||||
|
||||
# Called when a structure is removed
|
||||
func _on_structure_removed(structure_index, position):
|
||||
if !builder or structure_index < 0 or structure_index >= builder.structures.size():
|
||||
return
|
||||
|
||||
var structure = builder.structures[structure_index]
|
||||
|
||||
# Update population (but only for non-residential buildings in mission 3)
|
||||
# For residential buildings in mission 3, we handle population separately in builder._remove_resident_for_building
|
||||
var skip_population_update = false
|
||||
var mission_manager = get_node_or_null("/root/Main/MissionManager")
|
||||
|
||||
if mission_manager and mission_manager.current_mission:
|
||||
if mission_manager.current_mission.id == "3" and structure.type == Structure.StructureType.RESIDENTIAL_BUILDING:
|
||||
# Only update population for one resident, since we're removing them one by one
|
||||
# We don't do total reset based on structure.population_count
|
||||
skip_population_update = true
|
||||
# We decrement by 1 in builder._remove_resident_for_building instead
|
||||
|
||||
if !skip_population_update:
|
||||
total_population = max(0, total_population - structure.population_count)
|
||||
|
||||
# Update electricity
|
||||
total_kW_usage = max(0, total_kW_usage - structure.kW_usage)
|
||||
total_kW_production = max(0, total_kW_production - structure.kW_production)
|
||||
|
||||
# Update HUD
|
||||
update_hud()
|
||||
|
||||
# Emit signals
|
||||
electricity_updated.emit(total_kW_usage, total_kW_production)
|
||||
|
||||
|
||||
# Update Population
|
||||
func set_population_count(count: int):
|
||||
total_population += count
|
||||
population_label.text = str(total_population)
|
||||
|
||||
# # Emit signal
|
||||
# increased_population.emit(added_population)
|
||||
|
||||
# Updates the HUD elements
|
||||
func update_hud():
|
||||
# Update population label
|
||||
if population_label:
|
||||
population_label.text = str(total_population)
|
||||
|
||||
# Update electricity label and indicator
|
||||
if electricity_label:
|
||||
# Default to red for the electricity indicator
|
||||
var indicator_color = Color(1, 0, 0) # Red
|
||||
|
||||
if total_kW_usage > 0:
|
||||
# If we have usage, check if production meets or exceeds it
|
||||
|
||||
# Only set to green if we meet or exceed demand
|
||||
if total_kW_production >= total_kW_usage:
|
||||
indicator_color = Color(0, 1, 0) # Green
|
||||
else:
|
||||
# Not enough power - keep it red
|
||||
indicator_color = Color(1, 0, 0) # Red
|
||||
|
||||
# Update electricity label text (hidden for now but kept for future use)
|
||||
electricity_label.text = str(total_kW_usage) + "/" + str(total_kW_production) + " kW"
|
||||
else:
|
||||
# If no usage but we have production, show green
|
||||
if total_kW_production > 0:
|
||||
indicator_color = Color(0, 1, 0) # Green
|
||||
electricity_label.text = "0/" + str(total_kW_production) + " kW"
|
||||
else:
|
||||
# No usage and no production - show neutral color (gray)
|
||||
indicator_color = Color(0.7, 0.7, 0.7) # Gray
|
||||
electricity_label.text = "0/0 kW"
|
||||
|
||||
# Hide the text label for now, but keep implementation for later
|
||||
electricity_label.visible = false
|
||||
|
||||
# Update the color of the indicator rectangle
|
||||
if electricity_indicator:
|
||||
electricity_indicator.color = indicator_color
|
||||
|
||||
# Tooltip handling
|
||||
func _on_population_icon_mouse_entered():
|
||||
if population_tooltip:
|
||||
population_tooltip.visible = true
|
||||
|
||||
func _on_population_icon_mouse_exited():
|
||||
if population_tooltip:
|
||||
population_tooltip.visible = false
|
||||
|
||||
func _on_electricity_icon_mouse_entered():
|
||||
if electricity_tooltip:
|
||||
electricity_tooltip.visible = true
|
||||
|
||||
func _on_electricity_icon_mouse_exited():
|
||||
if electricity_tooltip:
|
||||
electricity_tooltip.visible = false
|
||||
|
||||
# Called when the sound button is pressed
|
||||
func _on_sound_button_pressed():
|
||||
# Consume the event to prevent click-through to the world
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
if sound_panel:
|
||||
sound_panel.show_panel()
|
||||
|
||||
# Called when the help button is pressed
|
||||
func _on_help_button_pressed():
|
||||
# Consume the event to prevent click-through to the world
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
if controls_panel:
|
||||
controls_panel.show_panel()
|
||||
|
||||
# Update money display
|
||||
func update_money(amount: float):
|
||||
current_money = amount
|
||||
if cash_label:
|
||||
cash_label.text = "$" + str(int(amount))
|
||||
|
||||
# Update energy balance display
|
||||
func update_energy_balance(production: float, consumption: float):
|
||||
total_kW_production = production
|
||||
total_kW_usage = consumption
|
||||
update_hud()
|
||||
@ -0,0 +1,244 @@
|
||||
extends Node
|
||||
|
||||
# Signals
|
||||
|
||||
signal electricity_updated(usage, production)
|
||||
# Variables
|
||||
var total_population: int = 0
|
||||
var total_kW_usage: float = 0.0
|
||||
var total_kW_production: float = 0.0
|
||||
var current_money: float = 0.0
|
||||
|
||||
# References
|
||||
var buildeJuj
|
||||
var building_construction_manager
|
||||
var population_label: Label
|
||||
var electricity_label: Label
|
||||
var electricity_indicator: ColorRect
|
||||
var population_tooltip: Control
|
||||
var electricity_tooltip: Control
|
||||
var controls_panel: PanelContainer
|
||||
var sound_panel: PanelContainer
|
||||
<<<<<<< Updated upstream
|
||||
var builder:Node
|
||||
=======
|
||||
var cash_label: Label
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
func _ready():
|
||||
# Connect to signals from the builder
|
||||
builder = get_node_or_null("/root/Main/Builder")
|
||||
if builder:
|
||||
builder.structure_placed.connect(_on_structure_placed)
|
||||
builder.structure_removed.connect(_on_structure_removed)
|
||||
|
||||
|
||||
# EventBus.population_update.connect(set_population_count)
|
||||
|
||||
# Initialize UI elements
|
||||
population_label = $HBoxContainer/PopulationItem/PopulationLabel
|
||||
if not population_label:
|
||||
push_error("Population label not found in HUD!")
|
||||
return
|
||||
|
||||
electricity_label = $HBoxContainer/ElectricityItem/ElectricityContainer/ElectricityValues/ElectricityLabel
|
||||
if not electricity_label:
|
||||
push_error("Electricity label not found in HUD!")
|
||||
return
|
||||
|
||||
electricity_indicator = $HBoxContainer/ElectricityItem/ElectricityContainer/ElectricityValues/ElectricityIndicator
|
||||
if not electricity_indicator:
|
||||
push_error("Electricity indicator not found in HUD!")
|
||||
return
|
||||
|
||||
population_tooltip = $PopulationTooltip
|
||||
if not population_tooltip:
|
||||
push_error("Population tooltip not found in HUD!")
|
||||
return
|
||||
|
||||
electricity_tooltip = $ElectricityTooltip
|
||||
<<<<<<< Updated upstream
|
||||
|
||||
|
||||
=======
|
||||
if not electricity_tooltip:
|
||||
push_error("Electricity tooltip not found in HUD!")
|
||||
return
|
||||
|
||||
cash_label = $HBoxContainer/CashItem/CashLabel
|
||||
if not cash_label:
|
||||
push_error("Cash label not found in HUD!")
|
||||
return
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
# Ensure electricity indicator starts with red color
|
||||
electricity_indicator.color = Color(1, 0, 0) # Start with red
|
||||
|
||||
# Hide the electricity label for now (keeping implementation for later)
|
||||
electricity_label.visible = false
|
||||
|
||||
# Set tooltips
|
||||
population_tooltip.visible = false
|
||||
electricity_tooltip.visible = false
|
||||
|
||||
# Update HUD
|
||||
update_hud()
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Update the population label if it changes
|
||||
if population_label and Globals.population != total_population:
|
||||
total_population = Globals.population
|
||||
population_label.text = str(total_population)
|
||||
|
||||
|
||||
# Called when a structure is placed
|
||||
func _on_structure_placed(structure_index, position):
|
||||
if !builder or structure_index < 0 or structure_index >= builder.structures.size():
|
||||
return
|
||||
|
||||
var structure = builder.structures[structure_index]
|
||||
|
||||
# Only update population for non-residential buildings or if we're NOT in the construction mission
|
||||
var is_residential = structure.type == Structure.StructureType.RESIDENTIAL_BUILDING
|
||||
var mission_manager = get_node_or_null("/root/Main/MissionManager")
|
||||
var using_construction = false
|
||||
if mission_manager and mission_manager.current_mission:
|
||||
var mission_id = mission_manager.current_mission.id
|
||||
using_construction = (mission_id == "3" or mission_id == "1")
|
||||
|
||||
# Always update electricity usage/production
|
||||
total_kW_usage += structure.kW_usage
|
||||
total_kW_production += structure.kW_production
|
||||
|
||||
# Update HUD
|
||||
update_hud()
|
||||
|
||||
# Emit signals
|
||||
electricity_updated.emit(total_kW_usage, total_kW_production)
|
||||
|
||||
# Called when a structure is removed
|
||||
func _on_structure_removed(structure_index, position):
|
||||
if !builder or structure_index < 0 or structure_index >= builder.structures.size():
|
||||
return
|
||||
|
||||
var structure = builder.structures[structure_index]
|
||||
|
||||
# Update population (but only for non-residential buildings in mission 3)
|
||||
# For residential buildings in mission 3, we handle population separately in builder._remove_resident_for_building
|
||||
var skip_population_update = false
|
||||
var mission_manager = get_node_or_null("/root/Main/MissionManager")
|
||||
|
||||
if mission_manager and mission_manager.current_mission:
|
||||
if mission_manager.current_mission.id == "3" and structure.type == Structure.StructureType.RESIDENTIAL_BUILDING:
|
||||
# Only update population for one resident, since we're removing them one by one
|
||||
# We don't do total reset based on structure.population_count
|
||||
skip_population_update = true
|
||||
# We decrement by 1 in builder._remove_resident_for_building instead
|
||||
|
||||
if !skip_population_update:
|
||||
total_population = max(0, total_population - structure.population_count)
|
||||
|
||||
# Update electricity
|
||||
total_kW_usage = max(0, total_kW_usage - structure.kW_usage)
|
||||
total_kW_production = max(0, total_kW_production - structure.kW_production)
|
||||
|
||||
# Update HUD
|
||||
update_hud()
|
||||
|
||||
# Emit signals
|
||||
electricity_updated.emit(total_kW_usage, total_kW_production)
|
||||
|
||||
|
||||
# Update Population
|
||||
func set_population_count(count: int):
|
||||
total_population += count
|
||||
population_label.text = str(total_population)
|
||||
|
||||
# # Emit signal
|
||||
# increased_population.emit(added_population)
|
||||
|
||||
# Updates the HUD elements
|
||||
func update_hud():
|
||||
# Update population label
|
||||
if population_label:
|
||||
population_label.text = str(total_population)
|
||||
|
||||
# Update electricity label and indicator
|
||||
if electricity_label:
|
||||
# Default to red for the electricity indicator
|
||||
var indicator_color = Color(1, 0, 0) # Red
|
||||
|
||||
if total_kW_usage > 0:
|
||||
# If we have usage, check if production meets or exceeds it
|
||||
|
||||
# Only set to green if we meet or exceed demand
|
||||
if total_kW_production >= total_kW_usage:
|
||||
indicator_color = Color(0, 1, 0) # Green
|
||||
else:
|
||||
# Not enough power - keep it red
|
||||
indicator_color = Color(1, 0, 0) # Red
|
||||
|
||||
# Update electricity label text (hidden for now but kept for future use)
|
||||
electricity_label.text = str(total_kW_usage) + "/" + str(total_kW_production) + " kW"
|
||||
else:
|
||||
# If no usage but we have production, show green
|
||||
if total_kW_production > 0:
|
||||
indicator_color = Color(0, 1, 0) # Green
|
||||
electricity_label.text = "0/" + str(total_kW_production) + " kW"
|
||||
else:
|
||||
# No usage and no production - show neutral color (gray)
|
||||
indicator_color = Color(0.7, 0.7, 0.7) # Gray
|
||||
electricity_label.text = "0/0 kW"
|
||||
|
||||
# Hide the text label for now, but keep implementation for later
|
||||
electricity_label.visible = false
|
||||
|
||||
# Update the color of the indicator rectangle
|
||||
if electricity_indicator:
|
||||
electricity_indicator.color = indicator_color
|
||||
|
||||
# Tooltip handling
|
||||
func _on_population_icon_mouse_entered():
|
||||
if population_tooltip:
|
||||
population_tooltip.visible = true
|
||||
|
||||
func _on_population_icon_mouse_exited():
|
||||
if population_tooltip:
|
||||
population_tooltip.visible = false
|
||||
|
||||
func _on_electricity_icon_mouse_entered():
|
||||
if electricity_tooltip:
|
||||
electricity_tooltip.visible = true
|
||||
|
||||
func _on_electricity_icon_mouse_exited():
|
||||
if electricity_tooltip:
|
||||
electricity_tooltip.visible = false
|
||||
|
||||
# Called when the sound button is pressed
|
||||
func _on_sound_button_pressed():
|
||||
# Consume the event to prevent click-through to the world
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
if sound_panel:
|
||||
sound_panel.show_panel()
|
||||
|
||||
# Called when the help button is pressed
|
||||
func _on_help_button_pressed():
|
||||
# Consume the event to prevent click-through to the world
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
if controls_panel:
|
||||
controls_panel.show_panel()
|
||||
|
||||
# Update money display
|
||||
func update_money(amount: float):
|
||||
current_money = amount
|
||||
if cash_label:
|
||||
cash_label.text = "$" + str(int(amount))
|
||||
|
||||
# Update energy balance display
|
||||
func update_energy_balance(production: float, consumption: float):
|
||||
total_kW_production = production
|
||||
total_kW_usage = consumption
|
||||
update_hud()
|
||||
@ -0,0 +1 @@
|
||||
uid://d02v1gsthvh03
|
||||
@ -0,0 +1 @@
|
||||
uid://b40gjqb6qr1w7
|
||||
@ -0,0 +1 @@
|
||||
uid://cegv6v6dfcsyt
|
||||
@ -0,0 +1 @@
|
||||
uid://dexknr7it5val
|
||||
@ -0,0 +1 @@
|
||||
uid://dfytqya2vsi81
|
||||
@ -0,0 +1 @@
|
||||
uid://dptrv1nv60fl2
|
||||
@ -0,0 +1 @@
|
||||
uid://d1wadrwuwmuuk
|
||||
@ -0,0 +1 @@
|
||||
uid://d4isuuaa51b7x
|
||||
@ -0,0 +1 @@
|
||||
uid://l2b10qh2u8n4
|
||||
@ -0,0 +1 @@
|
||||
uid://ynwv56k844ps
|
||||
@ -0,0 +1 @@
|
||||
uid://52tdmmosdbpa
|
||||
@ -0,0 +1 @@
|
||||
uid://dmelvshrg8l56
|
||||
@ -0,0 +1 @@
|
||||
uid://bqxaa6voplja8
|
||||
@ -0,0 +1 @@
|
||||
uid://qlxrdpwtysyp
|
||||
@ -0,0 +1 @@
|
||||
uid://b8b67y260mq6g
|
||||
@ -0,0 +1 @@
|
||||
uid://dkvwttwsfgj8b
|
||||
@ -0,0 +1 @@
|
||||
uid://lcb3ablmkaw8
|
||||
@ -0,0 +1 @@
|
||||
uid://uftqbpj0c2u8
|
||||
@ -0,0 +1 @@
|
||||
uid://urmot4hfnvtb
|
||||
@ -0,0 +1 @@
|
||||
uid://boe3mr1ujtk2s
|
||||
@ -0,0 +1,557 @@
|
||||
extends Node
|
||||
|
||||
signal music_volume_changed(new_volume)
|
||||
signal sfx_volume_changed(new_volume)
|
||||
signal music_muted_changed(is_muted)
|
||||
signal sfx_muted_changed(is_muted)
|
||||
signal audio_ready # Signal emitted when audio is initialized (important for web)
|
||||
|
||||
# Sound bridges for web builds
|
||||
var react_sound_bridge = null # Will be instantiated from a script
|
||||
var audio_bridge = null # Will be instantiated from a script
|
||||
|
||||
# Volume ranges from 0.0 to 1.0
|
||||
<<<<<<< Updated upstream
|
||||
var music_volume: float = 0.0
|
||||
var sfx_volume: float = 0.1
|
||||
=======
|
||||
var music_volume: float = 0.8:
|
||||
set(value):
|
||||
music_volume = value
|
||||
_apply_music_volume()
|
||||
_save_settings()
|
||||
music_volume_changed.emit(value)
|
||||
get:
|
||||
return music_volume
|
||||
|
||||
var sfx_volume: float = 0.8:
|
||||
set(value):
|
||||
sfx_volume = value
|
||||
_apply_sfx_volume()
|
||||
_save_settings()
|
||||
sfx_volume_changed.emit(value)
|
||||
get:
|
||||
return sfx_volume
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
# Mute states
|
||||
var music_muted: bool = false:
|
||||
set(value):
|
||||
music_muted = value
|
||||
_apply_music_volume()
|
||||
_save_settings()
|
||||
music_muted_changed.emit(value)
|
||||
get:
|
||||
return music_muted
|
||||
|
||||
var sfx_muted: bool = false:
|
||||
set(value):
|
||||
sfx_muted = value
|
||||
_apply_sfx_volume()
|
||||
_save_settings()
|
||||
sfx_muted_changed.emit(value)
|
||||
get:
|
||||
return sfx_muted
|
||||
|
||||
# Bus indices for easier reference
|
||||
var music_bus_index: int
|
||||
var sfx_bus_index: int
|
||||
|
||||
# Default bus names
|
||||
const MUSIC_BUS_NAME = "Music"
|
||||
const SFX_BUS_NAME = "SFX"
|
||||
|
||||
var audio_initialized: bool = false
|
||||
|
||||
# Sound files dictionary - mapping simplified names to file paths
|
||||
const SOUND_FILES = {
|
||||
"jazzNewOrleans": "res://sounds/jazz_new_orleans.mp3",
|
||||
"lofiChillJazz": "res://sounds/lofi-chill-jazz-272869.mp3",
|
||||
"buildingPlacing": "res://sounds/building_placing.wav",
|
||||
"construction": "res://sounds/construction.wav",
|
||||
"powerDrill": "res://sounds/power_drill.mp3"
|
||||
}
|
||||
|
||||
# Current music track
|
||||
var current_music: String = ""
|
||||
|
||||
# Currently playing audio streams (for direct Godot playback)
|
||||
var music_player: AudioStreamPlayer = null
|
||||
var sfx_players: Dictionary = {}
|
||||
|
||||
const MIN_VOLUME = -40
|
||||
const MAX_VOLUME = 0
|
||||
const CONFIG_PATH = "user://audio_settings.cfg"
|
||||
|
||||
func _ready():
|
||||
print("SoundManager: Initializing...")
|
||||
|
||||
# Create music player for all platforms
|
||||
music_player = AudioStreamPlayer.new()
|
||||
add_child(music_player)
|
||||
|
||||
# Set up the audio buses first
|
||||
_setup_audio_buses()
|
||||
|
||||
# Load and apply settings
|
||||
_load_settings()
|
||||
|
||||
# Set the music player bus
|
||||
music_player.bus = MUSIC_BUS_NAME
|
||||
|
||||
# Initialize audio
|
||||
audio_initialized = true
|
||||
|
||||
print("SoundManager: Initialization complete")
|
||||
print("SoundManager: Music Volume: ", music_volume, " Muted: ", music_muted)
|
||||
print("SoundManager: SFX Volume: ", sfx_volume, " Muted: ", sfx_muted)
|
||||
|
||||
# Emit the audio ready signal
|
||||
audio_ready.emit()
|
||||
|
||||
# Setup audio buses (doesn't start audio playback)
|
||||
func _setup_audio_buses():
|
||||
# Initialize audio bus indices
|
||||
music_bus_index = AudioServer.get_bus_index(MUSIC_BUS_NAME)
|
||||
sfx_bus_index = AudioServer.get_bus_index(SFX_BUS_NAME)
|
||||
|
||||
# If the buses don't exist yet, create them
|
||||
if music_bus_index == -1:
|
||||
# Create music bus
|
||||
music_bus_index = AudioServer.bus_count
|
||||
AudioServer.add_bus()
|
||||
AudioServer.set_bus_name(music_bus_index, MUSIC_BUS_NAME)
|
||||
AudioServer.set_bus_send(music_bus_index, "Master")
|
||||
|
||||
if sfx_bus_index == -1:
|
||||
# Create SFX bus
|
||||
sfx_bus_index = AudioServer.bus_count
|
||||
AudioServer.add_bus()
|
||||
AudioServer.set_bus_name(sfx_bus_index, SFX_BUS_NAME)
|
||||
AudioServer.set_bus_send(sfx_bus_index, "Master")
|
||||
|
||||
# Verify buses were created correctly
|
||||
music_bus_index = AudioServer.get_bus_index(MUSIC_BUS_NAME)
|
||||
sfx_bus_index = AudioServer.get_bus_index(SFX_BUS_NAME)
|
||||
|
||||
# Apply initial settings
|
||||
_apply_music_volume()
|
||||
_apply_sfx_volume()
|
||||
|
||||
# Make sure buses aren't muted by default
|
||||
if music_bus_index != -1:
|
||||
AudioServer.set_bus_mute(music_bus_index, false)
|
||||
|
||||
if sfx_bus_index != -1:
|
||||
AudioServer.set_bus_mute(sfx_bus_index, false)
|
||||
|
||||
# Process sound state received from JavaScript
|
||||
func process_js_audio_state(state: Dictionary):
|
||||
# Update local state based on received data
|
||||
if state.has("musicVolume"):
|
||||
music_volume = state.musicVolume
|
||||
if state.has("sfxVolume"):
|
||||
sfx_volume = state.sfxVolume
|
||||
if state.has("musicMuted"):
|
||||
music_muted = state.musicMuted
|
||||
if state.has("sfxMuted"):
|
||||
sfx_muted = state.sfxMuted
|
||||
if state.has("currentMusic"):
|
||||
current_music = state.currentMusic
|
||||
|
||||
# Emit signals about changes
|
||||
music_volume_changed.emit(music_volume)
|
||||
sfx_volume_changed.emit(sfx_volume)
|
||||
music_muted_changed.emit(music_muted)
|
||||
sfx_muted_changed.emit(sfx_muted)
|
||||
|
||||
# Called when ReactSoundBridge reports it's ready
|
||||
func _on_react_audio_ready():
|
||||
print("ReactSoundBridge reports ready")
|
||||
audio_initialized = true
|
||||
|
||||
# Update local state from React
|
||||
if react_sound_bridge != null:
|
||||
if react_sound_bridge.get("music_volume") != null:
|
||||
music_volume = react_sound_bridge.music_volume
|
||||
if react_sound_bridge.get("sfx_volume") != null:
|
||||
sfx_volume = react_sound_bridge.sfx_volume
|
||||
if react_sound_bridge.get("music_muted") != null:
|
||||
music_muted = react_sound_bridge.music_muted
|
||||
if react_sound_bridge.get("sfx_muted") != null:
|
||||
sfx_muted = react_sound_bridge.sfx_muted
|
||||
if react_sound_bridge.get("current_music") != null:
|
||||
current_music = react_sound_bridge.current_music
|
||||
|
||||
# Emit the audio ready signal
|
||||
audio_ready.emit()
|
||||
|
||||
# Called when AudioBridge connects to the platform-one sound manager
|
||||
func _on_audio_bridge_connected(is_connected: bool):
|
||||
print("AudioBridge connected: ", is_connected)
|
||||
|
||||
if is_connected:
|
||||
audio_initialized = true
|
||||
|
||||
# Request the sound state from the platform-one sound manager
|
||||
if audio_bridge.has_method("get_sound_state"):
|
||||
audio_bridge.get_sound_state()
|
||||
|
||||
# Emit the audio ready signal
|
||||
audio_ready.emit()
|
||||
|
||||
# Called when any user interaction happens in web builds
|
||||
func _on_user_interaction(_arg=null):
|
||||
if OS.has_feature("web") and not audio_initialized:
|
||||
_initialize_web_audio()
|
||||
|
||||
# Process input events directly
|
||||
func _input(event):
|
||||
if OS.has_feature("web") and not audio_initialized:
|
||||
if event is InputEventMouseButton or event is InputEventKey:
|
||||
if event.pressed:
|
||||
_initialize_web_audio()
|
||||
|
||||
# If this method is called from JavaScript, it will help the game to
|
||||
# initialize audio properly in web builds
|
||||
func init_web_audio_from_js():
|
||||
pass
|
||||
#if OS.has_feature("web") and not audio_initialized:
|
||||
#_initialize_web_audio()
|
||||
|
||||
# Initialize audio for web builds
|
||||
func _initialize_web_audio():
|
||||
if audio_initialized:
|
||||
return
|
||||
|
||||
# For web builds, we notify JavaScript to initialize audio
|
||||
# if OS.has_feature("web"):
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("INITIALIZE_AUDIO")
|
||||
#
|
||||
# # We don't need to create any dummy players, as JavaScript will handle the audio
|
||||
# audio_initialized = true
|
||||
# audio_ready.emit()
|
||||
# return
|
||||
|
||||
# For non-web platforms, initialize Godot audio (this shouldn't get called)
|
||||
# if not OS.has_feature("web"):
|
||||
# Set the flag to prevent multiple initializations
|
||||
audio_initialized = true
|
||||
audio_ready.emit()
|
||||
|
||||
# Play background music
|
||||
func play_music(sound_name: String, loop: bool = true):
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
# Store the current music name
|
||||
current_music = sound_name
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to play music: ", sound_name)
|
||||
# if audio_bridge.has_method("play_music") and audio_bridge.play_music(sound_name):
|
||||
# return
|
||||
#
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to play music: ", sound_name)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("PLAY_MUSIC", sound_name)
|
||||
# return
|
||||
|
||||
# For native builds, use Godot audio
|
||||
if not SOUND_FILES.has(sound_name):
|
||||
return
|
||||
|
||||
# Get the file path
|
||||
var file_path = SOUND_FILES[sound_name]
|
||||
|
||||
# Load the audio stream
|
||||
var stream = load(file_path)
|
||||
if stream == null:
|
||||
return
|
||||
|
||||
# Stop current music if playing
|
||||
if music_player.playing:
|
||||
music_player.stop()
|
||||
|
||||
# Set up and play the music
|
||||
music_player.stream = stream
|
||||
music_player.bus = MUSIC_BUS_NAME
|
||||
|
||||
# Set looping if supported by the stream
|
||||
if stream is AudioStreamMP3 or stream is AudioStreamOggVorbis:
|
||||
stream.loop = loop
|
||||
|
||||
# Ensure volume is set correctly before playing
|
||||
_apply_music_volume()
|
||||
|
||||
# Play the music
|
||||
music_player.play()
|
||||
|
||||
# Play a sound effect
|
||||
func play_sfx(sound_name: String):
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
#if OS.has_feature("web"):
|
||||
## Try AudioBridge first (platform-one integration)
|
||||
#if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
#print("Using AudioBridge to play sfx: ", sound_name)
|
||||
#if audio_bridge.has_method("play_sfx") and audio_bridge.play_sfx(sound_name):
|
||||
#return
|
||||
#
|
||||
## Fall back to JavaScript Bridge
|
||||
#print("Using JavaScriptBridge to play sfx: ", sound_name)
|
||||
#JSBridge.JavaScriptGlobal.handle_audio_action("PLAY_SFX", sound_name)
|
||||
#return
|
||||
|
||||
# For native builds, use Godot audio
|
||||
if not SOUND_FILES.has(sound_name):
|
||||
return
|
||||
|
||||
# Get the file path
|
||||
var file_path = SOUND_FILES[sound_name]
|
||||
|
||||
# Load the audio stream
|
||||
var stream = load(file_path)
|
||||
if stream == null:
|
||||
return
|
||||
|
||||
# Create or reuse a player for this sound
|
||||
var player: AudioStreamPlayer
|
||||
if not sfx_players.has(sound_name):
|
||||
player = AudioStreamPlayer.new()
|
||||
add_child(player)
|
||||
sfx_players[sound_name] = player
|
||||
else:
|
||||
player = sfx_players[sound_name]
|
||||
if player.playing:
|
||||
player.stop()
|
||||
|
||||
# Set up and play the sound
|
||||
player.stream = stream
|
||||
if sfx_muted:
|
||||
player.volume_db = linear_to_db(0)
|
||||
else:
|
||||
player.volume_db = linear_to_db(sfx_volume)
|
||||
player.bus = SFX_BUS_NAME
|
||||
player.play()
|
||||
|
||||
# Stop background music
|
||||
func stop_music():
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
#if OS.has_feature("web"):
|
||||
## Try AudioBridge first (platform-one integration)
|
||||
#if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
#print("Using AudioBridge to stop music")
|
||||
#if audio_bridge.has_method("stop_music") and audio_bridge.stop_music():
|
||||
#current_music = ""
|
||||
#return
|
||||
#
|
||||
## Fall back to JavaScript Bridge
|
||||
#print("Using JavaScriptBridge to stop music")
|
||||
#JSBridge.JavaScriptGlobal.handle_audio_action("STOP_MUSIC")
|
||||
#current_music = ""
|
||||
#return
|
||||
|
||||
# For native builds, use Godot audio
|
||||
if music_player and music_player.playing:
|
||||
music_player.stop()
|
||||
|
||||
current_music = ""
|
||||
|
||||
# Set music volume (0.0 to 1.0)
|
||||
func set_music_volume(volume: float):
|
||||
music_volume = clampf(volume, 0.0, 1.0)
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
if false:
|
||||
pass
|
||||
# if OS.has_feature("web"):
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to set music volume: ", music_volume)
|
||||
# if audio_bridge.has_method("set_music_volume"):
|
||||
# audio_bridge.set_music_volume(music_volume)
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to set music volume: ", music_volume)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("SET_MUSIC_VOLUME", "", music_volume)
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_music_volume()
|
||||
|
||||
# Emit signal
|
||||
music_volume_changed.emit(music_volume)
|
||||
|
||||
# Set SFX volume (0.0 to 1.0)
|
||||
func set_sfx_volume(volume: float):
|
||||
sfx_volume = clampf(volume, 0.0, 1.0)
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
if false:
|
||||
pass
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to set sfx volume: ", sfx_volume)
|
||||
# if audio_bridge.has_method("set_sfx_volume"):
|
||||
# audio_bridge.set_sfx_volume(sfx_volume)
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to set sfx volume: ", sfx_volume)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("SET_SFX_VOLUME", "", sfx_volume)
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_sfx_volume()
|
||||
|
||||
# Emit signal
|
||||
sfx_volume_changed.emit(sfx_volume)
|
||||
|
||||
# Toggle music mute state
|
||||
func toggle_music_mute():
|
||||
music_muted = !music_muted
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
if false:
|
||||
pass
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to toggle music mute: ", music_muted)
|
||||
# if audio_bridge.has_method("toggle_music_mute"):
|
||||
# audio_bridge.toggle_music_mute()
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to toggle music mute: ", music_muted)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("TOGGLE_MUSIC_MUTE")
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_music_volume()
|
||||
|
||||
# Emit signal
|
||||
music_muted_changed.emit(music_muted)
|
||||
|
||||
# Toggle SFX mute state
|
||||
func toggle_sfx_mute():
|
||||
sfx_muted = !sfx_muted
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
if false:
|
||||
pass
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to toggle sfx mute: ", sfx_muted)
|
||||
# if audio_bridge.has_method("toggle_sfx_mute"):
|
||||
# audio_bridge.toggle_sfx_mute()
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to toggle sfx mute: ", sfx_muted)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("TOGGLE_SFX_MUTE")
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_sfx_volume()
|
||||
|
||||
# Emit signal
|
||||
sfx_muted_changed.emit(sfx_muted)
|
||||
|
||||
# Apply music volume settings
|
||||
func _apply_music_volume():
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
var db = linear_to_db(music_volume)
|
||||
print("SoundManager: Applying music volume: ", music_volume, " (", db, "dB)")
|
||||
|
||||
if music_bus_index != -1:
|
||||
AudioServer.set_bus_mute(music_bus_index, music_muted)
|
||||
if not music_muted:
|
||||
AudioServer.set_bus_volume_db(music_bus_index, db)
|
||||
|
||||
if music_player != null:
|
||||
music_player.volume_db = -80.0 if music_muted else db
|
||||
|
||||
# Apply SFX volume settings
|
||||
func _apply_sfx_volume():
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
var db = linear_to_db(sfx_volume)
|
||||
print("SoundManager: Applying SFX volume: ", sfx_volume, " (", db, "dB)")
|
||||
|
||||
if sfx_bus_index != -1:
|
||||
AudioServer.set_bus_mute(sfx_bus_index, sfx_muted)
|
||||
if not sfx_muted:
|
||||
AudioServer.set_bus_volume_db(sfx_bus_index, db)
|
||||
|
||||
for player in sfx_players.values():
|
||||
if player != null:
|
||||
player.volume_db = -80.0 if sfx_muted else db
|
||||
|
||||
# Helper function to convert linear volume to decibels
|
||||
func linear_to_db(linear_value: float) -> float:
|
||||
if linear_value <= 0:
|
||||
return -80.0
|
||||
return 20.0 * log(linear_value) / log(10.0)
|
||||
|
||||
func _load_settings():
|
||||
print("SoundManager: Loading settings from ", CONFIG_PATH)
|
||||
var config = ConfigFile.new()
|
||||
var err = config.load(CONFIG_PATH)
|
||||
|
||||
if err == OK:
|
||||
print("SoundManager: Successfully loaded settings file")
|
||||
# Load saved values
|
||||
music_volume = config.get_value("audio", "music_volume", 0.8)
|
||||
sfx_volume = config.get_value("audio", "sfx_volume", 0.8)
|
||||
music_muted = config.get_value("audio", "music_muted", false)
|
||||
sfx_muted = config.get_value("audio", "sfx_muted", false)
|
||||
else:
|
||||
print("SoundManager: No settings file found, using defaults")
|
||||
# Set default values
|
||||
music_volume = 0.8
|
||||
sfx_volume = 0.8
|
||||
music_muted = false
|
||||
sfx_muted = false
|
||||
# Save the default values
|
||||
_save_settings()
|
||||
|
||||
print("SoundManager: Loaded values - Music: ", music_volume, " SFX: ", sfx_volume)
|
||||
|
||||
# Apply the loaded settings immediately
|
||||
_apply_music_volume()
|
||||
_apply_sfx_volume()
|
||||
|
||||
func _save_settings():
|
||||
print("SoundManager: Saving settings...")
|
||||
var config = ConfigFile.new()
|
||||
|
||||
# Save current values
|
||||
config.set_value("audio", "music_volume", music_volume)
|
||||
config.set_value("audio", "sfx_volume", sfx_volume)
|
||||
config.set_value("audio", "music_muted", music_muted)
|
||||
config.set_value("audio", "sfx_muted", sfx_muted)
|
||||
|
||||
# Save to file
|
||||
var err = config.save(CONFIG_PATH)
|
||||
if err == OK:
|
||||
print("SoundManager: Settings saved successfully")
|
||||
else:
|
||||
print("SoundManager: Error saving settings: ", err)
|
||||
|
||||
func get_music_volume() -> float:
|
||||
if music_muted:
|
||||
return MIN_VOLUME
|
||||
return music_volume
|
||||
|
||||
func get_sfx_volume() -> float:
|
||||
if sfx_muted:
|
||||
return MIN_VOLUME
|
||||
return sfx_volume
|
||||
@ -0,0 +1,557 @@
|
||||
extends Node
|
||||
|
||||
signal music_volume_changed(new_volume)
|
||||
signal sfx_volume_changed(new_volume)
|
||||
signal music_muted_changed(is_muted)
|
||||
signal sfx_muted_changed(is_muted)
|
||||
signal audio_ready # Signal emitted when audio is initialized (important for web)
|
||||
|
||||
# Sound bridges for web builds
|
||||
var react_sound_bridge = null # Will be instantiated from a script
|
||||
var audio_bridge = null # Will be instantiated from a script
|
||||
|
||||
# Volume ranges from 0.0 to 1.0
|
||||
<<<<<<< Updated upstream
|
||||
var music_volume: float = 0.0
|
||||
var sfx_volume: float = 0.1
|
||||
=======
|
||||
var music_volume: float = 0.8:
|
||||
set(value):
|
||||
music_volume = value
|
||||
_apply_music_volume()
|
||||
_save_settings()
|
||||
music_volume_changed.emit(value)
|
||||
get:
|
||||
return music_volume
|
||||
|
||||
var sfx_volume: float = 0.8:
|
||||
set(value):
|
||||
sfx_volume = value
|
||||
_apply_sfx_volume()
|
||||
_save_settings()
|
||||
sfx_volume_changed.emit(value)
|
||||
get:
|
||||
return sfx_volume
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
# Mute states
|
||||
var music_muted: bool = false:
|
||||
set(value):
|
||||
music_muted = value
|
||||
_apply_music_volume()
|
||||
_save_settings()
|
||||
music_muted_changed.emit(value)
|
||||
get:
|
||||
return music_muted
|
||||
|
||||
var sfx_muted: bool = false:
|
||||
set(value):
|
||||
sfx_muted = value
|
||||
_apply_sfx_volume()
|
||||
_save_settings()
|
||||
sfx_muted_changed.emit(value)
|
||||
get:
|
||||
return sfx_muted
|
||||
|
||||
# Bus indices for easier reference
|
||||
var music_bus_index: int
|
||||
var sfx_bus_index: int
|
||||
|
||||
# Default bus names
|
||||
const MUSIC_BUS_NAME = "Music"
|
||||
const SFX_BUS_NAME = "SFX"
|
||||
|
||||
var audio_initialized: bool = false
|
||||
|
||||
# Sound files dictionary - mapping simplified names to file paths
|
||||
const SOUND_FILES = {
|
||||
"jazzNewOrleans": "res://sounds/jazz_new_orleans.mp3",
|
||||
"lofiChillJazz": "res://sounds/lofi-chill-jazz-272869.mp3",
|
||||
"buildingPlacing": "res://sounds/building_placing.wav",
|
||||
"construction": "res://sounds/construction.wav",
|
||||
"powerDrill": "res://sounds/power_drill.mp3"
|
||||
}
|
||||
|
||||
# Current music track
|
||||
var current_music: String = ""
|
||||
|
||||
# Currently playing audio streams (for direct Godot playback)
|
||||
var music_player: AudioStreamPlayer = null
|
||||
var sfx_players: Dictionary = {}
|
||||
|
||||
const MIN_VOLUME = -40
|
||||
const MAX_VOLUME = 0
|
||||
const CONFIG_PATH = "user://audio_settings.cfg"
|
||||
|
||||
func _ready():
|
||||
print("SoundManager: Initializing...")
|
||||
|
||||
# Create music player for all platforms
|
||||
music_player = AudioStreamPlayer.new()
|
||||
add_child(music_player)
|
||||
|
||||
# Set up the audio buses first
|
||||
_setup_audio_buses()
|
||||
|
||||
# Load and apply settings
|
||||
_load_settings()
|
||||
|
||||
# Set the music player bus
|
||||
music_player.bus = MUSIC_BUS_NAME
|
||||
|
||||
# Initialize audio
|
||||
audio_initialized = true
|
||||
|
||||
print("SoundManager: Initialization complete")
|
||||
print("SoundManager: Music Volume: ", music_volume, " Muted: ", music_muted)
|
||||
print("SoundManager: SFX Volume: ", sfx_volume, " Muted: ", sfx_muted)
|
||||
|
||||
# Emit the audio ready signal
|
||||
audio_ready.emit()
|
||||
|
||||
# Setup audio buses (doesn't start audio playback)
|
||||
func _setup_audio_buses():
|
||||
# Initialize audio bus indices
|
||||
music_bus_index = AudioServer.get_bus_index(MUSIC_BUS_NAME)
|
||||
sfx_bus_index = AudioServer.get_bus_index(SFX_BUS_NAME)
|
||||
|
||||
# If the buses don't exist yet, create them
|
||||
if music_bus_index == -1:
|
||||
# Create music bus
|
||||
music_bus_index = AudioServer.bus_count
|
||||
AudioServer.add_bus()
|
||||
AudioServer.set_bus_name(music_bus_index, MUSIC_BUS_NAME)
|
||||
AudioServer.set_bus_send(music_bus_index, "Master")
|
||||
|
||||
if sfx_bus_index == -1:
|
||||
# Create SFX bus
|
||||
sfx_bus_index = AudioServer.bus_count
|
||||
AudioServer.add_bus()
|
||||
AudioServer.set_bus_name(sfx_bus_index, SFX_BUS_NAME)
|
||||
AudioServer.set_bus_send(sfx_bus_index, "Master")
|
||||
|
||||
# Verify buses were created correctly
|
||||
music_bus_index = AudioServer.get_bus_index(MUSIC_BUS_NAME)
|
||||
sfx_bus_index = AudioServer.get_bus_index(SFX_BUS_NAME)
|
||||
|
||||
# Apply initial settings
|
||||
_apply_music_volume()
|
||||
_apply_sfx_volume()
|
||||
|
||||
# Make sure buses aren't muted by default
|
||||
if music_bus_index != -1:
|
||||
AudioServer.set_bus_mute(music_bus_index, false)
|
||||
|
||||
if sfx_bus_index != -1:
|
||||
AudioServer.set_bus_mute(sfx_bus_index, false)
|
||||
|
||||
# Process sound state received from JavaScript
|
||||
func process_js_audio_state(state: Dictionary):
|
||||
# Update local state based on received data
|
||||
if state.has("musicVolume"):
|
||||
music_volume = state.musicVolume
|
||||
if state.has("sfxVolume"):
|
||||
sfx_volume = state.sfxVolume
|
||||
if state.has("musicMuted"):
|
||||
music_muted = state.musicMuted
|
||||
if state.has("sfxMuted"):
|
||||
sfx_muted = state.sfxMuted
|
||||
if state.has("currentMusic"):
|
||||
current_music = state.currentMusic
|
||||
|
||||
# Emit signals about changes
|
||||
music_volume_changed.emit(music_volume)
|
||||
sfx_volume_changed.emit(sfx_volume)
|
||||
music_muted_changed.emit(music_muted)
|
||||
sfx_muted_changed.emit(sfx_muted)
|
||||
|
||||
# Called when ReactSoundBridge reports it's ready
|
||||
func _on_react_audio_ready():
|
||||
print("ReactSoundBridge reports ready")
|
||||
audio_initialized = true
|
||||
|
||||
# Update local state from React
|
||||
if react_sound_bridge != null:
|
||||
if react_sound_bridge.get("music_volume") != null:
|
||||
music_volume = react_sound_bridge.music_volume
|
||||
if react_sound_bridge.get("sfx_volume") != null:
|
||||
sfx_volume = react_sound_bridge.sfx_volume
|
||||
if react_sound_bridge.get("music_muted") != null:
|
||||
music_muted = react_sound_bridge.music_muted
|
||||
if react_sound_bridge.get("sfx_muted") != null:
|
||||
sfx_muted = react_sound_bridge.sfx_muted
|
||||
if react_sound_bridge.get("current_music") != null:
|
||||
current_music = react_sound_bridge.current_music
|
||||
|
||||
# Emit the audio ready signal
|
||||
audio_ready.emit()
|
||||
|
||||
# Called when AudioBridge connects to the platform-one sound manager
|
||||
func _on_audio_bridge_connected(is_connected: bool):
|
||||
print("AudioBridge connected: ", is_connected)
|
||||
|
||||
if is_connected:
|
||||
audio_initialized = true
|
||||
|
||||
# Request the sound state from the platform-one sound manager
|
||||
if audio_bridge.has_method("get_sound_state"):
|
||||
audio_bridge.get_sound_state()
|
||||
|
||||
# Emit the audio ready signal
|
||||
audio_ready.emit()
|
||||
|
||||
# Called when any user interaction happens in web builds
|
||||
func _on_user_interaction(_arg=null):
|
||||
if OS.has_feature("web") and not audio_initialized:
|
||||
_initialize_web_audio()
|
||||
|
||||
# Process input events directly
|
||||
func _input(event):
|
||||
if OS.has_feature("web") and not audio_initialized:
|
||||
if event is InputEventMouseButton or event is InputEventKey:
|
||||
if event.pressed:
|
||||
_initialize_web_audio()
|
||||
|
||||
# If this method is called from JavaScript, it will help the game to
|
||||
# initialize audio properly in web builds
|
||||
func init_web_audio_from_js():
|
||||
pass
|
||||
#if OS.has_feature("web") and not audio_initialized:
|
||||
#_initialize_web_audio()
|
||||
|
||||
# Initialize audio for web builds
|
||||
func _initialize_web_audio():
|
||||
if audio_initialized:
|
||||
return
|
||||
|
||||
# For web builds, we notify JavaScript to initialize audio
|
||||
# if OS.has_feature("web"):
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("INITIALIZE_AUDIO")
|
||||
#
|
||||
# # We don't need to create any dummy players, as JavaScript will handle the audio
|
||||
# audio_initialized = true
|
||||
# audio_ready.emit()
|
||||
# return
|
||||
|
||||
# For non-web platforms, initialize Godot audio (this shouldn't get called)
|
||||
# if not OS.has_feature("web"):
|
||||
# Set the flag to prevent multiple initializations
|
||||
audio_initialized = true
|
||||
audio_ready.emit()
|
||||
|
||||
# Play background music
|
||||
func play_music(sound_name: String, loop: bool = true):
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
# Store the current music name
|
||||
current_music = sound_name
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to play music: ", sound_name)
|
||||
# if audio_bridge.has_method("play_music") and audio_bridge.play_music(sound_name):
|
||||
# return
|
||||
#
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to play music: ", sound_name)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("PLAY_MUSIC", sound_name)
|
||||
# return
|
||||
|
||||
# For native builds, use Godot audio
|
||||
if not SOUND_FILES.has(sound_name):
|
||||
return
|
||||
|
||||
# Get the file path
|
||||
var file_path = SOUND_FILES[sound_name]
|
||||
|
||||
# Load the audio stream
|
||||
var stream = load(file_path)
|
||||
if stream == null:
|
||||
return
|
||||
|
||||
# Stop current music if playing
|
||||
if music_player.playing:
|
||||
music_player.stop()
|
||||
|
||||
# Set up and play the music
|
||||
music_player.stream = stream
|
||||
music_player.bus = MUSIC_BUS_NAME
|
||||
|
||||
# Set looping if supported by the stream
|
||||
if stream is AudioStreamMP3 or stream is AudioStreamOggVorbis:
|
||||
stream.loop = loop
|
||||
|
||||
# Ensure volume is set correctly before playing
|
||||
_apply_music_volume()
|
||||
|
||||
# Play the music
|
||||
music_player.play()
|
||||
|
||||
# Play a sound effect
|
||||
func play_sfx(sound_name: String):
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
#if OS.has_feature("web"):
|
||||
## Try AudioBridge first (platform-one integration)
|
||||
#if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
#print("Using AudioBridge to play sfx: ", sound_name)
|
||||
#if audio_bridge.has_method("play_sfx") and audio_bridge.play_sfx(sound_name):
|
||||
#return
|
||||
#
|
||||
## Fall back to JavaScript Bridge
|
||||
#print("Using JavaScriptBridge to play sfx: ", sound_name)
|
||||
#JSBridge.JavaScriptGlobal.handle_audio_action("PLAY_SFX", sound_name)
|
||||
#return
|
||||
|
||||
# For native builds, use Godot audio
|
||||
if not SOUND_FILES.has(sound_name):
|
||||
return
|
||||
|
||||
# Get the file path
|
||||
var file_path = SOUND_FILES[sound_name]
|
||||
|
||||
# Load the audio stream
|
||||
var stream = load(file_path)
|
||||
if stream == null:
|
||||
return
|
||||
|
||||
# Create or reuse a player for this sound
|
||||
var player: AudioStreamPlayer
|
||||
if not sfx_players.has(sound_name):
|
||||
player = AudioStreamPlayer.new()
|
||||
add_child(player)
|
||||
sfx_players[sound_name] = player
|
||||
else:
|
||||
player = sfx_players[sound_name]
|
||||
if player.playing:
|
||||
player.stop()
|
||||
|
||||
# Set up and play the sound
|
||||
player.stream = stream
|
||||
if sfx_muted:
|
||||
player.volume_db = linear_to_db(0)
|
||||
else:
|
||||
player.volume_db = linear_to_db(sfx_volume)
|
||||
player.bus = SFX_BUS_NAME
|
||||
player.play()
|
||||
|
||||
# Stop background music
|
||||
func stop_music():
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
#if OS.has_feature("web"):
|
||||
## Try AudioBridge first (platform-one integration)
|
||||
#if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
#print("Using AudioBridge to stop music")
|
||||
#if audio_bridge.has_method("stop_music") and audio_bridge.stop_music():
|
||||
#current_music = ""
|
||||
#return
|
||||
#
|
||||
## Fall back to JavaScript Bridge
|
||||
#print("Using JavaScriptBridge to stop music")
|
||||
#JSBridge.JavaScriptGlobal.handle_audio_action("STOP_MUSIC")
|
||||
#current_music = ""
|
||||
#return
|
||||
|
||||
# For native builds, use Godot audio
|
||||
if music_player and music_player.playing:
|
||||
music_player.stop()
|
||||
|
||||
current_music = ""
|
||||
|
||||
# Set music volume (0.0 to 1.0)
|
||||
func set_music_volume(volume: float):
|
||||
music_volume = clampf(volume, 0.0, 1.0)
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
if false:
|
||||
pass
|
||||
# if OS.has_feature("web"):
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to set music volume: ", music_volume)
|
||||
# if audio_bridge.has_method("set_music_volume"):
|
||||
# audio_bridge.set_music_volume(music_volume)
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to set music volume: ", music_volume)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("SET_MUSIC_VOLUME", "", music_volume)
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_music_volume()
|
||||
|
||||
# Emit signal
|
||||
music_volume_changed.emit(music_volume)
|
||||
|
||||
# Set SFX volume (0.0 to 1.0)
|
||||
func set_sfx_volume(volume: float):
|
||||
sfx_volume = clampf(volume, 0.0, 1.0)
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
if false:
|
||||
pass
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to set sfx volume: ", sfx_volume)
|
||||
# if audio_bridge.has_method("set_sfx_volume"):
|
||||
# audio_bridge.set_sfx_volume(sfx_volume)
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to set sfx volume: ", sfx_volume)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("SET_SFX_VOLUME", "", sfx_volume)
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_sfx_volume()
|
||||
|
||||
# Emit signal
|
||||
sfx_volume_changed.emit(sfx_volume)
|
||||
|
||||
# Toggle music mute state
|
||||
func toggle_music_mute():
|
||||
music_muted = !music_muted
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
if false:
|
||||
pass
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to toggle music mute: ", music_muted)
|
||||
# if audio_bridge.has_method("toggle_music_mute"):
|
||||
# audio_bridge.toggle_music_mute()
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to toggle music mute: ", music_muted)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("TOGGLE_MUSIC_MUTE")
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_music_volume()
|
||||
|
||||
# Emit signal
|
||||
music_muted_changed.emit(music_muted)
|
||||
|
||||
# Toggle SFX mute state
|
||||
func toggle_sfx_mute():
|
||||
sfx_muted = !sfx_muted
|
||||
|
||||
# For web builds, try multiple bridge options
|
||||
# if OS.has_feature("web"):
|
||||
if false:
|
||||
pass
|
||||
# # Try AudioBridge first (platform-one integration)
|
||||
# if audio_bridge != null and audio_bridge.get("is_connected") == true:
|
||||
# print("Using AudioBridge to toggle sfx mute: ", sfx_muted)
|
||||
# if audio_bridge.has_method("toggle_sfx_mute"):
|
||||
# audio_bridge.toggle_sfx_mute()
|
||||
# else:
|
||||
# # Fall back to JavaScript Bridge
|
||||
# print("Using JavaScriptBridge to toggle sfx mute: ", sfx_muted)
|
||||
# JSBridge.JavaScriptGlobal.handle_audio_action("TOGGLE_SFX_MUTE")
|
||||
else:
|
||||
# Apply to local Godot audio system
|
||||
_apply_sfx_volume()
|
||||
|
||||
# Emit signal
|
||||
sfx_muted_changed.emit(sfx_muted)
|
||||
|
||||
# Apply music volume settings
|
||||
func _apply_music_volume():
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
var db = linear_to_db(music_volume)
|
||||
print("SoundManager: Applying music volume: ", music_volume, " (", db, "dB)")
|
||||
|
||||
if music_bus_index != -1:
|
||||
AudioServer.set_bus_mute(music_bus_index, music_muted)
|
||||
if not music_muted:
|
||||
AudioServer.set_bus_volume_db(music_bus_index, db)
|
||||
|
||||
if music_player != null:
|
||||
music_player.volume_db = -80.0 if music_muted else db
|
||||
|
||||
# Apply SFX volume settings
|
||||
func _apply_sfx_volume():
|
||||
if not audio_initialized:
|
||||
return
|
||||
|
||||
var db = linear_to_db(sfx_volume)
|
||||
print("SoundManager: Applying SFX volume: ", sfx_volume, " (", db, "dB)")
|
||||
|
||||
if sfx_bus_index != -1:
|
||||
AudioServer.set_bus_mute(sfx_bus_index, sfx_muted)
|
||||
if not sfx_muted:
|
||||
AudioServer.set_bus_volume_db(sfx_bus_index, db)
|
||||
|
||||
for player in sfx_players.values():
|
||||
if player != null:
|
||||
player.volume_db = -80.0 if sfx_muted else db
|
||||
|
||||
# Helper function to convert linear volume to decibels
|
||||
func linear_to_db(linear_value: float) -> float:
|
||||
if linear_value <= 0:
|
||||
return -80.0
|
||||
return 20.0 * log(linear_value) / log(10.0)
|
||||
|
||||
func _load_settings():
|
||||
print("SoundManager: Loading settings from ", CONFIG_PATH)
|
||||
var config = ConfigFile.new()
|
||||
var err = config.load(CONFIG_PATH)
|
||||
|
||||
if err == OK:
|
||||
print("SoundManager: Successfully loaded settings file")
|
||||
# Load saved values
|
||||
music_volume = config.get_value("audio", "music_volume", 0.8)
|
||||
sfx_volume = config.get_value("audio", "sfx_volume", 0.8)
|
||||
music_muted = config.get_value("audio", "music_muted", false)
|
||||
sfx_muted = config.get_value("audio", "sfx_muted", false)
|
||||
else:
|
||||
print("SoundManager: No settings file found, using defaults")
|
||||
# Set default values
|
||||
music_volume = 0.8
|
||||
sfx_volume = 0.8
|
||||
music_muted = false
|
||||
sfx_muted = false
|
||||
# Save the default values
|
||||
_save_settings()
|
||||
|
||||
print("SoundManager: Loaded values - Music: ", music_volume, " SFX: ", sfx_volume)
|
||||
|
||||
# Apply the loaded settings immediately
|
||||
_apply_music_volume()
|
||||
_apply_sfx_volume()
|
||||
|
||||
func _save_settings():
|
||||
print("SoundManager: Saving settings...")
|
||||
var config = ConfigFile.new()
|
||||
|
||||
# Save current values
|
||||
config.set_value("audio", "music_volume", music_volume)
|
||||
config.set_value("audio", "sfx_volume", sfx_volume)
|
||||
config.set_value("audio", "music_muted", music_muted)
|
||||
config.set_value("audio", "sfx_muted", sfx_muted)
|
||||
|
||||
# Save to file
|
||||
var err = config.save(CONFIG_PATH)
|
||||
if err == OK:
|
||||
print("SoundManager: Settings saved successfully")
|
||||
else:
|
||||
print("SoundManager: Error saving settings: ", err)
|
||||
|
||||
func get_music_volume() -> float:
|
||||
if music_muted:
|
||||
return MIN_VOLUME
|
||||
return music_volume
|
||||
|
||||
func get_sfx_volume() -> float:
|
||||
if sfx_muted:
|
||||
return MIN_VOLUME
|
||||
return sfx_volume
|
||||
@ -0,0 +1 @@
|
||||
uid://cgbiqwgcxlmsl
|
||||
@ -0,0 +1 @@
|
||||
uid://dvwq0fa5hatje
|
||||
@ -0,0 +1 @@
|
||||
uid://cw0jlq5d8r66g
|
||||
@ -0,0 +1 @@
|
||||
uid://dxuqcenrgbjxp
|
||||
@ -0,0 +1,85 @@
|
||||
extends Node
|
||||
|
||||
const SAVE_KEY = "stem_city_save_data"
|
||||
|
||||
func save_map(map: DataMap) -> void:
|
||||
if OS.has_feature("web"):
|
||||
# For web builds, use localStorage
|
||||
var save_data = {
|
||||
"cash": map.cash,
|
||||
"structures": []
|
||||
}
|
||||
|
||||
# Convert structures to a format that can be serialized
|
||||
for structure in map.structures:
|
||||
save_data.structures.append({
|
||||
"position": {"x": structure.position.x, "y": structure.position.y},
|
||||
"orientation": structure.orientation,
|
||||
"structure": structure.structure
|
||||
})
|
||||
|
||||
# Convert to JSON and save to localStorage
|
||||
var json = JSON.stringify(save_data)
|
||||
print("Saving game data: ", json) # Debug log
|
||||
|
||||
# Try to save to localStorage
|
||||
var result = JavaScriptBridge.eval("""
|
||||
try {
|
||||
localStorage.setItem('%s', '%s');
|
||||
return 'success';
|
||||
} catch(e) {
|
||||
console.error('Error saving game:', e);
|
||||
return 'error:' + e.message;
|
||||
}
|
||||
""" % [SAVE_KEY, json])
|
||||
|
||||
if result != "success":
|
||||
push_error("Failed to save game: " + result)
|
||||
else:
|
||||
# For desktop builds, use the existing ResourceSaver
|
||||
var result = ResourceSaver.save(map, "user://map.res")
|
||||
if result != OK:
|
||||
push_error("Failed to save game: " + str(result))
|
||||
|
||||
func load_map() -> DataMap:
|
||||
if OS.has_feature("web"):
|
||||
# For web builds, load from localStorage
|
||||
var map = DataMap.new()
|
||||
var json = JavaScriptBridge.eval("""
|
||||
try {
|
||||
return localStorage.getItem('%s');
|
||||
} catch(e) {
|
||||
console.error('Error loading game:', e);
|
||||
return null;
|
||||
}
|
||||
""" % SAVE_KEY)
|
||||
|
||||
print("Loaded game data: ", json) # Debug log
|
||||
|
||||
if json and json != "null":
|
||||
var save_data = JSON.parse_string(json)
|
||||
if save_data:
|
||||
map.cash = save_data.cash
|
||||
map.structures.clear()
|
||||
|
||||
for structure_data in save_data.structures:
|
||||
var data_structure = DataStructure.new()
|
||||
data_structure.position = Vector2i(structure_data.position.x, structure_data.position.y)
|
||||
data_structure.orientation = structure_data.orientation
|
||||
data_structure.structure = structure_data.structure
|
||||
map.structures.append(data_structure)
|
||||
else:
|
||||
push_error("Failed to parse save data")
|
||||
else:
|
||||
print("No save data found, starting new game")
|
||||
|
||||
return map
|
||||
else:
|
||||
# For desktop builds, use the existing ResourceLoader
|
||||
if ResourceLoader.exists("user://map.res"):
|
||||
var map = ResourceLoader.load("user://map.res")
|
||||
if map:
|
||||
return map
|
||||
else:
|
||||
push_error("Failed to load map resource")
|
||||
return DataMap.new()
|
||||
@ -0,0 +1 @@
|
||||
uid://b06spd3hdv3
|
||||
Loading…
Reference in New Issue