diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5563753 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "godotTools.editorPath.godot4": "c:\\Users\\danchie\\Documents\\Godot_v4.3\\Godot_v4.3-stable_win64.exe" +} \ No newline at end of file diff --git a/addons/enhanced_gridmap/enhanced_gridmap.gd b/addons/enhanced_gridmap/enhanced_gridmap.gd index 59faad9..7c220ec 100644 --- a/addons/enhanced_gridmap/enhanced_gridmap.gd +++ b/addons/enhanced_gridmap/enhanced_gridmap.gd @@ -32,6 +32,7 @@ enum Direction { var diagonal_movement: bool = false + class NeighborInfo: var position: Vector2i var direction: Direction @@ -430,6 +431,22 @@ func _on_mesh_library_changed(): validate_item_indices() if auto_generate: generate_grid() + _update_cell_option_buttons() + +func _update_cell_option_buttons(): + if not mesh_library: + return + + var item_list = mesh_library.get_item_list() + + for x in range(columns): + for z in range(rows): + var position = Vector3i(x, 0, z) + var cell_item = get_cell_item(position) + if cell_item != -1 and cell_item < item_list.size(): + set_cell_item(position, cell_item) + else: + set_cell_item(position, 0) func _set(property, value): if property == "mesh_library": diff --git a/addons/enhanced_gridmap/enhanced_gridmap_dock.gd b/addons/enhanced_gridmap/enhanced_gridmap_dock.gd index 5c89657..731c69f 100644 --- a/addons/enhanced_gridmap/enhanced_gridmap_dock.gd +++ b/addons/enhanced_gridmap/enhanced_gridmap_dock.gd @@ -152,6 +152,7 @@ func set_enhanced_gridmap(gridmap: EnhancedGridMap): if enhanced_gridmap: if enhanced_gridmap.grid_updated.is_connected(_on_grid_updated): enhanced_gridmap.grid_updated.disconnect(_on_grid_updated) + enhanced_gridmap = gridmap if enhanced_gridmap: @@ -193,7 +194,7 @@ func _update_grid_ui(): var item_list = enhanced_gridmap.mesh_library.get_item_list() var current_floor = floor_spin.value as int - + for z in range(enhanced_gridmap.rows): var row_container = HBoxContainer.new() row_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL @@ -204,7 +205,7 @@ func _update_grid_ui(): var cell_container = VBoxContainer.new() cell_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL cell_container.size_flags_vertical = Control.SIZE_EXPAND_FILL - + var coord_label = Label.new() coord_label.text = "(%d,%d,%d)" % [x, current_floor, z] coord_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER @@ -216,9 +217,14 @@ func _update_grid_ui(): option.set_meta("grid_position", Vector3i(x, current_floor, z)) for i in range(item_list.size()): option.add_item(enhanced_gridmap.mesh_library.get_item_name(item_list[i]), i) + + # Ensure the selected item in the OptionButton corresponds to the current cell item var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, current_floor, z)) - if cell_item != -1: # Changed from INVALID_CELL_ITEM to -1 + if cell_item != -1 and cell_item < option.get_item_count(): option.select(cell_item) + else: + option.select(0)# Select the first item if the cell is empty + option.item_selected.connect(_on_cell_item_selected.bind(option)) option.size_flags_horizontal = Control.SIZE_EXPAND_FILL option.size_flags_vertical = Control.SIZE_EXPAND_FILL @@ -239,10 +245,11 @@ func _update_grid_ui(): 16: rotation_option.select(2) 22: rotation_option.select(3) rotation_option.item_selected.connect(_on_cell_rotation_changed.bind(rotation_option)) - + cell_container.add_child(rotation_option) row_container.add_child(cell_container) cell_options.append(option) + enhanced_gridmap._update_cell_option_buttons() func _update_astar_ui(): start_x_spin.max_value = enhanced_gridmap.columns - 1 @@ -273,6 +280,9 @@ func _on_floors_count_changed(value): func _on_floor_changed(value): if enhanced_gridmap: _update_grid_ui() + _update_astar_ui() + _update_item_state_ui() + enhanced_gridmap.update_grid_data() func _on_auto_generate_toggled(button_pressed): if enhanced_gridmap: @@ -321,7 +331,8 @@ func _on_fill_pressed(): func _on_cell_item_selected(index: int, option: OptionButton): var position = option.get_meta("grid_position") if enhanced_gridmap: - enhanced_gridmap.set_cell_item(position, index) + if index >= 0 and index < enhanced_gridmap.mesh_library.get_item_list().size(): + enhanced_gridmap.set_cell_item(position, index) func _on_find_path_pressed(): if enhanced_gridmap: @@ -360,12 +371,14 @@ func _on_non_walkable_item_changed(value): func _on_grid_updated(): update_ui() + enhanced_gridmap._update_cell_option_buttons() func _on_cell_rotation_changed(index: int, option: OptionButton): var position = option.get_meta("grid_position") var rotation_value = option.get_item_id(index) if enhanced_gridmap: - enhanced_gridmap.set_cell_rotation(position, rotation_value) + if index >= 0 and index < 4: + enhanced_gridmap.set_cell_rotation(position, rotation_value) func _on_swap_items_pressed(): if enhanced_gridmap: diff --git a/addons/enhanced_gridmap/meshlibrary/default.tres b/addons/enhanced_gridmap/meshlibrary/default.tres index c8c096f..94b5d2d 100644 --- a/addons/enhanced_gridmap/meshlibrary/default.tres +++ b/addons/enhanced_gridmap/meshlibrary/default.tres @@ -1,14 +1,53 @@ -[gd_resource type="MeshLibrary" load_steps=14 format=4 uid="uid://54tpx8cmksfc"] +[gd_resource type="MeshLibrary" load_steps=17 format=4 uid="uid://54tpx8cmksfc"] [ext_resource type="ArrayMesh" uid="uid://dqguomxd16u0i" path="res://assets/models/meshes/start.res" id="1_xdwel"] [ext_resource type="ArrayMesh" uid="uid://dspusnbkr74hg" path="res://assets/models/meshes/hover.res" id="2_5gp4i"] -[ext_resource type="ArrayMesh" uid="uid://dr80txgr61irt" path="res://assets/models/tiles/tile_diamond.tres" id="3_gqbid"] [ext_resource type="Material" uid="uid://bsyh0x4cy5qyr" path="res://assets/models/meshes/end.tres" id="3_qi66w"] +[ext_resource type="Texture2D" uid="uid://dpkx1a780pvwv" path="res://assets/textures/tile_diamond.png" id="3_xej11"] [ext_resource type="ArrayMesh" uid="uid://d4himvyb81in8" path="res://assets/models/meshes/non-walkable.res" id="4_h83ju"] [ext_resource type="ArrayMesh" uid="uid://bgvropltcot0q" path="res://assets/models/meshes/normal.res" id="5_san4u"] [ext_resource type="ArrayMesh" uid="uid://36tgon3b60db" path="res://assets/models/tiles/tile_heart.tres" id="6_r6sve"] [ext_resource type="ArrayMesh" uid="uid://b5ta7tcw0iscd" path="res://assets/models/tiles/tile_coin.tres" id="9_44311"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_2vf4e"] +resource_name = "boost" +transparency = 1 +cull_mode = 2 +albedo_color = Color(0.91, 0.91, 0.91, 0.45098) +albedo_texture = ExtResource("3_xej11") + +[sub_resource type="ArrayMesh" id="ArrayMesh_0hihf"] +_surfaces = [{ +"aabb": AABB(-0.282176, -0.000324821, -0.282176, 0.564351, 0.050792, 0.564351), +"format": 34896613377, +"index_count": 36, +"index_data": PackedByteArray("BwAEAAUABwAGAAQABQACAAMABQAEAAIAAAAEAAYAAAACAAQABQABAAcABQADAAEAAgABAAMAAgAAAAEAAQAGAAcAAQAAAAYA"), +"name": "boost", +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 8, +"vertex_data": PackedByteArray("AAD/////AAAAAP7/AAAAAP///////wAA///+/wAAAAD//wAA//8AAP//AAAAAAAAAAAAAP//AAAAAAAAAAAAAA==") +}] +blend_shape_mode = 0 + +[sub_resource type="ArrayMesh" id="ArrayMesh_3eode"] +resource_name = "tile_diamond" +_surfaces = [{ +"aabb": AABB(-0.282176, -0.000324821, -0.282176, 0.564351, 0.050792, 0.564351), +"attribute_data": PackedByteArray("sPss5W0hot47+9DosPv6720hXCE7+6/6sPvl75Heot6r9qfksPu0+pHeXCHM5KfkSvvl78X6sfqr9kDkSvu0+sX6tuTM5EDkSvss5c7ksfrU+tDoSvv6787ktuTU+q/6"), +"format": 34896613399, +"index_count": 36, +"index_data": PackedByteArray("FgANABAAFgATAA0AEQAIAAsAEQAOAAgAAAAMABIAAAAGAAwADwADABUADwAJAAMABwAEAAoABwABAAQABQAUABcABQACABQA"), +"material": SubResource("StandardMaterial3D_2vf4e"), +"name": "tile_coin_diamond", +"primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), +"vertex_count": 24, +"vertex_data": PackedByteArray("AAD//////78AAP//////vwAA/////6oqAAD+/wAAAAAAAP7/AAD/vwAA/v8AAKoq/////////7//////////v//////////////+/wAAAAD///7/AAD/v////v8AAP////8AAP///7///wAA////P///AAD///////8AAAAAAAD//wAAAAD/P///AAAAAP//AAAAAP///78AAAAA////PwAAAAD//6oqAAAAAAAAAAAAAAAAAAD/PwAAAAAAAKoq/////////39U1VTV/7//v////39U1VTV/////////3//v/9//7//v////3//v/9//////wAA/3//v/9//7//vwAA/3//v/9//////wAA/39U1VTV/7//vwAA/39U1VTV") +}] +blend_shape_mode = 0 +shadow_mesh = SubResource("ArrayMesh_0hihf") + [sub_resource type="PlaneMesh" id="PlaneMesh_ti6kf"] material = ExtResource("3_qi66w") size = Vector2(1, 1) @@ -111,7 +150,7 @@ item/9/shapes = [] item/9/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) item/9/navigation_layers = 1 item/10/name = "tile_diamond" -item/10/mesh = ExtResource("3_gqbid") +item/10/mesh = SubResource("ArrayMesh_3eode") item/10/mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.9, 0) item/10/shapes = [] item/10/navigation_mesh_transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) diff --git a/assets/models/pboard/AdjacentRect.tres b/assets/models/pboard/AdjacentRect.tres new file mode 100644 index 0000000..5f52899 --- /dev/null +++ b/assets/models/pboard/AdjacentRect.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://dasaeaytvhll0"] + +[resource] +load_path = "res://.godot/imported/Adjacent.png-b8d91686b7ea46113134344311a2396a.ctex" diff --git a/assets/models/pboard/HighlightRect.tres b/assets/models/pboard/HighlightRect.tres new file mode 100644 index 0000000..bbc1198 --- /dev/null +++ b/assets/models/pboard/HighlightRect.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://c2bj21abtgda1"] + +[resource] +load_path = "res://.godot/imported/Hilight.png-1eaa7d98891b6551494fa706d4935a8a.ctex" diff --git a/assets/models/pboard/SelectRect.tres b/assets/models/pboard/SelectRect.tres new file mode 100644 index 0000000..d196917 --- /dev/null +++ b/assets/models/pboard/SelectRect.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://0wjk16jlgfq"] + +[resource] +load_path = "res://.godot/imported/Selected.png-8654749fa19cfb113e47fc569bbeed01.ctex" diff --git a/assets/models/tiles/tile_diamond.tres b/assets/models/tiles/tile_diamond.tres index b593302..8960223 100644 --- a/assets/models/tiles/tile_diamond.tres +++ b/assets/models/tiles/tile_diamond.tres @@ -1,4 +1,4 @@ -[gd_resource type="ArrayMesh" load_steps=4 format=4 uid="uid://dr80txgr61irt"] +[gd_resource type="ArrayMesh" load_steps=3 format=4 uid="uid://dr80txgr61irt"] [ext_resource type="Texture2D" uid="uid://dpkx1a780pvwv" path="res://assets/textures/tile_diamond.png" id="1_fck33"] @@ -9,20 +9,6 @@ cull_mode = 2 albedo_color = Color(0.91, 0.91, 0.91, 0.45098) albedo_texture = ExtResource("1_fck33") -[sub_resource type="ArrayMesh" id="ArrayMesh_vxvvp"] -_surfaces = [{ -"aabb": AABB(-0.282176, -0.000324821, -0.282176, 0.564351, 0.050792, 0.564351), -"format": 34896613377, -"index_count": 36, -"index_data": PackedByteArray("BwAEAAUABwAGAAQABQACAAMABQAEAAIAAAAEAAYAAAACAAQABQABAAcABQADAAEAAgABAAMAAgAAAAEAAQAGAAcAAQAAAAYA"), -"name": "boost", -"primitive": 3, -"uv_scale": Vector4(0, 0, 0, 0), -"vertex_count": 8, -"vertex_data": PackedByteArray("AAD/////AAAAAP7/AAAAAP///////wAA///+/wAAAAD//wAA//8AAP//AAAAAAAAAAAAAP//AAAAAAAAAAAAAA==") -}] -blend_shape_mode = 0 - [resource] resource_name = "tile_diamond" _surfaces = [{ @@ -39,4 +25,3 @@ _surfaces = [{ "vertex_data": PackedByteArray("AAD//////78AAP//////vwAA/////6oqAAD+/wAAAAAAAP7/AAD/vwAA/v8AAKoq/////////7//////////v//////////////+/wAAAAD///7/AAD/v////v8AAP////8AAP///7///wAA////P///AAD///////8AAAAAAAD//wAAAAD/P///AAAAAP//AAAAAP///78AAAAA////PwAAAAD//6oqAAAAAAAAAAAAAAAAAAD/PwAAAAAAAKoq/////////39U1VTV/7//v////39U1VTV/////////3//v/9//7//v////3//v/9//////wAA/3//v/9//7//vwAA/3//v/9//////wAA/39U1VTV/7//vwAA/39U1VTV") }] blend_shape_mode = 0 -shadow_mesh = SubResource("ArrayMesh_vxvvp") diff --git a/assets/textures/Adjacent.png b/assets/textures/Adjacent.png new file mode 100644 index 0000000..6193129 Binary files /dev/null and b/assets/textures/Adjacent.png differ diff --git a/assets/textures/Adjacent.png.import b/assets/textures/Adjacent.png.import new file mode 100644 index 0000000..ca2b319 --- /dev/null +++ b/assets/textures/Adjacent.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://68x88jj25yxg" +path="res://.godot/imported/Adjacent.png-b8d91686b7ea46113134344311a2396a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/Adjacent.png" +dest_files=["res://.godot/imported/Adjacent.png-b8d91686b7ea46113134344311a2396a.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=false +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 diff --git a/assets/textures/Hilight.png b/assets/textures/Hilight.png new file mode 100644 index 0000000..041b6e3 Binary files /dev/null and b/assets/textures/Hilight.png differ diff --git a/assets/textures/Hilight.png.import b/assets/textures/Hilight.png.import new file mode 100644 index 0000000..a662207 --- /dev/null +++ b/assets/textures/Hilight.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwxgdi7b4ps40" +path="res://.godot/imported/Hilight.png-1eaa7d98891b6551494fa706d4935a8a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/Hilight.png" +dest_files=["res://.godot/imported/Hilight.png-1eaa7d98891b6551494fa706d4935a8a.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=false +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 diff --git a/assets/textures/Selected.png b/assets/textures/Selected.png new file mode 100644 index 0000000..fe96624 Binary files /dev/null and b/assets/textures/Selected.png differ diff --git a/assets/textures/Selected.png.import b/assets/textures/Selected.png.import new file mode 100644 index 0000000..5d12b78 --- /dev/null +++ b/assets/textures/Selected.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dojnv8o6we4ey" +path="res://.godot/imported/Selected.png-8654749fa19cfb113e47fc569bbeed01.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/Selected.png" +dest_files=["res://.godot/imported/Selected.png-8654749fa19cfb113e47fc569bbeed01.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=false +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 diff --git a/assets/textures/player_board_and_blue_print/item_tiles.png b/assets/textures/player_board_and_blue_print/item_tiles.png new file mode 100644 index 0000000..804458f Binary files /dev/null and b/assets/textures/player_board_and_blue_print/item_tiles.png differ diff --git a/assets/textures/player_board_and_blue_print/item_tiles.png.import b/assets/textures/player_board_and_blue_print/item_tiles.png.import new file mode 100644 index 0000000..55d98e2 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/item_tiles.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwmgj46va5tyl" +path="res://.godot/imported/item_tiles.png-eb61f67bb0935f4efe45400a9e47f933.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/player_board_and_blue_print/item_tiles.png" +dest_files=["res://.godot/imported/item_tiles.png-eb61f67bb0935f4efe45400a9e47f933.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=false +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 diff --git a/assets/textures/player_board_and_blue_print/tile_coin.tres b/assets/textures/player_board_and_blue_print/tile_coin.tres new file mode 100644 index 0000000..91e50a7 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tile_coin.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://3m65qapks1kp"] + +[ext_resource type="Texture2D" uid="uid://bbpgm24rwlcdm" path="res://assets/textures/player_board_and_blue_print/tiles_atlas.tres" id="1_6d2ge"] + +[resource] +atlas = ExtResource("1_6d2ge") +region = Rect2(0, 36, 36, 36) diff --git a/assets/textures/player_board_and_blue_print/tile_diamond.tres b/assets/textures/player_board_and_blue_print/tile_diamond.tres new file mode 100644 index 0000000..c6f691e --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tile_diamond.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://cq80fn561r2jm"] + +[ext_resource type="Texture2D" uid="uid://bbpgm24rwlcdm" path="res://assets/textures/player_board_and_blue_print/tiles_atlas.tres" id="1_bno82"] + +[resource] +atlas = ExtResource("1_bno82") +region = Rect2(0, 0, 36, 36) diff --git a/assets/textures/player_board_and_blue_print/tile_heart.tres b/assets/textures/player_board_and_blue_print/tile_heart.tres new file mode 100644 index 0000000..3bc952c --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tile_heart.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://u378heff6oio"] + +[ext_resource type="Texture2D" uid="uid://bbpgm24rwlcdm" path="res://assets/textures/player_board_and_blue_print/tiles_atlas.tres" id="1_6ruq3"] + +[resource] +atlas = ExtResource("1_6ruq3") +region = Rect2(36, 36, 36, 36) diff --git a/assets/textures/player_board_and_blue_print/tile_null.tres b/assets/textures/player_board_and_blue_print/tile_null.tres new file mode 100644 index 0000000..a905a97 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tile_null.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://2yrc6rl4dmd8"] + +[resource] +load_path = "res://.godot/imported/tiles_null.png-6f85709d461b04e0754de2baef7b18ef.ctex" diff --git a/assets/textures/player_board_and_blue_print/tile_star.tres b/assets/textures/player_board_and_blue_print/tile_star.tres new file mode 100644 index 0000000..1cfbe31 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tile_star.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://bhg7uhpdxksno"] + +[ext_resource type="Texture2D" uid="uid://bbpgm24rwlcdm" path="res://assets/textures/player_board_and_blue_print/tiles_atlas.tres" id="1_ckxix"] + +[resource] +atlas = ExtResource("1_ckxix") +region = Rect2(36, 0, 36, 36) diff --git a/assets/textures/player_board_and_blue_print/tiles_atlas.tres b/assets/textures/player_board_and_blue_print/tiles_atlas.tres new file mode 100644 index 0000000..f74da9a --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tiles_atlas.tres @@ -0,0 +1,4 @@ +[gd_resource type="CompressedTexture2D" format=3 uid="uid://bbpgm24rwlcdm"] + +[resource] +load_path = "res://.godot/imported/item_tiles.png-eb61f67bb0935f4efe45400a9e47f933.ctex" diff --git a/assets/textures/player_board_and_blue_print/tiles_hologram.png b/assets/textures/player_board_and_blue_print/tiles_hologram.png new file mode 100644 index 0000000..a0a76b5 Binary files /dev/null and b/assets/textures/player_board_and_blue_print/tiles_hologram.png differ diff --git a/assets/textures/player_board_and_blue_print/tiles_hologram.png.import b/assets/textures/player_board_and_blue_print/tiles_hologram.png.import new file mode 100644 index 0000000..e37b676 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tiles_hologram.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ncohgicoismp" +path="res://.godot/imported/tiles_hologram.png-f24488bf20b1c49c03f0b2f505381964.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/player_board_and_blue_print/tiles_hologram.png" +dest_files=["res://.godot/imported/tiles_hologram.png-f24488bf20b1c49c03f0b2f505381964.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=false +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 diff --git a/assets/textures/player_board_and_blue_print/tiles_null.png b/assets/textures/player_board_and_blue_print/tiles_null.png new file mode 100644 index 0000000..504337c Binary files /dev/null and b/assets/textures/player_board_and_blue_print/tiles_null.png differ diff --git a/assets/textures/player_board_and_blue_print/tiles_null.png.import b/assets/textures/player_board_and_blue_print/tiles_null.png.import new file mode 100644 index 0000000..92e92f8 --- /dev/null +++ b/assets/textures/player_board_and_blue_print/tiles_null.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://mg6lr51n2yn7" +path="res://.godot/imported/tiles_null.png-6f85709d461b04e0754de2baef7b18ef.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/textures/player_board_and_blue_print/tiles_null.png" +dest_files=["res://.godot/imported/tiles_null.png-6f85709d461b04e0754de2baef7b18ef.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=false +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 diff --git a/scenes/mai4284.tmp b/scenes/mai4284.tmp new file mode 100644 index 0000000..8088b44 --- /dev/null +++ b/scenes/mai4284.tmp @@ -0,0 +1,186 @@ +[gd_scene load_steps=7 format=3 uid="uid://dxn87yj8qnfpp"] + +[ext_resource type="MeshLibrary" uid="uid://54tpx8cmksfc" path="res://addons/enhanced_gridmap/meshlibrary/default.tres" id="1_110wo"] +[ext_resource type="Script" path="res://scenes/main.gd" id="1_xcpe3"] +[ext_resource type="Script" path="res://addons/enhanced_gridmap/enhanced_gridmap.gd" id="2_hbe1v"] +[ext_resource type="Environment" uid="uid://jbptgqvstei3" path="res://assets/main-environment.tres" id="4_ky38j"] +[ext_resource type="StyleBox" uid="uid://dlw1ogamn741n" path="res://assets/styles/box_flat.tres" id="5_dvx6y"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1cewu"] + +[node name="Main" type="Node3D"] +script = ExtResource("1_xcpe3") +turn_based_mode = false + +[node name="EnhancedGridMap" type="GridMap" parent="."] +mesh_library = ExtResource("1_110wo") +cell_size = Vector3(1, 1, 1) +data = { +"cells": PackedInt32Array(9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 8, 0, 9, 9, 0, 9, 7, 0, 9, 6, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 65536, 0, 7, 65536, 1, 10, 65536, 2, 9, 65536, 3, 9, 65536, 4, 8, 65536, 5, 7, 65536, 6, 9, 65536, 7, 9, 65536, 8, 10, 65536, 9, 8, 65537, 0, 9, 65537, 1, 8, 65537, 2, 10, 65537, 3, 9, 65537, 4, 7, 65537, 5, 10, 65537, 6, 9, 65537, 7, 9, 65537, 8, 10, 65537, 9, 10, 65538, 0, 7, 65538, 1, 10, 65538, 2, 9, 65538, 3, 8, 65538, 4, 9, 65538, 5, 10, 65538, 6, 9, 65538, 7, 8, 65538, 8, 9, 65538, 9, 10, 65539, 0, 9, 65539, 1, 10, 65539, 2, 9, 65539, 3, 10, 65539, 4, 9, 65539, 5, 9, 65539, 6, 10, 65539, 7, 10, 65539, 8, 9, 65539, 9, 9, 65540, 0, 7, 65540, 1, 7, 65540, 2, 7, 65540, 3, 10, 65540, 4, 9, 65540, 5, 7, 65540, 6, 9, 65540, 7, 9, 65540, 8, 7, 65540, 9, 8, 65541, 0, 8, 65541, 1, 7, 65541, 2, 7, 65541, 3, 10, 65541, 4, 10, 65541, 5, 8, 65541, 6, 7, 65541, 7, 7, 65541, 8, 8, 65541, 9, 9, 65542, 0, 10, 65542, 1, 10, 65542, 2, 9, 65542, 3, 7, 65542, 4, 8, 65542, 5, 9, 65542, 6, 10, 65542, 7, 9, 65542, 8, 10, 65542, 9, 9, 65543, 0, 7, 65543, 1, 8, 65543, 2, 10, 65543, 3, 8, 65543, 4, 7, 65543, 5, 10, 65543, 6, 10, 65543, 7, 7, 65543, 8, 10, 65543, 9, 8, 65544, 0, 9, 65544, 1, 9, 65544, 2, 8, 65544, 3, 8, 65544, 4, 8, 65544, 5, 7, 65544, 6, 8, 65544, 7, 9, 65544, 8, 10, 65544, 9, 10, 65545, 0, 10, 65545, 1, 8, 65545, 2, 10, 65545, 3, 8, 65545, 4, 8, 65545, 5, 7, 65545, 6, 9, 65545, 7, 9, 65545, 8, 9, 65545, 9, 9) +} +script = ExtResource("2_hbe1v") +floors = 2 +non_walkable_items = Array[int]([4, 5]) +metadata/_editor_floor_ = Vector3(0, 1, 0) + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 5, 15, 12.36) +environment = ExtResource("4_ky38j") +fov = 35.5 + +[node name="Camera3D200" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 5, 30, 5) +visible = false +environment = ExtResource("4_ky38j") +fov = 35.5 + +[node name="Panel" type="Panel" parent="."] +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -77.0 +offset_top = 6.0 +offset_right = 77.0 +offset_bottom = 59.0 +grow_horizontal = 2 +theme_override_styles/panel = ExtResource("5_dvx6y") + +[node name="PlayerboardUI" type="GridContainer" parent="."] +custom_minimum_size = Vector2(200, 200) +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_left = 30.0 +offset_top = -230.0 +offset_right = 230.0 +offset_bottom = -30.0 +grow_vertical = 0 +columns = 5 + +[node name="ActionMenu" type="Control" parent="."] +layout_mode = 3 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -145.0 +offset_top = -218.0 +grow_horizontal = 0 +grow_vertical = 0 + +[node name="ActionButtonContainer" type="VBoxContainer" parent="ActionMenu"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="MoveButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Move" + +[node name="GrabButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Grab" + +[node name="PutButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Put" + +[node name="RandomizeButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Randomize" + +[node name="ArrangeButton" type="Button" parent="ActionMenu/ActionButtonContainer"] +layout_mode = 2 +text = "Arrange" + +[node name="NetworkInfo" type="VBoxContainer" parent="."] +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -58.0 +offset_top = 7.0 +offset_right = 58.0 +offset_bottom = 57.0 +grow_horizontal = 2 + +[node name="NetworkSideDisplay" type="Label" parent="NetworkInfo"] +layout_mode = 2 +text = "Network Side" +horizontal_alignment = 1 + +[node name="UniquePeerID" type="Label" parent="NetworkInfo"] +layout_mode = 2 +text = "Unique Peer ID" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="Menu" type="VBoxContainer" parent="."] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -85.0 +offset_top = -33.0 +offset_right = 85.0 +offset_bottom = 33.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/separation = 20 + +[node name="Host" type="Button" parent="Menu"] +layout_mode = 2 +theme_override_styles/focus = ExtResource("5_dvx6y") +theme_override_styles/disabled_mirrored = ExtResource("5_dvx6y") +theme_override_styles/disabled = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed = ExtResource("5_dvx6y") +theme_override_styles/hover_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover = ExtResource("5_dvx6y") +theme_override_styles/pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/pressed = ExtResource("5_dvx6y") +theme_override_styles/normal_mirrored = ExtResource("5_dvx6y") +theme_override_styles/normal = ExtResource("5_dvx6y") +text = "Host" + +[node name="Join" type="Button" parent="Menu"] +layout_mode = 2 +theme_override_styles/focus = ExtResource("5_dvx6y") +theme_override_styles/disabled_mirrored = ExtResource("5_dvx6y") +theme_override_styles/disabled = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover_pressed = ExtResource("5_dvx6y") +theme_override_styles/hover_mirrored = ExtResource("5_dvx6y") +theme_override_styles/hover = ExtResource("5_dvx6y") +theme_override_styles/pressed_mirrored = ExtResource("5_dvx6y") +theme_override_styles/pressed = ExtResource("5_dvx6y") +theme_override_styles/normal_mirrored = ExtResource("5_dvx6y") +theme_override_styles/normal = ExtResource("5_dvx6y") +text = "Join" + +[node name="MessageInput" type="LineEdit" parent="."] +anchors_preset = 7 +anchor_left = 0.5 +anchor_top = 1.0 +anchor_right = 0.5 +anchor_bottom = 1.0 +offset_left = -210.0 +offset_top = -46.0 +offset_right = 210.0 +offset_bottom = -15.0 +grow_horizontal = 2 +grow_vertical = 0 +theme_override_styles/focus = SubResource("StyleBoxFlat_1cewu") +theme_override_styles/normal = ExtResource("5_dvx6y") +placeholder_text = "Chat" +alignment = 1 + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = ExtResource("4_ky38j") + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[connection signal="pressed" from="Menu/Host" to="." method="_on_host_pressed"] +[connection signal="pressed" from="Menu/Join" to="." method="_on_join_pressed"] +[connection signal="text_submitted" from="MessageInput" to="." method="_on_message_input_text_submitted"] diff --git a/scenes/main.gd b/scenes/main.gd index a4110b7..a9543d4 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -10,18 +10,15 @@ var player_scene = preload("res://scenes/player.tscn") var current_turn_index = 0 @export var players = [] var game_started = false -var max_message_input_char = 51 var max_players = 4 var bots = [] -@export var turn_based_mode: bool = true # Toggle between turn-based and realtime modes -var bot_move_timer: float = 0.0 # Timer for bot movement in realtime mode -const BOT_MOVE_INTERVAL: float = 2.0 # Time between bot movements in realtime mode +@export var turn_based_mode: bool = true +var bot_move_timer: float = 0.0 +const BOT_MOVE_INTERVAL: float = 2.0 -# Bot movement state tracking -var moving_bots = {} # Dictionary to track which bots are currently moving +var moving_bots = {} -# Action State Management enum ActionState { NONE, MOVING, @@ -33,7 +30,6 @@ enum ActionState { var current_action_state = ActionState.NONE -# UI References @onready var action_menu = $ActionMenu @onready var move_button = $ActionMenu/ActionButtonContainer/MoveButton @onready var grab_button = $ActionMenu/ActionButtonContainer/GrabButton @@ -42,6 +38,14 @@ var current_action_state = ActionState.NONE @onready var arrange_button = $ActionMenu/ActionButtonContainer/ArrangeButton @onready var playerboard_ui = $PlayerboardUI +const item_tex = [ + preload("res://assets/textures/player_board_and_blue_print/tile_null.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_heart.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_diamond.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_star.tres"), + preload("res://assets/textures/player_board_and_blue_print/tile_coin.tres") +] + func _ready(): multiplayer_peer.peer_connected.connect(_on_peer_connected) multiplayer_peer.peer_disconnected.connect(_on_peer_disconnected) @@ -49,87 +53,132 @@ func _ready(): setup_playerboard_ui() func _process(delta): - if multiplayer.is_server(): - if game_started: - if turn_based_mode: - rpc("sync_turn_index", current_turn_index) - else: - # Handle realtime bot movement - bot_move_timer += delta - if bot_move_timer >= BOT_MOVE_INTERVAL: - bot_move_timer = 0.0 - for bot_id in bots: - if not moving_bots.get(bot_id, false): # Only move if bot isn't already moving - move_bot(bot_id) + if multiplayer.is_server() and game_started: + if turn_based_mode: + rpc("sync_turn_index", current_turn_index) + else: + bot_move_timer += delta + if bot_move_timer >= BOT_MOVE_INTERVAL: + bot_move_timer = 0.0 + var current_bots = bots.duplicate() + for bot_id in current_bots: + if not moving_bots.get(bot_id, false): + move_bot(bot_id) func setup_action_buttons(): move_button.pressed.connect(func(): set_action_state(ActionState.MOVING)) grab_button.pressed.connect(func(): set_action_state(ActionState.GRABBING)) - put_button.pressed.connect(func(): set_action_state(ActionState.PUTTING)) + put_button.pressed.connect(func(): + if local_player_character: + local_player_character.handle_put_action() + set_action_state(ActionState.PUTTING) + ) randomize_button.pressed.connect(func(): set_action_state(ActionState.RANDOMIZING)) - arrange_button.pressed.connect(func(): set_action_state(ActionState.ARRANGING)) + arrange_button.pressed.connect(func(): + if local_player_character and local_player_character.action_points >= 2: + set_action_state(ActionState.ARRANGING) + ) func setup_playerboard_ui(): - # Clear existing children for child in playerboard_ui.get_children(): child.queue_free() - # Setup grid playerboard_ui.columns = 5 - # Create slots for i in range(25): var slot = TextureRect.new() - slot.custom_minimum_size = Vector2(40, 40) + + var highlight_rect = TextureRect.new() + var hr_tex = load("res://assets/models/pboard/HighlightRect.tres") + + var select_rect = TextureRect.new() + var sr_tex = load("res://assets/models/pboard/SelectRect.tres") + + var adjacent_rect = TextureRect.new() + var ar_tex = load("res://assets/models/pboard/AdjacentRect.tres") + + slot.custom_minimum_size = Vector2(36, 36) slot.gui_input.connect(func(event): _on_playerboard_slot_clicked(event, i)) - # Add a colored rectangle as background - var style = StyleBoxFlat.new() - style.bg_color = Color(0.2, 0.2, 0.2, 1.0) - style.border_color = Color(0.4, 0.4, 0.4, 1.0) - slot.add_theme_stylebox_override("panel", style) - playerboard_ui.add_child(slot) + slot.texture = item_tex[0] + playerboard_ui.add_child(slot, true) + + highlight_rect.texture = hr_tex + highlight_rect.size = Vector2(36, 36) + select_rect.texture = sr_tex + select_rect.size = Vector2(36, 36) + adjacent_rect.texture = ar_tex + adjacent_rect.size = Vector2(36, 36) + + slot.add_child(highlight_rect) + slot.add_child(select_rect) + slot.add_child(adjacent_rect) + + slot.get_child(0).hide() + slot.get_child(1).hide() + slot.get_child(2).hide() func set_action_state(new_state): - if not local_player_character: + if not local_player_character or not local_player_character.is_multiplayer_authority() or current_action_state == new_state or local_player_character.action_points <= 0: return - - current_action_state = new_state - # Clear previous highlights + current_action_state = new_state local_player_character.clear_highlights() + local_player_character.clear_playerboard_highlights() match new_state: ActionState.MOVING: local_player_character.highlight_movement_range() ActionState.GRABBING: local_player_character.highlight_adjacent_cells() + if local_player_character.has_item_at_current_position(): + local_player_character.highlighted_cells.append(local_player_character.current_position) + local_player_character.enhanced_gridmap.set_cell_item( + Vector3i(local_player_character.current_position.x, 0, local_player_character.current_position.y), + local_player_character.enhanced_gridmap.hover_item + ) ActionState.PUTTING: - local_player_character.highlight_empty_adjacent_cells() + local_player_character.highlight_occupied_playerboard_slots() ActionState.RANDOMIZING: local_player_character.highlight_random_valid_cells() ActionState.ARRANGING: show_arrangement_ui() + local_player_character.highlight_occupied_playerboard_slots() func update_button_states(): - if not local_player_character: + if not local_player_character or local_player_character.is_in_group("Bots"): + move_button.visible = false + grab_button.visible = false + put_button.visible = false + randomize_button.visible = false + arrange_button.visible = false return - - var can_move = not local_player_character.is_player_moving and not local_player_character.has_performed_action - var can_grab = local_player_character.has_item_at_current_position() - var can_put = local_player_character.has_items_in_playerboard() and not local_player_character.has_item_at_current_position() - var can_randomize = not local_player_character.has_performed_action - var can_arrange = local_player_character.has_items_in_playerboard() - move_button.disabled = not can_move - grab_button.disabled = not can_grab - put_button.disabled = not can_put - randomize_button.disabled = not can_randomize - arrange_button.disabled = not can_arrange + move_button.visible = true + grab_button.visible = true + put_button.visible = true + randomize_button.visible = true + arrange_button.visible = true + + move_button.disabled = local_player_character.is_player_moving or local_player_character.has_performed_action + grab_button.disabled = not local_player_character.has_item_at_current_position() + put_button.disabled = not (local_player_character.has_items_in_playerboard() and not local_player_character.has_item_at_current_position()) + randomize_button.disabled = local_player_character.has_performed_action + arrange_button.disabled = not local_player_character.has_items_in_playerboard() + + func _on_playerboard_slot_clicked(event, slot_index): if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: - if current_action_state == ActionState.ARRANGING and local_player_character: - local_player_character.arrange_playerboard_item(slot_index) + if not local_player_character: + return + + match current_action_state: + ActionState.ARRANGING: + local_player_character.arrange_playerboard_item(slot_index) + ActionState.GRABBING: + local_player_character.handle_playerboard_slot_selected(slot_index) + ActionState.PUTTING: + local_player_character.handle_put_slot_selected(slot_index) func update_playerboard_ui(): if not local_player_character: @@ -138,14 +187,20 @@ func update_playerboard_ui(): for i in range(25): var slot = playerboard_ui.get_child(i) var item = local_player_character.playerboard[i] - if item != -1: - # Update slot appearance based on item - slot.modulate = Color(1, 1, 1, 1) - # You can set different colors or textures based on item type - slot.self_modulate = Color(0.5 + (item * 0.1), 0.7, 0.3, 1.0) - else: - slot.modulate = Color(0.5, 0.5, 0.5, 0.5) - slot.self_modulate = Color(1, 1, 1, 1) + + slot.texture = item_tex[0] + + match item: + 7: slot.texture = item_tex[1] + 8: slot.texture = item_tex[2] + 9: slot.texture = item_tex[3] + 10: slot.texture = item_tex[4] + +func update_playerboard_highlights(highlighted_slots: Array): + for i in range(playerboard_ui.get_child_count()): + var slot = playerboard_ui.get_child(i) + if slot.get_child_count() > 1: + slot.get_child(1).visible = highlighted_slots.has(i) func show_arrangement_ui(): if playerboard_ui: @@ -162,7 +217,6 @@ func _on_host_pressed(): add_player_character(1) players.append(1) - # Add bots to fill remaining slots for i in range(2, max_players + 1): add_bot(i) @@ -194,8 +248,15 @@ func add_player_character(peer_id): connected_peer_ids.append(peer_id) var player_character = player_scene.instantiate() player_character.set_multiplayer_authority(peer_id) + + if multiplayer.is_server() and bots.size() > 0: + var bot_to_replace = get_node_or_null(str(bots[0])) + if bot_to_replace: + player_character.current_position = bot_to_replace.current_position + add_child(player_character) player_character.add_to_group("Players", true) + if peer_id == multiplayer.get_unique_id(): local_player_character = player_character update_button_states() @@ -209,7 +270,7 @@ func add_bot(bot_id): @rpc("call_local") func create_bot(bot_id): var bot_character = player_scene.instantiate() - bot_character.set_multiplayer_authority(1) # Set server as authority for bots + bot_character.set_multiplayer_authority(1) bot_character.name = str(bot_id) add_child(bot_character) bot_character.add_to_group("Players", true) @@ -224,17 +285,17 @@ func replace_bot_with_player(player_id): var bot_id = bots.pop_front() players.erase(bot_id) players.append(player_id) - moving_bots.erase(bot_id) # Remove bot from moving tracking + moving_bots.erase(bot_id) rpc("remove_bot", bot_id) rpc("sync_players", players) @rpc("call_local") func remove_bot(bot_id): - var bot_node = get_node(str(bot_id)) + var bot_node = get_node_or_null(str(bot_id)) if bot_node: bot_node.queue_free() -func get_next_available_bot_id(): +func get_next_available_bot_id() -> int: for i in range(2, max_players + 1): if not i in players: return i @@ -256,7 +317,6 @@ func sync_game_state(current_players, current_bots, is_game_started, is_turn_bas game_started = is_game_started turn_based_mode = is_turn_based - # Create bot characters for existing bots for bot_id in bots: if not has_node(str(bot_id)): create_bot(bot_id) @@ -288,9 +348,7 @@ func sync_players(new_players): func next_turn(): if multiplayer.is_server() and turn_based_mode: - current_turn_index += 1 - if current_turn_index >= players.size(): - current_turn_index = 0 + current_turn_index = (current_turn_index + 1) % players.size() rpc("set_current_turn", players[current_turn_index]) if players[current_turn_index] in bots: move_bot(players[current_turn_index]) @@ -311,124 +369,145 @@ func set_current_turn(player_id): if not turn_based_mode: return - var players = get_tree().get_nodes_in_group("Players") - for player in players: - player.is_my_turn = (player.name == str(player_id)) - if player.is_my_turn: + for player in get_tree().get_nodes_in_group("Players"): + if player.name == str(player_id): + player.is_my_turn = true + player.action_points = 2 + player.has_moved_this_turn = false + player.has_performed_action = false player.start_turn() + else: + player.is_my_turn = false func end_current_turn(): if multiplayer.is_server(): next_turn() rpc("sync_turn_index", current_turn_index) -func _on_message_input_text_submitted(new_text): - if new_text.length() > max_message_input_char: - new_text = new_text.substr(0, max_message_input_char) + " ... " - local_player_character.rpc("display_message", new_text) - $MessageInput.text = "" - $MessageInput.release_focus() - func move_bot(bot_id): - if multiplayer.is_server(): - if moving_bots.get(bot_id, false): - return - - var bot = get_node(str(bot_id)) - if bot and (turn_based_mode or not bot.is_player_moving): - moving_bots[bot_id] = true - - var best_move = evaluate_bot_move(bot) - - match best_move.action: - "grab": - if bot.grab_item(): - bot.has_performed_action = true - moving_bots[bot_id] = false - # Don't end turn, allow movement after grab - move_bot(bot_id) # Try to move after grabbing - "put": - if bot.put_item(): - bot.has_performed_action = true - moving_bots[bot_id] = false - # Don't end turn, allow movement after put - move_bot(bot_id) # Try to move after putting - "move": - if bot.has_performed_action: - var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(best_move.position)) - if path.size() > 1: - path.pop_front() - var trimmed_path = path.slice(0, bot.movement_range) - bot.rotate_towards_target(best_move.position) - bot.move_bot_along_path(trimmed_path, bot_id) - else: - moving_bots[bot_id] = false - if turn_based_mode: - end_current_turn() - else: - moving_bots[bot_id] = false - if turn_based_mode: - end_current_turn() - _: - moving_bots[bot_id] = false - if turn_based_mode: - end_current_turn() + if not multiplayer.is_server() or moving_bots.get(bot_id, false): + return + + var bot = get_node_or_null(str(bot_id)) + if not is_instance_valid(bot) or bot.is_player_moving: + moving_bots.erase(bot_id) + return + + if bot.action_points <= 0: + if turn_based_mode: + moving_bots[bot_id] = false + end_current_turn() + else: + bot.action_points = 2 + bot.has_moved_this_turn = false + bot.has_performed_action = false + moving_bots[bot_id] = false + await get_tree().create_timer(0.5).timeout + move_bot(bot_id) + return + + moving_bots[bot_id] = true + await get_tree().create_timer(0.5).timeout + + if not is_instance_valid(bot): + moving_bots.erase(bot_id) + return + + var best_move = evaluate_bot_move(bot) + execute_bot_move(bot, bot_id, best_move) -func bot_movement_completed(bot_id): - if multiplayer.is_server(): - moving_bots[bot_id] = false +func execute_bot_move(bot, bot_id, move): + match move.action: + "arrange": + if bot.action_points >= 2: + bot.arrange_playerboard_item(bot.find_best_arrangement_slot()) + bot.action_points -= 2 + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + + "grab", "put": + var success = bot.grab_item(move.position) if move.action == "grab" else bot.put_item(move.position) + if success: + bot.action_points -= 1 + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + + "move": + if is_instance_valid(bot) and bot.action_points >= 1: + var path = bot.enhanced_gridmap.find_path(Vector2(bot.current_position), Vector2(move.position)) + if path.size() > 1: + path.pop_front() + var trimmed_path = path.slice(0, bot.movement_range) + bot.rotate_towards_target(move.position) + bot.move_bot_along_path(trimmed_path, bot_id) + bot.action_points -= 1 + else: + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + else: + moving_bots[bot_id] = false + if bot.action_points > 0 or not turn_based_mode: + move_bot(bot_id) + elif turn_based_mode: + end_current_turn() + + _: + moving_bots[bot_id] = false + if turn_based_mode: + end_current_turn() + else: + move_bot(bot_id) func evaluate_bot_move(bot: Node) -> Dictionary: - var best_move = { - "action": "none", - "position": bot.current_position, - "value": -1 - } + if not is_instance_valid(bot) or bot.action_points <= 0: + return { "action": "none", "position": Vector2i.ZERO, "value": -1 } + + var moves = [] - # If no action performed yet, prioritize grab/put - if not bot.has_performed_action: - # Check current position for grabbing - var current_cell = Vector3i(bot.current_position.x, 1, bot.current_position.y) - var current_item = bot.enhanced_gridmap.get_cell_item(current_cell) + if bot.action_points >= 2 and bot.check_playerboard_arrangement(bot): + moves.append({ "action": "arrange", "position": bot.current_position, "value": 20 }) + + if bot.action_points >= 1: + var put_position = bot.find_best_put_position(bot) + if put_position != Vector2i(-1, -1): + moves.append({ "action": "put", "position": put_position, "value": 18 }) + + if bot.action_points >= 1 and not bot.playerboard_is_full(): + var grab_position = bot.find_best_grab_position() + if grab_position != Vector2i(-1, -1): + moves.append({ "action": "grab", "position": grab_position, "value": 15 }) + + if bot.action_points >= 1 and not bot.has_moved_this_turn: + var random_pos = bot.find_random_valid_position_in_range() + if random_pos != bot.current_position: + moves.append({ "action": "move", "position": random_pos, "value": 5 }) + + moves.sort_custom(func(a, b): return a.value > b.value) + return moves[0] if moves.size() > 0 else { "action": "none", "position": bot.current_position, "value": 0 } + +func bot_movement_completed(bot_id): + if not multiplayer.is_server(): + return - # Evaluate grabbing current item if it matches goals - if current_item != -1 and current_item in bot.goals and bot.playerboard.find(-1) != -1: - return { - "action": "grab", - "position": bot.current_position, - "value": 10 - } - - # Evaluate putting item from playerboard - for goal in bot.goals: - var item_index = bot.playerboard.find(goal) - if item_index != -1 and current_item == -1: - return { - "action": "put", - "position": bot.current_position, - "value": 15 - } + moving_bots[bot_id] = false + var bot = get_node_or_null(str(bot_id)) + + if not is_instance_valid(bot): + moving_bots.erase(bot_id) + return + + if bot.action_points > 0 or not turn_based_mode: + await get_tree().create_timer(0.5).timeout + if is_instance_valid(bot): + move_bot(bot_id) else: - # Bot has performed action, look for movement - var neighbors = bot.enhanced_gridmap.get_neighbors(bot.current_position, 1) - for neighbor in neighbors: - if not neighbor.is_walkable: - continue - - if not bot.is_within_movement_range(neighbor.position): - continue - - var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) - var item = bot.enhanced_gridmap.get_cell_item(cell) - - # Evaluate position for next turn - if item in bot.goals or item == -1: - var value = 8 - if value > best_move.value: - best_move = { - "action": "move", - "position": neighbor.position, - "value": value - } - - return best_move + end_current_turn() diff --git a/scenes/main.tscn b/scenes/main.tscn index 74c42f5..f63cdfc 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -1,29 +1,38 @@ -[gd_scene load_steps=7 format=3 uid="uid://dxn87yj8qnfpp"] +[gd_scene load_steps=14 format=3 uid="uid://dxn87yj8qnfpp"] [ext_resource type="MeshLibrary" uid="uid://54tpx8cmksfc" path="res://addons/enhanced_gridmap/meshlibrary/default.tres" id="1_110wo"] [ext_resource type="Script" path="res://scenes/main.gd" id="1_xcpe3"] [ext_resource type="Script" path="res://addons/enhanced_gridmap/enhanced_gridmap.gd" id="2_hbe1v"] [ext_resource type="Environment" uid="uid://jbptgqvstei3" path="res://assets/main-environment.tres" id="4_ky38j"] [ext_resource type="StyleBox" uid="uid://dlw1ogamn741n" path="res://assets/styles/box_flat.tres" id="5_dvx6y"] +[ext_resource type="Texture2D" uid="uid://2yrc6rl4dmd8" path="res://assets/textures/player_board_and_blue_print/tile_null.tres" id="6_2vy7d"] +[ext_resource type="Texture2D" uid="uid://cwxgdi7b4ps40" path="res://assets/textures/Hilight.png" id="7_2nq2l"] +[ext_resource type="Texture2D" uid="uid://c2bj21abtgda1" path="res://assets/models/pboard/HighlightRect.tres" id="7_vv0nt"] +[ext_resource type="Texture2D" uid="uid://0wjk16jlgfq" path="res://assets/models/pboard/SelectRect.tres" id="8_8meci"] +[ext_resource type="Texture2D" uid="uid://dojnv8o6we4ey" path="res://assets/textures/Selected.png" id="8_b18m4"] +[ext_resource type="Texture2D" uid="uid://68x88jj25yxg" path="res://assets/textures/Adjacent.png" id="9_6gcb6"] +[ext_resource type="Texture2D" uid="uid://dasaeaytvhll0" path="res://assets/models/pboard/AdjacentRect.tres" id="9_aspsw"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1cewu"] [node name="Main" type="Node3D"] script = ExtResource("1_xcpe3") +turn_based_mode = false [node name="EnhancedGridMap" type="GridMap" parent="."] mesh_library = ExtResource("1_110wo") cell_size = Vector3(1, 1, 1) data = { -"cells": PackedInt32Array(9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 8, 0, 9, 9, 0, 9, 7, 0, 9, 6, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 65536, 0, 7, 65536, 1, 10, 65536, 2, 9, 65536, 3, 9, 65536, 4, 8, 65536, 5, 7, 65536, 6, 9, 65536, 7, 9, 65536, 8, 10, 65536, 9, 8, 65537, 0, 9, 65537, 1, 8, 65537, 2, 10, 65537, 3, 9, 65537, 4, 7, 65537, 5, 10, 65537, 6, 9, 65537, 7, 9, 65537, 8, 10, 65537, 9, 10, 65538, 0, 7, 65538, 1, 10, 65538, 2, 9, 65538, 3, 8, 65538, 4, 9, 65538, 5, 10, 65538, 6, 9, 65538, 7, 8, 65538, 8, 9, 65538, 9, 10, 65539, 0, 9, 65539, 1, 10, 65539, 2, 9, 65539, 3, 10, 65539, 4, 9, 65539, 5, 9, 65539, 6, 10, 65539, 7, 10, 65539, 8, 9, 65539, 9, 9, 65540, 0, 7, 65540, 1, 7, 65540, 2, 7, 65540, 3, 10, 65540, 4, 9, 65540, 5, 7, 65540, 6, 9, 65540, 7, 9, 65540, 8, 7, 65540, 9, 8, 65541, 0, 8, 65541, 1, 7, 65541, 2, 7, 65541, 3, 10, 65541, 4, 10, 65541, 5, 8, 65541, 6, 7, 65541, 7, 7, 65541, 8, 8, 65541, 9, 9, 65542, 0, 10, 65542, 1, 10, 65542, 2, 9, 65542, 3, 7, 65542, 4, 8, 65542, 5, 9, 65542, 6, 10, 65542, 7, 9, 65542, 8, 10, 65542, 9, 9, 65543, 0, 7, 65543, 1, 8, 65543, 2, 10, 65543, 3, 8, 65543, 4, 7, 65543, 5, 10, 65543, 6, 10, 65543, 7, 7, 65543, 8, 10, 65543, 9, 8, 65544, 0, 9, 65544, 1, 9, 65544, 2, 8, 65544, 3, 8, 65544, 4, 8, 65544, 5, 7, 65544, 6, 8, 65544, 7, 9, 65544, 8, 10, 65544, 9, 10, 65545, 0, 10, 65545, 1, 8, 65545, 2, 10, 65545, 3, 8, 65545, 4, 8, 65545, 5, 7, 65545, 6, 9, 65545, 7, 9, 65545, 8, 9, 65545, 9, 9) +"cells": PackedInt32Array(0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 7, 0, 0, 8, 0, 0, 9, 0, 0, 10, 0, 0, 11, 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5, 0, 1, 6, 0, 1, 7, 0, 1, 8, 0, 1, 9, 0, 1, 10, 0, 1, 11, 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5, 0, 2, 6, 0, 2, 7, 0, 2, 8, 0, 2, 9, 0, 2, 10, 0, 2, 11, 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5, 0, 3, 6, 0, 3, 7, 0, 3, 8, 0, 3, 9, 0, 3, 10, 0, 3, 11, 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5, 0, 4, 6, 0, 4, 7, 0, 4, 8, 0, 4, 9, 0, 4, 10, 0, 4, 11, 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5, 0, 5, 6, 0, 5, 7, 0, 5, 8, 0, 5, 9, 0, 5, 10, 0, 5, 11, 0, 6, 0, 0, 6, 1, 0, 6, 2, 0, 6, 3, 0, 6, 4, 0, 6, 5, 0, 6, 6, 0, 6, 7, 0, 6, 8, 0, 6, 9, 0, 6, 10, 0, 6, 11, 0, 7, 0, 0, 7, 1, 0, 7, 2, 0, 7, 3, 0, 7, 4, 0, 7, 5, 0, 7, 6, 0, 7, 7, 0, 7, 8, 0, 7, 9, 0, 7, 10, 0, 7, 11, 0, 8, 0, 0, 8, 1, 0, 8, 2, 0, 8, 3, 0, 8, 4, 0, 8, 5, 0, 8, 6, 0, 8, 7, 0, 8, 8, 0, 8, 9, 0, 8, 10, 0, 8, 11, 0, 9, 0, 0, 9, 1, 0, 9, 2, 0, 9, 3, 0, 9, 4, 0, 9, 5, 0, 9, 6, 0, 9, 7, 0, 9, 8, 0, 9, 9, 0, 9, 10, 0, 9, 11, 0, 10, 0, 0, 10, 1, 0, 10, 2, 0, 10, 3, 0, 10, 4, 0, 10, 5, 0, 10, 6, 0, 10, 7, 0, 10, 8, 0, 10, 9, 0, 10, 10, 0, 10, 11, 0, 11, 0, 0, 11, 1, 0, 11, 2, 0, 11, 3, 0, 11, 4, 0, 11, 5, 0, 11, 6, 0, 11, 7, 0, 11, 8, 0, 11, 9, 0, 11, 10, 0, 11, 11, 0, 12, 0, 0, 12, 1, 0, 12, 2, 0, 12, 3, 0, 12, 4, 0, 12, 5, 0, 12, 6, 0, 12, 7, 0, 12, 8, 0, 12, 9, 0, 12, 10, 0, 12, 11, 0, 13, 0, 0, 13, 1, 0, 13, 2, 0, 13, 3, 0, 13, 4, 0, 13, 5, 0, 13, 6, 0, 13, 7, 0, 13, 8, 0, 13, 9, 0, 13, 10, 0, 13, 11, 0, 65537, 1, 9, 65537, 2, 9, 65537, 3, 10, 65537, 4, 7, 65537, 5, 10, 65537, 6, 7, 65537, 7, 7, 65537, 8, 8, 65537, 9, 7, 65537, 10, 10, 65537, 11, 8, 65538, 1, 8, 65538, 2, 8, 65538, 3, 10, 65538, 4, 8, 65538, 5, 10, 65538, 6, 8, 65538, 7, 9, 65538, 8, 9, 65538, 9, 7, 65538, 10, 7, 65538, 11, 9, 65539, 0, 8, 65539, 1, 9, 65539, 2, 7, 65539, 3, 10, 65539, 4, 9, 65539, 5, 7, 65539, 6, 8, 65539, 7, 9, 65539, 8, 7, 65539, 9, 7, 65539, 10, 7, 65539, 11, 9, 65540, 0, 9, 65540, 1, 9, 65540, 2, 10, 65540, 3, 8, 65540, 4, 9, 65540, 5, 10, 65540, 6, 7, 65540, 7, 10, 65540, 8, 9, 65540, 9, 10, 65540, 10, 9, 65540, 11, 10, 65541, 0, 8, 65541, 1, 8, 65541, 2, 8, 65541, 3, 10, 65541, 4, 7, 65541, 5, 9, 65541, 6, 8, 65541, 7, 10, 65541, 8, 9, 65541, 9, 8, 65541, 10, 10, 65541, 11, 9, 65542, 0, 7, 65542, 1, 8, 65542, 2, 9, 65542, 3, 10, 65542, 4, 9, 65542, 5, 10, 65542, 6, 10, 65542, 7, 7, 65542, 8, 7, 65542, 9, 10, 65542, 10, 7, 65542, 11, 7, 65543, 0, 9, 65543, 1, 8, 65543, 2, 10, 65543, 3, 7, 65543, 4, 7, 65543, 5, 10, 65543, 6, 9, 65543, 7, 8, 65543, 8, 9, 65543, 9, 7, 65543, 10, 7, 65543, 11, 9, 65544, 0, 7, 65544, 1, 7, 65544, 2, 10, 65544, 3, 10, 65544, 4, 7, 65544, 5, 7, 65544, 6, 9, 65544, 7, 10, 65544, 8, 7, 65544, 9, 7, 65544, 10, 8, 65544, 11, 9, 65545, 0, 9, 65545, 1, 10, 65545, 2, 9, 65545, 3, 9, 65545, 4, 9, 65545, 5, 9, 65545, 6, 9, 65545, 7, 9, 65545, 8, 10, 65545, 9, 7, 65545, 10, 7, 65545, 11, 9, 65546, 0, 8, 65546, 1, 8, 65546, 2, 7, 65546, 3, 10, 65546, 4, 7, 65546, 5, 9, 65546, 6, 9, 65546, 7, 9, 65546, 8, 7, 65546, 9, 9, 65546, 10, 10, 65546, 11, 10, 65547, 0, 10, 65547, 1, 8, 65547, 2, 7, 65547, 3, 8, 65547, 4, 10, 65547, 5, 7, 65547, 6, 10, 65547, 7, 7, 65547, 8, 10, 65547, 9, 8, 65547, 10, 7, 65547, 11, 8, 65548, 0, 7, 65548, 1, 9, 65548, 2, 10, 65548, 3, 9, 65548, 4, 7, 65548, 5, 9, 65548, 6, 8, 65548, 7, 10, 65548, 8, 10, 65548, 9, 8, 65548, 10, 9, 65548, 11, 9, 65538, 0, 10, 65537, 0, 7) } script = ExtResource("2_hbe1v") +columns = 14 +rows = 12 floors = 2 -non_walkable_items = Array[int]([4, 5]) metadata/_editor_floor_ = Vector3(0, 1, 0) [node name="Camera3D" type="Camera3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 5, 15, 12.36) +transform = Transform3D(1, 0, 0, 0, 0.422618, 0.906308, 0, -0.906308, 0.422618, 6.75, 21, 16.5) environment = ExtResource("4_ky38j") fov = 35.5 @@ -45,17 +54,868 @@ grow_horizontal = 2 theme_override_styles/panel = ExtResource("5_dvx6y") [node name="PlayerboardUI" type="GridContainer" parent="."] -custom_minimum_size = Vector2(200, 200) +clip_contents = true anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 -offset_left = 30.0 -offset_top = -230.0 -offset_right = 230.0 -offset_bottom = -30.0 +offset_left = 40.0 +offset_top = -232.0 +offset_right = 236.0 +offset_bottom = -36.0 grow_vertical = 0 +size_flags_horizontal = 3 columns = 5 +[node name="Slot1" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot1"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_vv0nt") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot1"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_8meci") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot1"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_aspsw") + +[node name="Slot2" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot2"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot2"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot2"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot3" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot3"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot3"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot3"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot4" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot4"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot4"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot4"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot5" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot5"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot5"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot5"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot6" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot6"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot6"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot6"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot7" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot7"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot7"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot7"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot8" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot8"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot8"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot8"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot9" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot9"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot9"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot9"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot10" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot10"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot10"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot10"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot11" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot11"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot11"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot11"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot12" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot12"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot12"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot12"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot13" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot13"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot13"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot13"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot14" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot14"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot14"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot14"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot15" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot15"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot15"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot15"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot16" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot16"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot16"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot16"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot17" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot17"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot17"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot17"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot18" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot18"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot18"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot18"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot19" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot19"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot19"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot19"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot20" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot20"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot20"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot20"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot21" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot21"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot21"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot21"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot22" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot22"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot22"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot22"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot23" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot23"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot23"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot23"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot24" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot24"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot24"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot24"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + +[node name="Slot25" type="TextureRect" parent="PlayerboardUI"] +layout_mode = 2 +texture = ExtResource("6_2vy7d") + +[node name="HighlightRect" type="TextureRect" parent="PlayerboardUI/Slot25"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("7_2nq2l") + +[node name="SelectRect" type="TextureRect" parent="PlayerboardUI/Slot25"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("8_b18m4") + +[node name="AdjacentRect" type="TextureRect" parent="PlayerboardUI/Slot25"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("9_6gcb6") + [node name="ActionMenu" type="Control" parent="."] layout_mode = 3 anchors_preset = 3 diff --git a/scenes/player.gd b/scenes/player.gd index 5b4691c..4643142 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -8,21 +8,20 @@ var is_player_moving: bool = false @export var cell_size: Vector3 = Vector3(2, 2, 2) @export var cell_offset: Vector3 = Vector3(0, 0, 0) -@export var center_x: bool = false -@export var center_y: bool = false -@export var center_z: bool = false +@export var goals: Array[int] = [0,0,0,0,0,0,0,0,0] +@export var playerboard: Array[int] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] -# Goals & Playerboard Data -@export var goals: Array[int] = [0,0,0,0,0,0,0,0,0] # 9 length array for goals -@export var playerboard: Array[int] = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # 25 length array for holding items -var has_performed_action: bool = false # Track if grab/put action has been done +var has_performed_action: bool = false +var selected_gridmap_position = Vector2i(-1, -1) +var selected_playerboard_slot = -1 +var targeted_playerboard_slot = -1 +var action_points: int = 2 -# Player Rotation Config var target_rotation: float = 0.0 -var rotation_speed: float = 10.0 # Adjust this to control rotation speed +var rotation_speed: float = 10.0 -@export var movement_range: int = 1 # How many blocks can be moved at once -@export var use_diagonal_movement: bool = false: # Allow diagonal movement +@export var movement_range: int = 1 +@export var use_diagonal_movement: bool = false: set(value): use_diagonal_movement = value if enhanced_gridmap: @@ -33,6 +32,7 @@ var rotation_speed: float = 10.0 # Adjust this to control rotation speed is_my_turn = value if is_my_turn and is_multiplayer_authority(): rpc("display_message", "It's your turn!") + @export var has_moved_this_turn = false @onready var main_scene = get_tree().current_scene @@ -50,7 +50,7 @@ func _ready(): push_error("Main scene not found") if not enhanced_gridmap: - push_error("EnhancedGridMap node not found. Please set the correct path in the inspector.") + push_error("EnhancedGridMap node not found") return enhanced_gridmap.initialize_astar() @@ -59,14 +59,10 @@ func _ready(): current_position = find_valid_starting_position() update_player_position(current_position) - # Only set up input processing if this is not a bot if not is_in_group("Bots"): set_process_unhandled_input(is_multiplayer_authority()) - # Initialize random goals - initialize_random_goals() - - # Initialize playerboard with -1 (empty slots) + append_random_goals() playerboard.resize(25) playerboard.fill(-1) @@ -74,21 +70,7 @@ func _physics_process(_delta): if is_multiplayer_authority(): rpc("remote_set_position", global_position) -func _process(_delta): - # Skip processing for bots - if is_in_group("Bots"): - return - - if is_multiplayer_authority(): - if Input.is_action_just_pressed("grab_item"): - if grab_item(): - rpc("display_message", "Item grabbed!") - elif Input.is_action_just_pressed("put_item"): - if put_item(): - rpc("display_message", "Item placed!") - func _unhandled_input(event): - # First check if this is a bot if is_in_group("Bots"): return @@ -105,70 +87,85 @@ func _unhandled_input(event): if click_position != Vector2i(-1, -1): handle_grid_click(click_position) +func _on_slot_gui_input(event, slot_index, slot_ui) -> int: + if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: + var main = get_node("/root/Main") + if main.current_action_state == main.ActionState.ARRANGING: + if selected_playerboard_slot == -1: + select_playerboard_slot(slot_index) + return slot_index + else: + if selected_playerboard_slot == slot_index: + deselect_playerboard_slot() + return slot_index + elif can_move_to_target_playerboard_slot(): + target_playerboard_slot(slot_index) + main.emit_signal("can_move_item", true) + return slot_index + else: + return -1 + return -1 + func handle_grid_click(grid_position: Vector2i): var main = get_node("/root/Main") + if not main: + return + match main.current_action_state: main.ActionState.MOVING: if grid_position in highlighted_cells: move_player_to_clicked_position(grid_position) main.ActionState.GRABBING: - if grid_position in highlighted_cells: - grab_item_at_position(grid_position) + if grid_position in highlighted_cells or grid_position == current_position: + grab_item(grid_position) main.ActionState.PUTTING: - if grid_position in highlighted_cells: - put_item_at_position(grid_position) + if grid_position in highlighted_cells and selected_playerboard_slot != -1: + put_item(grid_position) main.ActionState.RANDOMIZING: if grid_position in highlighted_cells: - randomize_item_at_position(grid_position) + main.randomize_item_at_position(grid_position) + +func is_position_occupied(pos: Vector2i) -> bool: + for player in get_tree().get_nodes_in_group("Players"): + if player != self and player.current_position == pos: + return true + return false func find_valid_starting_position() -> Vector2i: var rng = RandomNumberGenerator.new() rng.randomize() - + var max_attempts = 100 var attempts = 0 - + while attempts < max_attempts: - current_position = Vector2i(0, rng.randi_range(0, 9)) - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(current_position.x, 0, current_position.y)) - - if cell_item not in enhanced_gridmap.non_walkable_items: - return current_position - + var x = rng.randi_range(0, enhanced_gridmap.columns - 1) + var y = rng.randi_range(0, enhanced_gridmap.rows - 1) + var pos = Vector2i(x, y) + if not is_position_occupied(pos): + return pos attempts += 1 - - return Vector2i(0, 0) + + return Vector2i.ZERO func find_random_valid_position_in_range() -> Vector2i: var rng = RandomNumberGenerator.new() rng.randomize() - var max_attempts = 100 - var attempts = 0 + var valid_positions = [] - while attempts < max_attempts: - var range_x = min(enhanced_gridmap.columns - 1, movement_range) - var range_y = min(enhanced_gridmap.rows - 1, movement_range) - - var offset_x = rng.randi_range(-range_x, range_x) - var offset_y = rng.randi_range(-range_y, range_y) - - var random_position = Vector2i( - clamp(current_position.x + offset_x, 0, enhanced_gridmap.columns - 1), - clamp(current_position.y + offset_y, 0, enhanced_gridmap.rows - 1) - ) - - if not is_within_movement_range(random_position): - attempts += 1 - continue - - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(random_position.x, 0, random_position.y)) - - if cell_item not in enhanced_gridmap.non_walkable_items and random_position != current_position: - return random_position - - attempts += 1 + for x in range(max(0, current_position.x - movement_range), + min(enhanced_gridmap.columns, current_position.x + movement_range + 1)): + for z in range(max(0, current_position.y - movement_range), + min(enhanced_gridmap.rows, current_position.y + movement_range + 1)): + var pos = Vector2i(x, z) + if pos != current_position and is_within_movement_range(pos): + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items) and not is_position_occupied(pos): + valid_positions.append(pos) + if valid_positions.size() > 0: + return valid_positions[rng.randi() % valid_positions.size()] return current_position func raycast_to_grid(from: Vector3, to: Vector3) -> Vector2i: @@ -189,55 +186,47 @@ func raycast_to_grid(from: Vector3, to: Vector3) -> Vector2i: return Vector2i(-1, -1) func is_within_movement_range(target_position: Vector2i) -> bool: - var distance = 0 + var distance: int if use_diagonal_movement: - # For diagonal movement, use max of x and y differences - distance = max(abs(target_position.x - current_position.x), - abs(target_position.y - current_position.y)) + distance = max(abs(target_position.x - current_position.x), abs(target_position.y - current_position.y)) else: - # For orthogonal movement, use Manhattan distance - distance = abs(target_position.x - current_position.x) + \ - abs(target_position.y - current_position.y) + distance = abs(target_position.x - current_position.x) + abs(target_position.y - current_position.y) return distance <= movement_range func move_player_to_clicked_position(grid_position: Vector2i): - if not is_multiplayer_authority(): + if not is_multiplayer_authority() or is_player_moving or action_points <= 0: return - if is_player_moving: - return - var main = get_node("/root/Main") - - # Check if we're in the correct action state - if main.current_action_state != main.ActionState.MOVING: + if not main or main.current_action_state != main.ActionState.MOVING or not grid_position in highlighted_cells: return - - # Validate the clicked position is highlighted - if not grid_position in highlighted_cells: - return - - # Check if movement is valid + if not is_within_movement_range(grid_position): - print("Movement out of range") return - + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(grid_position.x, 0, grid_position.y)) - - if cell_item in enhanced_gridmap.non_walkable_items: - print("Cannot move to non-walkable cell") + if cell_item in enhanced_gridmap.non_walkable_items or is_position_occupied(grid_position): return - + rotate_towards_target(grid_position) - + var path = enhanced_gridmap.find_path(Vector2(current_position), Vector2(grid_position)) - - if path.size() > 1: + if path.size() <= 1: + return + + var valid_path = true + for point in path.slice(1): + if is_position_occupied(Vector2i(point.x, point.y)): + valid_path = false + break + + if valid_path: path.pop_front() rpc("start_movement_along_path", path) - clear_highlights() # Clear highlights after movement starts + action_points -= 1 + clear_highlights() else: - print("No valid path found") + print("Path is blocked by other players") @rpc("any_peer", "call_local") func start_movement_along_path(path: Array): @@ -245,19 +234,17 @@ func start_movement_along_path(path: Array): var tween = create_tween() tween.set_trans(Tween.TRANS_CUBIC) tween.set_ease(Tween.EASE_IN_OUT) - + for point in path: - var target_position = grid_to_world(Vector2i(point.x, point.y)) - tween.tween_property(self, "position", target_position, 0.5) - + tween.tween_property(self, "position", grid_to_world(Vector2i(point.x, point.y)), 0.5) + tween.tween_callback(func(): current_position = Vector2i(path[-1].x, path[-1].y) is_player_moving = false enhanced_gridmap.clear_path_visualization() - has_moved_this_turn = true - var main = get_node("/root/Main") + has_moved_this_turn = path.size() <= movement_range - # Reset the action state + var main = get_node("/root/Main") main.set_action_state(main.ActionState.NONE) if main.turn_based_mode: @@ -265,61 +252,21 @@ func start_movement_along_path(path: Array): _after_action_completed() ) -func move_bot_along_path(path: Array, bot_id: int): - if not is_multiplayer_authority(): - return - - rpc("start_bot_movement_along_path", path, bot_id) - -@rpc("any_peer", "call_local") -func start_bot_movement_along_path(path: Array, bot_id: int): - is_player_moving = true - var tween = create_tween() - tween.set_trans(Tween.TRANS_CUBIC) - tween.set_ease(Tween.EASE_IN_OUT) - - for point in path: - var target_position = grid_to_world(Vector2i(point.x, point.y)) - tween.tween_property(self, "position", target_position, 0.5) - - tween.tween_callback(func(): - current_position = Vector2i(path[-1].x, path[-1].y) - is_player_moving = false - enhanced_gridmap.clear_path_visualization() - has_moved_this_turn = true - var main = get_node("/root/Main") - if main.turn_based_mode: - end_turn() - # Notify main that bot movement is complete - if multiplayer.is_server(): - main.bot_movement_completed(bot_id) - ) - func update_player_position(grid_position: Vector2i): position = grid_to_world(grid_position) func grid_to_world(grid_position: Vector2i) -> Vector3: var world_position = Vector3( - grid_position.x * cell_size.x, + grid_position.x * cell_size.x + cell_size.x * 0.5, cell_size.y, - grid_position.y * cell_size.z - ) - - world_position.x += cell_size.x * 0.5 - world_position.z += cell_size.z * 0.5 - - if center_x: - world_position.x += cell_size.x * 0.5 - if center_y: - world_position.y += cell_size.y * 0.5 - if center_z: - world_position.z += cell_size.z * 0.5 - - return world_position + cell_offset + grid_position.y * cell_size.z + cell_size.z * 0.5 + ) + cell_offset + return world_position func start_turn(): + action_points = 2 has_moved_this_turn = false - has_performed_action = false # Reset action flag at start of turn + has_performed_action = false is_my_turn = true if is_multiplayer_authority(): rpc("display_message", "It's your turn!") @@ -344,155 +291,594 @@ func display_message(message): $Bubble.hide() $Bubble/Message.hide() -func initialize_random_goals(): +func initialize_random_goals(_size:int, min_value:int, max_value:int, null_count:float) -> Array[int]: goals.clear() var rng = RandomNumberGenerator.new() rng.randomize() - for i in range(9): - goals.append(rng.randi_range(7, 10)) + var result : Array[int] = [] + var null_val = 0 + var max_nulls = 3 + + const SPECIAL_VALUES = {1: 7, 2: 8, 3: 9, 4: 10} + + for i in range(_size): + if null_val < max_nulls and rng.randf() < null_count: + result.append(-1) + null_val += 1 + else: + var val = rng.randi_range(min_value, max_value) + result.append(val if not val in SPECIAL_VALUES else SPECIAL_VALUES[val]) + + return result + +func append_random_goals(): + goals.append_array(initialize_random_goals(9, 7, 10, 1.0)) if is_multiplayer_authority(): rpc("sync_goals", goals) -func grab_item() -> bool: - if not enhanced_gridmap: +func grab_item(grid_position: Vector2i = current_position) -> bool: + if not enhanced_gridmap or action_points <= 0: return false - - var current_cell = Vector3i(current_position.x, 1, current_position.y) - var item = enhanced_gridmap.get_cell_item(current_cell) - if item == -1: # No item to grab - return false - - var empty_slot = playerboard.find(-1) - if empty_slot == -1: # No empty slots - return false - - playerboard[empty_slot] = item - enhanced_gridmap.set_cell_item(current_cell, -1) - - if is_multiplayer_authority(): - rpc("sync_playerboard", playerboard) - - has_performed_action = true # Set action flag - _after_action_completed() - return true - -func grab_item_at_position(grid_position: Vector2i) -> bool: - var main = get_node("/root/Main") - if main.current_action_state != main.ActionState.GRABBING: - return false - var cell = Vector3i(grid_position.x, 1, grid_position.y) var item = enhanced_gridmap.get_cell_item(cell) + if grid_position != current_position: + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + var is_adjacent = false + for neighbor in neighbors: + if neighbor.position == grid_position: + is_adjacent = true + break + if not is_adjacent: + return false + if item == -1: return false - - var empty_slot = playerboard.find(-1) - if empty_slot == -1: - return false - - playerboard[empty_slot] = item - enhanced_gridmap.set_cell_item(cell, -1) + if is_in_group("Bots"): + var empty_slot = playerboard.find(-1) + if empty_slot == -1: + return false + + if is_multiplayer_authority(): + playerboard[empty_slot] = item + rpc("sync_grid_item", cell.x, cell.y, cell.z, -1) + rpc("sync_playerboard", playerboard) + + has_performed_action = true + consume_action_points(1) + clear_playerboard_highlights() + _after_action_completed() + return true + else: + var main = get_node("/root/Main") + if main: + selected_gridmap_position = grid_position + clear_highlights() + clear_playerboard_highlights() + + for i in range(playerboard.size()): + if playerboard[i] == -1: + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: + slot.get_child(0).show() + highlighted_cells.append(i) + return true + + return false + +func put_item(grid_position: Vector2i = current_position) -> bool: + if not enhanced_gridmap or action_points <= 0 or selected_playerboard_slot == -1: + return false + + var cell = Vector3i(grid_position.x, 1, grid_position.y) + if enhanced_gridmap.get_cell_item(cell) != -1: + return false + + # Check if position is adjacent or current position + if grid_position != current_position: + var is_adjacent = false + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + for neighbor in neighbors: + if neighbor.position == grid_position: + is_adjacent = true + break + if not is_adjacent: + return false + + var item = playerboard[selected_playerboard_slot] if is_multiplayer_authority(): + rpc("sync_grid_item", cell.x, cell.y, cell.z, item) + playerboard[selected_playerboard_slot] = -1 rpc("sync_playerboard", playerboard) has_performed_action = true + consume_action_points(1) clear_highlights() - main.set_action_state(main.ActionState.MOVING) # Automatically switch to movement state + clear_playerboard_highlights() + selected_playerboard_slot = -1 + + var main = get_node("/root/Main") + if main: + main.set_action_state(main.ActionState.NONE) _after_action_completed() return true - -func put_item() -> bool: - if not enhanced_gridmap: - return false +func handle_put_action(): + var main = get_node("/root/Main") + if not main or action_points < 1: + return + clear_highlights() + clear_playerboard_highlights() + + # Highlight non-empty slots in playerboard + for i in range(playerboard.size()): + if playerboard[i] != -1: # Highlight occupied slots + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: + slot.get_child(0).show() # Show highlight for occupied slots + highlighted_cells.append(i) + +func handle_playerboard_slot_selected(slot_index: int): + var main = get_node("/root/Main") + if not main: + return + + if main.current_action_state == main.ActionState.PUTTING: + if playerboard[slot_index] != -1: # If slot has an item + selected_playerboard_slot = slot_index + clear_highlights() + highlight_empty_adjacent_cells() # Highlight valid put locations + elif main.current_action_state == main.ActionState.GRABBING: + if slot_index in highlighted_cells and playerboard[slot_index] == -1: + var cell = Vector3i(selected_gridmap_position.x, 1, selected_gridmap_position.y) + var item = enhanced_gridmap.get_cell_item(cell) + + if item != -1: + if is_multiplayer_authority(): + playerboard[slot_index] = item + rpc("sync_grid_item", cell.x, cell.y, cell.z, -1) + rpc("sync_playerboard", playerboard) + + has_performed_action = true + consume_action_points(1) + clear_highlights() + clear_playerboard_highlights() + selected_gridmap_position = Vector2i(-1, -1) + main.set_action_state(main.ActionState.NONE) + _after_action_completed() + +# We also need to add handle_put_slot_selected: +func handle_put_slot_selected(slot_index: int): + var main = get_node("/root/Main") + if not main or main.current_action_state != main.ActionState.PUTTING: + return + + if slot_index in highlighted_cells and playerboard[slot_index] in goals: + selected_playerboard_slot = slot_index + clear_highlights() + highlight_empty_adjacent_cells() + +#func arrange_playerboard_item(slot_index: int): + #if action_points < 2 or playerboard[slot_index] == -1: + #return +# + #var selected_item = playerboard[slot_index] + #var adjacent_slots = get_adjacent_playerboard_slots(slot_index) +# + #var main = get_node("/root/Main") + #if not main or not main.playerboard_ui: + #return +# + #var selected_slot_ui = main.playerboard_ui.get_child(slot_index) + #if selected_slot_ui.get_child_count() > 1: + #selected_slot_ui.get_child(1).show() +# + #for adj_slot in adjacent_slots: + #if playerboard[adj_slot] == -1 or is_valid_arrangement_slot(slot_index, adj_slot): + #var adj_slot_ui = main.playerboard_ui.get_child(adj_slot) + #if adj_slot_ui.get_child_count() > 2: + #adj_slot_ui.get_child(2).show() +# + #main.update_playerboard_highlights(adjacent_slots) +# + #var target_slot = await _on_slot_gui_input(null, slot_index, selected_slot_ui) + # + #if selected_slot_ui.get_child_count() > 1: + #selected_slot_ui.get_child(1).hide() + # + #for adj_slot in adjacent_slots: + #var adj_slot_ui = main.playerboard_ui.get_child(adj_slot) + #if adj_slot_ui.get_child_count() > 2: + #adj_slot_ui.get_child(2).hide() +# + #if target_slot != -1 and (playerboard[target_slot] == -1 or is_valid_arrangement_slot(slot_index, target_slot)): + #var temp_item = playerboard[target_slot] + #playerboard[target_slot] = selected_item + #playerboard[slot_index] = temp_item +# + #if is_multiplayer_authority(): + #rpc("sync_playerboard", playerboard) + #consume_action_points(2) + #has_performed_action = true + #_after_action_completed() + #main.update_playerboard_ui() + +func arrange_playerboard_item(slot_index: int): + if action_points < 2 or playerboard[slot_index] == -1: + return + + var selected_item = playerboard[slot_index] + var adjacent_slots = get_adjacent_playerboard_slots(slot_index) + + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + # Store the selected slot + selected_playerboard_slot = slot_index + + # Highlight selected slot + var selected_slot_ui = main.playerboard_ui.get_child(slot_index) + if selected_slot_ui.get_child_count() > 1: + selected_slot_ui.get_child(1).show() + + # Highlight valid adjacent slots + for adj_slot in adjacent_slots: + if playerboard[adj_slot] == -1: # Only highlight empty adjacent slots + var adj_slot_ui = main.playerboard_ui.get_child(adj_slot) + if adj_slot_ui.get_child_count() > 2: + adj_slot_ui.get_child(2).show() + highlighted_cells.append(adj_slot) + + # Connect to slot click signals + for i in range(playerboard.size()): + var slot = main.playerboard_ui.get_child(i) + if not slot.gui_input.is_connected(_on_slot_clicked): + slot.gui_input.connect(_on_slot_clicked.bind(i)) + +func _on_slot_clicked(event: InputEvent, slot_index: int): + if not event is InputEventMouseButton or not event.pressed or event.button_index != MOUSE_BUTTON_LEFT: + return + + var main = get_node("/root/Main") + if not main or main.current_action_state != main.ActionState.ARRANGING: + return + + if selected_playerboard_slot == -1 or slot_index == selected_playerboard_slot: + return + + var adjacent_slots = get_adjacent_playerboard_slots(selected_playerboard_slot) + if slot_index in adjacent_slots and playerboard[slot_index] == -1: + # Move item to empty target slot + var selected_item = playerboard[selected_playerboard_slot] + playerboard[slot_index] = selected_item + playerboard[selected_playerboard_slot] = -1 + + if is_multiplayer_authority(): + rpc("sync_playerboard", playerboard) + consume_action_points(2) + has_performed_action = true + + # Clear highlights + clear_highlights() + clear_playerboard_highlights() + + # Reset selection + selected_playerboard_slot = -1 + + # Update the visual representation + main.update_playerboard_ui() + main.set_action_state(main.ActionState.NONE) + + +func check_playerboard_arrangement(bot: Node) -> bool: + var goal_indices = [] # Store indices of non-empty goals + var goal_items = [] # Store the actual goal items + + # Get all valid goals (non -1) + for i in range(goals.size()): + if goals[i] != -1: + goal_indices.append(i) + goal_items.append(goals[i]) + + # Check if current arrangement matches goals + var current_items = [] + for i in range(playerboard.size()): + if playerboard[i] in goal_items: + current_items.append(playerboard[i]) + + # Compare current order with goal order + for i in range(min(current_items.size(), goal_items.size())): + if current_items[i] != goal_items[i]: + return true + + return false + +func is_valid_arrangement_slot(from_slot: int, to_slot: int) -> bool: + var from_row = from_slot / 5 + var from_col = from_slot % 5 + var to_row = to_slot / 5 + var to_col = to_slot % 5 + + var row_diff = abs(from_row - to_row) + var col_diff = abs(from_col - to_col) + + return (row_diff == 1 and col_diff == 0) or (row_diff == 0 and col_diff == 1) + +func get_adjacent_playerboard_slots(slot_index) -> Array: + var adjacent = [] + var row = slot_index / 5 + var col = slot_index % 5 + + if row > 0: adjacent.append(slot_index - 5) + if row < 4: adjacent.append(slot_index + 5) + if col > 0: adjacent.append(slot_index - 1) + if col < 4: adjacent.append(slot_index + 1) + + return adjacent + +func find_best_arrangement_slot() -> int: + for i in range(playerboard.size()): + if playerboard[i] != -1: + var neighbors = get_adjacent_playerboard_slots(i) + for adj_slot in neighbors: + if playerboard[adj_slot] == -1 and playerboard[i] in goals: + return adj_slot + return playerboard.find(-1) + +func find_best_put_position(bot: Node) -> Vector2i: + # Find the first empty cell adjacent to a matching item in the playerboard + for i in range(playerboard.size()): + if playerboard[i] in goals: + var neighbors = enhanced_gridmap.get_neighbors(current_position, 1) + for neighbor in neighbors: + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + if enhanced_gridmap.get_cell_item(cell) == -1: + return neighbor.position + return Vector2i(-1, -1) + +func find_best_grab_position() -> Vector2i: + # Find the first matching item in the grid or adjacent cells + var current_cell = Vector3i(current_position.x, 1, current_position.y) + if enhanced_gridmap.get_cell_item(current_cell) in goals: + return current_position + + var neighbors = enhanced_gridmap.get_neighbors(current_position, 1) + for neighbor in neighbors: + var cell = Vector3i(neighbor.position.x, 1, neighbor.position.y) + if enhanced_gridmap.get_cell_item(cell) in goals: + return neighbor.position + + return Vector2i(-1, -1) + +func has_item_at_current_position() -> bool: + var current_cell = Vector3i(current_position.x, 1, current_position.y) + return enhanced_gridmap.get_cell_item(current_cell) != -1 + +func has_items_in_playerboard() -> bool: + return playerboard.any(func(item): return item != -1) + +func playerboard_is_full() -> bool: + return playerboard.find(-1) == -1 + +func highlight_movement_range(): + if is_in_group("Bots"): + return + + for x in range(enhanced_gridmap.columns): + for z in range(enhanced_gridmap.rows): + var test_pos = Vector2i(x, z) + if is_within_movement_range(test_pos): + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items) and not is_position_occupied(test_pos): + highlighted_cells.append(test_pos) + enhanced_gridmap.set_cell_item(Vector3i(x, 0, z), enhanced_gridmap.hover_item) + +func highlight_adjacent_cells(): + if is_in_group("Bots"): + return + var current_cell = Vector3i(current_position.x, 1, current_position.y) if enhanced_gridmap.get_cell_item(current_cell) != -1: - return false # Cell is occupied - - var item_to_put = -1 - var item_index = -1 + highlighted_cells.append(current_position) + enhanced_gridmap.set_cell_item(Vector3i(current_position.x, 0, current_position.y), enhanced_gridmap.hover_item) - for goal in goals: - var index = playerboard.find(goal) - if index != -1: - item_to_put = goal - item_index = index - break - - if item_to_put == -1: - return false - - enhanced_gridmap.set_cell_item(current_cell, item_to_put) - playerboard[item_index] = -1 - - if is_multiplayer_authority(): - rpc("sync_playerboard", playerboard) - - has_performed_action = true # Set action flag - _after_action_completed() - return true + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + for neighbor in neighbors: + if neighbor.is_walkable: + var cell_pos = neighbor.position + if enhanced_gridmap.get_cell_item(Vector3i(cell_pos.x, 1, cell_pos.y)) != -1: + highlighted_cells.append(cell_pos) + enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), enhanced_gridmap.hover_item) -func put_item_at_position(grid_position: Vector2i) -> bool: - var main = get_node("/root/Main") - if main.current_action_state != main.ActionState.PUTTING: - return false + +func highlight_empty_adjacent_cells(): + if is_in_group("Bots"): + return - var cell = Vector3i(grid_position.x, 1, grid_position.y) - if enhanced_gridmap.get_cell_item(cell) != -1: - return false - - var item_to_put = -1 - var item_index = -1 - - for goal in goals: - var index = playerboard.find(goal) - if index != -1: - item_to_put = goal - item_index = index - break - - if item_to_put == -1: - return false - - enhanced_gridmap.set_cell_item(cell, item_to_put) - playerboard[item_index] = -1 - - if is_multiplayer_authority(): - rpc("sync_playerboard", playerboard) - - has_performed_action = true + # Clear previous highlights clear_highlights() - main.set_action_state(main.ActionState.MOVING) # Automatically switch to movement state - _after_action_completed() - return true + + # Highlight current position if empty + var current_cell = Vector3i(current_position.x, 1, current_position.y) + if enhanced_gridmap.get_cell_item(current_cell) == -1: + highlighted_cells.append(current_position) + enhanced_gridmap.set_cell_item(Vector3i(current_position.x, 0, current_position.y), + enhanced_gridmap.hover_item) + + # Highlight empty adjacent cells + var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) + for neighbor in neighbors: + if neighbor.is_walkable: + var cell_pos = neighbor.position + var cell = Vector3i(cell_pos.x, 1, cell_pos.y) + if enhanced_gridmap.get_cell_item(cell) == -1: # Check if cell is empty + highlighted_cells.append(cell_pos) + enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), + enhanced_gridmap.hover_item) + +func highlight_random_valid_cells(): + if is_in_group("Bots"): + return + + var valid_cells = [] + for x in range(enhanced_gridmap.columns): + for z in range(enhanced_gridmap.rows): + var cell_pos = Vector2i(x, z) + var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) + if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items): + valid_cells.append(cell_pos) -func randomize_item_at_position(grid_position: Vector2i) -> bool: - var main = get_node("/root/Main") - if main.current_action_state != main.ActionState.RANDOMIZING: - return false - - var cell = Vector3i(grid_position.x, 1, grid_position.y) - if enhanced_gridmap.get_cell_item(cell) != -1: - return false - var rng = RandomNumberGenerator.new() rng.randomize() + for _i in range(min(5, valid_cells.size())): + var index = rng.randi() % valid_cells.size() + var cell = valid_cells[index] + highlighted_cells.append(cell) + enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.hover_item) + valid_cells.remove_at(index) + +func highlight_occupied_playerboard_slots(): + if is_in_group("Bots"): + return + + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + # First reset all slots to normal + for i in range(playerboard.size()): + var slot = main.playerboard_ui.get_child(i) + for child in slot.get_children(): + child.hide() - # Assuming items are numbered 1-10 - var random_item = rng.randi_range(7, 10) - enhanced_gridmap.set_cell_item(cell, random_item) + # Highlight occupied slots that match goals + for i in range(playerboard.size()): + if playerboard[i] in goals: + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: + slot.get_child(0).show() # Show highlight for matching items + highlighted_cells.append(i) # Add to highlighted cells for tracking + + # Update the UI to reflect changes + main.update_playerboard_ui() + +func clear_highlights(): + if not enhanced_gridmap: + return + + for cell in highlighted_cells: + if cell is Vector2i: + enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.normal_items[0]) - has_performed_action = true - clear_highlights() - main.set_action_state(main.ActionState.MOVING) # Automatically switch to movement state - _after_action_completed() - return true + highlighted_cells.clear() + + var main = get_node("/root/Main") + if main and main.playerboard_ui: + for i in range(main.playerboard_ui.get_child_count()): + var slot = main.playerboard_ui.get_child(i) + for child in slot.get_children(): + child.hide() + +func clear_playerboard_highlights(): + var main = get_node("/root/Main") + if main and main.playerboard_ui: + for i in range(main.playerboard_ui.get_child_count()): + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 0: slot.get_child(0).hide() + if slot.get_child_count() > 1: slot.get_child(1).hide() + if slot.get_child_count() > 2: slot.get_child(2).hide() + + highlighted_cells.clear() + +func rotate_towards_target(target_pos: Vector2i): + var direction = Vector2(target_pos.x - current_position.x, target_pos.y - current_position.y).normalized() + target_rotation = atan2(direction.x, direction.y) + + if is_multiplayer_authority(): + rpc("sync_rotation", target_rotation) + + var tween = create_tween() + tween.tween_property(self, "rotation:y", target_rotation, 0.2) + +# We also need to add these supporting functions: +func select_playerboard_slot(slot_index: int): + selected_playerboard_slot = slot_index + _update_playerboard_slot_visual(slot_index) + _highlight_adjacent_playerboard_slots() + +func deselect_playerboard_slot(): + var old_selected = selected_playerboard_slot + selected_playerboard_slot = -1 + if old_selected != -1: + _update_playerboard_slot_visual(old_selected) + untarget_playerboard_slot() + _highlight_adjacent_playerboard_slots() + +func target_playerboard_slot(slot_index: int): + if targeted_playerboard_slot != -1: + untarget_playerboard_slot() + targeted_playerboard_slot = slot_index + _update_playerboard_slot_visual(slot_index) + +func untarget_playerboard_slot(): + if targeted_playerboard_slot != -1: + var old_targeted = targeted_playerboard_slot + targeted_playerboard_slot = -1 + _update_playerboard_slot_visual(old_targeted) + +func can_move_to_target_playerboard_slot() -> bool: + if selected_playerboard_slot == -1 or targeted_playerboard_slot == -1 or selected_playerboard_slot == targeted_playerboard_slot: + return false + + var adjacent_slots = get_adjacent_playerboard_slots(selected_playerboard_slot) + return adjacent_slots.has(targeted_playerboard_slot) + +func _update_playerboard_slot_visual(slot_index: int): + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + var slot = main.playerboard_ui.get_child(slot_index) + if slot: + if slot.get_child_count() > 0: + slot.get_child(0).visible = slot_index == selected_playerboard_slot + if slot.get_child_count() > 1: + slot.get_child(1).visible = slot_index == targeted_playerboard_slot + if slot.get_child_count() > 2: + slot.get_child(2).visible = selected_playerboard_slot != -1 and get_adjacent_playerboard_slots(selected_playerboard_slot).has(slot_index) + +func _highlight_adjacent_playerboard_slots(): + var main = get_node("/root/Main") + if not main or not main.playerboard_ui: + return + + for i in range(25): + var slot = main.playerboard_ui.get_child(i) + if slot.get_child_count() > 2: + slot.get_child(2).hide() + + if selected_playerboard_slot != -1: + var adjacent_slots = get_adjacent_playerboard_slots(selected_playerboard_slot) + for adj_slot in adjacent_slots: + var slot = main.playerboard_ui.get_child(adj_slot) + if slot.get_child_count() > 2: + slot.get_child(2).show() + +@rpc("any_peer", "call_local", "reliable") +func sync_rotation(new_rotation: float): + if not is_multiplayer_authority(): + rotation.y = new_rotation + +@rpc("any_peer", "call_local", "reliable") +func sync_grid_item(x: int, y: int, z: int, item: int): + if enhanced_gridmap: + enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item) @rpc("any_peer", "call_local") func sync_goals(new_goals: Array): @@ -503,118 +889,33 @@ func sync_playerboard(new_playerboard: Array): playerboard = new_playerboard _after_action_completed() -func rotate_towards_target(target_pos: Vector2i): - var direction = Vector2( - target_pos.x - current_position.x, - target_pos.y - current_position.y - ).normalized() - - target_rotation = atan2(direction.x, direction.y) - - # Create a tween for smooth rotation - var tween = create_tween() - tween.tween_property(self, "rotation:y", target_rotation, 0.2) - func _after_action_completed(): if multiplayer.get_unique_id() == get_multiplayer_authority(): var main = get_node("/root/Main") - main.update_button_states() - main.update_playerboard_ui() + if main: + if not main.turn_based_mode and action_points <= 0: + action_points = 2 + has_performed_action = false + has_moved_this_turn = false + main.update_button_states() + main.update_playerboard_ui() -func has_item_at_current_position() -> bool: - var current_cell = Vector3i(current_position.x, 1, current_position.y) - return enhanced_gridmap.get_cell_item(current_cell) != -1 - -func has_items_in_playerboard() -> bool: - return playerboard.any(func(item): return item != -1) - -func highlight_movement_range(): - var cells_to_highlight = [] - for x in range(enhanced_gridmap.columns): - for z in range(enhanced_gridmap.rows): - var test_pos = Vector2i(x, z) - if is_within_movement_range(test_pos): - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) - if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items): - cells_to_highlight.append(test_pos) - - for cell in cells_to_highlight: - highlighted_cells.append(cell) - # Store original item for restoration - var original_item = enhanced_gridmap.get_cell_item(Vector3i(cell.x, 0, cell.y)) - enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.hover_item) - -func highlight_adjacent_cells(): - var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) - for neighbor in neighbors: - if neighbor.is_walkable: - var cell_pos = neighbor.position - if enhanced_gridmap.get_cell_item(Vector3i(cell_pos.x, 1, cell_pos.y)) != -1: - highlighted_cells.append(cell_pos) - enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), enhanced_gridmap.hover_item) - -func highlight_empty_adjacent_cells(): - var neighbors = enhanced_gridmap.get_neighbors(current_position, 0) - for neighbor in neighbors: - if neighbor.is_walkable: - var cell_pos = neighbor.position - if enhanced_gridmap.get_cell_item(Vector3i(cell_pos.x, 1, cell_pos.y)) == -1: - highlighted_cells.append(cell_pos) - enhanced_gridmap.set_cell_item(Vector3i(cell_pos.x, 0, cell_pos.y), enhanced_gridmap.hover_item) - -func highlight_random_valid_cells(): - var valid_cells = [] - for x in range(enhanced_gridmap.columns): - for z in range(enhanced_gridmap.rows): - var cell_pos = Vector2i(x, z) - var cell_item = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) - if cell_item != -1 and not (cell_item in enhanced_gridmap.non_walkable_items): - valid_cells.append(cell_pos) - - # Highlight random subset of valid cells - var rng = RandomNumberGenerator.new() - rng.randomize() - for _i in range(min(5, valid_cells.size())): - var index = rng.randi() % valid_cells.size() - var cell = valid_cells[index] - highlighted_cells.append(cell) - enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.hover_item) - valid_cells.remove_at(index) - -func clear_highlights(): - for cell in highlighted_cells: - # Reset to normal item - enhanced_gridmap.set_cell_item(Vector3i(cell.x, 0, cell.y), enhanced_gridmap.normal_items[0]) - highlighted_cells.clear() - -func arrange_playerboard_item(slot_index: int): - if playerboard[slot_index] == -1: +func consume_action_points(points: int): + if not is_instance_valid(self) or not is_multiplayer_authority(): return - # Store the selected slot for arrangement - var temp_item = playerboard[slot_index] - playerboard[slot_index] = -1 - - # Wait for second click to complete arrangement - await get_tree().create_timer(0.1).timeout - - var target_slot = await wait_for_playerboard_click() - if target_slot != -1: - var swap_item = playerboard[target_slot] - playerboard[target_slot] = temp_item - playerboard[slot_index] = swap_item - - if multiplayer.is_server(): - rpc("sync_playerboard", playerboard) - -func wait_for_playerboard_click() -> int: + action_points -= points var main = get_node("/root/Main") - while true: - var event = await main.playerboard_ui.gui_input - if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT: - var local_pos = main.playerboard_ui.get_local_mouse_position() - for i in range(25): - var slot = main.playerboard_ui.get_child(i) - if slot.get_global_rect().has_point(event.global_position): - return i - return -1 + if not main: + return + + if action_points <= 0: + if main.turn_based_mode: + main.request_end_turn() + else: + action_points = 2 + has_performed_action = false + has_moved_this_turn = false + rpc("display_message", "Action Points Reset!") + + _after_action_completed()